├── .github └── workflows │ └── test-and-release.yml ├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── binding.gyp ├── deps └── snap7 │ ├── HISTORY.txt │ ├── gpl.txt │ ├── lgpl-3.0.txt │ └── src │ ├── core │ ├── s7_client.cpp │ ├── s7_client.h │ ├── s7_firmware.h │ ├── s7_isotcp.cpp │ ├── s7_isotcp.h │ ├── s7_micro_client.cpp │ ├── s7_micro_client.h │ ├── s7_partner.cpp │ ├── s7_partner.h │ ├── s7_peer.cpp │ ├── s7_peer.h │ ├── s7_server.cpp │ ├── s7_server.h │ ├── s7_text.cpp │ ├── s7_text.h │ └── s7_types.h │ ├── lib │ ├── snap7.def │ ├── snap7_libmain.cpp │ └── snap7_libmain.h │ └── sys │ ├── snap_msgsock.cpp │ ├── snap_msgsock.h │ ├── snap_platform.h │ ├── snap_sysutils.cpp │ ├── snap_sysutils.h │ ├── snap_tcpsrvr.cpp │ ├── snap_tcpsrvr.h │ ├── snap_threads.cpp │ ├── snap_threads.h │ ├── sol_threads.h │ ├── unix_threads.h │ └── win_threads.h ├── doc ├── client.md └── server.md ├── lib └── node-snap7.js ├── package.json └── src ├── node_snap7.cpp ├── node_snap7_client.cpp ├── node_snap7_client.h ├── node_snap7_server.cpp ├── node_snap7_server.h ├── snap7.cpp └── snap7.h /.github/workflows/test-and-release.yml: -------------------------------------------------------------------------------- 1 | name: Test and Release 2 | on: [push, pull_request] 3 | permissions: 4 | contents: read 5 | jobs: 6 | build: 7 | strategy: 8 | fail-fast: false 9 | matrix: 10 | os: [ubuntu-latest, macos-latest, windows-latest] 11 | node: [16, 18, 20, 22] 12 | arch: [x86, x64] 13 | exclude: 14 | - { os: ubuntu-latest, arch: x86 } 15 | - { os: macos-latest, arch: x86 } 16 | runs-on: ${{ matrix.os }} 17 | name: ${{ matrix.os }} / Node ${{ matrix.node }} ${{ matrix.arch }} 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@v4 21 | with: 22 | submodules: recursive 23 | fetch-depth: 2 24 | # Force Python to 3.10 until prebuild updates to node-gyp 10 25 | - name: Use Python 3.10 26 | if: ${{ matrix.os != 'windows-latest' }} 27 | uses: actions/setup-python@v4 28 | with: 29 | python-version: '3.10' 30 | - name: Use node ${{ matrix.node }} ${{ matrix.arch }} 31 | uses: actions/setup-node@v4 32 | with: 33 | node-version: ${{ matrix.node }} 34 | architecture: ${{ matrix.arch }} 35 | - name: Install 36 | run: npm install 37 | - name: Test 38 | env: 39 | PREBUILD_TOKEN: ${{ secrets.PREBUILD_TOKEN }} 40 | run: npm test 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | build/ 3 | node_modules/ 4 | test/ -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | test/ 2 | .travis.yml 3 | appveyor.yml 4 | .npmignore 5 | .gitignore 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2019 Mathias Küsel 4 | 5 | Permission is hereby granted, free of charge, to any person 6 | obtaining a copy of this software and associated documentation 7 | files (the "Software"), to deal in the Software without 8 | restriction, including without limitation the rights to use, 9 | copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the 11 | Software is furnished to do so, subject to the following 12 | conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | OTHER DEALINGS IN THE SOFTWARE. 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # node-snap7 2 | 3 | [![npm](https://img.shields.io/npm/v/node-snap7.svg?label=&logo=npm)](https://www.npmjs.com/package/node-snap7) 4 | [![Node version](https://img.shields.io/node/v/node-snap7.svg)](https://www.npmjs.com/package/node-snap7) 5 | [![Test and Release](https://github.com/mathiask88/node-snap7/actions/workflows/test-and-release.yml/badge.svg)](https://github.com/mathiask88/node-snap7/actions/workflows/test-and-release.yml) 6 | [![npm](https://img.shields.io/npm/dm/node-snap7.svg?label=dl)](https://www.npmjs.com/package/node-snap7) 7 | 8 | **Current node-snap7 version:** 1.0.8\ 9 | **Current snap7 version:** 1.4.2 10 | 11 | **In my spare time I am working on a [node-addon-api](https://github.com/nodejs/node-addon-api) rewrite and want to switch from [prebuild-install](https://github.com/prebuild/prebuild-install) to [prebuildify](https://github.com/prebuild/prebuildify).\ 12 | The current S7Server implementation has some bugs, please use with caution.** 13 | 14 | ## About 15 | This is a node.js wrapper for snap7. Snap7 is an open source, 32/64 bit, multi-platform Ethernet communication suite for interfacing natively with Siemens S7 PLCs (See [compatibility](http://snap7.sourceforge.net/snap7_client.html#target_compatibility)). 16 | 17 | ## Installation 18 | Install with: 19 | 20 | npm install node-snap7 21 | 22 | node-snap7 uses `prebuild` and `prebuild-install` for handling prebuilt binaries. See [this list](https://github.com/mathiask88/node-snap7/releases) of supported prebuilt platform binaries. When installing node-snap7 `prebuild-install` will install prebuilt binaries from GitHub if they exist and fallback to a compile step if they don't. 23 | 24 | If you don't want to use the `prebuild` for the platform you are installing on, specify the `--build-from-source` flag when you install. 25 | 26 | For building from source you need the following requirements: 27 | 28 | - Windows: 29 | - [Visual Studio 2013 Express or higher](https://www.visualstudio.com/de/vs/visual-studio-express/) 30 | - [Python 2.7](https://www.python.org/downloads/release/python-2714/) 31 | - Linux: 32 | - C++11 toolchain 33 | - [Python 2.7](https://www.python.org/downloads/release/python-2714/) 34 | 35 | ## Special thanks to 36 | - Davide Nardella for creating snap7 37 | 38 | ## How to use 39 | ### API 40 | - [Client](doc/client.md) 41 | - [Server](doc/server.md) 42 | 43 | ### Client Example 44 | ```javascript 45 | var snap7 = require('node-snap7'); 46 | 47 | var s7client = new snap7.S7Client(); 48 | s7client.ConnectTo('192.168.1.12', 0, 1, function(err) { 49 | if(err) 50 | return console.log(' >> Connection failed. Code #' + err + ' - ' + s7client.ErrorText(err)); 51 | 52 | // Read the first byte from PLC process outputs... 53 | s7client.ABRead(0, 1, function(err, res) { 54 | if(err) 55 | return console.log(' >> ABRead failed. Code #' + err + ' - ' + s7client.ErrorText(err)); 56 | 57 | // ... and write it to stdout 58 | console.log(res) 59 | }); 60 | }); 61 | ``` 62 | 63 | ### Server Example 64 | ```javascript 65 | var snap7 = require('node-snap7'); 66 | 67 | var s7server = new snap7.S7Server(); 68 | 69 | // Set up event listener 70 | s7server.on("event", function(event) { 71 | console.log(s7server.EventText(event)); 72 | }); 73 | 74 | // Create a new Buffer and register it to the server as DB1 75 | var db1 = new Buffer(100).fill('ÿ'); 76 | s7server.RegisterArea(s7server.srvAreaDB, 1, db1); 77 | 78 | // Start the server 79 | s7server.StartTo('127.0.0.1'); 80 | 81 | // Close the server after 20s in this example 82 | setTimeout(function() { 83 | s7server.Stop(); 84 | s7server.UnregisterArea(s7server.srvAreaDB, 1); 85 | }, 20000); 86 | ``` 87 | 88 | Have a look at the resourceless server example [here](doc/server.md#event-read-write). 89 | 90 | ## License & copyright 91 | Copyright (c) 2019, Mathias Küsel 92 | 93 | node-snap7 is licensed under the MIT license. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details. 94 | 95 | node-snap7 builds on the excellent work of the snap7 framework from Davide Nardella. Snap7 is issued under the GPL/LGPLv3 (see `./deps/snap7/gpl.txt ./deps/snap7/lgpl-3.0.txt`). 96 | -------------------------------------------------------------------------------- /binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [{ 3 | "target_name": "node_snap7", 4 | "include_dirs": [ 5 | " 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /deps/snap7/src/core/s7_client.h: -------------------------------------------------------------------------------- 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_client_h 27 | #define s7_client_h 28 | //--------------------------------------------------------------------------- 29 | #include "snap_threads.h" 30 | #include "s7_micro_client.h" 31 | //--------------------------------------------------------------------------- 32 | 33 | extern "C" { 34 | typedef void (S7API *pfn_CliCompletion) (void * usrPtr, int opCode, int opResult); 35 | } 36 | class TSnap7Client; 37 | 38 | class TClientThread: public TSnapThread 39 | { 40 | private: 41 | TSnap7Client * FClient; 42 | public: 43 | TClientThread(TSnap7Client *Client) 44 | { 45 | FClient = Client; 46 | } 47 | void Execute(); 48 | }; 49 | //--------------------------------------------------------------------------- 50 | class TSnap7Client: public TSnap7MicroClient 51 | { 52 | private: 53 | TClientThread *FThread; 54 | bool ThreadCreated; 55 | void CloseThread(); 56 | void OpenThread(); 57 | void StartAsyncJob(); 58 | protected: 59 | PSnapEvent EvtJob; 60 | PSnapEvent EvtComplete; 61 | pfn_CliCompletion CliCompletion; 62 | void *FUsrPtr; 63 | void DoCompletion(); 64 | public: 65 | friend class TClientThread; 66 | TSnap7Client(); 67 | ~TSnap7Client(); 68 | int Reset(bool DoReconnect); 69 | int SetAsCallback(pfn_CliCompletion pCompletion, void * usrPtr); 70 | int GetParam(int ParamNumber, void *pValue); 71 | int SetParam(int ParamNumber, void *pValue); 72 | // Async functions 73 | bool CheckAsCompletion( int & opResult); 74 | int WaitAsCompletion(unsigned long Timeout); 75 | int AsReadArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void * pUsrData); 76 | int AsWriteArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void * pUsrData); 77 | int AsListBlocksOfType(int BlockType, PS7BlocksOfType pUsrData, int & ItemsCount); 78 | int AsReadSZL(int ID, int Index, PS7SZL pUsrData, int & Size); 79 | int AsReadSZLList(PS7SZLList pUsrData, int &ItemsCount); 80 | int AsUpload(int BlockType, int BlockNum, void * pUsrData, int & Size); 81 | int AsFullUpload(int BlockType, int BlockNum, void * pUsrData, int & Size); 82 | int AsDownload(int BlockNum, void * pUsrData, int Size); 83 | int AsCopyRamToRom(int Timeout); 84 | int AsCompress(int Timeout); 85 | int AsDBRead(int DBNumber, int Start, int Size, void * pUsrData); 86 | int AsDBWrite(int DBNumber, int Start, int Size, void * pUsrData); 87 | int AsMBRead(int Start, int Size, void * pUsrData); 88 | int AsMBWrite(int Start, int Size, void * pUsrData); 89 | int AsEBRead(int Start, int Size, void * pUsrData); 90 | int AsEBWrite(int Start, int Size, void * pUsrData); 91 | int AsABRead(int Start, int Size, void * pUsrData); 92 | int AsABWrite(int Start, int Size, void * pUsrData); 93 | int AsTMRead(int Start, int Amount, void * pUsrData); 94 | int AsTMWrite(int Start, int Amount, void * pUsrData); 95 | int AsCTRead(int Start, int Amount, void * pUsrData); 96 | int AsCTWrite(int Start, int Amount, void * pUsrData); 97 | int AsDBGet(int DBNumber, void * pUsrData, int & Size); 98 | int AsDBFill(int DBNumber, int FillChar); 99 | }; 100 | 101 | typedef TSnap7Client *PSnap7Client; 102 | 103 | //--------------------------------------------------------------------------- 104 | #endif // s7_client_h 105 | -------------------------------------------------------------------------------- /deps/snap7/src/core/s7_isotcp.h: -------------------------------------------------------------------------------- 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_isotcp_h 27 | #define s7_isotcp_h 28 | //--------------------------------------------------------------------------- 29 | #include "snap_msgsock.h" 30 | //--------------------------------------------------------------------------- 31 | #pragma pack(1) 32 | 33 | #define isoTcpVersion 3 // RFC 1006 34 | #define isoTcpPort 102 // RFC 1006 35 | #define isoInvalidHandle 0 36 | #define MaxTSAPLength 16 // Max Lenght for Src and Dst TSAP 37 | #define MaxIsoFragments 64 // Max fragments 38 | #define IsoPayload_Size 4096 // Iso telegram Buffer size 39 | 40 | #define noError 0 41 | 42 | const longword errIsoMask = 0x000F0000; 43 | const longword errIsoBase = 0x0000FFFF; 44 | 45 | const longword errIsoConnect = 0x00010000; // Connection error 46 | const longword errIsoDisconnect = 0x00020000; // Disconnect error 47 | const longword errIsoInvalidPDU = 0x00030000; // Bad format 48 | const longword errIsoInvalidDataSize = 0x00040000; // Bad Datasize passed to send/recv : buffer is invalid 49 | const longword errIsoNullPointer = 0x00050000; // Null passed as pointer 50 | const longword errIsoShortPacket = 0x00060000; // A short packet received 51 | const longword errIsoTooManyFragments = 0x00070000; // Too many packets without EoT flag 52 | const longword errIsoPduOverflow = 0x00080000; // The sum of fragments data exceded maximum packet size 53 | const longword errIsoSendPacket = 0x00090000; // An error occurred during send 54 | const longword errIsoRecvPacket = 0x000A0000; // An error occurred during recv 55 | const longword errIsoInvalidParams = 0x000B0000; // Invalid TSAP params 56 | const longword errIsoResvd_1 = 0x000C0000; // Unassigned 57 | const longword errIsoResvd_2 = 0x000D0000; // Unassigned 58 | const longword errIsoResvd_3 = 0x000E0000; // Unassigned 59 | const longword errIsoResvd_4 = 0x000F0000; // Unassigned 60 | 61 | const longword ISO_OPT_TCP_NODELAY = 0x00000001; // Disable Nagle algorithm 62 | const longword ISO_OPT_INSIDE_MTU = 0x00000002; // Max packet size < MTU ethernet card 63 | 64 | // TPKT Header - ISO on TCP - RFC 1006 (4 bytes) 65 | typedef struct{ 66 | u_char Version; // Always 3 for RFC 1006 67 | u_char Reserved; // 0 68 | u_char HI_Lenght; // High part of packet lenght (entire frame, payload and TPDU included) 69 | u_char LO_Lenght; // Low part of packet lenght (entire frame, payload and TPDU included) 70 | } TTPKT; // Packet length : min 7 max 65535 71 | 72 | typedef struct { 73 | u_char PduSizeCode; 74 | u_char PduSizeLen; 75 | u_char PduSizeVal; 76 | u_char TSAP[245]; // We don't know in advance these fields.... 77 | } TCOPT_Params ; 78 | 79 | // PDU Type constants - ISO 8073, not all are mentioned in RFC 1006 80 | // For our purposes we use only those labeled with ** 81 | // These constants contains 4 low bit order 0 (credit nibble) 82 | // 83 | // $10 ED : Expedited Data 84 | // $20 EA : Expedited Data Ack 85 | // $40 UD : CLTP UD 86 | // $50 RJ : Reject 87 | // $70 AK : Ack data 88 | // ** $80 DR : Disconnect request (note : S7 doesn't use it) 89 | // ** $C0 DC : Disconnect confirm (note : S7 doesn't use it) 90 | // ** $D0 CC : Connection confirm 91 | // ** $E0 CR : Connection request 92 | // ** $F0 DT : Data 93 | // 94 | 95 | // COTP Header for CONNECTION REQUEST/CONFIRM - DISCONNECT REQUEST/CONFIRM 96 | typedef struct { 97 | u_char HLength; // Header length : initialized to 6 (length without params - 1) 98 | // descending classes that add values in params field must update it. 99 | u_char PDUType; // 0xE0 Connection request 100 | // 0xD0 Connection confirm 101 | // 0x80 Disconnect request 102 | // 0xDC Disconnect confirm 103 | u_short DstRef; // Destination reference : Always 0x0000 104 | u_short SrcRef; // Source reference : Always 0x0000 105 | u_char CO_R; // If the telegram is used for Connection request/Confirm, 106 | // the meaning of this field is CLASS+OPTION : 107 | // Class (High 4 bits) + Option (Low 4 bits) 108 | // Class : Always 4 (0100) but is ignored in input (RFC States this) 109 | // Option : Always 0, also this in ignored. 110 | // If the telegram is used for Disconnect request, 111 | // the meaning of this field is REASON : 112 | // 1 Congestion at TSAP 113 | // 2 Session entity not attached to TSAP 114 | // 3 Address unknown (at TCP connect time) 115 | // 128+0 Normal disconnect initiated by the session 116 | // entity. 117 | // 128+1 Remote transport entity congestion at connect 118 | // request time 119 | // 128+3 Connection negotiation failed 120 | // 128+5 Protocol Error 121 | // 128+8 Connection request refused on this network 122 | // connection 123 | // Parameter data : depending on the protocol implementation. 124 | // ISO 8073 define several type of parameters, but RFC 1006 recognizes only 125 | // TSAP related parameters and PDU size. See RFC 0983 for more details. 126 | TCOPT_Params Params; 127 | /* Other params not used here, list only for completeness 128 | ACK_TIME = 0x85, 1000 0101 Acknowledge Time 129 | RES_ERROR = 0x86, 1000 0110 Residual Error Rate 130 | PRIORITY = 0x87, 1000 0111 Priority 131 | TRANSIT_DEL = 0x88, 1000 1000 Transit Delay 132 | THROUGHPUT = 0x89, 1000 1001 Throughput 133 | SEQ_NR = 0x8A, 1000 1010 Subsequence Number (in AK) 134 | REASSIGNMENT = 0x8B, 1000 1011 Reassignment Time 135 | FLOW_CNTL = 0x8C, 1000 1100 Flow Control Confirmation (in AK) 136 | TPDU_SIZE = 0xC0, 1100 0000 TPDU Size 137 | SRC_TSAP = 0xC1, 1100 0001 TSAP-ID / calling TSAP ( in CR/CC ) 138 | DST_TSAP = 0xC2, 1100 0010 TSAP-ID / called TSAP 139 | CHECKSUM = 0xC3, 1100 0011 Checksum 140 | VERSION_NR = 0xC4, 1100 0100 Version Number 141 | PROTECTION = 0xC5, 1100 0101 Protection Parameters (user defined) 142 | OPT_SEL = 0xC6, 1100 0110 Additional Option Selection 143 | PROTO_CLASS = 0xC7, 1100 0111 Alternative Protocol Classes 144 | PREF_MAX_TPDU_SIZE = 0xF0, 1111 0000 145 | INACTIVITY_TIMER = 0xF2, 1111 0010 146 | ADDICC = 0xe0 1110 0000 Additional Information on Connection Clearing 147 | */ 148 | } TCOTP_CO ; 149 | typedef TCOTP_CO *PCOTP_CO; 150 | 151 | // COTP Header for DATA EXCHANGE 152 | typedef struct { 153 | u_char HLength; // Header length : 3 for this header 154 | u_char PDUType; // 0xF0 for this header 155 | u_char EoT_Num; // EOT (bit 7) + PDU Number (bits 0..6) 156 | // EOT = 1 -> End of Trasmission Packet (This packet is complete) 157 | // PDU Number : Always 0 158 | } TCOTP_DT; 159 | typedef TCOTP_DT *PCOTP_DT; 160 | 161 | // Info part of a PDU, only common parts. We use it to check the consistence 162 | // of a telegram regardless of it's nature (control or data). 163 | typedef struct { 164 | TTPKT TPKT; // TPKT Header 165 | // Common part of any COTP 166 | u_char HLength; // Header length : 3 for this header 167 | u_char PDUType; // Pdu type 168 | } TIsoHeaderInfo ; 169 | typedef TIsoHeaderInfo *PIsoHeaderInfo; 170 | 171 | // PDU Type consts (Code + Credit) 172 | const byte pdu_type_CR = 0xE0; // Connection request 173 | const byte pdu_type_CC = 0xD0; // Connection confirm 174 | const byte pdu_type_DR = 0x80; // Disconnect request 175 | const byte pdu_type_DC = 0xC0; // Disconnect confirm 176 | const byte pdu_type_DT = 0xF0; // Data transfer 177 | 178 | const byte pdu_EoT = 0x80; // End of Trasmission Packet (This packet is complete) 179 | 180 | const longword DataHeaderSize = sizeof(TTPKT)+sizeof(TCOTP_DT); 181 | const longword IsoFrameSize = IsoPayload_Size+DataHeaderSize; 182 | 183 | typedef struct { 184 | TTPKT TPKT; // TPKT Header 185 | TCOTP_CO COTP; // COPT Header for CONNECTION stuffs 186 | } TIsoControlPDU; 187 | typedef TIsoControlPDU *PIsoControlPDU; 188 | 189 | typedef u_char TIsoPayload[IsoPayload_Size]; 190 | 191 | typedef struct { 192 | TTPKT TPKT; // TPKT Header 193 | TCOTP_DT COTP; // COPT Header for DATA EXCHANGE 194 | TIsoPayload Payload; // Payload 195 | } TIsoDataPDU ; 196 | 197 | typedef TIsoDataPDU *PIsoDataPDU; 198 | typedef TIsoPayload *PIsoPayload; 199 | 200 | typedef enum { 201 | pkConnectionRequest, 202 | pkDisconnectRequest, 203 | pkEmptyFragment, 204 | pkInvalidPDU, 205 | pkUnrecognizedType, 206 | pkValidData 207 | } TPDUKind ; 208 | 209 | #pragma pack() 210 | 211 | void ErrIsoText(int Error, char *Msg, int len); 212 | 213 | class TIsoTcpSocket : public TMsgSocket 214 | { 215 | private: 216 | 217 | TIsoControlPDU FControlPDU; 218 | int IsoMaxFragments; // max fragments allowed for an ISO telegram 219 | // Checks the PDU format 220 | int CheckPDU(void *pPDU, u_char PduTypeExpected); 221 | // Receives the next fragment 222 | int isoRecvFragment(void *From, int Max, int &Size, bool &EoT); 223 | protected: 224 | TIsoDataPDU PDU; 225 | int SetIsoError(int Error); 226 | // Builds the control PDU starting from address properties 227 | virtual int BuildControlPDU(); 228 | // Calcs the PDU size 229 | int PDUSize(void *pPDU); 230 | // Parses the connection request PDU to extract TSAP and PDU size info 231 | virtual void IsoParsePDU(TIsoControlPDU PDU); 232 | // Confirms the connection, override this method for special pourpose 233 | // By default it checks the PDU format and resend it changing the pdu type 234 | int IsoConfirmConnection(u_char PDUType); 235 | void ClrIsoError(); 236 | virtual void FragmentSkipped(int Size); 237 | public: 238 | word SrcTSap; // Source TSAP 239 | word DstTSap; // Destination TSAP 240 | word SrcRef; // Source Reference 241 | word DstRef; // Destination Reference 242 | int IsoPDUSize; 243 | int LastIsoError; 244 | //-------------------------------------------------------------------------- 245 | TIsoTcpSocket(); 246 | ~TIsoTcpSocket(); 247 | // HIGH Level functions (work on payload hiding the underlying protocol) 248 | // Connects with a peer, the connection PDU is automatically built starting from address scheme (see below) 249 | int isoConnect(); 250 | // Disconnects from a peer, if OnlyTCP = true, only a TCP disconnect is performed, 251 | // otherwise a disconnect PDU is built and send. 252 | int isoDisconnect(bool OnlyTCP); 253 | // Sends a buffer, a valid header is created 254 | int isoSendBuffer(void *Data, int Size); 255 | // Receives a buffer 256 | int isoRecvBuffer(void *Data, int & Size); 257 | // Exchange cycle send->receive 258 | int isoExchangeBuffer(void *Data, int & Size); 259 | // A PDU is ready (at least its header) to be read 260 | bool IsoPDUReady(); 261 | // Same as isoSendBuffer, but the entire PDU has to be provided (in any case a check is performed) 262 | int isoSendPDU(PIsoDataPDU Data); 263 | // Same as isoRecvBuffer, but it returns the entire PDU, automatically enques the fragments 264 | int isoRecvPDU(PIsoDataPDU Data); 265 | // Same as isoExchangeBuffer, but the entire PDU has to be provided (in any case a check is performed) 266 | int isoExchangePDU(PIsoDataPDU Data); 267 | // Peeks an header info to know which kind of telegram is incoming 268 | void IsoPeek(void *pPDU, TPDUKind &PduKind); 269 | }; 270 | 271 | #endif // s7_isotcp_h 272 | -------------------------------------------------------------------------------- /deps/snap7/src/core/s7_micro_client.h: -------------------------------------------------------------------------------- 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_micro_client_h 27 | #define s7_micro_client_h 28 | //--------------------------------------------------------------------------- 29 | #include "s7_peer.h" 30 | //--------------------------------------------------------------------------- 31 | 32 | const longword errCliMask = 0xFFF00000; 33 | const longword errCliBase = 0x000FFFFF; 34 | 35 | const longword errCliInvalidParams = 0x00200000; 36 | const longword errCliJobPending = 0x00300000; 37 | const longword errCliTooManyItems = 0x00400000; 38 | const longword errCliInvalidWordLen = 0x00500000; 39 | const longword errCliPartialDataWritten = 0x00600000; 40 | const longword errCliSizeOverPDU = 0x00700000; 41 | const longword errCliInvalidPlcAnswer = 0x00800000; 42 | const longword errCliAddressOutOfRange = 0x00900000; 43 | const longword errCliInvalidTransportSize = 0x00A00000; 44 | const longword errCliWriteDataSizeMismatch = 0x00B00000; 45 | const longword errCliItemNotAvailable = 0x00C00000; 46 | const longword errCliInvalidValue = 0x00D00000; 47 | const longword errCliCannotStartPLC = 0x00E00000; 48 | const longword errCliAlreadyRun = 0x00F00000; 49 | const longword errCliCannotStopPLC = 0x01000000; 50 | const longword errCliCannotCopyRamToRom = 0x01100000; 51 | const longword errCliCannotCompress = 0x01200000; 52 | const longword errCliAlreadyStop = 0x01300000; 53 | const longword errCliFunNotAvailable = 0x01400000; 54 | const longword errCliUploadSequenceFailed = 0x01500000; 55 | const longword errCliInvalidDataSizeRecvd = 0x01600000; 56 | const longword errCliInvalidBlockType = 0x01700000; 57 | const longword errCliInvalidBlockNumber = 0x01800000; 58 | const longword errCliInvalidBlockSize = 0x01900000; 59 | const longword errCliDownloadSequenceFailed = 0x01A00000; 60 | const longword errCliInsertRefused = 0x01B00000; 61 | const longword errCliDeleteRefused = 0x01C00000; 62 | const longword errCliNeedPassword = 0x01D00000; 63 | const longword errCliInvalidPassword = 0x01E00000; 64 | const longword errCliNoPasswordToSetOrClear = 0x01F00000; 65 | const longword errCliJobTimeout = 0x02000000; 66 | const longword errCliPartialDataRead = 0x02100000; 67 | const longword errCliBufferTooSmall = 0x02200000; 68 | const longword errCliFunctionRefused = 0x02300000; 69 | const longword errCliDestroying = 0x02400000; 70 | const longword errCliInvalidParamNumber = 0x02500000; 71 | const longword errCliCannotChangeParam = 0x02600000; 72 | 73 | const time_t DeltaSecs = 441763200; // Seconds between 1970/1/1 (C time base) and 1984/1/1 (Siemens base) 74 | 75 | #pragma pack(1) 76 | 77 | // Read/Write Multivars 78 | typedef struct{ 79 | int Area; 80 | int WordLen; 81 | int Result; 82 | int DBNumber; 83 | int Start; 84 | int Amount; 85 | void *pdata; 86 | } TS7DataItem, *PS7DataItem; 87 | 88 | typedef int TS7ResultItems[MaxVars]; 89 | typedef TS7ResultItems *PS7ResultItems; 90 | 91 | typedef struct { 92 | int OBCount; 93 | int FBCount; 94 | int FCCount; 95 | int SFBCount; 96 | int SFCCount; 97 | int DBCount; 98 | int SDBCount; 99 | } TS7BlocksList, *PS7BlocksList; 100 | 101 | typedef struct { 102 | int BlkType; 103 | int BlkNumber; 104 | int BlkLang; 105 | int BlkFlags; 106 | int MC7Size; // The real size in bytes 107 | int LoadSize; 108 | int LocalData; 109 | int SBBLength; 110 | int CheckSum; 111 | int Version; 112 | // Chars info 113 | char CodeDate[11]; 114 | char IntfDate[11]; 115 | char Author[9]; 116 | char Family[9]; 117 | char Header[9]; 118 | } TS7BlockInfo, *PS7BlockInfo ; 119 | 120 | typedef word TS7BlocksOfType[0x2000]; 121 | typedef TS7BlocksOfType *PS7BlocksOfType; 122 | 123 | typedef struct { 124 | char Code[21]; // Order Code 125 | byte V1; // Version V1.V2.V3 126 | byte V2; 127 | byte V3; 128 | } TS7OrderCode, *PS7OrderCode; 129 | 130 | typedef struct { 131 | char ModuleTypeName[33]; 132 | char SerialNumber[25]; 133 | char ASName[25]; 134 | char Copyright[27]; 135 | char ModuleName[25]; 136 | } TS7CpuInfo, *PS7CpuInfo; 137 | 138 | typedef struct { 139 | int MaxPduLengt; 140 | int MaxConnections; 141 | int MaxMpiRate; 142 | int MaxBusRate; 143 | } TS7CpInfo, *PS7CpInfo; 144 | 145 | // See §33.1 of "System Software for S7-300/400 System and Standard Functions" 146 | // and see SFC51 description too 147 | typedef struct { 148 | word LENTHDR; 149 | word N_DR; 150 | } SZL_HEADER, *PSZL_HEADER; 151 | 152 | typedef struct { 153 | SZL_HEADER Header; 154 | byte Data[0x4000-4]; 155 | } TS7SZL, *PS7SZL; 156 | 157 | // SZL List of available SZL IDs : same as SZL but List items are big-endian adjusted 158 | typedef struct { 159 | SZL_HEADER Header; 160 | word List[0x2000-2]; 161 | } TS7SZLList, *PS7SZLList; 162 | 163 | // See §33.19 of "System Software for S7-300/400 System and Standard Functions" 164 | typedef struct { 165 | word sch_schal; 166 | word sch_par; 167 | word sch_rel; 168 | word bart_sch; 169 | word anl_sch; 170 | } TS7Protection, *PS7Protection; 171 | 172 | #define s7opNone 0 173 | #define s7opReadArea 1 174 | #define s7opWriteArea 2 175 | #define s7opReadMultiVars 3 176 | #define s7opWriteMultiVars 4 177 | #define s7opDBGet 5 178 | #define s7opUpload 6 179 | #define s7opDownload 7 180 | #define s7opDelete 8 181 | #define s7opListBlocks 9 182 | #define s7opAgBlockInfo 10 183 | #define s7opListBlocksOfType 11 184 | #define s7opReadSzlList 12 185 | #define s7opReadSZL 13 186 | #define s7opGetDateTime 14 187 | #define s7opSetDateTime 15 188 | #define s7opGetOrderCode 16 189 | #define s7opGetCpuInfo 17 190 | #define s7opGetCpInfo 18 191 | #define s7opGetPlcStatus 19 192 | #define s7opPlcHotStart 20 193 | #define s7opPlcColdStart 21 194 | #define s7opCopyRamToRom 22 195 | #define s7opCompress 23 196 | #define s7opPlcStop 24 197 | #define s7opGetProtection 25 198 | #define s7opSetPassword 26 199 | #define s7opClearPassword 27 200 | #define s7opDBFill 28 201 | 202 | // Param Number (to use with setparam) 203 | 204 | // Low level : change them to experiment new connections, their defaults normally work well 205 | const int pc_iso_SendTimeout = 6; 206 | const int pc_iso_RecvTimeout = 7; 207 | const int pc_iso_ConnTimeout = 8; 208 | const int pc_iso_SrcRef = 1; 209 | const int pc_iso_DstRef = 2; 210 | const int pc_iso_SrcTSAP = 3; 211 | const int pc_iso_DstTSAP = 4; 212 | const int pc_iso_IsoPduSize = 5; 213 | 214 | // Client Connection Type 215 | const word CONNTYPE_PG = 0x01; // Connect to the PLC as a PG 216 | const word CONNTYPE_OP = 0x02; // Connect to the PLC as an OP 217 | const word CONNTYPE_BASIC = 0x03; // Basic connection 218 | 219 | #pragma pack() 220 | 221 | // Internal struct for operations 222 | // Commands are not executed directly in the function such as "DBRead(...", 223 | // but this struct is filled and then PerformOperation() is called. 224 | // This allow us to implement async function very easily. 225 | 226 | struct TSnap7Job 227 | { 228 | int Op; // Operation Code 229 | int Result; // Operation result 230 | bool Pending; // A Job is pending 231 | longword Time; // Job Execution time 232 | // Read/Write 233 | int Area; // Also used for Block type and Block of type 234 | int Number; // Used for DB Number, Block number 235 | int Start; // Offset start 236 | int WordLen; // Word length 237 | // SZL 238 | int ID; // SZL ID 239 | int Index; // SZL Index 240 | // ptr info 241 | void * pData; // User data pointer 242 | int Amount; // Items amount/Size in input 243 | int *pAmount; // Items amount/Size in output 244 | // Generic 245 | int IParam; // Used for full upload and CopyRamToRom extended timeout 246 | }; 247 | 248 | class TSnap7MicroClient: public TSnap7Peer 249 | { 250 | private: 251 | void FillTime(word SiemensTime, char *PTime); 252 | byte BCDtoByte(byte B); 253 | byte WordToBCD(word Value); 254 | int opReadArea(); 255 | int opWriteArea(); 256 | int opReadMultiVars(); 257 | int opWriteMultiVars(); 258 | int opListBlocks(); 259 | int opListBlocksOfType(); 260 | int opAgBlockInfo(); 261 | int opDBGet(); 262 | int opDBFill(); 263 | int opUpload(); 264 | int opDownload(); 265 | int opDelete(); 266 | int opReadSZL(); 267 | int opReadSZLList(); 268 | int opGetDateTime(); 269 | int opSetDateTime(); 270 | int opGetOrderCode(); 271 | int opGetCpuInfo(); 272 | int opGetCpInfo(); 273 | int opGetPlcStatus(); 274 | int opPlcStop(); 275 | int opPlcHotStart(); 276 | int opPlcColdStart(); 277 | int opCopyRamToRom(); 278 | int opCompress(); 279 | int opGetProtection(); 280 | int opSetPassword(); 281 | int opClearPassword(); 282 | int CpuError(int Error); 283 | longword DWordAt(void * P); 284 | int CheckBlock(int BlockType, int BlockNum, void *pBlock, int Size); 285 | int SubBlockToBlock(int SBB); 286 | protected: 287 | word ConnectionType; 288 | longword JobStart; 289 | TSnap7Job Job; 290 | int DataSizeByte(int WordLength); 291 | int opSize; // last operation size 292 | int PerformOperation(); 293 | public: 294 | TS7Buffer opData; 295 | TSnap7MicroClient(); 296 | ~TSnap7MicroClient(); 297 | int Reset(bool DoReconnect); 298 | void SetConnectionParams(const char *RemAddress, word LocalTSAP, word RemoteTsap); 299 | void SetConnectionType(word ConnType); 300 | int ConnectTo(const char *RemAddress, int Rack, int Slot); 301 | int Connect(); 302 | int Disconnect(); 303 | int GetParam(int ParamNumber, void *pValue); 304 | int SetParam(int ParamNumber, void *pValue); 305 | // Fundamental Data I/O functions 306 | int ReadArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void * pUsrData); 307 | int WriteArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void * pUsrData); 308 | int ReadMultiVars(PS7DataItem Item, int ItemsCount); 309 | int WriteMultiVars(PS7DataItem Item, int ItemsCount); 310 | // Data I/O Helper functions 311 | int DBRead(int DBNumber, int Start, int Size, void * pUsrData); 312 | int DBWrite(int DBNumber, int Start, int Size, void * pUsrData); 313 | int MBRead(int Start, int Size, void * pUsrData); 314 | int MBWrite(int Start, int Size, void * pUsrData); 315 | int EBRead(int Start, int Size, void * pUsrData); 316 | int EBWrite(int Start, int Size, void * pUsrData); 317 | int ABRead(int Start, int Size, void * pUsrData); 318 | int ABWrite(int Start, int Size, void * pUsrData); 319 | int TMRead(int Start, int Amount, void * pUsrData); 320 | int TMWrite(int Start, int Amount, void * pUsrData); 321 | int CTRead(int Start, int Amount, void * pUsrData); 322 | int CTWrite(int Start, int Amount, void * pUsrData); 323 | // Directory functions 324 | int ListBlocks(PS7BlocksList pUsrData); 325 | int GetAgBlockInfo(int BlockType, int BlockNum, PS7BlockInfo pUsrData); 326 | int GetPgBlockInfo(void * pBlock, PS7BlockInfo pUsrData, int Size); 327 | int ListBlocksOfType(int BlockType, TS7BlocksOfType *pUsrData, int & ItemsCount); 328 | // Blocks functions 329 | int Upload(int BlockType, int BlockNum, void * pUsrData, int & Size); 330 | int FullUpload(int BlockType, int BlockNum, void * pUsrData, int & Size); 331 | int Download(int BlockNum, void * pUsrData, int Size); 332 | int Delete(int BlockType, int BlockNum); 333 | int DBGet(int DBNumber, void * pUsrData, int & Size); 334 | int DBFill(int DBNumber, int FillChar); 335 | // Date/Time functions 336 | int GetPlcDateTime(tm &DateTime); 337 | int SetPlcDateTime(tm * DateTime); 338 | int SetPlcSystemDateTime(); 339 | // System Info functions 340 | int GetOrderCode(PS7OrderCode pUsrData); 341 | int GetCpuInfo(PS7CpuInfo pUsrData); 342 | int GetCpInfo(PS7CpInfo pUsrData); 343 | int ReadSZL(int ID, int Index, PS7SZL pUsrData, int &Size); 344 | int ReadSZLList(PS7SZLList pUsrData, int &ItemsCount); 345 | // Control functions 346 | int PlcHotStart(); 347 | int PlcColdStart(); 348 | int PlcStop(); 349 | int CopyRamToRom(int Timeout); 350 | int Compress(int Timeout); 351 | int GetPlcStatus(int &Status); 352 | // Security functions 353 | int GetProtection(PS7Protection pUsrData); 354 | int SetSessionPassword(char *Password); 355 | int ClearSessionPassword(); 356 | // Properties 357 | bool Busy(){ return Job.Pending; }; 358 | int Time(){ return int(Job.Time);} 359 | }; 360 | 361 | typedef TSnap7MicroClient *PSnap7MicroClient; 362 | 363 | //--------------------------------------------------------------------------- 364 | #endif // s7_micro_client_h 365 | -------------------------------------------------------------------------------- /deps/snap7/src/core/s7_partner.h: -------------------------------------------------------------------------------- 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_partner_h 27 | #define s7_partner_h 28 | //--------------------------------------------------------------------------- 29 | #include "snap_threads.h" 30 | #include "s7_peer.h" 31 | //--------------------------------------------------------------------------- 32 | using namespace std; 33 | //--------------------------------------------------------------------------- 34 | 35 | #define MaxPartners 256 36 | #define MaxAdapters 256 37 | #define csTimeout 1500 // Connection server destruction timeout 38 | 39 | const int par_stopped = 0; // stopped 40 | const int par_connecting = 1; // running and active connecting 41 | const int par_waiting = 2; // running and waiting for a connection 42 | const int par_linked = 3; // running and connected 43 | const int par_sending = 4; // sending data 44 | const int par_receiving = 5; // receiving data 45 | const int par_binderror = 6; // error starting passive partner 46 | 47 | const longword errParMask = 0xFFF00000; 48 | const longword errParBase = 0x000FFFFF; 49 | 50 | const longword errParAddressInUse = 0x00200000; 51 | const longword errParNoRoom = 0x00300000; 52 | const longword errServerNoRoom = 0x00400000; 53 | const longword errParInvalidParams = 0x00500000; 54 | const longword errParNotLinked = 0x00600000; 55 | const longword errParBusy = 0x00700000; 56 | const longword errParFrameTimeout = 0x00800000; 57 | const longword errParInvalidPDU = 0x00900000; 58 | const longword errParSendTimeout = 0x00A00000; 59 | const longword errParRecvTimeout = 0x00B00000; 60 | const longword errParSendRefused = 0x00C00000; 61 | const longword errParNegotiatingPDU = 0x00D00000; 62 | const longword errParSendingBlock = 0x00E00000; 63 | const longword errParRecvingBlock = 0x00F00000; 64 | const longword errParBindError = 0x01000000; 65 | const longword errParDestroying = 0x01100000; 66 | const longword errParInvalidParamNumber = 0x01200000; // Invalid param (par_get/set_param) 67 | const longword errParCannotChangeParam = 0x01300000; // Cannot change because running 68 | const longword errParBufferTooSmall = 0x01400000; // Raised by LabVIEW wrapper 69 | 70 | class TSnap7Partner; 71 | typedef TSnap7Partner *PSnap7Partner; 72 | 73 | class TConnectionServer; 74 | typedef TConnectionServer *PConnectionServer; 75 | 76 | //------------------------------------------------------------------------------ 77 | // CONNECTION SERVERS MANAGER 78 | //------------------------------------------------------------------------------ 79 | class TServersManager 80 | { 81 | private: 82 | PConnectionServer Servers[MaxAdapters]; 83 | TSnapCriticalSection *cs; 84 | void Lock(); 85 | void Unlock(); 86 | int CreateServer(longword BindAddress, PConnectionServer &Server); 87 | void AddServer(PConnectionServer Server); 88 | public: 89 | int ServersCount; 90 | TServersManager(); 91 | ~TServersManager(); 92 | 93 | int GetServer(longword BindAddress, PConnectionServer &Server); 94 | void RemovePartner(PConnectionServer Server, PSnap7Partner Partner); 95 | 96 | }; 97 | typedef TServersManager *PServersManager; 98 | 99 | //------------------------------------------------------------------------------ 100 | // CONNECTION SERVER (Don't inherit from TcpSrv to avoid dependence) 101 | //------------------------------------------------------------------------------ 102 | 103 | class TConnListenerThread : public TSnapThread 104 | { 105 | private: 106 | TMsgSocket *FListener; 107 | TConnectionServer *FServer; 108 | public: 109 | TConnListenerThread(TMsgSocket *Listener, TConnectionServer *Server) 110 | { 111 | FServer=Server; 112 | FListener=Listener; 113 | FreeOnTerminate=false; 114 | }; 115 | void Execute(); 116 | }; 117 | typedef TConnListenerThread *PConnListenerThread; 118 | 119 | 120 | class TConnectionServer 121 | { 122 | private: 123 | TSnapCriticalSection *cs; 124 | bool FRunning; 125 | // Bind Address 126 | char FLocalAddress[16]; 127 | // Server listener 128 | PConnListenerThread ServerThread; 129 | // Socket listener 130 | PMsgSocket SockListener; 131 | // Finds a partner bound to the address 132 | PSnap7Partner FindPartner(longword Address); 133 | // Locks the Partner list 134 | void Lock(); 135 | // Unlocks the Partner list 136 | void Unlock(); 137 | protected: 138 | // Workers list 139 | PSnap7Partner Partners[MaxPartners]; 140 | bool Destroying; 141 | void Incoming(socket_t Sock); 142 | int Start(); 143 | int FirstFree(); 144 | public: 145 | int PartnersCount; 146 | longword LocalBind; 147 | TConnectionServer(); 148 | ~TConnectionServer(); 149 | 150 | int StartTo(const char *Address); 151 | void Stop(); 152 | int RegisterPartner(PSnap7Partner Partner); 153 | void RemovePartner(PSnap7Partner Partner); 154 | friend class TConnListenerThread; 155 | }; 156 | typedef TConnectionServer * PConnectionServer; 157 | 158 | //------------------------------------------------------------------------------ 159 | // PARTNER THREAD 160 | //------------------------------------------------------------------------------ 161 | class TPartnerThread : public TSnapThread 162 | { 163 | private: 164 | TSnap7Partner *FPartner; 165 | longword FRecoveryTime; 166 | longword FKaElapsed; 167 | protected: 168 | void Execute(); 169 | public: 170 | TPartnerThread(TSnap7Partner *Partner, longword RecoveryTime) 171 | { 172 | FPartner = Partner; 173 | FRecoveryTime =RecoveryTime; 174 | FreeOnTerminate =false; 175 | }; 176 | ~TPartnerThread(){}; 177 | }; 178 | typedef TPartnerThread *PPartnerThread; 179 | //------------------------------------------------------------------------------ 180 | // S7 PARTNER 181 | //------------------------------------------------------------------------------ 182 | 183 | typedef struct{ 184 | bool First; 185 | bool Done; 186 | uintptr_t Offset; 187 | longword TotalLength; 188 | longword In_R_ID; 189 | longword Elapsed; 190 | byte Seq_Out; 191 | }TRecvStatus; 192 | 193 | typedef struct{ 194 | bool Done; 195 | int Size; 196 | int Result; 197 | longword R_ID; 198 | longword Count; 199 | }TRecvLast; 200 | 201 | extern "C" { 202 | typedef void (S7API *pfn_ParBRecvCallBack)(void * usrPtr, int opResult, longword R_ID, void *pdata, int Size); 203 | typedef void (S7API *pfn_ParBSendCompletion)(void * usrPtr, int opResult); 204 | } 205 | 206 | class TSnap7Partner : public TSnap7Peer 207 | { 208 | private: 209 | PS7ReqHeader PDUH_in; 210 | void *FRecvUsrPtr; 211 | void *FSendUsrPtr; 212 | PSnapEvent SendEvt; 213 | PSnapEvent RecvEvt; 214 | PConnectionServer FServer; 215 | PPartnerThread FWorkerThread; 216 | bool FSendPending; 217 | bool FRecvPending; 218 | TRecvStatus FRecvStatus; 219 | TRecvLast FRecvLast; 220 | TPendingBuffer TxBuffer; 221 | TPendingBuffer RxBuffer; 222 | longword FSendElapsed; 223 | bool BindError; 224 | byte NextByte; 225 | pfn_ParBRecvCallBack OnBRecv; 226 | pfn_ParBSendCompletion OnBSend; 227 | void ClearRecv(); 228 | byte GetNextByte(); 229 | void CloseWorker(); 230 | bool BlockSend(); 231 | bool PickData(); 232 | bool BlockRecv(); 233 | bool ConnectionConfirm(); 234 | protected: 235 | bool Stopping; 236 | bool Execute(); 237 | void Disconnect(); 238 | bool ConnectToPeer(); 239 | bool PerformFunctionNegotiate(); 240 | public: 241 | bool Active; 242 | bool Running; 243 | longword PeerAddress; 244 | longword SrcAddress; 245 | int BRecvTimeout; 246 | int BSendTimeout; 247 | longword SendTime; 248 | longword RecvTime; 249 | longword RecoveryTime; 250 | longword KeepAliveTime; 251 | longword BytesSent; 252 | longword BytesRecv; 253 | longword SendErrors; 254 | longword RecvErrors; 255 | // The partner is linked when the init sequence is terminated 256 | //(TCP connection + ISO connection + PDU Length negotiation) 257 | bool Linked; 258 | TSnap7Partner(bool CreateActive); 259 | ~TSnap7Partner(); 260 | // Control 261 | int Start(); 262 | int StartTo(const char *LocAddress, const char *RemAddress, word LocTsap, word RemTsap); 263 | int Stop(); 264 | int Status(); 265 | int GetParam(int ParamNumber, void * pValue); 266 | int SetParam(int ParamNumber, void * pValue); 267 | // Block send 268 | int BSend(longword R_ID, void *pUsrData, int Size); 269 | int AsBSend(longword R_ID, void *pUsrData, int Size); 270 | bool CheckAsBSendCompletion(int &opResult); 271 | int WaitAsBSendCompletion(longword Timeout); 272 | int SetSendCallback(pfn_ParBSendCompletion pCompletion, void *usrPtr); 273 | // Block recv 274 | int BRecv(longword &R_ID, void *pData, int &Size, longword Timeout); 275 | bool CheckAsBRecvCompletion(int &opResult, longword &R_ID, 276 | void *pData, int &Size); 277 | int SetRecvCallback(pfn_ParBRecvCallBack pCompletion, void *usrPtr); 278 | 279 | friend class TConnectionServer; 280 | friend class TPartnerThread; 281 | }; 282 | 283 | 284 | #endif // s7_partner_h 285 | -------------------------------------------------------------------------------- /deps/snap7/src/core/s7_peer.cpp: -------------------------------------------------------------------------------- 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 | #include "s7_peer.h" 27 | //--------------------------------------------------------------------------- 28 | 29 | TSnap7Peer::TSnap7Peer() 30 | { 31 | PDUH_out=PS7ReqHeader(&PDU.Payload); 32 | PDURequest=480; // Our request, FPDULength will contain the CPU answer 33 | LastError=0; 34 | Destroying = false; 35 | } 36 | //--------------------------------------------------------------------------- 37 | TSnap7Peer::~TSnap7Peer() 38 | { 39 | Destroying = true; 40 | } 41 | //--------------------------------------------------------------------------- 42 | int TSnap7Peer::SetError(int Error) 43 | { 44 | if (Error==0) 45 | ClrError(); 46 | else 47 | LastError=Error | LastIsoError | LastTcpError; 48 | return Error; 49 | } 50 | //--------------------------------------------------------------------------- 51 | void TSnap7Peer::ClrError() 52 | { 53 | LastError=0; 54 | LastIsoError=0; 55 | LastTcpError=0; 56 | } 57 | //--------------------------------------------------------------------------- 58 | word TSnap7Peer::GetNextWord() 59 | { 60 | if (cntword==0xFFFF) 61 | cntword=0; 62 | return cntword++; 63 | } 64 | //--------------------------------------------------------------------------- 65 | int TSnap7Peer::NegotiatePDULength( ) 66 | { 67 | int Result, IsoSize = 0; 68 | PReqFunNegotiateParams ReqNegotiate; 69 | PResFunNegotiateParams ResNegotiate; 70 | PS7ResHeader23 Answer; 71 | ClrError(); 72 | // Setup Pointers 73 | ReqNegotiate = PReqFunNegotiateParams(pbyte(PDUH_out) + sizeof(TS7ReqHeader)); 74 | // Header 75 | PDUH_out->P = 0x32; // Always $32 76 | PDUH_out->PDUType = PduType_request; // $01 77 | PDUH_out->AB_EX = 0x0000; // Always $0000 78 | PDUH_out->Sequence = GetNextWord(); // AutoInc 79 | PDUH_out->ParLen = SwapWord(sizeof(TReqFunNegotiateParams)); // 8 bytes 80 | PDUH_out->DataLen = 0x0000; 81 | // Params 82 | ReqNegotiate->FunNegotiate = pduNegotiate; 83 | ReqNegotiate->Unknown = 0x00; 84 | ReqNegotiate->ParallelJobs_1 = 0x0100; 85 | ReqNegotiate->ParallelJobs_2 = 0x0100; 86 | ReqNegotiate->PDULength = SwapWord(PDURequest); 87 | IsoSize = sizeof( TS7ReqHeader ) + sizeof( TReqFunNegotiateParams ); 88 | Result = isoExchangeBuffer(NULL, IsoSize); 89 | if ((Result == 0) && (IsoSize == int(sizeof(TS7ResHeader23) + sizeof(TResFunNegotiateParams)))) 90 | { 91 | // Setup pointers 92 | Answer = PS7ResHeader23(&PDU.Payload); 93 | ResNegotiate = PResFunNegotiateParams(pbyte(Answer) + sizeof(TS7ResHeader23)); 94 | if ( Answer->Error != 0 ) 95 | Result = SetError(errNegotiatingPDU); 96 | if ( Result == 0 ) 97 | PDULength = SwapWord(ResNegotiate->PDULength); 98 | } 99 | return Result; 100 | } 101 | //--------------------------------------------------------------------------- 102 | void TSnap7Peer::PeerDisconnect( ) 103 | { 104 | ClrError(); 105 | isoDisconnect(true); 106 | } 107 | //--------------------------------------------------------------------------- 108 | int TSnap7Peer::PeerConnect( ) 109 | { 110 | int Result; 111 | 112 | ClrError(); 113 | Result = isoConnect(); 114 | if (Result == 0) 115 | { 116 | Result = NegotiatePDULength(); 117 | if (Result != 0) 118 | PeerDisconnect(); 119 | } 120 | return Result; 121 | } 122 | -------------------------------------------------------------------------------- /deps/snap7/src/core/s7_peer.h: -------------------------------------------------------------------------------- 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_peer_h 27 | #define s7_peer_h 28 | //--------------------------------------------------------------------------- 29 | #include "s7_types.h" 30 | #include "s7_isotcp.h" 31 | //--------------------------------------------------------------------------- 32 | 33 | const longword errPeerMask = 0xFFF00000; 34 | const longword errPeerBase = 0x000FFFFF; 35 | const longword errNegotiatingPDU = 0x00100000; 36 | 37 | class TSnap7Peer: public TIsoTcpSocket 38 | { 39 | private: 40 | word cntword; 41 | protected: 42 | bool Destroying; 43 | PS7ReqHeader PDUH_out; 44 | word GetNextWord(); 45 | int SetError(int Error); 46 | int NegotiatePDULength(); 47 | void ClrError(); 48 | public: 49 | int LastError; 50 | int PDULength; 51 | int PDURequest; 52 | TSnap7Peer(); 53 | ~TSnap7Peer(); 54 | void PeerDisconnect(); 55 | int PeerConnect(); 56 | }; 57 | //--------------------------------------------------------------------------- 58 | #endif 59 | -------------------------------------------------------------------------------- /deps/snap7/src/core/s7_server.h: -------------------------------------------------------------------------------- 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: 75 | 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(); 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 | -------------------------------------------------------------------------------- /deps/snap7/src/core/s7_text.h: -------------------------------------------------------------------------------- 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_text_h 27 | #define s7_text_h 28 | //--------------------------------------------------------------------------- 29 | #include "s7_micro_client.h" 30 | #include "s7_server.h" 31 | #include "s7_partner.h" 32 | //--------------------------------------------------------------------------- 33 | 34 | const int errLibInvalidParam = -1; 35 | const int errLibInvalidObject = -2; 36 | // Errors areas definition 37 | const longword ErrTcpMask = 0x0000FFFF; 38 | const longword ErrIsoMask = 0x000F0000; 39 | const longword ErrS7Mask = 0xFFF00000; 40 | 41 | char* ErrCliText(int Error, char* Result, int TextLen); 42 | char* ErrSrvText(int Error, char* Result, int TextLen); 43 | char* ErrParText(int Error, char* Result, int TextLen); 44 | char* EvtSrvText(TSrvEvent &Event, char* Result, int TextLen); 45 | 46 | 47 | #endif 48 | 49 | 50 | -------------------------------------------------------------------------------- /deps/snap7/src/lib/snap7.def: -------------------------------------------------------------------------------- 1 | LIBRARY SNAP7.DLL 2 | EXPORTS 3 | Cli_Create 4 | Cli_Destroy 5 | Cli_ConnectTo 6 | Cli_SetConnectionParams 7 | Cli_SetConnectionType 8 | Cli_Connect 9 | Cli_Disconnect 10 | Cli_GetParam 11 | Cli_SetParam 12 | Cli_SetAsCallback 13 | Cli_ReadArea 14 | Cli_WriteArea 15 | Cli_ReadMultiVars 16 | Cli_WriteMultiVars 17 | Cli_DBRead 18 | Cli_DBWrite 19 | Cli_MBRead 20 | Cli_MBWrite 21 | Cli_EBRead 22 | Cli_EBWrite 23 | Cli_ABRead 24 | Cli_ABWrite 25 | Cli_TMRead 26 | Cli_TMWrite 27 | Cli_CTRead 28 | Cli_CTWrite 29 | Cli_ListBlocks 30 | Cli_GetAgBlockInfo 31 | Cli_GetPgBlockInfo 32 | Cli_ListBlocksOfType 33 | Cli_Upload 34 | Cli_FullUpload 35 | Cli_Download 36 | Cli_Delete 37 | Cli_DBGet 38 | Cli_DBFill 39 | Cli_GetPlcDateTime 40 | Cli_SetPlcDateTime 41 | Cli_SetPlcSystemDateTime 42 | Cli_GetOrderCode 43 | Cli_GetCpuInfo 44 | Cli_GetCpInfo 45 | Cli_ReadSZL 46 | Cli_ReadSZLList 47 | Cli_PlcHotStart 48 | Cli_PlcColdStart 49 | Cli_PlcStop 50 | Cli_CopyRamToRom 51 | Cli_Compress 52 | Cli_GetPlcStatus 53 | Cli_GetProtection 54 | Cli_SetSessionPassword 55 | Cli_ClearSessionPassword 56 | Cli_IsoExchangeBuffer 57 | Cli_GetExecTime 58 | Cli_GetLastError 59 | Cli_GetPduLength 60 | Cli_AsReadArea 61 | Cli_AsWriteArea 62 | Cli_AsDBRead 63 | Cli_AsDBWrite 64 | Cli_AsMBRead 65 | Cli_AsMBWrite 66 | Cli_AsEBRead 67 | Cli_AsEBWrite 68 | Cli_AsABRead 69 | Cli_AsABWrite 70 | Cli_AsTMRead 71 | Cli_AsTMWrite 72 | Cli_AsCTRead 73 | Cli_AsCTWrite 74 | Cli_AsListBlocksOfType 75 | Cli_AsReadSZL 76 | Cli_AsReadSZLList 77 | Cli_AsUpload 78 | Cli_AsFullUpload 79 | Cli_AsDownload 80 | Cli_AsCopyRamToRom 81 | Cli_AsCompress 82 | Cli_AsDBGet 83 | Cli_AsDBFill 84 | Cli_CheckAsCompletion 85 | Cli_WaitAsCompletion 86 | Cli_ErrorText 87 | Cli_GetConnected 88 | Srv_Create 89 | Srv_Destroy 90 | Srv_GetParam 91 | Srv_SetParam 92 | Srv_StartTo 93 | Srv_Start 94 | Srv_Stop 95 | Srv_RegisterArea 96 | Srv_UnregisterArea 97 | Srv_LockArea 98 | Srv_UnlockArea 99 | Srv_GetStatus 100 | Srv_SetCpuStatus 101 | Srv_ClearEvents 102 | Srv_PickEvent 103 | Srv_GetMask 104 | Srv_SetMask 105 | Srv_SetEventsCallback 106 | Srv_SetReadEventsCallback 107 | Srv_SetRWAreaCallback 108 | Srv_ErrorText 109 | Srv_EventText 110 | Par_Create 111 | Par_Destroy 112 | Par_GetParam 113 | Par_SetParam 114 | Par_StartTo 115 | Par_Start 116 | Par_Stop 117 | Par_BSend 118 | Par_AsBSend 119 | Par_CheckAsBSendCompletion 120 | Par_WaitAsBSendCompletion 121 | Par_SetSendCallback 122 | Par_BRecv 123 | Par_CheckAsBRecvCompletion 124 | Par_SetRecvCallback 125 | Par_GetTimes 126 | Par_GetStats 127 | Par_GetLastError 128 | Par_GetStatus 129 | Par_ErrorText 130 | -------------------------------------------------------------------------------- /deps/snap7/src/lib/snap7_libmain.h: -------------------------------------------------------------------------------- 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 snap7_libmain_h 27 | #define snap7_libmain_h 28 | //--------------------------------------------------------------------------- 29 | #include "s7_client.h" 30 | #include "s7_server.h" 31 | #include "s7_partner.h" 32 | #include "s7_text.h" 33 | //--------------------------------------------------------------------------- 34 | 35 | const int mkEvent = 0; 36 | const int mkLog = 1; 37 | 38 | typedef uintptr_t S7Object; // multi platform/processor object reference 39 | 40 | //============================================================================== 41 | // CLIENT EXPORT LIST - Sync functions 42 | //============================================================================== 43 | EXPORTSPEC S7Object S7API Cli_Create(); 44 | EXPORTSPEC void S7API Cli_Destroy(S7Object &Client); 45 | EXPORTSPEC int S7API Cli_Connect(S7Object Client); 46 | EXPORTSPEC int S7API Cli_SetConnectionParams(S7Object Client, const char *Address, word LocalTSAP, word RemoteTSAP); 47 | EXPORTSPEC int S7API Cli_SetConnectionType(S7Object Client, word ConnectionType); 48 | EXPORTSPEC int S7API Cli_ConnectTo(S7Object Client, const char *Address, int Rack, int Slot); 49 | EXPORTSPEC int S7API Cli_Disconnect(S7Object Client); 50 | EXPORTSPEC int S7API Cli_GetParam(S7Object Client, int ParamNumber, void *pValue); 51 | EXPORTSPEC int S7API Cli_SetParam(S7Object Client, int ParamNumber, void *pValue); 52 | EXPORTSPEC int S7API Cli_SetAsCallback(S7Object Client, pfn_CliCompletion pCompletion, void *usrPtr); 53 | // Data I/O functions 54 | EXPORTSPEC int S7API Cli_ReadArea(S7Object Client, int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData); 55 | EXPORTSPEC int S7API Cli_WriteArea(S7Object Client, int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData); 56 | EXPORTSPEC int S7API Cli_ReadMultiVars(S7Object Client, PS7DataItem Item, int ItemsCount); 57 | EXPORTSPEC int S7API Cli_WriteMultiVars(S7Object Client, PS7DataItem Item, int ItemsCount); 58 | // Data I/O Lean functions 59 | EXPORTSPEC int S7API Cli_DBRead(S7Object Client, int DBNumber, int Start, int Size, void *pUsrData); 60 | EXPORTSPEC int S7API Cli_DBWrite(S7Object Client, int DBNumber, int Start, int Size, void *pUsrData); 61 | EXPORTSPEC int S7API Cli_MBRead(S7Object Client, int Start, int Size, void *pUsrData); 62 | EXPORTSPEC int S7API Cli_MBWrite(S7Object Client, int Start, int Size, void *pUsrData); 63 | EXPORTSPEC int S7API Cli_EBRead(S7Object Client, int Start, int Size, void *pUsrData); 64 | EXPORTSPEC int S7API Cli_EBWrite(S7Object Client, int Start, int Size, void *pUsrData); 65 | EXPORTSPEC int S7API Cli_ABRead(S7Object Client, int Start, int Size, void *pUsrData); 66 | EXPORTSPEC int S7API Cli_ABWrite(S7Object Client, int Start, int Size, void *pUsrData); 67 | EXPORTSPEC int S7API Cli_TMRead(S7Object Client, int Start, int Amount, void *pUsrData); 68 | EXPORTSPEC int S7API Cli_TMWrite(S7Object Client, int Start, int Amount, void *pUsrData); 69 | EXPORTSPEC int S7API Cli_CTRead(S7Object Client, int Start, int Amount, void *pUsrData); 70 | EXPORTSPEC int S7API Cli_CTWrite(S7Object Client, int Start, int Amount, void *pUsrData); 71 | // Directory functions 72 | EXPORTSPEC int S7API Cli_ListBlocks(S7Object Client, TS7BlocksList *pUsrData); 73 | EXPORTSPEC int S7API Cli_GetAgBlockInfo(S7Object Client, int BlockType, int BlockNum, TS7BlockInfo *pUsrData); 74 | EXPORTSPEC int S7API Cli_GetPgBlockInfo(S7Object Client, void *pBlock, TS7BlockInfo *pUsrData, int Size); 75 | EXPORTSPEC int S7API Cli_ListBlocksOfType(S7Object Client, int BlockType, TS7BlocksOfType *pUsrData, int &ItemsCount); 76 | // Blocks functions 77 | EXPORTSPEC int S7API Cli_Upload(S7Object Client, int BlockType, int BlockNum, void *pUsrData, int &Size); 78 | EXPORTSPEC int S7API Cli_FullUpload(S7Object Client, int BlockType, int BlockNum, void *pUsrData, int &Size); 79 | EXPORTSPEC int S7API Cli_Download(S7Object Client, int BlockNum, void *pUsrData, int Size); 80 | EXPORTSPEC int S7API Cli_Delete(S7Object Client, int BlockType, int BlockNum); 81 | EXPORTSPEC int S7API Cli_DBGet(S7Object Client, int DBNumber, void *pUsrData, int &Size); 82 | EXPORTSPEC int S7API Cli_DBFill(S7Object Client, int DBNumber, int FillChar); 83 | // Date/Time functions 84 | EXPORTSPEC int S7API Cli_GetPlcDateTime(S7Object Client, tm &DateTime); 85 | EXPORTSPEC int S7API Cli_SetPlcDateTime(S7Object Client, tm *DateTime); 86 | EXPORTSPEC int S7API Cli_SetPlcSystemDateTime(S7Object Client); 87 | // System Info functions 88 | EXPORTSPEC int S7API Cli_GetOrderCode(S7Object Client, TS7OrderCode *pUsrData); 89 | EXPORTSPEC int S7API Cli_GetCpuInfo(S7Object Client, TS7CpuInfo *pUsrData); 90 | EXPORTSPEC int S7API Cli_GetCpInfo(S7Object Client, TS7CpInfo *pUsrData); 91 | EXPORTSPEC int S7API Cli_ReadSZL(S7Object Client, int ID, int Index, TS7SZL *pUsrData, int &Size); 92 | EXPORTSPEC int S7API Cli_ReadSZLList(S7Object Client, TS7SZLList *pUsrData, int &ItemsCount); 93 | // Control functions 94 | EXPORTSPEC int S7API Cli_PlcHotStart(S7Object Client); 95 | EXPORTSPEC int S7API Cli_PlcColdStart(S7Object Client); 96 | EXPORTSPEC int S7API Cli_PlcStop(S7Object Client); 97 | EXPORTSPEC int S7API Cli_CopyRamToRom(S7Object Client, int Timeout); 98 | EXPORTSPEC int S7API Cli_Compress(S7Object Client, int Timeout); 99 | EXPORTSPEC int S7API Cli_GetPlcStatus(S7Object Client, int &Status); 100 | // Security functions 101 | EXPORTSPEC int S7API Cli_GetProtection(S7Object Client, TS7Protection *pUsrData); 102 | EXPORTSPEC int S7API Cli_SetSessionPassword(S7Object Client, char *Password); 103 | EXPORTSPEC int S7API Cli_ClearSessionPassword(S7Object Client); 104 | // Low level 105 | EXPORTSPEC int S7API Cli_IsoExchangeBuffer(S7Object Client, void *pUsrData, int &Size); 106 | // Misc 107 | EXPORTSPEC int S7API Cli_GetExecTime(S7Object Client, int &Time); 108 | EXPORTSPEC int S7API Cli_GetLastError(S7Object Client, int &LastError); 109 | EXPORTSPEC int S7API Cli_GetPduLength(S7Object Client, int &Requested, int &Negotiated); 110 | EXPORTSPEC int S7API Cli_ErrorText(int Error, char *Text, int TextLen); 111 | EXPORTSPEC int S7API Cli_GetConnected(S7Object Client, int &Connected); 112 | //============================================================================== 113 | // CLIENT EXPORT LIST - Async functions 114 | //============================================================================== 115 | EXPORTSPEC int S7API Cli_AsReadArea(S7Object Client, int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData); 116 | EXPORTSPEC int S7API Cli_AsWriteArea(S7Object Client, int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData); 117 | EXPORTSPEC int S7API Cli_AsDBRead(S7Object Client, int DBNumber, int Start, int Size, void *pUsrData); 118 | EXPORTSPEC int S7API Cli_AsDBWrite(S7Object Client, int DBNumber, int Start, int Size, void *pUsrData); 119 | EXPORTSPEC int S7API Cli_AsMBRead(S7Object Client, int Start, int Size, void *pUsrData); 120 | EXPORTSPEC int S7API Cli_AsMBWrite(S7Object Client, int Start, int Size, void *pUsrData); 121 | EXPORTSPEC int S7API Cli_AsEBRead(S7Object Client, int Start, int Size, void *pUsrData); 122 | EXPORTSPEC int S7API Cli_AsEBWrite(S7Object Client, int Start, int Size, void *pUsrData); 123 | EXPORTSPEC int S7API Cli_AsABRead(S7Object Client, int Start, int Size, void *pUsrData); 124 | EXPORTSPEC int S7API Cli_AsABWrite(S7Object Client, int Start, int Size, void *pUsrData); 125 | EXPORTSPEC int S7API Cli_AsTMRead(S7Object Client, int Start, int Amount, void *pUsrData); 126 | EXPORTSPEC int S7API Cli_AsTMWrite(S7Object Client, int Start, int Amount, void *pUsrData); 127 | EXPORTSPEC int S7API Cli_AsCTRead(S7Object Client, int Start, int Amount, void *pUsrData); 128 | EXPORTSPEC int S7API Cli_AsCTWrite(S7Object Client, int Start, int Amount, void *pUsrData); 129 | EXPORTSPEC int S7API Cli_AsListBlocksOfType(S7Object Client, int BlockType, TS7BlocksOfType *pUsrData, int &ItemsCount); 130 | EXPORTSPEC int S7API Cli_AsReadSZL(S7Object Client, int ID, int Index, TS7SZL *pUsrData, int &Size); 131 | EXPORTSPEC int S7API Cli_AsReadSZLList(S7Object Client, TS7SZLList *pUsrData, int &ItemsCount); 132 | EXPORTSPEC int S7API Cli_AsUpload(S7Object Client, int BlockType, int BlockNum, void *pUsrData, int &Size); 133 | EXPORTSPEC int S7API Cli_AsFullUpload(S7Object Client, int BlockType, int BlockNum, void *pUsrData, int &Size); 134 | EXPORTSPEC int S7API Cli_AsDownload(S7Object Client, int BlockNum, void *pUsrData, int Size); 135 | EXPORTSPEC int S7API Cli_AsCopyRamToRom(S7Object Client, int Timeout); 136 | EXPORTSPEC int S7API Cli_AsCompress(S7Object Client, int Timeout); 137 | EXPORTSPEC int S7API Cli_AsDBGet(S7Object Client, int DBNumber, void *pUsrData, int &Size); 138 | EXPORTSPEC int S7API Cli_AsDBFill(S7Object Client, int DBNumber, int FillChar); 139 | EXPORTSPEC int S7API Cli_CheckAsCompletion(S7Object Client, int &opResult); 140 | EXPORTSPEC int S7API Cli_WaitAsCompletion(S7Object Client, int Timeout); 141 | //============================================================================== 142 | // SERVER EXPORT LIST 143 | //============================================================================== 144 | EXPORTSPEC S7Object S7API Srv_Create(); 145 | EXPORTSPEC void S7API Srv_Destroy(S7Object &Server); 146 | EXPORTSPEC int S7API Srv_GetParam(S7Object Server, int ParamNumber, void *pValue); 147 | EXPORTSPEC int S7API Srv_SetParam(S7Object Server, int ParamNumber, void *pValue); 148 | EXPORTSPEC int S7API Srv_Start(S7Object Server); 149 | EXPORTSPEC int S7API Srv_StartTo(S7Object Server, const char *Address); 150 | EXPORTSPEC int S7API Srv_Stop(S7Object Server); 151 | // Data 152 | EXPORTSPEC int S7API Srv_RegisterArea(S7Object Server, int AreaCode, word Index, void *pUsrData, int Size); 153 | EXPORTSPEC int S7API Srv_UnregisterArea(S7Object Server, int AreaCode, word Index); 154 | EXPORTSPEC int S7API Srv_LockArea(S7Object Server, int AreaCode, word Index); 155 | EXPORTSPEC int S7API Srv_UnlockArea(S7Object Server, int AreaCode, word Index); 156 | // Events 157 | EXPORTSPEC int S7API Srv_ClearEvents(S7Object Server); 158 | EXPORTSPEC int S7API Srv_PickEvent(S7Object Server, TSrvEvent *pEvent, int &EvtReady); 159 | EXPORTSPEC int S7API Srv_GetMask(S7Object Server, int MaskKind, longword &Mask); 160 | EXPORTSPEC int S7API Srv_SetMask(S7Object Server, int MaskKind, longword Mask); 161 | EXPORTSPEC int S7API Srv_SetEventsCallback(S7Object Server, pfn_SrvCallBack pCallback, void *usrPtr); 162 | EXPORTSPEC int S7API Srv_SetReadEventsCallback(S7Object Server, pfn_SrvCallBack pCallback, void *usrPtr); 163 | EXPORTSPEC int S7API Srv_EventText(TSrvEvent &Event, char *Text, int TextLen); 164 | EXPORTSPEC int S7API Srv_SetRWAreaCallback(S7Object Server, pfn_RWAreaCallBack pCallback, void *usrPtr); 165 | // Misc 166 | EXPORTSPEC int S7API Srv_GetStatus(S7Object Server, int &ServerStatus, int &CpuStatus, int &ClientsCount); 167 | EXPORTSPEC int S7API Srv_SetCpuStatus(S7Object Server, int CpuStatus); 168 | EXPORTSPEC int S7API Srv_ErrorText(int Error, char *Text, int TextLen); 169 | //============================================================================== 170 | // PARTNER EXPORT LIST 171 | //============================================================================== 172 | EXPORTSPEC S7Object S7API Par_Create(int Active); 173 | EXPORTSPEC void S7API Par_Destroy(S7Object &Partner); 174 | EXPORTSPEC int S7API Par_GetParam(S7Object Partner, int ParamNumber, void *pValue); 175 | EXPORTSPEC int S7API Par_SetParam(S7Object Partner, int ParamNumber, void *pValue); 176 | EXPORTSPEC int S7API Par_Start(S7Object Partner); 177 | EXPORTSPEC int S7API Par_StartTo(S7Object Partner, const char *LocalAddress, const char *RemoteAddress, 178 | word LocTsap, word RemTsap); 179 | EXPORTSPEC int S7API Par_Stop(S7Object Partner); 180 | // BSend 181 | EXPORTSPEC int S7API Par_BSend(S7Object Partner, longword R_ID, void *pUsrData, int Size); 182 | EXPORTSPEC int S7API Par_AsBSend(S7Object Partner, longword R_ID, void *pUsrData, int Size); 183 | EXPORTSPEC int S7API Par_CheckAsBSendCompletion(S7Object Partner, int &opResult); 184 | EXPORTSPEC int S7API Par_WaitAsBSendCompletion(S7Object Partner, longword Timeout); 185 | EXPORTSPEC int S7API Par_SetSendCallback(S7Object Partner, pfn_ParBSendCompletion pCompletion, void *usrPtr); 186 | // BRecv 187 | EXPORTSPEC int S7API Par_BRecv(S7Object Partner, longword &R_ID, void *pData, int &Size, longword Timeout); 188 | EXPORTSPEC int S7API Par_CheckAsBRecvCompletion(S7Object Partner, int &opResult, longword &R_ID, 189 | void *pData, int &Size); 190 | EXPORTSPEC int S7API Par_SetRecvCallback(S7Object Partner, pfn_ParBRecvCallBack pCompletion, void *usrPtr); 191 | // Stat 192 | EXPORTSPEC int S7API Par_GetTimes(S7Object Partner, longword &SendTime, longword &RecvTime); 193 | EXPORTSPEC int S7API Par_GetStats(S7Object Partner, longword &BytesSent, longword &BytesRecv, 194 | longword &SendErrors, longword &RecvErrors); 195 | EXPORTSPEC int S7API Par_GetLastError(S7Object Partner, int &LastError); 196 | EXPORTSPEC int S7API Par_GetStatus(S7Object Partner, int &Status); 197 | EXPORTSPEC int S7API Par_ErrorText(int Error, char *Text, int TextLen); 198 | 199 | 200 | 201 | #endif // snap7_libmain_h 202 | -------------------------------------------------------------------------------- /deps/snap7/src/sys/snap_msgsock.h: -------------------------------------------------------------------------------- 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 snap_msgsock_h 27 | #define snap_msgsock_h 28 | //--------------------------------------------------------------------------- 29 | #include "snap_platform.h" 30 | #include "snap_sysutils.h" 31 | //---------------------------------------------------------------------------- 32 | #if defined(OS_WINDOWS) || defined (OS_SOLARIS) || defined(OS_OSX) 33 | # define MSG_NOSIGNAL 0 34 | #endif 35 | //---------------------------------------------------------------------------- 36 | // Non blocking connection to avoid root priviledges under UNIX 37 | // i.e. raw socket pinger is not more used. 38 | // Thanks to Rolf Stalder that made it ;) 39 | //---------------------------------------------------------------------------- 40 | #ifdef PLATFORM_UNIX 41 | #define NON_BLOCKING_CONNECT 42 | #endif 43 | #ifdef NON_BLOCKING_CONNECT 44 | #include 45 | #endif 46 | //---------------------------------------------------------------------------- 47 | /* 48 | In Windows sizeof socket varies depending of the platform : 49 | win32 -> sizeof(SOCKET) = 4 50 | win64 -> sizeof(SOCKET) = 8 51 | 52 | Even though sizeof(SOCKET) is 8, should be safe to cast it to int, because 53 | the value constitutes an index in per-process table of limited size 54 | and not a real pointer. 55 | 56 | Other Os define the socket as int regardless of the processor. 57 | 58 | We want to sleep peacefully, so it's better to define a portable socket. 59 | */ 60 | 61 | #ifdef OS_WINDOWS 62 | typedef SOCKET socket_t; 63 | #else 64 | typedef int socket_t; 65 | #endif 66 | 67 | //---------------------------------------------------------------------------- 68 | #define SD_RECEIVE 0x00 69 | #define SD_SEND 0x01 70 | #define SD_BOTH 0x02 71 | #define MaxPacketSize 65536 72 | 73 | //---------------------------------------------------------------------------- 74 | // For other platform we need to re-define next constants 75 | #if defined(PLATFORM_UNIX) || defined(OS_OSX) 76 | 77 | #define INVALID_SOCKET (socket_t)(~0) 78 | #define SOCKET_ERROR (-1) 79 | 80 | #define WSAEINTR EINTR 81 | #define WSAEBADF EBADF 82 | #define WSAEACCES EACCES 83 | #define WSAEFAULT EFAULT 84 | #define WSAEINVAL EINVAL 85 | #define WSAEMFILE EMFILE 86 | #define WSAEWOULDBLOCK EWOULDBLOCK 87 | #define WSAEINPROGRESS EINPROGRESS 88 | #define WSAEALREADY EALREADY 89 | #define WSAENOTSOCK ENOTSOCK 90 | #define WSAEDESTADDRREQ EDESTADDRREQ 91 | #define WSAEMSGSIZE EMSGSIZE 92 | #define WSAEPROTOTYPE EPROTOTYPE 93 | #define WSAENOPROTOOPT ENOPROTOOPT 94 | #define WSAEPROTONOSUPPORT EPROTONOSUPPORT 95 | #define WSAESOCKTNOSUPPORT ESOCKTNOSUPPORT 96 | #define WSAEOPNOTSUPP EOPNOTSUPP 97 | #define WSAEPFNOSUPPORT EPFNOSUPPORT 98 | #define WSAEAFNOSUPPORT EAFNOSUPPORT 99 | #define WSAEADDRINUSE EADDRINUSE 100 | #define WSAEADDRNOTAVAIL EADDRNOTAVAIL 101 | #define WSAENETDOWN ENETDOWN 102 | #define WSAENETUNREACH ENETUNREACH 103 | #define WSAENETRESET ENETRESET 104 | #define WSAECONNABORTED ECONNABORTED 105 | #define WSAECONNRESET ECONNRESET 106 | #define WSAENOBUFS ENOBUFS 107 | #define WSAEISCONN EISCONN 108 | #define WSAENOTCONN ENOTCONN 109 | #define WSAESHUTDOWN ESHUTDOWN 110 | #define WSAETOOMANYREFS ETOOMANYREFS 111 | #define WSAETIMEDOUT ETIMEDOUT 112 | #define WSAECONNREFUSED ECONNREFUSED 113 | #define WSAELOOP ELOOP 114 | #define WSAENAMETOOLONG ENAMETOOLONG 115 | #define WSAEHOSTDOWN EHOSTDOWN 116 | #define WSAEHOSTUNREACH EHOSTUNREACH 117 | #define WSAENOTEMPTY ENOTEMPTY 118 | #define WSAEUSERS EUSERS 119 | #define WSAEDQUOT EDQUOT 120 | #define WSAESTALE ESTALE 121 | #define WSAEREMOTE EREMOTE 122 | #endif 123 | 124 | #define WSAEINVALIDADDRESS 12001 125 | 126 | #define ICmpBufferSize 4096 127 | typedef byte TIcmpBuffer[ICmpBufferSize]; 128 | 129 | // Ping result 130 | #define PR_CANNOT_PERFORM -1 // cannot ping : 131 | // unix : no root rights or SUID flag set to 132 | // open raw sockets 133 | // windows : neither helper DLL found nor raw 134 | // sockets can be opened (no administrator rights) 135 | // In this case the execution continues whitout 136 | // the benefit of the smart-connect. 137 | 138 | #define PR_SUCCESS 0 // Host found 139 | #define PR_ERROR 1 // Ping Error, Ping was performed but ... 140 | // - host didn't replied (not found) 141 | // - routing error 142 | // - TTL expired 143 | // - ... all other icmp error that we don't need 144 | // to know. 145 | 146 | // Ping Kind 147 | #define pkCannotPing 1 // see PR_CANNOT_PERFORM comments 148 | #define pkWinHelper 2 // use iphlpapi.dll (only windows) 149 | #define pkRawSocket 3 // use raw sockets (unix/windows) 150 | 151 | const byte ICMP_ECHORP = 0; // ECHO Reply 152 | const byte ICMP_ECHORQ = 8; // ECHO Request 153 | //--------------------------------------------------------------------------- 154 | // RAW SOCKET PING STRUCTS 155 | //--------------------------------------------------------------------------- 156 | #pragma pack(1) 157 | typedef struct{ 158 | byte ip_hl_v; 159 | byte ip_tos; 160 | word ip_len; 161 | word ip_id ; 162 | word ip_off; 163 | byte ip_ttl; 164 | byte ip_p; 165 | word ip_sum; 166 | longword ip_src; 167 | longword ip_dst; 168 | }TIPHeader; 169 | 170 | typedef struct{ 171 | byte ic_type; // Type of message 172 | byte ic_code; // Code 173 | word ic_cksum; // 16 bit checksum 174 | word ic_id; // ID (ic1 : ipv4) 175 | word ic_seq; // Sequence 176 | }TIcmpHeader; 177 | 178 | typedef struct{ 179 | TIcmpHeader Header; 180 | byte Data[32]; // use the well known default 181 | }TIcmpPacket, *PIcmpPacket; 182 | 183 | typedef struct{ 184 | TIPHeader IPH; 185 | TIcmpPacket ICmpReply; 186 | }TIcmpReply, *PIcmpReply; 187 | #pragma pack() 188 | 189 | //--------------------------------------------------------------------------- 190 | class TRawSocketPinger 191 | { 192 | private: 193 | socket_t FSocket; 194 | PIcmpPacket SendPacket; 195 | TIcmpBuffer IcmpBuffer; 196 | word FId, FSeq; 197 | void InitPacket(); 198 | word PacketChecksum(); 199 | bool CanRead(int Timeout); 200 | public: 201 | bool Ping(longword ip_addr, int Timeout); 202 | TRawSocketPinger(); 203 | ~TRawSocketPinger(); 204 | }; 205 | typedef TRawSocketPinger *PRawSocketPinger; 206 | //--------------------------------------------------------------------------- 207 | class TPinger 208 | { 209 | private: 210 | PRawSocketPinger RawPinger; 211 | bool RawAvail; 212 | #ifdef OS_WINDOWS 213 | bool WinPing(longword ip_addr, int Timeout); 214 | #endif 215 | bool RawPing(longword ip_addr, int Timeout); 216 | public: 217 | TPinger(); 218 | ~TPinger(); 219 | bool Ping(char *Host, int Timeout); 220 | bool Ping(longword ip_addr, int Timeout); 221 | }; 222 | typedef TPinger *PPinger; 223 | //--------------------------------------------------------------------------- 224 | class TSnapBase // base class endian-aware 225 | { 226 | private: 227 | bool LittleEndian; 228 | protected: 229 | longword SwapDWord(longword Value); 230 | word SwapWord(word Value); 231 | public: 232 | TSnapBase(); 233 | }; 234 | //--------------------------------------------------------------------------- 235 | class TMsgSocket : public TSnapBase 236 | { 237 | private: 238 | PPinger Pinger; 239 | int GetLastSocketError(); 240 | int SockCheck(int SockResult); 241 | void DestroySocket(); 242 | void SetSocketOptions(); 243 | bool CanWrite(int Timeout); 244 | void GetLocal(); 245 | void GetRemote(); 246 | void SetSin(sockaddr_in &sin, char *Address, u_short Port); 247 | void GetSin(sockaddr_in sin, char *Address, u_short &Port); 248 | protected: 249 | socket_t FSocket; 250 | sockaddr_in LocalSin; 251 | sockaddr_in RemoteSin; 252 | //-------------------------------------------------------------------------- 253 | // low level socket 254 | void CreateSocket(); 255 | // Called when a socket is assigned externally 256 | void GotSocket(); 257 | // Returns how many bytes are ready to be read in the winsock buffer 258 | int WaitingData(); 259 | // Waits until there at least "size" bytes ready to be read or until receive timeout occurs 260 | int WaitForData(int Size, int Timeout); 261 | // Clear socket input buffer 262 | void Purge(); 263 | public: 264 | longword ClientHandle; 265 | longword LocalBind; 266 | // Coordinates Address:Port 267 | char LocalAddress[16]; 268 | char RemoteAddress[16]; 269 | word LocalPort; 270 | word RemotePort; 271 | // "speed" of the socket listener (used server-side) 272 | int WorkInterval; 273 | // Timeouts : 3 different values for fine tuning. 274 | // Send timeout should be small since with work with small packets and TCP_NO_DELAY 275 | // option, so we don't expect "time to wait". 276 | // Recv timeout depends of equipment's processing time : we send a packet, the equipment 277 | // processes the message, finally it sends the answer. In any case Recv timeout > Send Timeout. 278 | // PingTimeout is the maximum time interval during which we expect that the PLC answers. 279 | // By default is 750 ms, increase it if there are many switch/repeaters. 280 | int PingTimeout; 281 | int RecvTimeout; 282 | int SendTimeout; 283 | //int ConnTimeout; 284 | // Output : Last operation error 285 | int LastTcpError; 286 | // Output : Connected to the remote Host/Peer/Client 287 | bool Connected; 288 | //-------------------------------------------------------------------------- 289 | TMsgSocket(); 290 | virtual ~TMsgSocket(); 291 | // Returns true if "something" can be read during the Timeout interval.. 292 | bool CanRead(int Timeout); 293 | // Connects to a peer (using RemoteAddress and RemotePort) 294 | int SckConnect(); // (client-side) 295 | // Disconnects from a peer (gracefully) 296 | void SckDisconnect(); 297 | // Disconnects RAW 298 | void ForceClose(); 299 | // Binds to a local adapter (using LocalAddress and LocalPort) (server-side) 300 | int SckBind(); 301 | // Listens for an incoming connection (server-side) 302 | int SckListen(); 303 | // Set an external socket reference (tipically from a listener) 304 | void SetSocket(socket_t s); 305 | // Accepts an incoming connection returning a socket descriptor (server-side) 306 | socket_t SckAccept(); 307 | // Pings the peer before connecting 308 | bool Ping(char *Host); 309 | bool Ping(sockaddr_in Addr); 310 | // Sends a packet 311 | int SendPacket(void *Data, int Size); 312 | // Returns true if a Packet at least of "Size" bytes is ready to be read 313 | bool PacketReady(int Size); 314 | // Receives everything 315 | int Receive(void *Data, int BufSize, int & SizeRecvd); 316 | // Receives a packet of size specified. 317 | int RecvPacket(void *Data, int Size); 318 | // Peeks a packet of size specified without extract it from the socket queue 319 | int PeekPacket(void *Data, int Size); 320 | virtual bool Execute(); 321 | }; 322 | 323 | typedef TMsgSocket *PMsgSocket; 324 | //--------------------------------------------------------------------------- 325 | void Msg_CloseSocket(socket_t FSocket); 326 | longword Msg_GetSockAddr(socket_t FSocket); 327 | //--------------------------------------------------------------------------- 328 | class SocketsLayer 329 | { 330 | private: 331 | #ifdef OS_WINDOWS 332 | WSADATA wsaData; 333 | #endif 334 | public: 335 | SocketsLayer(); 336 | ~SocketsLayer(); 337 | }; 338 | 339 | #endif // snap_msgsock_h 340 | -------------------------------------------------------------------------------- /deps/snap7/src/sys/snap_platform.h: -------------------------------------------------------------------------------- 1 | /*=============================================================================| 2 | | PROJECT SNAP7 1.4.1 | 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 snap_platform_h 27 | #define snap_platform_h 28 | //--------------------------------------------------------------------------- 29 | #if defined (_WIN32)|| defined(_WIN64)|| defined(__WIN32__) || defined(__WINDOWS__) 30 | # define OS_WINDOWS 31 | #endif 32 | 33 | // Visual Studio needs this to use the correct time_t size 34 | #if defined (_WIN32) && !defined(_WIN64) && !defined(_EMBEDDING_VS2013UP) 35 | # define _USE_32BIT_TIME_T 36 | #endif 37 | 38 | // Linux, BSD and Solaris define "unix", OSX doesn't, even though it derives from BSD 39 | #if defined(unix) || defined(__unix__) || defined(__unix) 40 | # define PLATFORM_UNIX 41 | #endif 42 | 43 | #if BSD>=0 44 | # define OS_BSD 45 | #endif 46 | 47 | #if __APPLE__ 48 | # define OS_OSX 49 | #endif 50 | 51 | #if defined(__SVR4) || defined(__svr4__) 52 | # define OS_SOLARIS 53 | // Thanks to Rolf Stalder now it's possible to use pthreads also for Solaris 54 | // In any case the Solaris native threads model is still present and can be 55 | // used uncommenting the #define line below. 56 | # undef OS_SOLARIS_NATIVE_THREADS 57 | // # define OS_SOLARIS_NATIVE_THREADS 58 | #endif 59 | 60 | #if defined(PLATFORM_UNIX) 61 | # include 62 | # include 63 | # if defined(_POSIX_VERSION) 64 | # define POSIX 65 | # endif 66 | #endif 67 | 68 | #ifdef OS_OSX 69 | # include 70 | #endif 71 | 72 | #if (!defined (OS_WINDOWS)) && (!defined(PLATFORM_UNIX)) && (!defined(OS_BSD)) && (!defined(OS_OSX)) 73 | # error platform still unsupported (please add it yourself and report ;-) 74 | #endif 75 | 76 | // Visual C++ not C99 compliant (VS2008--) 77 | #ifdef _MSC_VER 78 | # if _MSC_VER >= 1600 79 | # include // VS2010++ have it 80 | # else 81 | typedef signed __int8 int8_t; 82 | typedef signed __int16 int16_t; 83 | typedef signed __int32 int32_t; 84 | typedef signed __int64 int64_t; 85 | typedef unsigned __int8 uint8_t; 86 | typedef unsigned __int16 uint16_t; 87 | typedef unsigned __int32 uint32_t; 88 | typedef unsigned __int64 uint64_t; 89 | #ifdef _WIN64 90 | typedef unsigned __int64 uintptr_t; 91 | #else 92 | typedef unsigned __int32 uintptr_t; 93 | #endif 94 | # endif 95 | #else 96 | # include 97 | #endif 98 | 99 | #include 100 | #include 101 | #include 102 | 103 | #ifdef OS_WINDOWS 104 | # define WIN32_LEAN_AND_MEAN 105 | # include 106 | # include 107 | # include 108 | #endif 109 | 110 | #ifdef OS_SOLARIS 111 | # include 112 | # include 113 | # include 114 | #endif 115 | 116 | #if defined(PLATFORM_UNIX) || defined(OS_OSX) 117 | # include 118 | # include 119 | # include 120 | # include 121 | # include 122 | # include 123 | # include 124 | #endif 125 | 126 | #ifdef OS_WINDOWS 127 | # define EXPORTSPEC extern "C" __declspec ( dllexport ) 128 | # define S7API __stdcall 129 | #else 130 | # define EXPORTSPEC extern "C" 131 | # define S7API 132 | #endif 133 | 134 | // Exact length types regardless of platform/processor 135 | // We absolute need of them, all structs have an exact size that 136 | // must be the same across the processor used 32/64 bit 137 | 138 | // *Use them* if you change/expand the code and avoid long, u_long and so on... 139 | 140 | typedef uint8_t byte; 141 | typedef uint16_t word; 142 | typedef uint32_t longword; 143 | typedef byte *pbyte; 144 | typedef word *pword; 145 | typedef uintptr_t snap_obj; // multi platform/processor object reference 146 | 147 | #ifndef OS_WINDOWS 148 | # define INFINITE 0XFFFFFFFF 149 | #endif 150 | 151 | 152 | #endif // snap_platform_h 153 | -------------------------------------------------------------------------------- /deps/snap7/src/sys/snap_sysutils.cpp: -------------------------------------------------------------------------------- 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 | 27 | #include "snap_sysutils.h" 28 | 29 | #ifdef OS_OSX 30 | int clock_gettime(int clk_id, struct timespec* t) 31 | { 32 | struct timeval now; 33 | int rv = gettimeofday(&now, NULL); 34 | if (rv) return rv; 35 | t->tv_sec = now.tv_sec; 36 | t->tv_nsec = now.tv_usec * 1000; 37 | return 0; 38 | } 39 | #endif 40 | 41 | //--------------------------------------------------------------------------- 42 | longword SysGetTick() 43 | { 44 | #ifdef OS_WINDOWS 45 | return timeGetTime(); 46 | #else 47 | struct timespec ts; 48 | clock_gettime(CLOCK_MONOTONIC, &ts); 49 | return (longword) (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000); 50 | #endif 51 | } 52 | //--------------------------------------------------------------------------- 53 | void SysSleep(longword Delay_ms) 54 | { 55 | #ifdef OS_WINDOWS 56 | Sleep(Delay_ms); 57 | #else 58 | struct timespec ts; 59 | ts.tv_sec = (time_t)(Delay_ms / 1000); 60 | ts.tv_nsec =(long)((Delay_ms - ts.tv_sec) * 1000000); 61 | nanosleep(&ts, (struct timespec *)0); 62 | #endif 63 | } 64 | //--------------------------------------------------------------------------- 65 | longword DeltaTime(longword &Elapsed) 66 | { 67 | longword TheTime; 68 | TheTime=SysGetTick(); 69 | // Checks for rollover 70 | if (TheTimeDestroying) 113 | { 114 | try 115 | { 116 | if (!WorkerSocket->Execute()) // False -> End of Activities 117 | SelfClose = true; 118 | } catch (...) 119 | { 120 | Exception = true; 121 | } 122 | }; 123 | if (!FServer->Destroying) 124 | { 125 | // Exception detected during Worker activity 126 | if (Exception) 127 | { 128 | WorkerSocket->ForceClose(); 129 | FServer->DoEvent(WorkerSocket->ClientHandle, evcClientException, 0, 0, 0, 0, 0); 130 | } 131 | else 132 | if (SelfClose) 133 | { 134 | FServer->DoEvent(WorkerSocket->ClientHandle, evcClientDisconnected, 0, 0, 0, 0, 0); 135 | } 136 | else 137 | FServer->DoEvent(WorkerSocket->ClientHandle, evcClientTerminated, 0, 0, 0, 0, 0); 138 | } 139 | delete WorkerSocket; 140 | // Delete reference from list 141 | FServer->Delete(Index); 142 | } 143 | //--------------------------------------------------------------------------- 144 | // LISTENER THREAD 145 | //--------------------------------------------------------------------------- 146 | 147 | TMsgListenerThread::TMsgListenerThread(TMsgSocket *Listener, TCustomMsgServer *Server) 148 | { 149 | FServer = Server; 150 | FListener = Listener; 151 | FreeOnTerminate = false; 152 | } 153 | //--------------------------------------------------------------------------- 154 | 155 | void TMsgListenerThread::Execute() 156 | { 157 | socket_t Sock; 158 | bool Valid; 159 | 160 | while (!Terminated) 161 | { 162 | if (FListener->CanRead(FListener->WorkInterval)) 163 | { 164 | Sock = FListener->SckAccept(); // in any case we must accept 165 | Valid = Sock != INVALID_SOCKET; 166 | // check if we are not destroying 167 | if ((!Terminated) && (!FServer->Destroying)) 168 | { 169 | if (Valid) 170 | FServer->Incoming(Sock); 171 | } 172 | else 173 | if (Valid) 174 | Msg_CloseSocket(Sock); 175 | }; 176 | } 177 | } 178 | //--------------------------------------------------------------------------- 179 | // TCP SERVER 180 | //--------------------------------------------------------------------------- 181 | TCustomMsgServer::TCustomMsgServer() 182 | { 183 | strcpy(FLocalAddress, "0.0.0.0"); 184 | CSList = new TSnapCriticalSection(); 185 | CSEvent = new TSnapCriticalSection(); 186 | FEventQueue = new TMsgEventQueue(MaxEvents, sizeof (TSrvEvent)); 187 | memset(Workers, 0, sizeof (Workers)); 188 | for (int i = 0; i < MaxWorkers; i++) 189 | Workers[i] = NULL; 190 | Status = SrvStopped; 191 | EventMask = 0xFFFFFFFF; 192 | LogMask = 0xFFFFFFFF; 193 | Destroying = false; 194 | FLastError = 0; 195 | ClientsCount = 0; 196 | LocalBind = 0; 197 | MaxClients = MaxWorkers; 198 | OnEvent = NULL; 199 | } 200 | //--------------------------------------------------------------------------- 201 | TCustomMsgServer::~TCustomMsgServer() 202 | { 203 | Destroying = true; 204 | Stop(); 205 | OnEvent = NULL; 206 | delete CSList; 207 | delete CSEvent; 208 | delete FEventQueue; 209 | } 210 | //--------------------------------------------------------------------------- 211 | void TCustomMsgServer::LockList() 212 | { 213 | CSList->Enter(); 214 | } 215 | //--------------------------------------------------------------------------- 216 | void TCustomMsgServer::UnlockList() 217 | { 218 | CSList->Leave(); 219 | } 220 | //--------------------------------------------------------------------------- 221 | int TCustomMsgServer::FirstFree() 222 | { 223 | int i; 224 | for (i = 0; i < MaxWorkers; i++) 225 | { 226 | if (Workers[i] == 0) 227 | return i; 228 | } 229 | return -1; 230 | } 231 | //--------------------------------------------------------------------------- 232 | 233 | int TCustomMsgServer::StartListener() 234 | { 235 | int Result; 236 | // Creates the listener 237 | SockListener = new TMsgSocket(); 238 | strncpy(SockListener->LocalAddress, FLocalAddress, 16); 239 | SockListener->LocalPort = LocalPort; 240 | // Binds 241 | Result = SockListener->SckBind(); 242 | if (Result == 0) 243 | { 244 | LocalBind = SockListener->LocalBind; 245 | // Listen 246 | Result = SockListener->SckListen(); 247 | if (Result == 0) 248 | { 249 | // Creates the Listener thread 250 | ServerThread = new TMsgListenerThread(SockListener, this); 251 | ServerThread->Start(); 252 | } 253 | else 254 | delete SockListener; 255 | } 256 | else 257 | delete SockListener; 258 | 259 | return Result; 260 | } 261 | //--------------------------------------------------------------------------- 262 | void TCustomMsgServer::TerminateAll() 263 | { 264 | int c; 265 | longword Elapsed; 266 | bool Timeout; 267 | 268 | if (ClientsCount > 0) 269 | { 270 | for (c = 0; c < MaxWorkers; c++) 271 | { 272 | if (Workers[c] != 0) 273 | PMsgWorkerThread(Workers[c])->Terminate(); 274 | } 275 | // Wait for closing 276 | Elapsed = SysGetTick(); 277 | Timeout = false; 278 | while (!Timeout && (ClientsCount > 0)) 279 | { 280 | Timeout = DeltaTime(Elapsed) > WkTimeout; 281 | if (!Timeout) 282 | SysSleep(100); 283 | }; 284 | if (ClientsCount > 0) 285 | KillAll(); // one o more threads are hanged 286 | ClientsCount = 0; 287 | } 288 | } 289 | //--------------------------------------------------------------------------- 290 | void TCustomMsgServer::KillAll() 291 | { 292 | int c, cnt = 0; 293 | LockList(); 294 | for (c = 0; c < MaxWorkers; c++) 295 | { 296 | if (Workers[c] != 0) 297 | try 298 | { 299 | PMsgWorkerThread(Workers[c])->Kill(); 300 | PMsgWorkerThread(Workers[c])->WorkerSocket->ForceClose(); 301 | delete PMsgWorkerThread(Workers[c]); 302 | Workers[c] = 0; 303 | cnt++; 304 | } catch (...) 305 | { 306 | }; 307 | } 308 | UnlockList(); 309 | DoEvent(0, evcClientsDropped, 0, cnt, 0, 0, 0); 310 | } 311 | //--------------------------------------------------------------------------- 312 | bool TCustomMsgServer::CanAccept(socket_t Socket) 313 | { 314 | return ((MaxClients == 0) || (ClientsCount < MaxClients)); 315 | } 316 | //--------------------------------------------------------------------------- 317 | PWorkerSocket TCustomMsgServer::CreateWorkerSocket(socket_t Sock) 318 | { 319 | PWorkerSocket Result; 320 | // Creates a funny default class : a tcp echo worker 321 | Result = new TEcoTcpWorker(); 322 | Result->SetSocket(Sock); 323 | return Result; 324 | } 325 | //--------------------------------------------------------------------------- 326 | void TCustomMsgServer::DoEvent(int Sender, longword Code, word RetCode, word Param1, word Param2, word Param3, word Param4) 327 | { 328 | TSrvEvent SrvEvent; 329 | bool GoLog = (Code & LogMask) != 0; 330 | bool GoEvent = (Code & EventMask) != 0; 331 | 332 | if (!Destroying && (GoLog || GoEvent)) 333 | { 334 | CSEvent->Enter(); 335 | 336 | time(&SrvEvent.EvtTime); 337 | SrvEvent.EvtSender = Sender; 338 | SrvEvent.EvtCode = Code; 339 | SrvEvent.EvtRetCode = RetCode; 340 | SrvEvent.EvtParam1 = Param1; 341 | SrvEvent.EvtParam2 = Param2; 342 | SrvEvent.EvtParam3 = Param3; 343 | SrvEvent.EvtParam4 = Param4; 344 | 345 | if (GoEvent && (OnEvent != NULL)) 346 | try 347 | { // callback is outside here, we have to shield it 348 | OnEvent(FUsrPtr, &SrvEvent, sizeof (TSrvEvent)); 349 | } catch (...) 350 | { 351 | }; 352 | 353 | if (GoLog) 354 | FEventQueue->Insert(&SrvEvent); 355 | 356 | CSEvent->Leave(); 357 | }; 358 | } 359 | //--------------------------------------------------------------------------- 360 | void TCustomMsgServer::Delete(int Index) 361 | { 362 | LockList(); 363 | Workers[Index] = 0; 364 | ClientsCount--; 365 | UnlockList(); 366 | } 367 | //--------------------------------------------------------------------------- 368 | void TCustomMsgServer::Incoming(socket_t Sock) 369 | { 370 | int idx; 371 | PWorkerSocket WorkerSocket; 372 | longword ClientHandle = Msg_GetSockAddr(Sock); 373 | 374 | if (CanAccept(Sock)) 375 | { 376 | LockList(); 377 | // First position available in the thread buffer 378 | idx = FirstFree(); 379 | if (idx >= 0) 380 | { 381 | // Creates the Worker and assigns it the connected socket 382 | WorkerSocket = CreateWorkerSocket(Sock); 383 | // Creates the Worker thread 384 | Workers[idx] = new TMsgWorkerThread(WorkerSocket, this); 385 | PMsgWorkerThread(Workers[idx])->Index = idx; 386 | // Update the number 387 | ClientsCount++; 388 | // And Starts the worker 389 | PMsgWorkerThread(Workers[idx])->Start(); 390 | DoEvent(WorkerSocket->ClientHandle, evcClientAdded, 0, 0, 0, 0, 0); 391 | } 392 | else 393 | { 394 | DoEvent(ClientHandle, evcClientNoRoom, 0, 0, 0, 0, 0); 395 | Msg_CloseSocket(Sock); 396 | } 397 | UnlockList(); 398 | } 399 | else 400 | { 401 | Msg_CloseSocket(Sock); 402 | DoEvent(ClientHandle, evcClientRejected, 0, 0, 0, 0, 0); 403 | }; 404 | } 405 | //--------------------------------------------------------------------------- 406 | int TCustomMsgServer::Start() 407 | { 408 | int Result = 0; 409 | if (Status != SrvRunning) 410 | { 411 | Result = StartListener(); 412 | if (Result != 0) 413 | { 414 | DoEvent(0, evcListenerCannotStart, Result, 0, 0, 0, 0); 415 | Status = SrvError; 416 | } 417 | else 418 | { 419 | DoEvent(0, evcServerStarted, SockListener->ClientHandle, LocalPort, 0, 0, 0); 420 | Status = SrvRunning; 421 | }; 422 | }; 423 | FLastError = Result; 424 | return Result; 425 | } 426 | //--------------------------------------------------------------------------- 427 | int TCustomMsgServer::StartTo(const char *Address, word Port) 428 | { 429 | strncpy(FLocalAddress, Address, 16); 430 | LocalPort = Port; 431 | return Start(); 432 | } 433 | //--------------------------------------------------------------------------- 434 | void TCustomMsgServer::Stop() 435 | { 436 | if (Status == SrvRunning) 437 | { 438 | // Kills the listener thread 439 | ServerThread->Terminate(); 440 | if (ServerThread->WaitFor(ThTimeout) != WAIT_OBJECT_0) 441 | ServerThread->Kill(); 442 | delete ServerThread; 443 | // Kills the listener 444 | delete SockListener; 445 | 446 | // Terminate all client threads 447 | TerminateAll(); 448 | 449 | Status = SrvStopped; 450 | LocalBind = 0; 451 | DoEvent(0, evcServerStopped, 0, 0, 0, 0, 0); 452 | }; 453 | FLastError = 0; 454 | } 455 | //--------------------------------------------------------------------------- 456 | int TCustomMsgServer::SetEventsCallBack(pfn_SrvCallBack PCallBack, void *UsrPtr) 457 | { 458 | OnEvent = PCallBack; 459 | FUsrPtr = UsrPtr; 460 | return 0; 461 | } 462 | //--------------------------------------------------------------------------- 463 | bool TCustomMsgServer::PickEvent(void *pEvent) 464 | { 465 | try 466 | { 467 | return FEventQueue->Extract(pEvent); 468 | } catch (...) 469 | { 470 | return false; 471 | }; 472 | } 473 | //--------------------------------------------------------------------------- 474 | bool TCustomMsgServer::EventEmpty() 475 | { 476 | return FEventQueue->Empty(); 477 | } 478 | //--------------------------------------------------------------------------- 479 | void TCustomMsgServer::EventsFlush() 480 | { 481 | CSEvent->Enter(); 482 | FEventQueue->Flush(); 483 | CSEvent->Leave(); 484 | } 485 | //--------------------------------------------------------------------------- 486 | 487 | 488 | -------------------------------------------------------------------------------- /deps/snap7/src/sys/snap_tcpsrvr.h: -------------------------------------------------------------------------------- 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 snap_tcpsrvr_h 27 | #define snap_tcpsrvr_h 28 | //--------------------------------------------------------------------------- 29 | #include "snap_msgsock.h" 30 | #include "snap_threads.h" 31 | //--------------------------------------------------------------------------- 32 | 33 | #define MaxWorkers 1024 34 | #define MaxEvents 1500 35 | 36 | const int SrvStopped = 0; 37 | const int SrvRunning = 1; 38 | const int SrvError = 2; 39 | 40 | const longword evcServerStarted = 0x00000001; 41 | const longword evcServerStopped = 0x00000002; 42 | const longword evcListenerCannotStart = 0x00000004; 43 | const longword evcClientAdded = 0x00000008; 44 | const longword evcClientRejected = 0x00000010; 45 | const longword evcClientNoRoom = 0x00000020; 46 | const longword evcClientException = 0x00000040; 47 | const longword evcClientDisconnected = 0x00000080; 48 | const longword evcClientTerminated = 0x00000100; 49 | const longword evcClientsDropped = 0x00000200; 50 | const longword evcReserved_00000400 = 0x00000400; 51 | const longword evcReserved_00000800 = 0x00000800; 52 | const longword evcReserved_00001000 = 0x00001000; 53 | const longword evcReserved_00002000 = 0x00002000; 54 | const longword evcReserved_00004000 = 0x00004000; 55 | const longword evcReserved_00008000 = 0x00008000; 56 | 57 | // Server Interface errors 58 | const longword errSrvBase = 0x0000FFFF; 59 | const longword errSrvMask = 0xFFFF0000; 60 | const longword errSrvCannotStart = 0x00100000; 61 | 62 | const longword ThTimeout = 2000; // Thread timeout 63 | const longword WkTimeout = 3000; // Workers termination timeout 64 | 65 | #pragma pack(1) 66 | 67 | typedef struct{ 68 | time_t EvtTime; // Timestamp 69 | int EvtSender; // Sender 70 | longword EvtCode; // Event code 71 | word EvtRetCode; // Event result 72 | word EvtParam1; // Param 1 (if available) 73 | word EvtParam2; // Param 2 (if available) 74 | word EvtParam3; // Param 3 (if available) 75 | word EvtParam4; // Param 4 (if available) 76 | }TSrvEvent, *PSrvEvent; 77 | 78 | extern "C" 79 | { 80 | typedef void (S7API *pfn_SrvCallBack)(void * usrPtr, PSrvEvent PEvent, int Size); 81 | } 82 | #pragma pack() 83 | 84 | //--------------------------------------------------------------------------- 85 | // EVENTS QUEUE 86 | //--------------------------------------------------------------------------- 87 | class TMsgEventQueue 88 | { 89 | private: 90 | int IndexIn; // <-- insert index 91 | int IndexOut; // --> extract index 92 | int Max; // Buffer upper bound [0..Max] 93 | int FCapacity; // Queue capacity 94 | pbyte Buffer; 95 | int FBlockSize; 96 | public: 97 | TMsgEventQueue(const int Capacity, const int BlockSize); 98 | ~TMsgEventQueue(); 99 | void Flush(); 100 | void Insert(void *lpdata); 101 | bool Extract(void *lpdata); 102 | bool Empty(); 103 | bool Full(); 104 | }; 105 | typedef TMsgEventQueue *PMsgEventQueue; 106 | 107 | //--------------------------------------------------------------------------- 108 | // WORKER THREAD 109 | //--------------------------------------------------------------------------- 110 | class TCustomMsgServer; // forward declaration 111 | 112 | // It's created when connection is accepted, it will interface with the client. 113 | class TMsgWorkerThread : public TSnapThread 114 | { 115 | private: 116 | TCustomMsgServer *FServer; 117 | protected: 118 | TMsgSocket *WorkerSocket; 119 | public: 120 | int Index; 121 | friend class TCustomMsgServer; 122 | TMsgWorkerThread(TMsgSocket *Socket, TCustomMsgServer *Server); 123 | void Execute(); 124 | }; 125 | typedef TMsgWorkerThread *PMsgWorkerThread; 126 | 127 | //--------------------------------------------------------------------------- 128 | // LISTENER THREAD 129 | //--------------------------------------------------------------------------- 130 | // It listens for incoming connection. 131 | class TMsgListenerThread : public TSnapThread 132 | { 133 | private: 134 | TMsgSocket *FListener; 135 | TCustomMsgServer *FServer; 136 | public: 137 | TMsgListenerThread(TMsgSocket *Listener, TCustomMsgServer *Server); 138 | void Execute(); 139 | }; 140 | typedef TMsgListenerThread *PMsgListenerThread; 141 | 142 | //--------------------------------------------------------------------------- 143 | // TCP SERVER 144 | //--------------------------------------------------------------------------- 145 | typedef TMsgSocket *PWorkerSocket; 146 | 147 | class TCustomMsgServer 148 | { 149 | private: 150 | int FLastError; 151 | char FLocalAddress[16]; 152 | // Socket listener 153 | PMsgSocket SockListener; 154 | // Server listener 155 | PMsgListenerThread ServerThread; 156 | // Critical section to lock Workers list activities 157 | PSnapCriticalSection CSList; 158 | // Event queue 159 | PMsgEventQueue FEventQueue; 160 | // Callback related 161 | pfn_SrvCallBack OnEvent; 162 | void *FUsrPtr; 163 | // private methods 164 | int StartListener(); 165 | void LockList(); 166 | void UnlockList(); 167 | int FirstFree(); 168 | protected: 169 | bool Destroying; 170 | // Critical section to lock Event activities 171 | PSnapCriticalSection CSEvent; 172 | // Workers list 173 | void *Workers[MaxWorkers]; 174 | // Terminates all worker threads 175 | virtual void TerminateAll(); 176 | // Kills all worker threads that are unresponsive 177 | void KillAll(); 178 | // if (true the connection is accepted, otherwise the connection 179 | // is closed gracefully 180 | virtual bool CanAccept(socket_t Socket); 181 | // Returns the class of the worker socket, override it for real servers 182 | virtual PWorkerSocket CreateWorkerSocket(socket_t Sock); 183 | // Handles the event 184 | virtual void DoEvent(int Sender, longword Code, word RetCode, word Param1, 185 | word Param2, word Param3, word Param4); 186 | // Delete the worker from the list (It's invoked by Worker Thread) 187 | void Delete(int Index); 188 | // Incoming connection (It's invoked by ServerThread, the listener) 189 | virtual void Incoming(socket_t Sock); 190 | public: 191 | friend class TMsgWorkerThread; 192 | friend class TMsgListenerThread; 193 | word LocalPort; 194 | longword LocalBind; 195 | longword LogMask; 196 | longword EventMask; 197 | int Status; 198 | int ClientsCount; 199 | int MaxClients; 200 | TCustomMsgServer(); 201 | virtual ~TCustomMsgServer(); 202 | // Starts the server 203 | int Start(); 204 | int StartTo(const char *Address, word Port); 205 | // Stops the server 206 | void Stop(); 207 | // Sets Event callback 208 | int SetEventsCallBack(pfn_SrvCallBack PCallBack, void *UsrPtr); 209 | // Pick an event from the circular queue 210 | bool PickEvent(void *pEvent); 211 | // Returns true if (the Event queue is empty 212 | bool EventEmpty(); 213 | // Flushes Event queue 214 | void EventsFlush(); 215 | }; 216 | 217 | //--------------------------------------------------------------------------- 218 | // TCP WORKER 219 | //--------------------------------------------------------------------------- 220 | // Default worker class, a simply tcp echo to test the connection and 221 | // data I/O to use the server outside the project 222 | class TEcoTcpWorker : public TMsgSocket 223 | { 224 | public: 225 | bool Execute() 226 | { 227 | byte Buffer[4096]; 228 | int Size; 229 | 230 | if (CanRead(WorkInterval)) // Small time to avoid time wait during the close 231 | { 232 | Receive(&Buffer,sizeof(Buffer),Size); 233 | if ((LastTcpError==0) && (Size>0)) 234 | { 235 | SendPacket(&Buffer,Size); 236 | return LastTcpError==0; 237 | } 238 | else 239 | return false; 240 | } 241 | else 242 | return true; 243 | }; 244 | }; 245 | 246 | //--------------------------------------------------------------------------- 247 | #endif // snap_tcpsrvr_h 248 | -------------------------------------------------------------------------------- /deps/snap7/src/sys/snap_threads.cpp: -------------------------------------------------------------------------------- 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 | 27 | #include "snap_threads.h" 28 | //--------------------------------------------------------------------------- 29 | #ifdef OS_WINDOWS 30 | DWORD WINAPI ThreadProc(LPVOID param) 31 | #else 32 | 33 | void* ThreadProc(void* param) 34 | #endif 35 | { 36 | PSnapThread Thread; 37 | // Unix but not Solaris 38 | #if (defined(POSIX) || defined(OS_OSX)) && (!defined(OS_SOLARIS_NATIVE_THREADS)) 39 | int last_type, last_state; 40 | pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &last_type); 41 | pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &last_state); 42 | #endif 43 | Thread = PSnapThread(param); 44 | 45 | if (!Thread->Terminated) 46 | try 47 | { 48 | Thread->Execute(); 49 | } catch (...) 50 | { 51 | }; 52 | Thread->Closed = true; 53 | if (Thread->FreeOnTerminate) 54 | { 55 | delete Thread; 56 | }; 57 | #ifdef OS_WINDOWS 58 | ExitThread(0); 59 | #endif 60 | #if defined(POSIX) && (!defined(OS_SOLARIS_NATIVE_THREADS)) 61 | pthread_exit((void*)0); 62 | #endif 63 | #if defined(OS_OSX) 64 | pthread_exit((void*)0); 65 | #endif 66 | #ifdef OS_SOLARIS_NATIVE_THREADS 67 | thr_exit((void*)0); 68 | #endif 69 | return 0; // never reach, only to avoid compiler warning 70 | } 71 | //--------------------------------------------------------------------------- 72 | TSnapThread::TSnapThread() 73 | { 74 | Started = false; 75 | Closed=false; 76 | Terminated = false; 77 | FreeOnTerminate = false; 78 | } 79 | //--------------------------------------------------------------------------- 80 | TSnapThread::~TSnapThread() 81 | { 82 | if (Started && !Closed) 83 | { 84 | Terminate(); 85 | Join(); 86 | }; 87 | #ifdef OS_WINDOWS 88 | if (Started) 89 | CloseHandle(th); 90 | #endif 91 | } 92 | //--------------------------------------------------------------------------- 93 | void TSnapThread::ThreadCreate() 94 | { 95 | #ifdef OS_WINDOWS 96 | th = CreateThread(0, 0, ThreadProc, this, 0, 0); 97 | #endif 98 | #if defined(POSIX) && (!defined(OS_SOLARIS_NATIVE_THREADS)) 99 | pthread_attr_t a; 100 | pthread_attr_init(&a); 101 | pthread_attr_setdetachstate(&a, PTHREAD_CREATE_DETACHED); 102 | pthread_create(&th, &a, &ThreadProc, this); 103 | #endif 104 | #if defined(OS_OSX) 105 | pthread_create(&th, 0, &ThreadProc, this); 106 | #endif 107 | #ifdef OS_SOLARIS_NATIVE_THREADS 108 | thr_create(0, // default stack base 109 | 0, // default stack size 110 | &ThreadProc, // Thread routine 111 | this, // argument 112 | 0, 113 | &th); 114 | #endif 115 | } 116 | //--------------------------------------------------------------------------- 117 | void TSnapThread::Start() 118 | { 119 | if (!Started) 120 | { 121 | ThreadCreate(); 122 | Started = true; 123 | } 124 | } 125 | //--------------------------------------------------------------------------- 126 | void TSnapThread::Terminate() 127 | { 128 | Terminated = true; 129 | } 130 | //--------------------------------------------------------------------------- 131 | void TSnapThread::Kill() 132 | { 133 | if (Started && !Closed) 134 | { 135 | ThreadKill(); 136 | Closed = true; 137 | } 138 | } 139 | //--------------------------------------------------------------------------- 140 | void TSnapThread::Join() 141 | { 142 | if (Started && !Closed) 143 | { 144 | ThreadJoin(); 145 | Closed = true; 146 | } 147 | } 148 | //--------------------------------------------------------------------------- 149 | longword TSnapThread::WaitFor(uint64_t Timeout) 150 | { 151 | if (Started) 152 | { 153 | if (!Closed) 154 | return ThreadWait(Timeout); 155 | else 156 | return WAIT_OBJECT_0; 157 | } 158 | else 159 | return WAIT_OBJECT_0; 160 | } 161 | //--------------------------------------------------------------------------- 162 | 163 | -------------------------------------------------------------------------------- /deps/snap7/src/sys/snap_threads.h: -------------------------------------------------------------------------------- 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 snap_threads_h 27 | #define snap_threads_h 28 | //--------------------------------------------------------------------------- 29 | #include "snap_platform.h" 30 | 31 | #ifdef OS_WINDOWS 32 | # include "win_threads.h" 33 | #endif 34 | #if defined(POSIX) && (!defined(OS_SOLARIS_NATIVE_THREADS)) 35 | # include "unix_threads.h" 36 | #endif 37 | #ifdef OS_SOLARIS_NATIVE_THREADS 38 | # include "sol_threads.h" 39 | #endif 40 | #if defined(OS_OSX) 41 | # include "unix_threads.h" 42 | #endif 43 | 44 | //--------------------------------------------------------------------------- 45 | #endif // snap_threads_h 46 | -------------------------------------------------------------------------------- /deps/snap7/src/sys/sol_threads.h: -------------------------------------------------------------------------------- 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 | | | 27 | | Solaris 11 Threads support | 28 | | | 29 | |=============================================================================*/ 30 | #ifndef sol_threads_h 31 | #define sol_threads_h 32 | //--------------------------------------------------------------------------- 33 | #include "snap_platform.h" 34 | #include "snap_sysutils.h" 35 | #include 36 | #include 37 | //--------------------------------------------------------------------------- 38 | 39 | class TSnapCriticalSection { 40 | private: 41 | mutex_t mx; 42 | int result; 43 | public: 44 | 45 | TSnapCriticalSection() { 46 | mutex_init(&mx, USYNC_THREAD, 0); 47 | }; 48 | 49 | ~TSnapCriticalSection() { 50 | mutex_destroy(&mx); 51 | }; 52 | 53 | void Enter() { 54 | mutex_lock(&mx); 55 | }; 56 | 57 | void Leave() { 58 | mutex_unlock(&mx); 59 | }; 60 | 61 | bool TryEnter() { 62 | return mutex_trylock(&mx) == 0; 63 | }; 64 | }; 65 | typedef TSnapCriticalSection *PSnapCriticalSection; 66 | 67 | //--------------------------------------------------------------------------- 68 | const longword WAIT_OBJECT_0 = 0x00000000L; 69 | const longword WAIT_ABANDONED = 0x00000080L; 70 | const longword WAIT_TIMEOUT = 0x00000102L; 71 | const longword WAIT_FAILED = 0xFFFFFFFFL; 72 | 73 | class TSnapEvent { 74 | private: 75 | cond_t CVariable; 76 | mutex_t Mutex; 77 | bool AutoReset; 78 | bool State; 79 | public: 80 | 81 | TSnapEvent(bool ManualReset) 82 | { 83 | AutoReset = !ManualReset; 84 | cond_init(&CVariable, USYNC_THREAD, 0) == 0; 85 | mutex_init(&Mutex, USYNC_THREAD, 0); 86 | State = false; 87 | } 88 | 89 | ~TSnapEvent() 90 | { 91 | cond_destroy(&CVariable); 92 | mutex_destroy(&Mutex); 93 | }; 94 | 95 | void Set() 96 | { 97 | mutex_lock(&Mutex); 98 | State = true; 99 | if (AutoReset) 100 | cond_signal(&CVariable); 101 | else 102 | cond_broadcast(&CVariable); 103 | mutex_unlock(&Mutex); 104 | }; 105 | 106 | void Reset() 107 | { 108 | mutex_lock(&Mutex); 109 | State = false; 110 | mutex_unlock(&Mutex); 111 | } 112 | 113 | longword WaitForever() 114 | { 115 | mutex_lock(&Mutex); 116 | while (!State) // <-- to avoid spurious wakeups 117 | cond_wait(&CVariable, &Mutex); 118 | if (AutoReset) 119 | State = false; 120 | mutex_unlock(&Mutex); 121 | return WAIT_OBJECT_0; 122 | }; 123 | 124 | longword WaitFor(int64_t Timeout) 125 | { 126 | longword Result = WAIT_OBJECT_0; 127 | if (Timeout == 0) 128 | Timeout = 1; // 0 is not allowed 129 | 130 | if (Timeout > 0) { 131 | mutex_lock(&Mutex); 132 | if (!State) { 133 | timespec ts; 134 | timeval tv; 135 | gettimeofday(&tv, NULL); 136 | uint64_t nsecs = ((uint64_t) tv.tv_sec) * 1000000000 + 137 | Timeout * 1000000 + 138 | ((uint64_t) tv.tv_usec) * 1000; 139 | ts.tv_sec = nsecs / 1000000000; 140 | ts.tv_nsec = (nsecs - ((uint64_t) ts.tv_sec) * 1000000000); 141 | do 142 | { 143 | Result = cond_timedwait(&CVariable, &Mutex, &ts); 144 | if (Result == ETIMEDOUT) 145 | Result = WAIT_TIMEOUT; 146 | } 147 | while (Result == 0 && !State); 148 | } 149 | else 150 | if (AutoReset) // take the ownership 151 | State = false; 152 | mutex_unlock(&Mutex); 153 | return Result; 154 | } 155 | else // Timeout<0 156 | return WaitForever(); 157 | }; 158 | }; 159 | typedef TSnapEvent *PSnapEvent; 160 | //--------------------------------------------------------------------------- 161 | 162 | class TSnapThread { 163 | private: 164 | thread_t th; 165 | bool FCreateSuspended; 166 | void ThreadCreate(); 167 | 168 | void ThreadJoin() 169 | { 170 | thr_join(th, 0, 0); 171 | }; 172 | 173 | void ThreadKill() 174 | { 175 | thr_kill(th, 0); 176 | }; 177 | 178 | longword ThreadWait(uint64_t Timeout) 179 | { 180 | longword Elapsed = SysGetTick(); 181 | while (!Closed && !(DeltaTime(Elapsed) > Timeout)) 182 | SysSleep(100); 183 | if (Closed) 184 | return WAIT_OBJECT_0; 185 | else 186 | return WAIT_TIMEOUT; 187 | }; 188 | protected: 189 | bool Started; 190 | public: 191 | bool Terminated; 192 | bool Closed; 193 | bool FreeOnTerminate; 194 | TSnapThread(); 195 | virtual ~TSnapThread(); 196 | 197 | virtual void Execute() { 198 | }; 199 | void Start(); 200 | void Terminate(); 201 | void Kill(); 202 | void Join(); 203 | longword WaitFor(uint64_t Timeout); 204 | }; 205 | typedef TSnapThread *PSnapThread; 206 | 207 | //--------------------------------------------------------------------------- 208 | #endif // sol_threads_h 209 | -------------------------------------------------------------------------------- /deps/snap7/src/sys/unix_threads.h: -------------------------------------------------------------------------------- 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 | | | 27 | | Posix Threads support (Linux, FreeBSD) | 28 | | | 29 | |=============================================================================*/ 30 | #ifndef unix_threads_h 31 | #define unix_threads_h 32 | //--------------------------------------------------------------------------- 33 | #include "snap_platform.h" 34 | #include "snap_sysutils.h" 35 | #include 36 | #include 37 | //--------------------------------------------------------------------------- 38 | 39 | class TSnapCriticalSection 40 | { 41 | private: 42 | pthread_mutex_t mx; 43 | // int result; 44 | public: 45 | 46 | TSnapCriticalSection() 47 | { 48 | /* 49 | 50 | This would be the best code, but very often it causes a segmentation fault in many 51 | unix systems (the problem seems to be pthread_mutexattr_destroy()). 52 | So, to avoid problems in future kernel/libc release, we use the "safe" default. 53 | 54 | pthread_mutexattr_t mxAttr; 55 | pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_RECURSIVE); 56 | pthread_mutex_init(&mx, &mxAttr); 57 | pthread_mutexattr_destroy(&mxAttr); 58 | 59 | */ 60 | pthread_mutex_init(&mx, 0); 61 | }; 62 | 63 | ~TSnapCriticalSection() 64 | { 65 | pthread_mutex_destroy(&mx); 66 | }; 67 | 68 | void Enter() 69 | { 70 | pthread_mutex_lock(&mx); 71 | }; 72 | 73 | void Leave() 74 | { 75 | pthread_mutex_unlock(&mx); 76 | }; 77 | 78 | bool TryEnter() 79 | { 80 | return pthread_mutex_trylock(&mx) == 0; 81 | }; 82 | }; 83 | typedef TSnapCriticalSection *PSnapCriticalSection; 84 | 85 | //--------------------------------------------------------------------------- 86 | const longword WAIT_OBJECT_0 = 0x00000000L; 87 | const longword WAIT_ABANDONED = 0x00000080L; 88 | const longword WAIT_TIMEOUT = 0x00000102L; 89 | const longword WAIT_FAILED = 0xFFFFFFFFL; 90 | 91 | class TSnapEvent 92 | { 93 | private: 94 | pthread_cond_t CVariable; 95 | pthread_mutex_t Mutex; 96 | bool AutoReset; 97 | bool State; 98 | public: 99 | 100 | TSnapEvent(bool ManualReset) 101 | { 102 | AutoReset = !ManualReset; 103 | if (pthread_cond_init(&CVariable, 0) == 0) 104 | pthread_mutex_init(&Mutex, 0); 105 | State = false; 106 | } 107 | 108 | ~TSnapEvent() 109 | { 110 | pthread_cond_destroy(&CVariable); 111 | pthread_mutex_destroy(&Mutex); 112 | }; 113 | 114 | void Set() 115 | { 116 | pthread_mutex_lock(&Mutex); 117 | State = true; 118 | if (AutoReset) 119 | pthread_cond_signal(&CVariable); 120 | else 121 | pthread_cond_broadcast(&CVariable); 122 | pthread_mutex_unlock(&Mutex); 123 | }; 124 | 125 | void Reset() 126 | { 127 | pthread_mutex_lock(&Mutex); 128 | State = false; 129 | pthread_mutex_unlock(&Mutex); 130 | } 131 | 132 | longword WaitForever() 133 | { 134 | pthread_mutex_lock(&Mutex); 135 | while (!State) // <-- to avoid spurious wakeups 136 | pthread_cond_wait(&CVariable, &Mutex); 137 | if (AutoReset) 138 | State = false; 139 | pthread_mutex_unlock(&Mutex); 140 | return WAIT_OBJECT_0; 141 | }; 142 | 143 | longword WaitFor(int64_t Timeout) 144 | { 145 | longword Result = WAIT_OBJECT_0; 146 | if (Timeout == 0) 147 | Timeout = 1; // 0 is not allowed 148 | 149 | if (Timeout > 0) 150 | { 151 | pthread_mutex_lock(&Mutex); 152 | if (!State) 153 | { 154 | timespec ts; 155 | timeval tv; 156 | gettimeofday(&tv, NULL); 157 | uint64_t nsecs = ((uint64_t) tv.tv_sec) * 1000000000 + 158 | Timeout * 1000000 + 159 | ((uint64_t) tv.tv_usec) * 1000; 160 | ts.tv_sec = nsecs / 1000000000; 161 | ts.tv_nsec = (nsecs - ((uint64_t) ts.tv_sec) * 1000000000); 162 | do { 163 | Result = pthread_cond_timedwait(&CVariable, &Mutex, &ts); 164 | if (Result == ETIMEDOUT) 165 | Result = WAIT_TIMEOUT; 166 | } while (Result == 0 && !State); 167 | } 168 | else 169 | if (AutoReset) // take the ownership 170 | State = false; 171 | pthread_mutex_unlock(&Mutex); 172 | return Result; 173 | } 174 | else // Timeout<0 175 | return WaitForever(); 176 | }; 177 | }; 178 | typedef TSnapEvent *PSnapEvent; 179 | //--------------------------------------------------------------------------- 180 | class TSnapThread 181 | { 182 | private: 183 | pthread_t th; 184 | bool FCreateSuspended; 185 | void ThreadCreate(); 186 | 187 | void ThreadJoin() 188 | { 189 | pthread_join(th, 0); 190 | }; 191 | 192 | void ThreadKill() 193 | { 194 | pthread_cancel(th); 195 | }; 196 | 197 | longword ThreadWait(uint64_t Timeout) 198 | { 199 | longword Elapsed = SysGetTick(); 200 | while (!Closed && !(DeltaTime(Elapsed) > Timeout)) 201 | SysSleep(100); 202 | if (Closed) 203 | return WAIT_OBJECT_0; 204 | else 205 | return WAIT_TIMEOUT; 206 | }; 207 | protected: 208 | bool Started; 209 | public: 210 | bool Terminated; 211 | bool Closed; 212 | bool FreeOnTerminate; 213 | TSnapThread(); 214 | virtual ~TSnapThread(); 215 | 216 | virtual void Execute() 217 | { 218 | }; 219 | void Start(); 220 | void Terminate(); 221 | void Kill(); 222 | void Join(); 223 | longword WaitFor(uint64_t Timeout); 224 | }; 225 | typedef TSnapThread *PSnapThread; 226 | 227 | //--------------------------------------------------------------------------- 228 | #endif // unix_threads_h 229 | -------------------------------------------------------------------------------- /deps/snap7/src/sys/win_threads.h: -------------------------------------------------------------------------------- 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 | | | 27 | | Windows Threads support (Windows, ReactOS) | 28 | | | 29 | |=============================================================================*/ 30 | #ifndef win_threads_h 31 | #define win_threads_h 32 | //--------------------------------------------------------------------------- 33 | #include "snap_platform.h" 34 | #include "snap_sysutils.h" 35 | //--------------------------------------------------------------------------- 36 | 37 | class TSnapCriticalSection 38 | { 39 | private: 40 | CRITICAL_SECTION cs; 41 | public: 42 | 43 | TSnapCriticalSection() 44 | { 45 | InitializeCriticalSection(&cs); 46 | }; 47 | 48 | ~TSnapCriticalSection() 49 | { 50 | DeleteCriticalSection(&cs); 51 | }; 52 | 53 | void Enter() 54 | { 55 | EnterCriticalSection(&cs); 56 | }; 57 | 58 | void Leave() 59 | { 60 | LeaveCriticalSection(&cs); 61 | }; 62 | 63 | bool TryEnter() 64 | { 65 | return (TryEnterCriticalSection(&cs) != 0); 66 | }; 67 | }; 68 | typedef TSnapCriticalSection *PSnapCriticalSection; 69 | //--------------------------------------------------------------------------- 70 | 71 | class TSnapEvent 72 | { 73 | private: 74 | HANDLE Event; 75 | public: 76 | 77 | TSnapEvent(bool ManualReset) 78 | { 79 | Event = CreateEvent(0, ManualReset, false, 0); 80 | }; 81 | 82 | ~TSnapEvent() 83 | { 84 | if (Event != 0) 85 | CloseHandle(Event); 86 | }; 87 | 88 | void Set() 89 | { 90 | if (Event != 0) 91 | SetEvent(Event); 92 | }; 93 | 94 | void Reset() 95 | { 96 | if (Event != 0) 97 | ResetEvent(Event); 98 | }; 99 | 100 | longword WaitForever() 101 | { 102 | if (Event != 0) 103 | return WaitForSingleObject(Event, INFINITE); 104 | else 105 | return WAIT_FAILED; 106 | }; 107 | 108 | longword WaitFor(int64_t Timeout) { 109 | if (Event != 0) 110 | return WaitForSingleObject(Event, DWORD(Timeout)); 111 | else 112 | return WAIT_FAILED; 113 | }; 114 | }; 115 | typedef TSnapEvent *PSnapEvent; 116 | //--------------------------------------------------------------------------- 117 | 118 | class TSnapThread { 119 | private: 120 | HANDLE th; 121 | bool FCreateSuspended; 122 | void ThreadCreate(); 123 | 124 | void ThreadJoin() 125 | { 126 | WaitForSingleObject(th, INFINITE); 127 | }; 128 | 129 | void ThreadKill() 130 | { 131 | TerminateThread(th, 0); 132 | }; 133 | 134 | longword ThreadWait(uint64_t Timeout) 135 | { 136 | return WaitForSingleObject(th, DWORD(Timeout)); 137 | }; 138 | protected: 139 | bool Started; 140 | public: 141 | bool Terminated; 142 | bool Closed; 143 | bool FreeOnTerminate; 144 | TSnapThread(); 145 | virtual ~TSnapThread(); 146 | 147 | virtual void Execute() 148 | { 149 | }; 150 | void Start(); 151 | void Terminate(); 152 | void Kill(); 153 | void Join(); 154 | longword WaitFor(uint64_t Timeout); 155 | }; 156 | typedef TSnapThread *PSnapThread; 157 | 158 | //--------------------------------------------------------------------------- 159 | #endif // win_threads_h 160 | -------------------------------------------------------------------------------- /doc/server.md: -------------------------------------------------------------------------------- 1 | ## S7Server 2 | - [Administrative functions](#administrative-functions) 3 | - [Start()](#start) 4 | - [StartTo()](#start-to) 5 | - [Stop()](#stop) 6 | - [GetParam()](#get-param) 7 | - [SetParam()](#set-param) 8 | - [SetResourceless()](#set-resourceless) 9 | - [Memory functions](#memory-functions) 10 | - [RegisterArea()](#register-area) 11 | - [UnregisterArea()](#unregister-area) 12 | - [GetArea()](#get-area) 13 | - [SetArea()](#set-area) 14 | - [LockArea()](#lock-area) 15 | - [UnlockArea()](#unlock-area) 16 | - [Event functions](#event-functions) 17 | - [Event 'event'](#event-event) 18 | - [Event 'readWrite'](#event-read-write) 19 | - [GetEventMask()](#get-event-mask) 20 | - [SetEventMask()](#set-event-mask) 21 | - [Miscellaneous functions](#miscellaneous-functions) 22 | - [LastError()](#last-error) 23 | - [EventText()](#event-text) 24 | - [ErrorText()](#error-text) 25 | - [ServerStatus()](#server-status) 26 | - [ClientsCount()](#clients-count) 27 | - [GetCpuStatus()](#get-cpu-status) 28 | - [SetCpuStatus()](#set-cpu-status) 29 | 30 | ### API - Administrative functions 31 | 32 | ---------- 33 | 34 | #### S7Server.Start([callback]) 35 | Starts the server and binds it to the IP address specified in the previous call of `StartTo()`. If `StartTo()` was not previously called, `0.0.0.0` is assumed as IP address. 36 | 37 | - The optional `callback` parameter will be executed after completion 38 | 39 | If `callback` is **not** set the function is **blocking** and returns `true` on success or `false` on error.
40 | If `callback` is set the function is **non-blocking** and an `error` argument is given to the callback. 41 | 42 | #### S7Server.StartTo(ip[, callback]) 43 | Starts the server and binds it to the specified IP address and the IsoTCP port. 44 | 45 | - `ip` PLC/Equipment IPV4 Address ex. “192.168.1.12” 46 | - The optional `callback` parameter will be executed after completion 47 | 48 | If `callback` is **not** set the function is **blocking** and returns the CPU status on success or `false` on error.
49 | If `callback` is set the function is **non-blocking** and an `error` argument is given to the callback. 50 | 51 | #### S7Server.Stop([callback]) 52 | Stops the server, disconnects gracefully all clients, destroys al S7 workers and unbinds the listener socket from its address. 53 | 54 | - The optional `callback` parameter will be executed after completion 55 | 56 | If `callback` is **not** set the function is **blocking** and returns the CPU status on success or `false` on error.
57 | If `callback` is set the function is **non-blocking** and an `error` argument is given to the callback. 58 | 59 | #### S7Server.GetParam(paramNumber) 60 | Returns an internal server parameter. 61 | 62 | - `paramNumber` One from the parameter list [below](#table-area) 63 | 64 | 65 | 66 | | Name | Value | Description | 67 | |:------------------------|:-----:|:------------| 68 | | `S7Server.LocalPort` | 1 | Socket local port 69 | | `S7Server.WorkInterval` | 6 | Socket worker interval 70 | | `S7Server.PDURequest` | 10 | Initial PDU length request 71 | | `S7Server.MaxClients` | 11 | Max clients allowed 72 | 73 | Returns the `parameter value` on success or `false` on error. 74 | 75 | #### S7Server.SetParam(paramNumber, value) 76 | Sets an internal server parameter. 77 | 78 | - `paramNumber` One from the parameter list [above](#table-area) 79 | - `value` New parameter value 80 | 81 | Returns `true` on success or `false` on error. 82 | 83 | #### S7Server.SetResourceless(value) 84 | Sets the server to resourceless mode. 85 | 86 | - `value` new value 87 | 88 | Returns `true` on success or `false` on error. 89 | 90 | ### API - Memory functions 91 | 92 | ---------- 93 | 94 | #### S7Server.RegisterArea(areaCode[, index], buffer) 95 | Registers a memory area in the server. That memory block will be visible by the clients. 96 | 97 | - `areaCode` Area identifier (see table [below](#table-area)) 98 | - `index` DB number if `areaCode` equals `srvAreaDB`, otherwise ignored 99 | - `buffer` User buffer 100 | 101 | Returns `true` on success or `false` on error. 102 | 103 | #### S7Server.UnregisterArea(areaCode[, index]) 104 | Unregisters a memory area in the server. 105 | 106 | - `areaCode` Area identifier (see table [below](#table-area)) 107 | - `index` DB number if `areaCode` equals `srvAreaDB`, otherwise ignored 108 | 109 | Returns `true` on success or `false` on error. 110 | 111 | #### S7Server.GetArea(areaCode[, index]) 112 | Gets the content of a previously registered memory area block. 113 | 114 | - `areaCode` Area identifier (see table [below](#table-area)) 115 | - `index` DB number if `areaCode` equals `srvAreaDB`, otherwise ignored 116 | 117 | Returns a `buffer` object. 118 | 119 | #### S7Server.SetArea(areaCode[, index], buffer) 120 | Sets the content of a previously registered memory area block. 121 | 122 | - `areaCode` Area identifier (see table [below](#table-area)) 123 | - `index` DB number if `areaCode` equals `srvAreaDB`, otherwise ignored 124 | - `buffer` Buffer object 125 | 126 | #### S7Server.LockArea(areaCode[, index]) 127 | Locks the memory area so that a server worker thread is blocked on access attempt until the lock is released with [UnlockArea()](#unlock-area). 128 | 129 | - `areaCode` Area identifier (see table [below](#table-area)) 130 | - `index` DB number if `areaCode` equals `srvAreaDB`, otherwise ignored 131 | 132 | #### S7Server.UnlockArea(areaCode[, index]) 133 | Unlocks a previously locked memory area. 134 | 135 | 136 | - `areaCode` Area identifier (see table [below](#table-area)) 137 | - `index` DB number if `areaCode` equals `srvAreaDB`, otherwise ignored 138 | 139 | 140 | 141 | | Area | Value | Description | 142 | |:-----------------------|:-----:|:------------| 143 | | `S7Server.srvAreaPE` | 0 | Process inputs 144 | | `S7Server.srvAreaPA` | 1 | Process outputs 145 | | `S7Server.srvAreaMK` | 2 | Merkers 146 | | `S7Server.srvAreaCT` | 3 | Counters 147 | | `S7Server.srvAreaTM` | 4 | Timers 148 | | `S7Server.srvAreaDB` | 5 | DB 149 | 150 | ### API - Event functions 151 | 152 | ---------- 153 | 154 | #### S7Server event: 'event' 155 | Emitted on server events. 156 | 157 | - `event` Event object 158 | 159 | Event object: 160 | 161 | ```javascript 162 | { 163 | EvtTime; // Date 164 | EvtSender; // Sender 165 | EvtCode; // Event code 166 | EvtRetCode; // Event result 167 | EvtParam1; // Param 1 (if available) 168 | EvtParam2; // Param 2 (if available) 169 | EvtParam3; // Param 3 (if available) 170 | EvtParam4; // Param 4 (if available) 171 | } 172 | ``` 173 | Example: 174 | 175 | ```javascript 176 | var s7server = new snap7.S7Server(); 177 | 178 | s7server.on("event", function(event) { 179 | console.log(s7server.EventText(event)); 180 | }); 181 | 182 | s7server.StartTo('127.0.0.1'); 183 | ``` 184 | 185 | #### S7Server event: 'readWrite' 186 | Emitted on every read/write event. Only available in resourceless mode. 187 | 188 | - `sender` IPv4 address of the sender 189 | - `operation` Operation type 190 | - `tagObj` Tag object 191 | - `buffer` Buffer object 192 | - `callback` Callback function 193 | 194 | The server worker thread is **blocked** until `callback` is called. Therefore **calling is crucial**, to prevent a deadlock in the worker thread.
195 | On a read event the `callback` expects a buffer as argument that is provided to the client. You can use the `buffer` argument which is an empty buffer of the correct size. 196 | 197 | 198 | 199 | | Operation type | Value | Description | 200 | |:--------------------------|:-----:|:---------------------| 201 | | `S7Server.operationRead` | 0x00 | Read operation 202 | | `S7Server.operationWrite` | 0x01 | Write operation 203 | 204 | Tag object: 205 | 206 | ```javascript 207 | { 208 | Area; // Area code (DB, MK,…) 209 | DBNumber; // DB number (if any or 0) 210 | Start; // Offset start 211 | Size; // Number of elements 212 | WordLen; // Tag WordLength 213 | } 214 | ``` 215 | 216 | Example: 217 | 218 | ```javascript 219 | var s7server = new snap7.S7Server(); 220 | 221 | s7server.SetResourceless(true); 222 | 223 | s7server.on("readWrite", function(sender, operation, tagObj, buffer, callback) { 224 | console.log((operation === s7server.operationRead ? 'Read' : 'Write') + ' event from ' + sender); 225 | console.log('Area : ' + tagObj.Area); 226 | console.log('DBNumber : ' + tagObj.DBNumber); 227 | console.log('Start : ' + tagObj.Start); 228 | console.log('Size : ' + tagObj.Size); 229 | console.log('WordLen : ' + tagObj.WordLen); 230 | 231 | if (operation === s7server.operationRead) { 232 | buffer.fill(255); 233 | return callback(buffer); 234 | } else { 235 | console.log('Buffer : ' + buffer); 236 | return callback(); 237 | } 238 | }); 239 | 240 | s7server.StartTo('127.0.0.1'); 241 | ``` 242 | 243 | #### S7Server.GetEventMask() 244 | Returns the server event filter mask. 245 | 246 | 247 | #### S7Server.SetEventMask(mask) 248 | Sets the server event filter mask. 249 | 250 | - `mask` Bit mask (see table [below](#table-mask)) 251 | 252 | 253 | 254 | | Event code | Value | 255 | |:------------------------------------|:--------------:| 256 | | `S7Server.evcAll` | 0xFFFFFFFF 257 | | `S7Server.evcNone` | 0x00000000 258 | | `S7Server.evcServerStarted` | 0x00000001 259 | | `S7Server.evcServerStopped` | 0x00000002 260 | | `S7Server.evcListenerCannotStart` | 0x00000004 261 | | `S7Server.evcClientAdded` | 0x00000008 262 | | `S7Server.evcClientRejected` | 0x00000010 263 | | `S7Server.evcClientNoRoom` | 0x00000020 264 | | `S7Server.evcClientException` | 0x00000040 265 | | `S7Server.evcClientDisconnected` | 0x00000080 266 | | `S7Server.evcClientTerminated` | 0x00000100 267 | | `S7Server.evcClientsDropped` | 0x00000200 268 | | `S7Server.evcPDUincoming` | 0x00010000 269 | | `S7Server.evcDataRead` | 0x00020000 270 | | `S7Server.evcDataWrite` | 0x00040000 271 | | `S7Server.evcNegotiatePDU` | 0x00080000 272 | | `S7Server.evcReadSZL` | 0x00100000 273 | | `S7Server.evcClock` | 0x00200000 274 | | `S7Server.evcUpload` | 0x00400000 275 | | `S7Server.evcDownload` | 0x00800000 276 | | `S7Server.evcDirectory` | 0x01000000 277 | | `S7Server.evcSecurity` | 0x02000000 278 | | `S7Server.evcControl` | 0x04000000 279 | 280 | 281 | ### API - Miscellaneous functions 282 | 283 | ---------- 284 | 285 | #### S7Server.LastError() 286 | Returns the last job result. 287 | 288 | #### S7Server.EventText(eventObj) 289 | Returns a textual explanation of a given event. 290 | 291 | - `eventObj` Event object (example [here](#event-object)) 292 | 293 | #### S7Server.ErrorText(errNum) 294 | Returns a textual explanation of a given error number. 295 | 296 | - `errNum` Error number 297 | 298 | #### S7Server.ServerStatus() 299 | Returns the server status. (see table [below](#table-server-status)) 300 | 301 | 302 | 303 | | Status | Value | Description | 304 | |:----------------------|:-----:|:---------------------| 305 | | `S7Server.SrvStopped` | 0x00 | The Server is stopped 306 | | `S7Server.SrvRunning` | 0x01 | The Server is Running 307 | | `S7Server.SrvError` | 0x02 | Server Error 308 | 309 | #### S7Server.ClientsCount() 310 | Returns the number of clients connected to the server. 311 | 312 | #### S7Server.GetCpuStatus() 313 | Returns the Virtual CPU status. (see table [below](#table-cpu-status)) 314 | 315 | #### S7Server.SetCpuStatus(cpuStatus) 316 | Sets the Virtual CPU status. 317 | 318 | - `cpuStatus` Status value (see table [below](#table-cpu-status)) 319 | 320 | 321 | 322 | | Status | Value | Description | 323 | |:------------------------------|:-----:|:-------------------------| 324 | | `S7Server.S7CpuStatusUnknown` | 0x00 | The CPU status is unknown 325 | | `S7Server.S7CpuStatusRun` | 0x08 | The CPU is running 326 | | `S7Server.S7CpuStatusStop` | 0x04 | The CPU is stopped 327 | -------------------------------------------------------------------------------- /lib/node-snap7.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Mathias Küsel 3 | * MIT License 4 | */ 5 | 6 | var events = require('events'); 7 | 8 | module.exports = snap7 = require('bindings')('node_snap7.node'); 9 | 10 | snap7.S7Client.prototype.DBRead = function (dbNumber, start, size, cb) { 11 | return this.ReadArea(this.S7AreaDB, dbNumber, start, size, this.S7WLByte, cb); 12 | } 13 | 14 | snap7.S7Client.prototype.DBWrite = function (dbNumber, start, size, buf, cb) { 15 | return this.WriteArea(this.S7AreaDB, dbNumber, start, size, this.S7WLByte, buf, cb); 16 | } 17 | 18 | snap7.S7Client.prototype.MBRead = function (start, size, cb) { 19 | return this.ReadArea(this.S7AreaMK, 0, start, size, this.S7WLByte, cb); 20 | } 21 | 22 | snap7.S7Client.prototype.MBWrite = function (start, size, buf, cb) { 23 | return this.WriteArea(this.S7AreaMK, 0, start, size, this.S7WLByte, buf, cb); 24 | } 25 | 26 | snap7.S7Client.prototype.EBRead = function (start, size, cb) { 27 | return this.ReadArea(this.S7AreaPE, 0, start, size, this.S7WLByte, cb); 28 | } 29 | 30 | snap7.S7Client.prototype.EBWrite = function (start, size, buf, cb) { 31 | return this.WriteArea(this.S7AreaPE, 0, start, size, this.S7WLByte, buf, cb); 32 | } 33 | 34 | snap7.S7Client.prototype.ABRead = function (start, size, cb) { 35 | return this.ReadArea(this.S7AreaPA, 0, start, size, this.S7WLByte, cb); 36 | } 37 | 38 | snap7.S7Client.prototype.ABWrite = function (start, size, buf, cb) { 39 | return this.WriteArea(this.S7AreaPA, 0, start, size, this.S7WLByte, buf, cb); 40 | } 41 | 42 | snap7.S7Client.prototype.TMRead = function (start, size, cb) { 43 | return this.ReadArea(this.S7AreaTM, 0, start, size, this.S7WLTimer, cb); 44 | } 45 | 46 | snap7.S7Client.prototype.TMWrite = function (start, size, buf, cb) { 47 | return this.WriteArea(this.S7AreaTM, 0, start, size, this.S7WLTimer, buf, cb); 48 | } 49 | 50 | snap7.S7Client.prototype.CTRead = function (start, size, cb) { 51 | return this.ReadArea(this.S7AreaCT, 0, start, size, this.S7WLCounter, cb); 52 | } 53 | 54 | snap7.S7Client.prototype.CTWrite = function (start, size, buf, cb) { 55 | return this.WriteArea(this.S7AreaCT, 0, start, size, this.S7WLCounter, buf, cb); 56 | } 57 | 58 | snap7.S7Server.super_ = events.EventEmitter; 59 | Object.setPrototypeOf(snap7.S7Server.prototype, events.EventEmitter.prototype); 60 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-snap7", 3 | "main": "./lib/node-snap7.js", 4 | "version": "1.0.8", 5 | "description": "Native node.js addon/wrapper for snap7", 6 | "homepage": "https://github.com/mathiask88/node-snap7", 7 | "repository": { 8 | "type": "git", 9 | "url": "git://github.com/mathiask88/node-snap7.git" 10 | }, 11 | "keywords": [ 12 | "snap7", 13 | "sps", 14 | "S7", 15 | "PLC" 16 | ], 17 | "author": { 18 | "name": "Mathias Küsel" 19 | }, 20 | "engines": { 21 | "node": "^16 || ^18 || ^20 || ^22" 22 | }, 23 | "license": "MIT", 24 | "readmeFilename": "README.md", 25 | "dependencies": { 26 | "nan": "^2.22.0", 27 | "bindings": "^1.5.0", 28 | "prebuild-install": "^7.1.2" 29 | }, 30 | "devDependencies": { 31 | "prebuild": "^13.0.1", 32 | "prebuild-ci": "^4.0.0" 33 | }, 34 | "scripts": { 35 | "install": "prebuild-install || node-gyp rebuild", 36 | "test": "prebuild-ci" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/node_snap7.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Mathias Küsel 3 | * MIT License 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | namespace node_snap7 { 10 | 11 | NAN_MODULE_INIT(InitAll) { 12 | S7Client::Init(target); 13 | S7Server::Init(target); 14 | } 15 | 16 | NODE_MODULE(node_snap7, InitAll) 17 | 18 | } // namespace node_snap7 19 | -------------------------------------------------------------------------------- /src/node_snap7_client.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Mathias Küsel 3 | * MIT License 4 | */ 5 | 6 | #ifndef SRC_NODE_SNAP7_CLIENT_H_ 7 | #define SRC_NODE_SNAP7_CLIENT_H_ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace node_snap7 { 14 | 15 | enum DataIOFunction { READAREA = 1, WRITEAREA, READMULTI, WRITEMULTI 16 | , PLCSTATUS, GETPROTECTION, CLEARSESSIONPW, SETSESSIONPW, PLCSTOP 17 | , PLCCOLDSTART, PLCHOTSTART, GETCPINFO, GETCPUINFO, GETORDERCODE 18 | , SETPLCSYSTEMDATETIME, GETPLCDATETIME, COMPRESS, COPYRAMTOROM 19 | , SETPLCDATETIME, DBFILL, DBGET, DELETEBLOCK, DOWNLOAD, FULLUPLOAD 20 | , UPLOAD, LISTBLOCKSOFTYPE, GETAGBLOCKINFO, LISTBLOCKS, CONNECT 21 | , CONNECTTO, READSZLLIST, READSZL 22 | }; 23 | 24 | class S7Client : public Nan::ObjectWrap { 25 | public: 26 | S7Client(); 27 | static NAN_MODULE_INIT(Init); 28 | static NAN_METHOD(New); 29 | // Control functions 30 | static NAN_METHOD(Connect); 31 | static NAN_METHOD(ConnectTo); 32 | static NAN_METHOD(SetConnectionParams); 33 | static NAN_METHOD(SetConnectionType); 34 | static NAN_METHOD(Disconnect); 35 | static NAN_METHOD(GetParam); 36 | static NAN_METHOD(SetParam); 37 | // Data I/O Main functions 38 | static NAN_METHOD(ReadArea); 39 | static NAN_METHOD(WriteArea); 40 | static NAN_METHOD(ReadMultiVars); 41 | static NAN_METHOD(WriteMultiVars); 42 | // Directory functions 43 | static NAN_METHOD(ListBlocks); 44 | static NAN_METHOD(GetAgBlockInfo); 45 | static NAN_METHOD(GetPgBlockInfo); 46 | static NAN_METHOD(ListBlocksOfType); 47 | // Blocks functions 48 | static NAN_METHOD(Upload); 49 | static NAN_METHOD(FullUpload); 50 | static NAN_METHOD(Download); 51 | static NAN_METHOD(Delete); 52 | static NAN_METHOD(DBGet); 53 | static NAN_METHOD(DBFill); 54 | // Date/Time functions 55 | static NAN_METHOD(GetPlcDateTime); 56 | static NAN_METHOD(SetPlcDateTime); 57 | static NAN_METHOD(SetPlcSystemDateTime); 58 | // System Info functions 59 | static NAN_METHOD(GetOrderCode); 60 | static NAN_METHOD(GetCpuInfo); 61 | static NAN_METHOD(GetCpInfo); 62 | static NAN_METHOD(ReadSZL); 63 | static NAN_METHOD(ReadSZLList); 64 | // Control functions 65 | static NAN_METHOD(PlcHotStart); 66 | static NAN_METHOD(PlcColdStart); 67 | static NAN_METHOD(PlcStop); 68 | static NAN_METHOD(CopyRamToRom); 69 | static NAN_METHOD(Compress); 70 | // Security functions 71 | static NAN_METHOD(GetProtection); 72 | static NAN_METHOD(SetSessionPassword); 73 | static NAN_METHOD(ClearSessionPassword); 74 | // Properties 75 | static NAN_METHOD(ExecTime); 76 | static NAN_METHOD(LastError); 77 | static NAN_METHOD(PDURequested); 78 | static NAN_METHOD(PDULength); 79 | static NAN_METHOD(PlcStatus); 80 | static NAN_METHOD(Connected); 81 | 82 | static NAN_METHOD(ErrorText); 83 | // Internal Helper functions 84 | static int GetByteCountFromWordLen(int WordLen); 85 | v8::Local S7DataItemToArray(PS7DataItem Items, int len 86 | , bool readMulti); 87 | v8::Local S7ProtectionToObject(PS7Protection S7Protection); 88 | v8::Local S7CpInfoToObject(PS7CpInfo CpInfo); 89 | v8::Local S7CpuInfoToObject(PS7CpuInfo CpuInfo); 90 | v8::Local S7OrderCodeToObject(PS7OrderCode OrderCode); 91 | v8::Local S7BlockInfoToObject(PS7BlockInfo BlockInfo); 92 | v8::Local S7BlocksListToObject(PS7BlocksList BlocksList); 93 | v8::Local S7BlocksOfTypeToArray(PS7BlocksOfType BlocksList 94 | , int count); 95 | v8::Local S7SZLListToArray(PS7SZLList SZLList, int count); 96 | 97 | static void FreeCallback(char *data, void* hint); 98 | static void FreeCallbackSZL(char *data, void* hint); 99 | 100 | 101 | uv_mutex_t mutex; 102 | TS7Client *snap7Client; 103 | 104 | private: 105 | ~S7Client(); 106 | static Nan::Persistent constructor; 107 | }; 108 | 109 | class IOWorker : public Nan::AsyncWorker { 110 | public: 111 | // No args 112 | IOWorker(Nan::Callback *callback, S7Client *s7client, DataIOFunction caller) 113 | : Nan::AsyncWorker(callback), s7client(s7client), caller(caller) {} 114 | // 1 args 115 | IOWorker(Nan::Callback *callback, S7Client *s7client, DataIOFunction caller 116 | , void *arg1) 117 | : Nan::AsyncWorker(callback), s7client(s7client), caller(caller) 118 | , pData(arg1) {} 119 | IOWorker(Nan::Callback *callback, S7Client *s7client, DataIOFunction caller 120 | , int arg1) 121 | : Nan::AsyncWorker(callback), s7client(s7client), caller(caller) 122 | , int1(arg1) {} 123 | // 2 args 124 | IOWorker(Nan::Callback *callback, S7Client *s7client, DataIOFunction caller 125 | , void *arg1, int arg2) 126 | : Nan::AsyncWorker(callback), s7client(s7client), caller(caller) 127 | , pData(arg1), int1(arg2) {} 128 | IOWorker(Nan::Callback *callback, S7Client *s7client, DataIOFunction caller 129 | , int arg1, int arg2) 130 | : Nan::AsyncWorker(callback), s7client(s7client), caller(caller) 131 | , int1(arg1), int2(arg2) {} 132 | // 3 args 133 | IOWorker(Nan::Callback *callback, S7Client *s7client, DataIOFunction caller 134 | , void *arg1, int arg2, int arg3) 135 | : Nan::AsyncWorker(callback), s7client(s7client), caller(caller) 136 | , pData(arg1), int1(arg2), int2(arg3) {} 137 | // 4 args 138 | IOWorker(Nan::Callback *callback, S7Client *s7client, DataIOFunction caller 139 | , void *arg1, int arg2, int arg3, int arg4) 140 | : Nan::AsyncWorker(callback), s7client(s7client), caller(caller) 141 | , pData(arg1), int1(arg2), int2(arg3), int3(arg4) {} 142 | // 6 args 143 | IOWorker(Nan::Callback *callback, S7Client *s7client, DataIOFunction caller 144 | , void *arg1, int arg2, int arg3, int arg4, int arg5, int arg6) 145 | : Nan::AsyncWorker(callback), s7client(s7client), caller(caller) 146 | , pData(arg1), int1(arg2), int2(arg3), int3(arg4), int4(arg5), int5(arg6) {} 147 | 148 | ~IOWorker() {} 149 | 150 | private: 151 | void Execute(); 152 | void HandleOKCallback(); 153 | 154 | S7Client *s7client; 155 | DataIOFunction caller; 156 | void *pData; 157 | int int1, int2, int3, int4, int5, returnValue; 158 | }; 159 | 160 | } // namespace node_snap7 161 | 162 | #endif // SRC_NODE_SNAP7_CLIENT_H_ 163 | -------------------------------------------------------------------------------- /src/node_snap7_server.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Mathias Küsel 3 | * MIT License 4 | */ 5 | 6 | #ifndef SRC_NODE_SNAP7_SERVER_H_ 7 | #define SRC_NODE_SNAP7_SERVER_H_ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace node_snap7 { 17 | 18 | enum ServerIOFunction { 19 | START = 1, STARTTO, STOP 20 | }; 21 | 22 | typedef struct { 23 | char* pBuffer; 24 | word size; 25 | }TBufferInfo; 26 | 27 | class S7Server : public Nan::ObjectWrap { 28 | public: 29 | explicit S7Server(v8::Local resource); 30 | static NAN_MODULE_INIT(Init); 31 | static NAN_METHOD(New); 32 | 33 | static NAN_METHOD(Start); 34 | static NAN_METHOD(StartTo); 35 | static NAN_METHOD(Stop); 36 | static NAN_METHOD(SetResourceless); 37 | static NAN_METHOD(GetParam); 38 | static NAN_METHOD(SetParam); 39 | static NAN_METHOD(GetEventsMask); 40 | static NAN_METHOD(SetEventsMask); 41 | static NAN_METHOD(RegisterArea); 42 | static NAN_METHOD(UnregisterArea); 43 | static NAN_METHOD(SetArea); 44 | static NAN_METHOD(GetArea); 45 | static NAN_METHOD(LockArea); 46 | static NAN_METHOD(UnlockArea); 47 | static NAN_METHOD(ServerStatus); 48 | static NAN_METHOD(ClientsCount); 49 | static NAN_METHOD(GetCpuStatus); 50 | static NAN_METHOD(SetCpuStatus); 51 | 52 | static NAN_METHOD(ErrorText); 53 | static NAN_METHOD(EventText); 54 | static NAN_METHOD(LastError); 55 | 56 | static int GetByteCountFromWordLen(int WordLen); 57 | 58 | #if NODE_VERSION_AT_LEAST(0, 11, 13) 59 | static void HandleEvent(uv_async_t* handle); 60 | #else 61 | static void HandleEvent(uv_async_t* handle, int status); 62 | #endif 63 | 64 | #if NODE_VERSION_AT_LEAST(0, 11, 13) 65 | static void HandleReadWriteEvent(uv_async_t* handle); 66 | #else 67 | static void HandleReadWriteEvent(uv_async_t* handle, int status); 68 | #endif 69 | 70 | static NAN_METHOD(RWBufferCallback); 71 | 72 | uv_mutex_t mutex; 73 | TS7Server *snap7Server; 74 | std::map > area2buffer; 75 | int lastError; 76 | Nan::AsyncResource async_resource; 77 | 78 | private: 79 | ~S7Server(); 80 | static Nan::Persistent constructor; 81 | }; 82 | 83 | class IOWorkerServer : public Nan::AsyncWorker { 84 | public: 85 | // No args 86 | IOWorkerServer(Nan::Callback *callback, S7Server *s7server, ServerIOFunction caller) 87 | : Nan::AsyncWorker(callback), s7server(s7server), caller(caller) {} 88 | // 1 args 89 | IOWorkerServer(Nan::Callback *callback, S7Server *s7server, ServerIOFunction caller 90 | , void *arg1) 91 | : Nan::AsyncWorker(callback), s7server(s7server), caller(caller) 92 | , pData(arg1) {} 93 | 94 | ~IOWorkerServer() {} 95 | 96 | private: 97 | void Execute(); 98 | void HandleOKCallback(); 99 | 100 | S7Server *s7server; 101 | ServerIOFunction caller; 102 | void *pData; 103 | int ret; 104 | }; 105 | 106 | } // namespace node_snap7 107 | 108 | #endif // SRC_NODE_SNAP7_SERVER_H_ 109 | --------------------------------------------------------------------------------