[
  {
    "path": ".github/workflows/test-and-release.yml",
    "content": "name: Test and Release\non: [push, pull_request, workflow_dispatch]\npermissions:\n  contents: read\njobs:\n  build:\n    strategy:\n      fail-fast: false\n      matrix:\n        os: [ubuntu-latest, macos-latest, windows-latest]\n        node: [16, 18, 20, 22, 24]\n        arch: [x86, x64]\n        exclude:\n          - { os: ubuntu-latest, arch: x86 }\n          - { os: macos-latest, arch: x86 }\n          - { os: windows-latest, arch: x86, node: 24 }\n    runs-on: ${{ matrix.os }}\n    name: ${{ matrix.os }} / Node ${{ matrix.node }} ${{ matrix.arch }}\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n        with:\n          submodules: recursive\n          fetch-depth: 2\n      # Force Python to 3.10 until prebuild updates to node-gyp 10\n      - name: Use Python 3.10\n        if: ${{ matrix.os != 'windows-latest' }}\n        uses: actions/setup-python@v4\n        with:\n          python-version: '3.10'\n      - name: Use node ${{ matrix.node }} ${{ matrix.arch }}\n        uses: actions/setup-node@v4\n        with:\n          node-version: ${{ matrix.node }}\n          architecture: ${{ matrix.arch }}\n      - name: Install\n        run: npm install\n      - name: Test\n        env:\n          PREBUILD_TOKEN: ${{ secrets.PREBUILD_TOKEN }}\n        run: npm test\n"
  },
  {
    "path": ".gitignore",
    "content": ".vscode/\nbuild/\nnode_modules/\ntest/"
  },
  {
    "path": ".npmignore",
    "content": "test/\n.travis.yml\nappveyor.yml\n.npmignore\n.gitignore\n"
  },
  {
    "path": "LICENSE",
    "content": "(The MIT License)\n\nCopyright (c) 2019 Mathias Küsel\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# node-snap7\n\n[![npm](https://img.shields.io/npm/v/node-snap7.svg?label=&logo=npm)](https://www.npmjs.com/package/node-snap7)\n[![Node version](https://img.shields.io/node/v/node-snap7.svg)](https://www.npmjs.com/package/node-snap7)\n[![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)\n[![npm](https://img.shields.io/npm/dm/node-snap7.svg?label=dl)](https://www.npmjs.com/package/node-snap7)\n\n**Current node-snap7 version:** 1.0.9\\\n**Current snap7 version:** 1.4.2\n\n**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).\\\nThe current S7Server implementation has some bugs, please use with caution.**\n\n## About\nThis 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)).\n\n## Installation\nInstall with:\n\n    npm install node-snap7\n\nnode-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.\n\nIf you don't want to use the `prebuild` for the platform you are installing on, specify the `--build-from-source` flag when you install.\n\nFor building from source you need the following requirements:\n\n - Windows:\n    - [Visual Studio 2013 Express or higher](https://www.visualstudio.com/de/vs/visual-studio-express/)\n    - [Python 2.7](https://www.python.org/downloads/release/python-2714/)\n - Linux:\n    - C++11 toolchain\n    - [Python 2.7](https://www.python.org/downloads/release/python-2714/)\n\n## Special thanks to\n- Davide Nardella for creating snap7\n\n## How to use\n### API\n- [Client](doc/client.md)\n- [Server](doc/server.md)\n\n### Client Example\n```javascript\nvar snap7 = require('node-snap7');\n\nvar s7client = new snap7.S7Client();\ns7client.ConnectTo('192.168.1.12', 0, 1, function(err) {\n    if(err)\n        return console.log(' >> Connection failed. Code #' + err + ' - ' + s7client.ErrorText(err));\n\n    // Read the first byte from PLC process outputs...\n    s7client.ABRead(0, 1, function(err, res) {\n        if(err)\n            return console.log(' >> ABRead failed. Code #' + err + ' - ' + s7client.ErrorText(err));\n\n        // ... and write it to stdout\n        console.log(res)\n    });\n});\n```\n\n### Server Example\n```javascript\nvar snap7 = require('node-snap7');\n\nvar s7server = new snap7.S7Server();\n\n// Set up event listener\ns7server.on(\"event\", function(event) {\n    console.log(s7server.EventText(event));\n});\n\n// Create a new Buffer and register it to the server as DB1\nvar db1 = new Buffer(100).fill('ÿ');\ns7server.RegisterArea(s7server.srvAreaDB, 1, db1);\n\n// Start the server\ns7server.StartTo('127.0.0.1');\n\n// Close the server after 20s in this example\nsetTimeout(function() {\n    s7server.Stop();\n    s7server.UnregisterArea(s7server.srvAreaDB, 1);\n}, 20000);\n```\n\nHave a look at the resourceless server example [here](doc/server.md#event-read-write).\n\n## License & copyright\nCopyright (c) 2019, Mathias Küsel\n\nnode-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.\n\nnode-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`).\n"
  },
  {
    "path": "binding.gyp",
    "content": "{\n    \"targets\": [{\n        \"target_name\": \"node_snap7\",\n        \"include_dirs\": [\n            \"<!(node -e \\\"require('nan')\\\")\",\n            \"./src\"\n        ],\n        \"sources\": [\n            \"./src/node_snap7.cpp\",\n            \"./src/node_snap7_client.cpp\",\n            \"./src/node_snap7_server.cpp\",\n            \"./src/snap7.cpp\"\n        ],\n        \"conditions\": [\n            [\"OS=='win'\", {\n                \"libraries\": [\"-lws2_32.lib\", \"-lwinmm.lib\"],\n                \"defines\": [\"_WINSOCK_DEPRECATED_NO_WARNINGS\", \"_HAS_EXCEPTIONS=0\"] # Make sure the STL doesn't try to use exceptions\n            }]\n        ],\n        \"dependencies\": [\n            \"snap7\"\n        ]\n    }, {\n        \"target_name\": \"snap7\",\n        \"type\": \"static_library\",\n        \"include_dirs\": [\n            \"./deps/snap7/src/sys\",\n            \"./deps/snap7/src/core\",\n            \"./deps/snap7/src/lib\"\n        ],\n        \"sources\": [\n            \"./deps/snap7/src/sys/snap_msgsock.cpp\",\n            \"./deps/snap7/src/sys/snap_sysutils.cpp\",\n            \"./deps/snap7/src/sys/snap_tcpsrvr.cpp\",\n            \"./deps/snap7/src/sys/snap_threads.cpp\",\n            \"./deps/snap7/src/core/s7_client.cpp\",\n            \"./deps/snap7/src/core/s7_isotcp.cpp\",\n            \"./deps/snap7/src/core/s7_partner.cpp\",\n            \"./deps/snap7/src/core/s7_peer.cpp\",\n            \"./deps/snap7/src/core/s7_server.cpp\",\n            \"./deps/snap7/src/core/s7_text.cpp\",\n            \"./deps/snap7/src/core/s7_micro_client.cpp\",\n            \"./deps/snap7/src/lib/snap7_libmain.cpp\"\n        ],\n        \"conditions\": [\n            [\"OS=='linux' or OS=='freebsd'\", {\n                \"cflags_cc\": [\"-fPIC\", \"-pedantic\", \"-fexceptions\"],\n                \"cflags_cc!\": [\"-fno-exceptions\"]\n            }],\n            [\"OS=='win'\", {\n                \"msvs_settings\": {\n                    \"VCCLCompilerTool\": {\n                        \"ExceptionHandling\": 1,\n                        \"AdditionalOptions\": [\"/EHsc\"] # ExceptionHandling=1 is not enough for some versions\n                    }\n                },\n                \"defines!\": [\"_HAS_EXCEPTIONS=0\"],\n                \"defines\": [\"_WINSOCK_DEPRECATED_NO_WARNINGS\"]\n            }],\n            [\"OS=='mac'\", {\n                \"xcode_settings\": {\n                    \"GCC_ENABLE_CPP_EXCEPTIONS\": \"YES\",\n                    \"GCC_DYNAMIC_NO_PIC\": \"NO\",\n                    \"OTHER_CFLAGS\": [\"-pedantic\"]\n                }\n            }]\n        ]\n    }],\n    'variables' : {\n        'openssl_fips': '',\n    }\n}\n"
  },
  {
    "path": "deps/snap7/HISTORY.txt",
    "content": "======================================================================[2015-06-14]\nVersion 1.4.0 - release for gourmets (fully compatible with 1.0.0)\n----------------------------------------------------------------------------------\n\n- Resourceless Server\n- Utility added\n- Improved .NET wrapper\n- New .NET Demos\n- Solution also for .NET Console demos\n- Small bugfix\n\n[Added]\n\n- Resourceless server\n  Now Snap7Server can work in \"resourceless\" mode, i.e. you dont need to share \n  resources (DB, E, A) with it : On every read/write request a callback is \n  called passing it the TAG (Type of memory E,A,DB..,DB number if any, Start, \n  Size, WordLen), and a pointer to the internal server area to read/write your \n  data on demand.\n\n  The 1.4.0 wrappers were updated to reflect this new mode and I wrote some \n  examples on how to use this feature, that however is very simple.\n  Purpose:\n  - Protocol converters.\n  - HMI Analyzers.\n  - Flow Splitters/Routers.\n\n- Utility \n  There is a new folder that contains some interesting (I hope) utilities.\n  They are demo programs with a \"real purpose\".\n  The first is HMITracer, a program that shows how use the new resourceless\n  server. It simulates a PLC and lists all Tags referenced by an external HMI.\n  A detailed PDF report is generated also.\n\n[Improved]\n\n- Improved .NET wrapper \n  Now the S7 Helper class can convert *ALL* S7 types, including the new \n  S71200/1500 64 bit   types : \n  - 8, 16, 32, 64 bit signed and unsigned values.\n  - Long real (64 bit)\n  - Long Date/Time, Long Time of Day\n\n- Added the class S7MultiVars which greatly simplifies the reading and writing of\n  MultiVars.\n\n- New .NET Demos\n  Added WinForm Server Demo and MultiRead vars Demo.\n  Added 64 platform for all demos\n  Added the compilation of Snap7.net.cs for VB demos.\n\n- Solution also for .NET Console demos\n  A VS2013 solution for .NET console demos was added.\n  you no longer need the of the batch file to build the demos.\n\n- Reduced the memory footprint of Snap7Server (there was an unused memory block).\n\n[Fixed]\n\n- (Only Windows) If an attacker gains control of the application directory, he \n  could force the application to load a malicious copy of iphlpapi.dll (which \n  is used for ping).\n  Now iphlpapi.dll is loaded from the Windows system directory.\n  Thanks to the Security engineer Alexandre CHERON for reporting it.\n\n\n======================================================================[2015-01-01]\nVersion 1.3.0 - Platform / Comfort release (fully compatible with 1.0.0)\n----------------------------------------------------------------------------------\n\nPlatform\n- Runtime Big-Endian architecture support. No compilers swithes are needed.\n- Sun Sparc and Mips BE architectures are now supported.\n- Arduino YUN\n\nComfort\n- Added WinForm.net demos (C# and VB)\n- Improved documentation (added .NET chapter for beginners *please read it*)\n  Added also a chapter about Siemens data format.\n- Added Helper class/functions\n\n==================================================================================\n[Added]\n\n\n- Helper class/function to insert/extract S7 typed vars from a byte[] buffer. \n  You will find them into the wrappers (.net/Pascal/C++)\n- Solaris Sparc support\n  (Thanks to Rolf Stalder for makefiles)\n- Arduino YUN support\n  (Thanks to Fulvio Bosco and Stefano Bonnin)\n- .Net Winform small demos\n- .Net solution for rebuilding snap7.net.cs\n\n\n[Improved]\n\n- Unix, now the client doesn't need root priviledges to perform the SmartConnect.\n  (Thanks to Rolf Stalder)\n- Solaris now uses standard pthreads.\n  (Thanks to Rolf Stalder)\n- Read/WriteMultiVars now checks in advance if the data fits into the PDU size.\n- .net S7Client.ReadMultivars (and Write) was improved.\n  (Thanks to LanceL who made it)\n- S7Client now checks if it's connected before do anything.\n  (Thanks to Mathias Ksel for reporting it)\n\n\n[Latest OS]\n\n- Tested with Ubuntu 14.10 (32/64)\n- Tested with Windows 10 Technical Preview (32/64)\n\n\n[fixed]\n\n- Fixed some Typo errors into snap7.net.cs\n- Fixed a small bug into Read/WriteMultiVars\n\n\n======================================================================[2014-04-17]\nVersion 1.2.1 - Bugfix/Small changes release (fully compatible with 1.0.0)\n----------------------------------------------------------------------------------\n- Some small Apple Mac OSX changes (Tested under OSX 10.9.1 Mavericks)\n- Some bug fixed\n- Documentation updated.\n\n- Some OLD/RARELY USED libraries are not longer deployed.\n  but *THEY ARE STILL TESTED AND SUPPORTED*\n\n  If you don't have the way to rebuild Snap7 in these platforms please contact me \n  and I will try to help you.\n\n  They are :\n  - Linux i386/x86_64 GLIBC 2.11 up to 2.15  \n  - Linux ARMHF BeagleBone Black, CubieBoard 2, PcDuino.\n\n- A new Linux distro is supported (Ubuntu 14.04 LTS and derivatives GLIBC 2.19)\n\n- Old Windows Platforms are still fully supported but you will find them into\n  \\release\\windows\\Legacy\\Win32 and Win64.\n\n  This because many people had problems with .NET environment (which doesn't like\n  non-Microsoft Libraries on some platforms), so the official Windows libraries are\n  now compiled with Visual Studio.\n\n  If you plan to use MinGW64, use Legacy libraries (wich work fine up to Windows 8).\n\n==================================================================================\n\n[Changed]\n\n- Unix, now it's possible to specify the destination folder of the library using the\n  optional param LibInstall=<NewPath> into the make command line. If not specified\n  the default path is /usr/lib.\n  (thanks to Gijs Molenaar)\n\n- Apple OSX, now the library suffix is .dylib instead of .so\n  however it's possible override the suffix using the LibExt param (see doc.)\n  (thanks to Gijs Molenaar)\n\n[fixed]\n\n- Fixed a typo error into snap7.net.cs (Cli_GetPlcStatus)\n  (Thanks to Dabbadoeber for reporting)\n\n- Fixed a bug into s7_micro_client.cpp into block download function.\n  (Thanks to Mark Konst for reporting)\n\n- fixed a bug into s7_partner.cpp (issues for transfers>PDU size)\n  (Thanks to Volker Sarnes)\n\n- fixed a bug into s7_server.cpp (wrong bit access)\n  (Thanks to Thomas Costa)\n\n- little modification to client.cs and ppartner.cs to be compiled with VS2008 which\n  doesn't handle the constant (default) parameter in a method declaration.\n  (thanks to Max Schaetzel for reporting) \n\n\n======================================================================[2014-01-01]\nVersion 1.2.0 - New Minor platform release (fully compatible with 1.0.0)\n----------------------------------------------------------------------------------\n- Apple Mac OSX support (Tested under OSX 10.9.1 Mavericks)\n- Some bug fixed\n- Documentation improved and updated.\n==================================================================================\n\n[Added]\n\n- Apple OSX full support :\n  makefiles, source examples, binary library and binary demos supplied.\n  new osx folders added in the entire project. \n\n[fixed]\n\n- S7API directive missing for two functions in snap7_libmain.h\n  (Thanks to Mathias Ksel for reporting)\n\n- fixed Snap7.S7Server.Srv_RegisterArea in snap7.net.cs\n  (Thanks to Andr for reporting).\n\n- Added a static var to contain the callback addresses into c# examples.\n  The .net garbage collector *sometime* garbages the delegates (called by unmanaged\n  code) if their address is not stored into a static var.\n  MS says that it's not a clr bug (maybe a feature ????)\n  However this solves the problem.\n  PLEASE SEE THE .NET EXAMPLES IF YOU PLAN TO USE SNAP7 (or other unmanaged)\n  CALLBACKS.\n  (Thanks to Martin Bratt for reporting).\n\n- Srv_SetReadEventsCallback prototype missing in Snap7.pas\n\n\n======================================================================[2013-11-10]\nVersion 1.1.0 - New Minor hardware release (fully compatible with 1.0.0)\n----------------------------------------------------------------------------------\n- LOGO 0BA7 Ethernet support (as client/server and Network I/O blocks)\n- S7200 (via CP243) experimental support\n- New Callback for S7Server that allow writing full synchronous gateways (protocol\n  translators)\n- New rich-demos\n- Some bug fixed\n- Documentation improved and updated.\n==================================================================================\n\n[Added]\n\n- Cli_GetConnected function added.\n  It returns the connection status of the client.\n\n- Cli_SetConnectionType function added.\n  For a Client it's possible to connect to a PLC as PG/OP/S7 Basic.\n\n- Cli_SetConnectionParams function added.\n  For a Client now it's possible to specifying Local and Remote TSAP before the\n  connection.\n  Needed for LOGO, S7200 and future hardware compatible with S7Protocol.\n\n- Srv_SetReadEventsCallback function added.\n  It allows to trap the read event from a client *before* the data getting.\n\n- New ClientDemo and ServerDemo for the latter functions were supplied.\n\n- LOGO examples were supplied.\n\n- New rich-demos for Cubieboard 2 (under Cubian OS)\n\n- Glibc_2.11 for Linux x86_64 Release\n\n- Full documentation updated.\n\n[Fixed]\n\n- Expression bug in line 491 of /examples/pascal/client.dpr\n  \"if ParamCount=4\" must be \"if ParamCount=3\"\n  (thanks to Jean-Noel Voirol)\n\n- Bug in S7Worker (Snap7Server) that returned \"Data mismatch\" error in MultiWrite\n  function when writing ODD amount of bytes in items with index>1\n\n- Bug in TSAP calculation in S7Client connection that sent wrong connection\n  telegram to S7400 when the CPU was in Rack>1\n  (thanks to hujingqi for the detailed analysis)\n\n\n======================================================================[2013-09-03]\nVersion 1.0.0 \n==================================================================================\n\n- First public release.\n\n==================================================================================\n\n\n\n\n"
  },
  {
    "path": "deps/snap7/gpl.txt",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<http://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<http://www.gnu.org/philosophy/why-not-lgpl.html>.\n"
  },
  {
    "path": "deps/snap7/lgpl-3.0.txt",
    "content": "                   GNU LESSER GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n\n  This version of the GNU Lesser General Public License incorporates\nthe terms and conditions of version 3 of the GNU General Public\nLicense, supplemented by the additional permissions listed below.\n\n  0. Additional Definitions.\n\n  As used herein, \"this License\" refers to version 3 of the GNU Lesser\nGeneral Public License, and the \"GNU GPL\" refers to version 3 of the GNU\nGeneral Public License.\n\n  \"The Library\" refers to a covered work governed by this License,\nother than an Application or a Combined Work as defined below.\n\n  An \"Application\" is any work that makes use of an interface provided\nby the Library, but which is not otherwise based on the Library.\nDefining a subclass of a class defined by the Library is deemed a mode\nof using an interface provided by the Library.\n\n  A \"Combined Work\" is a work produced by combining or linking an\nApplication with the Library.  The particular version of the Library\nwith which the Combined Work was made is also called the \"Linked\nVersion\".\n\n  The \"Minimal Corresponding Source\" for a Combined Work means the\nCorresponding Source for the Combined Work, excluding any source code\nfor portions of the Combined Work that, considered in isolation, are\nbased on the Application, and not on the Linked Version.\n\n  The \"Corresponding Application Code\" for a Combined Work means the\nobject code and/or source code for the Application, including any data\nand utility programs needed for reproducing the Combined Work from the\nApplication, but excluding the System Libraries of the Combined Work.\n\n  1. Exception to Section 3 of the GNU GPL.\n\n  You may convey a covered work under sections 3 and 4 of this License\nwithout being bound by section 3 of the GNU GPL.\n\n  2. Conveying Modified Versions.\n\n  If you modify a copy of the Library, and, in your modifications, a\nfacility refers to a function or data to be supplied by an Application\nthat uses the facility (other than as an argument passed when the\nfacility is invoked), then you may convey a copy of the modified\nversion:\n\n   a) under this License, provided that you make a good faith effort to\n   ensure that, in the event an Application does not supply the\n   function or data, the facility still operates, and performs\n   whatever part of its purpose remains meaningful, or\n\n   b) under the GNU GPL, with none of the additional permissions of\n   this License applicable to that copy.\n\n  3. Object Code Incorporating Material from Library Header Files.\n\n  The object code form of an Application may incorporate material from\na header file that is part of the Library.  You may convey such object\ncode under terms of your choice, provided that, if the incorporated\nmaterial is not limited to numerical parameters, data structure\nlayouts and accessors, or small macros, inline functions and templates\n(ten or fewer lines in length), you do both of the following:\n\n   a) Give prominent notice with each copy of the object code that the\n   Library is used in it and that the Library and its use are\n   covered by this License.\n\n   b) Accompany the object code with a copy of the GNU GPL and this license\n   document.\n\n  4. Combined Works.\n\n  You may convey a Combined Work under terms of your choice that,\ntaken together, effectively do not restrict modification of the\nportions of the Library contained in the Combined Work and reverse\nengineering for debugging such modifications, if you also do each of\nthe following:\n\n   a) Give prominent notice with each copy of the Combined Work that\n   the Library is used in it and that the Library and its use are\n   covered by this License.\n\n   b) Accompany the Combined Work with a copy of the GNU GPL and this license\n   document.\n\n   c) For a Combined Work that displays copyright notices during\n   execution, include the copyright notice for the Library among\n   these notices, as well as a reference directing the user to the\n   copies of the GNU GPL and this license document.\n\n   d) Do one of the following:\n\n       0) Convey the Minimal Corresponding Source under the terms of this\n       License, and the Corresponding Application Code in a form\n       suitable for, and under terms that permit, the user to\n       recombine or relink the Application with a modified version of\n       the Linked Version to produce a modified Combined Work, in the\n       manner specified by section 6 of the GNU GPL for conveying\n       Corresponding Source.\n\n       1) Use a suitable shared library mechanism for linking with the\n       Library.  A suitable mechanism is one that (a) uses at run time\n       a copy of the Library already present on the user's computer\n       system, and (b) will operate properly with a modified version\n       of the Library that is interface-compatible with the Linked\n       Version.\n\n   e) Provide Installation Information, but only if you would otherwise\n   be required to provide such information under section 6 of the\n   GNU GPL, and only to the extent that such information is\n   necessary to install and execute a modified version of the\n   Combined Work produced by recombining or relinking the\n   Application with a modified version of the Linked Version. (If\n   you use option 4d0, the Installation Information must accompany\n   the Minimal Corresponding Source and Corresponding Application\n   Code. If you use option 4d1, you must provide the Installation\n   Information in the manner specified by section 6 of the GNU GPL\n   for conveying Corresponding Source.)\n\n  5. Combined Libraries.\n\n  You may place library facilities that are a work based on the\nLibrary side by side in a single library together with other library\nfacilities that are not Applications and are not covered by this\nLicense, and convey such a combined library under terms of your\nchoice, if you do both of the following:\n\n   a) Accompany the combined library with a copy of the same work based\n   on the Library, uncombined with any other library facilities,\n   conveyed under the terms of this License.\n\n   b) Give prominent notice with the combined library that part of it\n   is a work based on the Library, and explaining where to find the\n   accompanying uncombined form of the same work.\n\n  6. Revised Versions of the GNU Lesser General Public License.\n\n  The Free Software Foundation may publish revised and/or new versions\nof the GNU Lesser General Public License from time to time. Such new\nversions will be similar in spirit to the present version, but may\ndiffer in detail to address new problems or concerns.\n\n  Each version is given a distinguishing version number. If the\nLibrary as you received it specifies that a certain numbered version\nof the GNU Lesser General Public License \"or any later version\"\napplies to it, you have the option of following the terms and\nconditions either of that published version or of any later version\npublished by the Free Software Foundation. If the Library as you\nreceived it does not specify a version number of the GNU Lesser\nGeneral Public License, you may choose any version of the GNU Lesser\nGeneral Public License ever published by the Free Software Foundation.\n\n  If the Library as you received it specifies that a proxy can decide\nwhether future versions of the GNU Lesser General Public License shall\napply, that proxy's public statement of acceptance of any version is\npermanent authorization for you to choose that version for the\nLibrary.\n"
  },
  {
    "path": "deps/snap7/src/core/s7_client.cpp",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.3.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|=============================================================================*/\n#include \"s7_client.h\"\n\n//---------------------------------------------------------------------------\nTSnap7Client::TSnap7Client()\n{\n     FThread = 0;\n     CliCompletion = 0;\n\t EvtJob = NULL;\n     EvtComplete = NULL;\n\t FThread=NULL;\n\t ThreadCreated = false;\n}\n//---------------------------------------------------------------------------\nTSnap7Client::~TSnap7Client()\n{\n    Destroying=true;\n    Disconnect();\n    CliCompletion=NULL;\n\tif (ThreadCreated)\n\t{\n\t    CloseThread();\n\t    delete EvtComplete;\n\t    delete EvtJob;\n\t\tThreadCreated=false;\n\t}\n}\n//---------------------------------------------------------------------------\nvoid TSnap7Client::CloseThread()\n{\n     int Timeout;\n\n     if (FThread)\n     {\n          FThread->Terminate();\n          if (Job.Pending)\n              Timeout=3000;\n          else\n              Timeout=1000;\n          EvtJob->Set();\n\t\t  if (FThread->WaitFor(Timeout)!=WAIT_OBJECT_0)\n              FThread->Kill();\n          try {\n             delete FThread;\n          }\n          catch (...){\n          }\n\n          FThread=0;\n     }\n}\n//---------------------------------------------------------------------------\nvoid TSnap7Client::OpenThread()\n{\n    FThread = new TClientThread(this);\n    FThread->Start();\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::Reset(bool DoReconnect)\n{\n    bool WasConnected = Connected;\n    if (ThreadCreated)\n\t{\n\t\tCloseThread();\n\t\tDisconnect();\n\t\tOpenThread();\n\t}\n\telse\n\t\tDisconnect();\n\t\n\tif (DoReconnect || WasConnected)\n       return Connect();\n    else\n       return 0;\n}\n//---------------------------------------------------------------------------\nvoid TSnap7Client::DoCompletion()\n{\n    if ((CliCompletion!=NULL) && !Destroying)\n    {\n      try{\n          CliCompletion(FUsrPtr, Job.Op, Job.Result);\n      }catch (...)\n\t  {\n      }\n    }\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::SetAsCallback(pfn_CliCompletion pCompletion, void * usrPtr)\n{\n    CliCompletion=pCompletion;\n    FUsrPtr=usrPtr;\n    return 0;\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::GetParam(int ParamNumber, void * pValue)\n{\n    // Actually there are no specific client params, maybe in future...\n\treturn TSnap7MicroClient::GetParam(ParamNumber, pValue);\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::SetParam(int ParamNumber, void * pValue)\n{\n    // Actually there are no specific client params, maybe in future...\n\treturn TSnap7MicroClient::SetParam(ParamNumber, pValue);\n}\n//---------------------------------------------------------------------------\nbool TSnap7Client::CheckAsCompletion(int &opResult)\n{\n    if (!Job.Pending)\n        opResult=Job.Result;\n    else\n        if (!Destroying)\n            opResult=errCliJobPending; // don't set LastError here\n        else\n        {\n            opResult=errCliDestroying;\n            return true;\n        }\n\n    return !Job.Pending;\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::AsReadArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void * pUsrData)\n{\n     if (!Job.Pending)\n     {\n          Job.Pending  = true;\n          Job.Op       = s7opReadArea;\n          Job.Area     = Area;\n          Job.Number   = DBNumber;\n          Job.Start    = Start;\n          Job.Amount   = Amount;\n          Job.WordLen  = WordLen;\n          Job.pData    = pUsrData;\n          JobStart     = SysGetTick();\n          StartAsyncJob();\n          return 0;\n     }\n     else\n          return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::AsWriteArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void * pUsrData)\n{\n    int ByteSize, TotalSize;\n\n    if (!Job.Pending)\n    {\n        Job.Pending =true;\n        Job.Op      =s7opWriteArea;\n        Job.Area    =Area;\n        Job.Number  =DBNumber;\n        Job.Start   =Start;\n        // Performs some check first to copy the data\n        ByteSize=DataSizeByte(WordLen);\n        TotalSize=ByteSize*Amount; // Total size in bytes\n        if (ByteSize==0)\n            return SetError(errCliInvalidWordLen);\n        if ((TotalSize < 1) || (TotalSize > int(sizeof(opData))))\n            return SetError(errCliInvalidParams);\n        Job.Amount  =Amount;\n        Job.WordLen =WordLen;\n        // Doublebuffering\n        memcpy(&opData, pUsrData, TotalSize);\n        Job.pData =&opData;\n        JobStart  =SysGetTick();\n        StartAsyncJob();\n        return 0;\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::AsListBlocksOfType(int BlockType, PS7BlocksOfType pUsrData, int & ItemsCount)\n{\n    if (!Job.Pending)\n    {\n        Job.Pending  =true;\n        Job.Op       =s7opListBlocksOfType;\n        Job.Area     =BlockType;\n        Job.pData    =pUsrData;\n        Job.pAmount  =&ItemsCount;\n        JobStart     =SysGetTick();\n        StartAsyncJob();\n        return 0;\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::AsReadSZL(int ID, int Index, PS7SZL pUsrData, int & Size)\n{\n    if (!Job.Pending)\n    {\n        Job.Pending  =true;\n        Job.Op       =s7opReadSZL;\n        Job.ID       =ID;\n        Job.Index    =Index;\n        Job.pData    =pUsrData;\n        Job.pAmount  =&Size;\n        Job.Amount   =Size;\n        Job.IParam   =1; // Data has to be copied into user buffer\n        JobStart     =SysGetTick();\n        StartAsyncJob();\n        return 0;\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::AsReadSZLList(PS7SZLList pUsrData, int &ItemsCount)\n{\n    if (!Job.Pending)\n    {\n        Job.Pending  =true;\n        Job.Op       =s7opReadSzlList;\n        Job.pData    =pUsrData;\n        Job.pAmount  =&ItemsCount;\n        Job.Amount   =ItemsCount;\n        JobStart     =SysGetTick();\n        StartAsyncJob();\n        return 0;\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::AsUpload(int BlockType, int BlockNum, void * pUsrData, int & Size)\n{\n    if (!Job.Pending)\n     {\n        Job.Pending  =true;\n        Job.Op       =s7opUpload;\n        Job.Area     =BlockType;\n        Job.pData    =pUsrData;\n        Job.pAmount  =&Size;\n        Job.Amount   =Size;\n        Job.Number   =BlockNum;\n        Job.IParam   =0; // not full upload, only data\n        JobStart     =SysGetTick();\n        StartAsyncJob();\n        return 0;\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::AsFullUpload(int BlockType, int BlockNum, void * pUsrData, int & Size)\n{\n    if (!Job.Pending)\n    {\n        Job.Pending  =true;\n        Job.Op       =s7opUpload;\n        Job.Area     =BlockType;\n        Job.pData    =pUsrData;\n        Job.pAmount  =&Size;\n        Job.Amount   =Size;\n        Job.Number   =BlockNum;\n        Job.IParam   =1; // full upload\n        JobStart     =SysGetTick();\n        StartAsyncJob();\n        return 0;\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::AsDownload(int BlockNum, void * pUsrData, int Size)\n{\n    if (!Job.Pending)\n    {\n        // Checks the size : here we only need a size>0 to avoid problems during\n        // doublebuffering, the real test of the block size will be done in\n        // Checkblock.\n        if (Size<1)\n            return SetError(errCliInvalidBlockSize);\n        Job.Pending  =true;\n        Job.Op       =s7opDownload;\n        // Doublebuffering\n        memcpy(&opData, pUsrData, Size);\n        Job.Number   =BlockNum;\n        Job.Amount   =Size;\n        JobStart     =SysGetTick();\n        StartAsyncJob();\n        return 0;\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::AsCopyRamToRom(int Timeout)\n{\n    if (!Job.Pending)\n    {\n        Job.Pending  =true;\n        Job.Op       =s7opCopyRamToRom;\n        if (Timeout>0)\n        {\n          Job.IParam   =Timeout;\n          JobStart     =SysGetTick();\n          StartAsyncJob();\n          return 0;\n        }\n        else\n            return SetError(errCliInvalidParams);\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::AsCompress(int Timeout)\n{\n    if (!Job.Pending)\n    {\n        Job.Pending  =true;\n        Job.Op       =s7opCompress;\n        if (Timeout>0)\n        {\n            Job.IParam   =Timeout;\n            JobStart     =SysGetTick();\n            StartAsyncJob();\n            return 0;\n        }\n        else\n            return SetError(errCliInvalidParams);\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::AsDBRead(int DBNumber, int Start, int Size, void * pUsrData)\n{\n    return AsReadArea(S7AreaDB, DBNumber, Start, Size, S7WLByte, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::AsDBWrite(int DBNumber, int Start, int Size, void * pUsrData)\n{\n    return AsWriteArea(S7AreaDB, DBNumber, Start, Size, S7WLByte, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::AsMBRead(int Start, int Size, void * pUsrData)\n{\n    return AsReadArea(S7AreaMK, 0, Start, Size, S7WLByte, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::AsMBWrite(int Start, int Size, void * pUsrData)\n{\n    return AsWriteArea(S7AreaMK, 0, Start, Size, S7WLByte, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::AsEBRead(int Start, int Size, void * pUsrData)\n{\n    return AsReadArea(S7AreaPE, 0, Start, Size, S7WLByte, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::AsEBWrite(int Start, int Size, void * pUsrData)\n{\n    return AsWriteArea(S7AreaPE, 0, Start, Size, S7WLByte, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::AsABRead(int Start, int Size, void * pUsrData)\n{\n    return AsReadArea(S7AreaPA, 0, Start, Size, S7WLByte, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::AsABWrite(int Start, int Size, void * pUsrData)\n{\n    return AsWriteArea(S7AreaPA, 0, Start, Size, S7WLByte, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::AsTMRead(int Start, int Amount, void * pUsrData)\n{\n    return AsReadArea(S7AreaTM, 0, Start, Amount, S7WLTimer, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::AsTMWrite(int Start, int Amount, void * pUsrData)\n{\n    return AsWriteArea(S7AreaTM, 0, Start, Amount, S7WLTimer, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::AsCTRead(int Start, int Amount, void * pUsrData)\n{\n    return AsReadArea(S7AreaCT, 0, Start, Amount, S7WLCounter, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::AsCTWrite(int Start, int Amount, void * pUsrData)\n{\n    return AsWriteArea(S7AreaCT, 0, Start, Amount, S7WLCounter, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::AsDBGet(int DBNumber, void * pUsrData, int &Size)\n{\n    if (!Job.Pending)\n    {\n        if (Size<=0)\n            return SetError(errCliInvalidBlockSize);\n        Job.Pending  =true;\n        Job.Op       =s7opDBGet;\n        Job.Number   =DBNumber;\n        Job.pData    =pUsrData;\n        Job.pAmount  =&Size;\n        Job.Amount   =Size;\n        JobStart     =SysGetTick();\n        StartAsyncJob();\n        return 0;\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::AsDBFill(int DBNumber, int FillChar)\n{\n    if (!Job.Pending)\n    {\n        Job.Pending  =true;\n        Job.Op       =s7opDBFill;\n        Job.Number   =DBNumber;\n        Job.IParam   =FillChar;\n        JobStart     =SysGetTick();\n        StartAsyncJob();\n        return 0;\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nvoid TSnap7Client::StartAsyncJob()\n{\n    ClrError();\n\tif (!ThreadCreated)\n\t{\n\t\tEvtJob =  new TSnapEvent(false);\n\t\tEvtComplete = new TSnapEvent(false);\n\t    OpenThread();\n\t\tThreadCreated=true;\n\t}\n\tEvtComplete->Reset(); // reset if previously was not called WaitAsCompletion\n    EvtJob->Set();\n}\n//---------------------------------------------------------------------------\nint TSnap7Client::WaitAsCompletion(unsigned long Timeout)\n{\n    if (Job.Pending)\n    {\n        if (ThreadCreated)\n\t\t{\n\t\t\tif (EvtComplete->WaitFor(Timeout)==WAIT_OBJECT_0)\n\t\t\t\treturn Job.Result;\n\t\t\telse\n\t\t\t{  \n\t\t\t\tif (Destroying)\n\t\t\t\t\treturn errCliDestroying;\n\t\t\t\telse\n\t\t\t\t\treturn SetError(errCliJobTimeout);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t\treturn SetError(errCliJobTimeout);\n    }\n    else\n        return Job.Result;\n}\n//---------------------------------------------------------------------------\nvoid TClientThread::Execute()\n{\n     while (!Terminated)\n     {\n          FClient->EvtJob->WaitForever();\n          if (!Terminated)\n          {\n               FClient->PerformOperation();\n               FClient->EvtComplete->Set();\n               // Notify the caller the end of job (if callback is set)\n               FClient->DoCompletion();\n          }\n     };\n}\n\n"
  },
  {
    "path": "deps/snap7/src/core/s7_client.h",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.3.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|=============================================================================*/\n#ifndef s7_client_h\n#define s7_client_h\n//---------------------------------------------------------------------------\n#include \"snap_threads.h\"\n#include \"s7_micro_client.h\"\n//---------------------------------------------------------------------------\n\nextern \"C\" {\ntypedef void (S7API *pfn_CliCompletion) (void * usrPtr, int opCode, int opResult);\n}\nclass TSnap7Client;\n\nclass TClientThread: public TSnapThread\n{\nprivate:\n\tTSnap7Client * FClient;\npublic:\n     TClientThread(TSnap7Client *Client)\n     {\n           FClient = Client;\n     }\n\tvoid Execute();\n};\n//---------------------------------------------------------------------------\nclass TSnap7Client: public TSnap7MicroClient\n{\nprivate:\n    TClientThread *FThread;\n\tbool ThreadCreated;\n    void CloseThread();\n    void OpenThread();\n    void StartAsyncJob();\nprotected:\n    PSnapEvent EvtJob;\n    PSnapEvent EvtComplete;\n    pfn_CliCompletion CliCompletion;\n    void *FUsrPtr;\n    void DoCompletion();\npublic:\n    friend class TClientThread;\n    TSnap7Client();\n    ~TSnap7Client();\n    int Reset(bool DoReconnect);\n    int SetAsCallback(pfn_CliCompletion pCompletion, void * usrPtr);\n    int GetParam(int ParamNumber, void *pValue);\n    int SetParam(int ParamNumber, void *pValue);\n    // Async functions\n    bool CheckAsCompletion( int & opResult);\n    int WaitAsCompletion(unsigned long Timeout);\n    int AsReadArea(int Area, int DBNumber, int Start, int Amount, int WordLen,  void * pUsrData);\n    int AsWriteArea(int Area, int DBNumber, int Start, int Amount, int WordLen,  void * pUsrData);\n    int AsListBlocksOfType(int BlockType,  PS7BlocksOfType pUsrData,   int & ItemsCount);\n    int AsReadSZL(int ID, int Index,  PS7SZL pUsrData, int & Size);\n    int AsReadSZLList(PS7SZLList pUsrData, int &ItemsCount);\n    int AsUpload(int BlockType, int BlockNum,  void * pUsrData,   int & Size);\n    int AsFullUpload(int BlockType, int BlockNum,  void * pUsrData,   int & Size);\n    int AsDownload(int BlockNum,  void * pUsrData,  int Size);\n    int AsCopyRamToRom(int Timeout);\n    int AsCompress(int Timeout);\n    int AsDBRead(int DBNumber, int Start, int Size,  void * pUsrData);\n    int AsDBWrite(int DBNumber, int Start, int Size,  void * pUsrData);\n    int AsMBRead(int Start, int Size, void * pUsrData);\n    int AsMBWrite(int Start, int Size, void * pUsrData);\n    int AsEBRead(int Start, int Size, void * pUsrData);\n    int AsEBWrite(int Start, int Size, void * pUsrData);\n    int AsABRead(int Start, int Size, void * pUsrData);\n    int AsABWrite(int Start, int Size, void * pUsrData);\n    int AsTMRead(int Start, int Amount, void * pUsrData);\n    int AsTMWrite(int Start, int Amount, void * pUsrData);\n    int AsCTRead(int Start, int Amount, void * pUsrData);\n    int AsCTWrite(int Start, int Amount, void * pUsrData);\n    int AsDBGet(int DBNumber,  void * pUsrData,   int & Size);\n    int AsDBFill(int DBNumber,  int FillChar);\n};\n\ntypedef TSnap7Client *PSnap7Client;\n\n//---------------------------------------------------------------------------\n#endif // s7_client_h\n"
  },
  {
    "path": "deps/snap7/src/core/s7_firmware.h",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.3.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|=============================================================================*/\n#ifndef s7_firmware_h\n#define s7_firmware_h\n//---------------------------------------------------------------------------\n\n#include \"snap_platform.h\"\n\n//******************************************************************************\n// CPU DATABANK\n//******************************************************************************\n\n  byte SZLNotAvail[4] = {\n    0x0A,0x00,0x00,0x00\n  };\n\n  byte SZLSysState[6] = {\n    0xFF,0x09,0x00,0x02,0x02,0x00\n  };\n\n  byte SZL_ID_0000_IDX_XXXX[236] = {\n    0xFF,0x09,0x00,0xE8,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x70,0x00,0x00,0x0F,0x00,0x00,0x02,0x00,\n    0x11,0x01,0x11,0x0F,0x11,0x00,0x12,0x01,0x12,0x0F,0x12,0x00,0x13,0x01,0x13,0x00,0x14,0x0F,0x14,\n    0x00,0x15,0x01,0x15,0x00,0x17,0x01,0x17,0x0F,0x17,0x00,0x18,0x01,0x18,0x0F,0x18,0x00,0x19,0x0F,\n    0x19,0x00,0x1A,0x0F,0x1A,0x00,0x1B,0x0F,0x1B,0x00,0x1C,0x01,0x1C,0x0F,0x1C,0x00,0x21,0x0A,0x21,\n    0x0F,0x21,0x02,0x22,0x00,0x23,0x0F,0x23,0x00,0x24,0x01,0x24,0x04,0x24,0x05,0x24,0x00,0x25,0x01,\n    0x25,0x02,0x25,0x0F,0x25,0x01,0x31,0x01,0x32,0x02,0x32,0x00,0x36,0x01,0x36,0x0F,0x36,0x00,0x37,\n    0x01,0x37,0x0F,0x37,0x00,0x38,0x01,0x38,0x02,0x38,0x0F,0x38,0x01,0x39,0x00,0x3A,0x0F,0x3A,0x00,\n    0x74,0x01,0x74,0x0F,0x74,0x05,0x91,0x0A,0x91,0x0C,0x91,0x0D,0x91,0x00,0x92,0x02,0x92,0x06,0x92,\n    0x0F,0x92,0x00,0x94,0x01,0x94,0x02,0x94,0x06,0x94,0x07,0x94,0x0F,0x94,0x00,0x95,0x01,0x95,0x0F,\n    0x95,0x06,0x96,0x0C,0x96,0x0C,0x97,0x0D,0x97,0x01,0x9A,0x02,0x9A,0x0F,0x9A,0x0C,0x9B,0x00,0x9C,\n    0x01,0x9C,0x02,0x9C,0x03,0x9C,0x0F,0x9C,0x00,0xA0,0x01,0xA0,0x0F,0xA0,0x00,0xB1,0x00,0xB2,0x00,\n    0xB3,0x00,0xB4,0x01,0xB5,0x02,0xB5,0x03,0xB5,0x04,0xB5,0x05,0xB5,0x06,0xB5,0x07,0xB5,0x08,0xB5,\n    0x01,0xB6,0x02,0xB6,0x03,0xB6,0x04,0xB6\n  };\n\n  byte SZL_ID_0F00_IDX_XXXX[12] = {\n    0xFF,0x09,0x00,0x08,0x0F,0x00,0x00,0x00,0x00,0x02,0x00,0x70\n  };\n\n  byte SZL_ID_0002_IDX_XXXX[458] = {  // <--Wrapped to 458 bytes\n    0xFF,0x09,0x01,0xC6,0x00,0x02,0x00,0x00,0x00,0x08,0x00,0x71,0x01,0xAC,0x00,0x01,0x00,0x28,0x00,\n    0x1C,0x01,0xAC,0x24,0x00,0x00,0x24,0x00,0x00,0x01,0xAC,0x23,0x00,0x00,0x06,0x04,0xB0,0x01,0xAC,\n    0x22,0x00,0x00,0x08,0x00,0x01,0x01,0xAC,0x31,0x00,0x04,0x00,0x00,0x01,0x01,0xAC,0x12,0xFF,0x00,\n    0x08,0x00,0x01,0x01,0xAC,0x12,0x31,0x00,0x08,0x00,0x01,0x01,0xAD,0x00,0x00,0x80,0x00,0x00,0x01,\n    0x01,0xAD,0x01,0x00,0x80,0x00,0x00,0x01,0x01,0xAD,0x02,0x00,0x80,0x00,0x00,0x01,0x01,0xAD,0x03,\n    0x00,0x80,0x00,0x00,0x01,0x01,0xAD,0x04,0x00,0x80,0x00,0x00,0x01,0x01,0xAD,0x05,0x00,0x80,0x00,\n    0x00,0x01,0x01,0xAD,0x06,0x00,0x80,0x00,0x00,0x01,0x01,0xAD,0x07,0x00,0x80,0x00,0x00,0x01,0x01,\n    0xAD,0x00,0x01,0x80,0x00,0x00,0x01,0x01,0xAD,0x01,0x01,0x80,0x00,0x00,0x01,0x01,0xAD,0x02,0x01,\n    0x80,0x00,0x00,0x01,0x01,0xAD,0x03,0x01,0x80,0x00,0x00,0x01,0x01,0xAD,0x04,0x01,0x80,0x00,0x00,\n    0x01,0x01,0xAD,0x05,0x01,0x80,0x00,0x00,0x01,0x01,0xAD,0x06,0x01,0x80,0x00,0x00,0x01,0x01,0xAD,\n    0x07,0x01,0x80,0x00,0x00,0x01,0x01,0xAD,0x00,0x03,0x80,0x00,0x00,0x01,0x01,0xAD,0x01,0x03,0x80,\n    0x00,0x00,0x01,0x01,0xAD,0x02,0x03,0x80,0x00,0x00,0x01,0x01,0xAD,0x03,0x03,0x80,0x00,0x00,0x01,\n    0x01,0xAD,0x04,0x03,0x80,0x00,0x00,0x01,0x01,0xAD,0x05,0x03,0x80,0x00,0x00,0x01,0x01,0xAD,0x06,\n    0x03,0x80,0x00,0x00,0x01,0x01,0xAD,0x07,0x03,0x80,0x00,0x00,0x01,0x01,0xAD,0x00,0x04,0x80,0x00,\n    0x00,0x01,0x01,0xAD,0x01,0x04,0x80,0x00,0x00,0x01,0x01,0xAD,0x02,0x04,0x80,0x00,0x00,0x01,0x01,\n    0xAD,0x03,0x04,0x80,0x00,0x00,0x01,0x01,0xAD,0x04,0x04,0x80,0x00,0x00,0x01,0x01,0xAD,0x05,0x04,\n    0x80,0x00,0x00,0x01,0x01,0xAD,0x06,0x04,0x80,0x00,0x00,0x01,0x01,0xAD,0x07,0x04,0x80,0x00,0x00,\n    0x01,0x01,0xAD,0x00,0x05,0x80,0x00,0x00,0x01,0x01,0xAD,0x01,0x05,0x80,0x00,0x00,0x01,0x01,0xAD,\n    0x02,0x05,0x80,0x00,0x00,0x01,0x01,0xAD,0x03,0x05,0x80,0x00,0x00,0x01,0x01,0xAD,0x04,0x05,0x80,\n    0x00,0x00,0x01,0x01,0xAD,0x05,0x05,0x80,0x00,0x00,0x01,0x01,0xAD,0x06,0x05,0x80,0x00,0x00,0x01,\n    0x01,0xAD,0x07,0x05,0x80,0x00,0x00,0x01,0x01,0xAD,0x00,0x06,0x80,0x00,0x00,0x01,0x01,0xAD,0x01,\n    0x06,0x80,0x00,0x00,0x01,0x01,0xAD,0x02,0x06,0x80,0x00,0x00,0x01,0x01,0xAD,0x03,0x06,0x80,0x00,\n    0x00,0x01,0x01,0xAD,0x04,0x06,0x80,0x00,0x00,0x01,0x01,0xAD,0x05,0x06,0x80,0x00,0x00,0x01,0x01,\n    0xAD,0x06,0x06,0x80,0x00,0x00,0x01,0x01,0xAD,0x07,0x06,0x80,0x00,0x00,0x01,0x01,0xAD,0x00,0x07,\n    0x80,0x00\n  };\n\n  byte SZL_ID_0011_IDX_XXXX[124] = {\n    0xFF,0x09,0x00,0x78,0x00,0x11,0x00,0x00,0x00,0x1C,0x00,0x04,0x00,0x01,0x36,0x45,0x53,0x37,0x20,\n    0x33,0x31,0x35,0x2D,0x32,0x45,0x48,0x31,0x34,0x2D,0x30,0x41,0x42,0x30,0x20,0x00,0xC0,0x00,0x04,\n    0x00,0x01,0x00,0x06,0x36,0x45,0x53,0x37,0x20,0x33,0x31,0x35,0x2D,0x32,0x45,0x48,0x31,0x34,0x2D,\n    0x30,0x41,0x42,0x30,0x20,0x00,0xC0,0x00,0x04,0x00,0x01,0x00,0x07,0x20,0x20,0x20,0x20,0x20,0x20,\n    0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0xC0,0x56,0x03,0x02,\n    0x06,0x00,0x81,0x42,0x6F,0x6F,0x74,0x20,0x4C,0x6F,0x61,0x64,0x65,0x72,0x20,0x20,0x20,0x20,0x20,\n    0x20,0x20,0x20,0x20,0x00,0x00,0x41,0x20,0x09,0x09\n  };\n\n  byte SZL_ID_0012_IDX_XXXX[58] = {\n    0xFF,0x09,0x00,0x36,0x00,0x12,0x00,0x00,0x00,0x02,0x00,0x17,0x00,0x01,0x01,0x01,0x01,0x04,0x03,\n    0x02,0x03,0x03,0x03,0x04,0x03,0x06,0x03,0x07,0x03,0x08,0x03,0x09,0x03,0x0A,0x03,0x0B,0x03,0x0C,\n    0x03,0x0D,0x03,0x0E,0x03,0x0F,0x03,0x10,0x03,0x11,0x03,0x12,0x03,0x13,0x03,0x14,0x03,0x15,0x03,\n    0x17\n  };\n\n  byte SZL_ID_0013_IDX_XXXX[192] = {\n    0xFF,0x09,0x00,0xBC,0x00,0x13,0x00,0x00,0x00,0x24,0x00,0x05,0x00,0x01,0x00,0x01,0x00,0x06,0x00,\n    0x00,0x00,0x11,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x26,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x00,0x00,\n    0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x02,0x00,0x08,0x00,0x00,0x00,0x02,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,\n    0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x02,0x00,0x80,0x00,0x00,0x00,0x02,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x02,0x00,0x00,0x0C,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x00,0x20,0x00,0x00,\n    0x00,0x00\n  };\n\n  byte SZL_ID_0014_IDX_XXXX[84] = {\n    0xFF,0x09,0x00,0x50,0x00,0x14,0x00,0x00,0x00,0x08,0x00,0x09,0x00,0x01,0x00,0x01,0x08,0x00,0x00,\n    0x00,0x00,0x02,0x00,0x01,0x08,0x00,0x00,0x00,0x00,0x03,0x00,0x01,0x40,0x00,0x00,0x80,0x00,0x04,\n    0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x05,0x00,0x01,0x01,0x00,0x00,0x08,0x00,0x06,0x00,0x01,0x08,\n    0x00,0x00,0x00,0x00,0x07,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x08,0x00,0x01,0x08,0x00,0x00,0x10,\n    0x00,0x09,0x00,0x01,0x00,0x20,0x00,0x00\n  };\n\n  byte SZL_ID_0015_IDX_XXXX[62] = {\n    0xFF,0x09,0x00,0x3A,0x00,0x15,0x00,0x00,0x00,0x0A,0x00,0x05,0x08,0x00,0x00,0x16,0x03,0xD1,0x00,\n    0x00,0xFF,0xFE,0x0A,0x00,0x3E,0x81,0x03,0xD1,0x00,0x00,0xFF,0xFE,0x0B,0x00,0x04,0x22,0x03,0xD1,\n    0x00,0x00,0xFF,0xFE,0x0C,0x00,0x1F,0x40,0x03,0xD1,0x00,0x00,0xFF,0xFE,0x0E,0x00,0x1F,0x40,0x03,\n    0xD1,0x00,0x00,0xFF,0xFE\n  };\n\n  byte SZL_ID_0F14_IDX_XXXX[12] = {\n    0xFF,0x09,0x00,0x08,0x0F,0x14,0x00,0x00,0x00,0x08,0x00,0x09\n  };\n\n  byte SZL_ID_0019_IDX_XXXX[40] = {\n    0xFF,0x09,0x00,0x24,0x00,0x19,0x00,0x00,0x00,0x04,0x00,0x07,0x00,0x01,0x00,0x00,0x00,0x04,0x01,\n    0x00,0x00,0x05,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x15,\n    0x00,0x00\n  };\n\n  byte SZL_ID_0F19_IDX_XXXX[12] = {\n    0xFF,0x09,0x00,0x08,0x0F,0x19,0x00,0x00,0x00,0x04,0x00,0x07\n  };\n\n  byte SZL_ID_001C_IDX_XXXX[352] = {\n    0xFF,0x09,0x01,0x5C,0x00,0x1C,0x00,0x00,0x00,0x22,0x00,0x0A,0x00,0x01,0x53,0x4E,0x41,0x50,0x37,\n    0x2D,0x53,0x45,0x52,0x56,0x45,0x52,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x43,0x50,0x55,0x20,0x33,0x31,0x35,0x2D,0x32,\n    0x20,0x50,0x4E,0x2F,0x44,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x04,0x4F,0x72,0x69,0x67,0x69,0x6E,0x61,0x6C,0x20,0x53,0x69,0x65,0x6D,0x65,0x6E,0x73,0x20,\n    0x45,0x71,0x75,0x69,0x70,0x6D,0x65,0x6E,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x53,0x20,\n    0x43,0x2D,0x43,0x32,0x55,0x52,0x32,0x38,0x39,0x32,0x32,0x30,0x31,0x32,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x43,0x50,0x55,0x20,0x33,0x31,\n    0x35,0x2D,0x32,0x20,0x50,0x4E,0x2F,0x44,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x4D,0x4D,0x43,0x20,0x32,0x36,0x37,0x46,0x46,0x31,\n    0x31,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x09,0x00,0x2A,0xF6,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0F1C_IDX_XXXX[12] = {\n    0xFF,0x09,0x00,0x08,0x0F,0x1C,0x00,0x00,0x00,0x22,0x00,0x0A\n  };\n\n  byte SZL_ID_0036_IDX_XXXX[12] = {\n    0xFF,0x09,0x00,0x08,0x00,0x36,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0F36_IDX_XXXX[12] = {\n    0xFF,0x09,0x00,0x08,0x0F,0x36,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0025_IDX_XXXX[16] = {\n    0xFF,0x09,0x00,0x0C,0x00,0x25,0x00,0x00,0x00,0x04,0x00,0x01,0x01,0x0C,0x3D,0x00\n  };\n\n  byte SZL_ID_0F25_IDX_XXXX[12] = {\n    0xFF,0x09,0x00,0x08,0x0F,0x25,0x00,0x00,0x00,0x04,0x00,0x01\n  };\n\n  byte SZL_ID_0037_IDX_XXXX[60] = {\n    0xFF,0x09,0x00,0x38,0x00,0x37,0x00,0x00,0x00,0x30,0x00,0x01,0x07,0xFE,0xC0,0xA8,0x01,0x0A,0xFF,\n    0xFF,0xFF,0x00,0xC0,0xA8,0x01,0x0A,0x00,0x1B,0x1B,0x1D,0x1A,0x2D,0x01,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x8F,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0F37_IDX_XXXX[12] = {\n    0xFF,0x09,0x00,0x08,0x0F,0x37,0x00,0x00,0x00,0x30,0x00,0x01\n  };\n\n  byte SZL_ID_0074_IDX_XXXX[40] = {\n    0xFF,0x09,0x00,0x24,0x00,0x74,0x00,0x00,0x00,0x04,0x00,0x07,0x00,0x01,0x00,0x00,0x00,0x04,0x01,\n    0x00,0x00,0x05,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x15,\n    0x00,0x00\n  };\n\n  byte SZL_ID_0F74_IDX_XXXX[12] = {\n    0xFF,0x09,0x00,0x08,0x0F,0x74,0x00,0x00,0x00,0x04,0x00,0x07\n  };\n\n  byte SZL_ID_0591_IDX_XXXX[76] = {\n    0xFF,0x09,0x00,0x48,0x05,0x91,0x00,0x00,0x00,0x10,0x00,0x04,0x00,0x00,0x02,0x01,0x07,0xFF,0xC4,\n    0xC0,0xC4,0xC0,0x00,0x00,0xB4,0x02,0x00,0x11,0x00,0x00,0x02,0x02,0x07,0xFE,0xA7,0xC4,0xA7,0xC4,\n    0x00,0x00,0xB4,0x02,0x00,0x11,0x00,0x00,0x02,0x03,0x07,0xFD,0x97,0xC5,0x97,0xC5,0x00,0x00,0xB4,\n    0x02,0x00,0x11,0x00,0x00,0x02,0x04,0x07,0xFC,0x97,0xC5,0x97,0xC5,0x00,0x00,0xB4,0x02,0x00,0x11\n  };\n\n  byte SZL_ID_0A91_IDX_XXXX[44] = {\n    0xFF,0x09,0x00,0x28,0x0A,0x91,0x00,0x00,0x00,0x10,0x00,0x02,0x01,0x00,0x02,0x01,0x07,0xFF,0xC4,\n    0xC0,0xC4,0xC0,0x00,0x01,0xFE,0x02,0x00,0x11,0x80,0x00,0x00,0x00,0x07,0xFB,0xA7,0xC4,0xA7,0xC4,\n    0x00,0x01,0xFE,0x02,0x00,0x11\n  };\n\n  byte SZL_ID_0F92_IDX_XXXX[12] = {\n    0xFF,0x09,0x00,0x08,0x0F,0x92,0x00,0x00,0x00,0x10,0x00,0x01\n  };\n\n  byte SZL_ID_0294_IDX_XXXX[270] = {\n    0xFF,0x09,0x01,0x0A,0x02,0x94,0x00,0x00,0x01,0x02,0x00,0x01,0x00,0x00,0x03,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0794_IDX_XXXX[270] = {\n    0xFF,0x09,0x01,0x0A,0x07,0x94,0x00,0x00,0x01,0x02,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0F94_IDX_XXXX[12] = {\n    0xFF,0x09,0x00,0x08,0x0F,0x94,0x00,0x00,0x01,0x02,0x00,0x01\n  };\n\n  byte SZL_ID_0095_IDX_XXXX[52] = {\n    0xFF,0x09,0x00,0x30,0x00,0x95,0x00,0x00,0x00,0x28,0x00,0x01,0x64,0x00,0x02,0x02,0x07,0xFE,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0F95_IDX_XXXX[12] = {\n    0xFF,0x09,0x00,0x08,0x0F,0x95,0x00,0x00,0x00,0x28,0x00,0x01\n  };\n\n  byte SZL_ID_00A0_IDX_XXXX[212] = {\n    0xFF,0x09,0x00,0xD0,0x00,0xA0,0x00,0x00,0x00,0x14,0x00,0x0A,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,\n    0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x86,0x13,0x81,0xFE,0x64,0xC7,0x72,\n    0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x76,0x43,0x01,0xFF,0x46,0xC7,\n    0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x29,0x66,0x43,0x04,0xFF,0x84,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x52,0x13,0x90,0x16,0x43,0x02,0xFF,\n    0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x56,0x13,0x81,\n    0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x46,0x43,\n    0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x79,0x46,\n    0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x51,0x19,0x48,\n    0x26,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x50,0x45,\n    0x09,0x96,0x13,0x81,0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x50,\n    0x45,0x09,0x86\n  };\n\n  byte SZL_ID_0FA0_IDX_XXXX[12] = {\n    0xFF,0x09,0x00,0x08,0x0F,0xA0,0x00,0x00,0x00,0x14,0x01,0xF4\n  };\n\n  byte SZL_ID_0017_IDX_XXXX[458] = {  // <--Wrapped to 458 bytes\n    0xFF,0x09,0x01,0xC6,0x00,0x17,0x00,0x00,0x00,0x04,0x00,0x73,0x00,0x00,0x00,0x01,0x00,0x01,0x00,\n    0x03,0x00,0x02,0x00,0x02,0x00,0x03,0x00,0x01,0x00,0x04,0x00,0x01,0x00,0x07,0x00,0x01,0x00,0x16,\n    0x00,0x01,0x00,0x64,0x00,0x01,0x00,0x65,0x00,0x01,0x00,0x66,0x00,0x01,0x00,0x67,0x00,0x01,0x00,\n    0x7A,0x00,0x01,0x00,0xC8,0x00,0x01,0x00,0xD2,0x00,0x01,0x02,0xBC,0x00,0x01,0x02,0xBD,0x00,0x01,\n    0x02,0xBE,0x00,0x01,0x02,0xBF,0x00,0x01,0x02,0xC0,0x00,0x01,0x02,0xC1,0x00,0x01,0x02,0xC2,0x00,\n    0x01,0x02,0xC3,0x00,0x01,0x02,0xC4,0x00,0x01,0x02,0xC5,0x00,0x01,0x02,0xC6,0x00,0x01,0x02,0xC7,\n    0x00,0x01,0x02,0xC8,0x00,0x01,0x02,0xC9,0x00,0x01,0x02,0xCA,0x00,0x01,0x02,0xCB,0x00,0x01,0x02,\n    0xCC,0x00,0x01,0x02,0xCD,0x00,0x01,0x02,0xCE,0x00,0x01,0x02,0xCF,0x00,0x01,0x02,0xD0,0x00,0x01,\n    0x02,0xD1,0x00,0x01,0x02,0xD2,0x00,0x01,0x02,0xD3,0x00,0x01,0x02,0xD4,0x00,0x01,0x02,0xD5,0x00,\n    0x01,0x02,0xD6,0x00,0x01,0x02,0xD7,0x00,0x01,0x02,0xD8,0x00,0x01,0x02,0xD9,0x00,0x01,0x02,0xDA,\n    0x00,0x01,0x02,0xDB,0x00,0x01,0x02,0xDC,0x00,0x01,0x02,0xDD,0x00,0x01,0x02,0xDE,0x00,0x01,0x02,\n    0xDF,0x00,0x01,0x02,0xE0,0x00,0x01,0x02,0xE1,0x00,0x01,0x02,0xE2,0x00,0x01,0x02,0xE3,0x00,0x01,\n    0x02,0xE4,0x00,0x01,0x02,0xE5,0x00,0x01,0x02,0xE6,0x00,0x01,0x02,0xE7,0x00,0x01,0x02,0xE8,0x00,\n    0x01,0x02,0xE9,0x00,0x01,0x02,0xEA,0x00,0x01,0x02,0xEB,0x00,0x01,0x02,0xEC,0x00,0x01,0x02,0xED,\n    0x00,0x01,0x02,0xEE,0x00,0x01,0x02,0xEF,0x00,0x01,0x02,0xF0,0x00,0x01,0x02,0xF1,0x00,0x01,0x02,\n    0xF2,0x00,0x01,0x02,0xF3,0x00,0x01,0x02,0xF4,0x00,0x01,0x02,0xF5,0x00,0x01,0x02,0xF6,0x00,0x01,\n    0x02,0xF7,0x00,0x01,0x02,0xF8,0x00,0x01,0x02,0xF9,0x00,0x01,0x02,0xFA,0x00,0x01,0x02,0xFB,0x00,\n    0x01,0x02,0xFC,0x00,0x01,0x02,0xFD,0x00,0x01,0x02,0xFE,0x00,0x01,0x02,0xFF,0x00,0x01,0x03,0x00,\n    0x00,0x01,0x03,0x01,0x00,0x01,0x03,0x02,0x00,0x01,0x03,0x03,0x00,0x01,0x03,0x04,0x00,0x01,0x03,\n    0x05,0x00,0x01,0x03,0x06,0x00,0x01,0x03,0x07,0x00,0x01,0x03,0x08,0x00,0x01,0x03,0x09,0x00,0x01,\n    0x03,0x0A,0x00,0x01,0x03,0x0B,0x00,0x01,0x03,0x0C,0x00,0x01,0x03,0x0D,0x00,0x01,0x03,0x0E,0x00,\n    0x01,0x03,0x0F,0x00,0x01,0x03,0x10,0x00,0x01,0x03,0x11,0x00,0x01,0x03,0x12,0x00,0x01,0x03,0x13,\n    0x00,0x01,0x03,0x14,0x00,0x01,0x03,0x15,0x00,0x01,0x03,0x16,0x00,0x01,0x03,0x17,0x00,0x01,0x03,\n    0x18,0x00,0x01,0x03,0x19,0x00,0x01,0x03,0x1A,0x00,0x01,0x03,0x1B,0x00,0x01,0x03,0x1C,0x00,0x01,\n    0x03,0x1D\n  };\n\n  byte SZL_ID_0F17_IDX_XXXX[12] = {\n    0xFF,0x09,0x00,0x08,0x0F,0x17,0x00,0x00,0x00,0x04,0x00,0x73\n  };\n\n  byte SZL_ID_0018_IDX_XXXX[28] = {\n    0xFF,0x09,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x08,0x00,0x01,0x00,\n    0x08,0x00,0x02,0x00,0x08,0x00,0x03,0x00,0x08\n  };\n\n  byte SZL_ID_0F18_IDX_XXXX[12] = {\n    0xFF,0x09,0x00,0x08,0x0F,0x18,0x00,0x00,0x00,0x04,0x00,0x04\n  };\n\n  byte SZL_ID_001A_IDX_XXXX[48] = {\n    0xFF,0x09,0x00,0x2C,0x00,0x1A,0x00,0x00,0x00,0x0C,0x00,0x03,0x09,0x01,0x01,0x05,0x00,0x08,0x00,\n    0x00,0x00,0x80,0x00,0x00,0x12,0x01,0x00,0x02,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x18,0x01,\n    0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00\n  };\n\n  byte SZL_ID_0F1A_IDX_XXXX[12] = {\n    0xFF,0x09,0x00,0x08,0x0F,0x1A,0x00,0x00,0x00,0x0C,0x00,0x03\n  };\n\n  byte SZL_ID_001B_IDX_XXXX[132] = {\n    0xFF,0x09,0x00,0x80,0x00,0x1B,0x00,0x00,0x00,0x14,0x00,0x06,0x09,0x00,0x00,0x00,0x00,0x02,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x06,0x00,0x00,0x00,0x00,0x09,0x00,0x00,0x70,0x00,0x02,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xF3,0xFA,0x00,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x26,0x00,0x00,0x00,0x00,0x12,0x00,0x00,0x70,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xFF,0xDA,0x00,0x00,0x00,0x00,0x18,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,\n    0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0F1B_IDX_XXXX[12] = {\n    0xFF,0x09,0x00,0x08,0x0F,0x1B,0x00,0x00,0x00,0x14,0x00,0x06\n  };\n\n  byte SZL_ID_0021_IDX_XXXX[100] = {\n    0xFF,0x09,0x00,0x60,0x00,0x21,0x00,0x00,0x00,0x04,0x00,0x16,0x01,0x01,0x01,0x01,0x01,0x11,0xFE,\n    0x0A,0x01,0x21,0xFE,0x14,0x01,0x22,0xFE,0x15,0x01,0x33,0xFE,0x20,0x01,0x34,0xFE,0x21,0x01,0x35,\n    0xFE,0x22,0x01,0x36,0xFE,0x23,0x01,0x41,0xFE,0x28,0x01,0x55,0xFE,0x37,0x01,0x56,0xFE,0x38,0x01,\n    0x57,0xFE,0x39,0x01,0x64,0xFE,0x3D,0x00,0x01,0xFE,0x50,0x00,0x42,0xFE,0x52,0x00,0x61,0xFE,0x53,\n    0x00,0xA1,0xFE,0x55,0x00,0xC1,0xFE,0x56,0x00,0xD2,0xFE,0x57,0x00,0x81,0xFE,0x64,0x00,0x21,0xFE,\n    0x79,0x00,0x42,0xFE,0x7A\n  };\n\n  byte SZL_ID_0A21_IDX_XXXX[16] = {\n    0xFF,0x09,0x00,0x0C,0x0A,0x21,0x00,0x00,0x00,0x04,0x00,0x01,0x01,0x01,0x01,0x01\n  };\n\n  byte SZL_ID_0F21_IDX_XXXX[12] = {\n    0xFF,0x09,0x00,0x08,0x0F,0x21,0x00,0x00,0x00,0x04,0x00,0x16\n  };\n\n  byte SZL_ID_0023_IDX_XXXX[228] = {\n    0xFF,0x09,0x00,0xE0,0x00,0x23,0x00,0x00,0x00,0x12,0x00,0x0C,0x1A,0x00,0x00,0x00,0x10,0xBE,0x00,\n    0x00,0x08,0x00,0x0B,0xC0,0xFC,0x01,0xFF,0xFF,0xFF,0xF3,0x19,0x00,0x00,0x00,0x10,0x01,0x00,0x00,\n    0x08,0x00,0x0B,0xC0,0xFC,0x01,0xFF,0xFF,0xFF,0xF3,0x10,0x00,0x00,0x00,0x10,0x26,0x00,0x00,0x08,\n    0x00,0x0B,0xC0,0xFC,0x01,0xFF,0xFF,0xFF,0xF3,0x0C,0x00,0x00,0x00,0x10,0x01,0x00,0x00,0x08,0x00,\n    0x0B,0xC0,0xFC,0x01,0xFF,0xFF,0xFF,0xF3,0x0B,0x00,0x00,0x00,0x10,0x01,0x00,0x00,0x08,0x00,0x0B,\n    0xC0,0xFC,0x01,0xFF,0xFF,0xFF,0xF3,0x0A,0x00,0x00,0x00,0x10,0x01,0x00,0x00,0x08,0x00,0x0B,0xC0,\n    0xFC,0x01,0xFF,0xFF,0xFF,0xF3,0x09,0x00,0x00,0x00,0x10,0x01,0x00,0x00,0x08,0x00,0x0B,0xC0,0xFC,\n    0x01,0xFF,0xFF,0xFF,0xF3,0x04,0x00,0x00,0x00,0x10,0x01,0x00,0x00,0x08,0x00,0x0B,0xC0,0xFC,0x01,\n    0xFF,0xFF,0xFF,0xF3,0x03,0x00,0x00,0x00,0x10,0x01,0x00,0x00,0x08,0x00,0x0B,0xC0,0xFC,0x01,0xFF,\n    0xFF,0xFF,0xF3,0x02,0x00,0x00,0x00,0x10,0x16,0x00,0x00,0x08,0x00,0x0B,0xC0,0xFC,0x01,0xFF,0xFF,\n    0xFF,0xF3,0x01,0x00,0x00,0x00,0x10,0x01,0x00,0x00,0x08,0x00,0x0B,0xC0,0xFC,0x01,0xFF,0xFF,0xFF,\n    0xF3,0x1B,0x00,0x00,0x00,0x10,0x01,0x00,0x00,0x08,0x00,0x0B,0xC0,0xFC,0x01,0xFF,0xFF,0xFF,0xF3\n  };\n\n  byte SZL_ID_0F23_IDX_XXXX[12] = {\n    0xFF,0x09,0x00,0x08,0x0F,0x23,0x00,0x00,0x00,0x12,0x00,0x0C\n  };\n\n  byte SZL_ID_0024_IDX_XXXX[92] = {\n    0xFF,0x09,0x00,0x58,0x00,0x24,0x00,0x00,0x00,0x14,0x00,0x04,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,\n    0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x86,0x43,0x01,0xFF,0x46,0xC7,0x72,\n    0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x29,0x66,0x43,0x04,0xFF,0x84,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x52,0x13,0x90,0x16,0x43,0x02,0xFF,0x68,\n    0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x56\n  };\n\n  byte SZL_ID_0124_IDX_XXXX[32] = {\n    0xFF,0x09,0x00,0x1C,0x01,0x24,0x00,0x00,0x00,0x14,0x00,0x01,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,\n    0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x86\n  };\n\n  byte SZL_ID_0424_IDX_XXXX[32] = {\n    0xFF,0x09,0x00,0x1C,0x04,0x24,0x00,0x00,0x00,0x14,0x00,0x01,0x51,0x44,0xFF,\n    0x08,  // <-- CPU Status\n    0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x05,0x02,0x01,0x55,0x90,0x67\n  };\n\n  byte SZL_ID_0038_IDX_XXXX[78] = {\n    0xFF,0x09,0x00,0x4A,0x00,0x38,0x00,0x00,0x00,0x42,0x00,0x01,0x00,0x01,0x07,0xFE,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAB,0xE3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xEE,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00\n  };\n\n  byte SZL_ID_0F38_IDX_XXXX[12] = {\n    0xFF,0x09,0x00,0x08,0x0F,0x38,0x00,0x00,0x00,0x42,0x00,0x01\n  };\n\n  byte SZL_ID_003A_IDX_XXXX[12] = {\n    0xFF,0x09,0x00,0x08,0x00,0x3A,0x00,0x00,0x00,0x94,0x00,0x00\n  };\n\n  byte SZL_ID_0F3A_IDX_XXXX[12] = {\n    0xFF,0x09,0x00,0x08,0x0F,0x3A,0x00,0x00,0x00,0x94,0x00,0x08\n  };\n\n  byte SZL_ID_0F9A_IDX_XXXX[12] = {\n    0xFF,0x09,0x00,0x08,0x0F,0x9A,0x00,0x00,0x01,0x1C,0x00,0x01\n  };\n\n  byte SZL_ID_0D91_IDX_0000[28] = {\n    0xFF,0x09,0x00,0x18,0x0D,0x91,0x00,0x00,0x00,0x10,0x00,0x01,0x00,0x00,0x02,0x00,0x7F,0xFF,0x00,\n    0xC0,0x00,0xC0,0x00,0x00,0xB4,0x02,0x00,0x11\n  };\n\n  byte SZL_ID_0092_IDX_0000[28] = {\n    0xFF,0x09,0x00,0x18,0x00,0x92,0x00,0x00,0x00,0x10,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0292_IDX_0000[28] = {\n    0xFF,0x09,0x00,0x18,0x02,0x92,0x00,0x00,0x00,0x10,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0692_IDX_0000[28] = {\n    0xFF,0x09,0x00,0x18,0x06,0x92,0x00,0x00,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0094_IDX_0000[270] = {\n    0xFF,0x09,0x01,0x0A,0x00,0x94,0x00,0x00,0x01,0x02,0x00,0x01,0x00,0x00,0x03,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0D97_IDX_0000[60] = {\n    0xFF,0x09,0x00,0x38,0x0D,0x97,0x00,0x00,0x00,0x30,0x00,0x01,0x7F,0xFF,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x02,0x00,0x04,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0111_IDX_0001[40] = {\n    0xFF,0x09,0x00,0x24,0x01,0x11,0x00,0x01,0x00,0x1C,0x00,0x01,0x00,0x01,0x36,0x45,0x53,0x37,0x20,\n    0x33,0x31,0x35,0x2D,0x32,0x45,0x48,0x31,0x34,0x2D,0x30,0x41,0x42,0x30,0x20,0x00,0xC0,0x00,0x04,\n    0x00,0x01\n  };\n\n  byte SZL_ID_0111_IDX_0006[40] = {\n    0xFF,0x09,0x00,0x24,0x01,0x11,0x00,0x06,0x00,0x1C,0x00,0x01,0x00,0x06,0x36,0x45,0x53,0x37,0x20,\n    0x33,0x31,0x35,0x2D,0x32,0x45,0x48,0x31,0x34,0x2D,0x30,0x41,0x42,0x30,0x20,0x00,0xC0,0x00,0x04,\n    0x00,0x01\n  };\n\n  byte SZL_ID_0111_IDX_0007[40] = {\n    0xFF,0x09,0x00,0x24,0x01,0x11,0x00,0x07,0x00,0x1C,0x00,0x01,0x00,0x07,0x20,0x20,0x20,0x20,0x20,\n    0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0xC0,0x56,0x03,\n    0x02,0x06\n  };\n\n  byte SZL_ID_0F11_IDX_0001[12] = {\n    0xFF,0x09,0x00,0x08,0x0F,0x11,0x00,0x00,0x00,0x1C,0x00,0x04\n  };\n\n  byte SZL_ID_0F11_IDX_0006[12] = {\n    0xFF,0x09,0x00,0x08,0x0F,0x11,0x00,0x00,0x00,0x1C,0x00,0x04\n  };\n\n  byte SZL_ID_0F11_IDX_0007[12] = {\n    0xFF,0x09,0x00,0x08,0x0F,0x11,0x00,0x00,0x00,0x1C,0x00,0x04\n  };\n\n  byte SZL_ID_0112_IDX_0000[14] = {\n    0xFF,0x09,0x00,0x0A,0x01,0x12,0x00,0x00,0x00,0x02,0x00,0x01,0x00,0x01\n  };\n\n  byte SZL_ID_0112_IDX_0100[16] = {\n    0xFF,0x09,0x00,0x0C,0x01,0x12,0x01,0x00,0x00,0x02,0x00,0x02,0x01,0x01,0x01,0x04\n  };\n\n  byte SZL_ID_0112_IDX_0200[12] = {\n    0xFF,0x09,0x00,0x08,0x01,0x12,0x02,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0112_IDX_0400[12] = {\n    0xFF,0x09,0x00,0x08,0x01,0x12,0x04,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0F12_IDX_0000[12] = {\n    0xFF,0x09,0x00,0x08,0x0F,0x12,0x00,0x00,0x00,0x02,0x00,0x17\n  };\n\n  byte SZL_ID_0F12_IDX_0100[12] = {\n    0xFF,0x09,0x00,0x08,0x0F,0x12,0x00,0x00,0x00,0x02,0x00,0x17\n  };\n\n  byte SZL_ID_0F12_IDX_0200[12] = {\n    0xFF,0x09,0x00,0x08,0x0F,0x12,0x00,0x00,0x00,0x02,0x00,0x17\n  };\n\n  byte SZL_ID_0F12_IDX_0400[12] = {\n    0xFF,0x09,0x00,0x08,0x0F,0x12,0x00,0x00,0x00,0x02,0x00,0x17\n  };\n\n  byte SZL_ID_0113_IDX_0001[48] = {\n    0xFF,0x09,0x00,0x2C,0x01,0x13,0x00,0x01,0x00,0x24,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x06,0x00,\n    0x00,0x00,0x11,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x26,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0115_IDX_0800[22] = {\n    0xFF,0x09,0x00,0x12,0x01,0x15,0x08,0x00,0x00,0x0A,0x00,0x01,0x08,0x00,0x00,0x16,0x03,0xD1,0x00,\n    0x00,0xFF,0xFE\n  };\n\n  byte SZL_ID_011C_IDX_0001[46] = {\n    0xFF,0x09,0x00,0x2A,0x01,0x1C,0x00,0x01,0x00,0x22,0x00,0x01,0x00,0x01,0x53,0x4D,0x41,0x52,0x54,\n    0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_011C_IDX_0002[46] = {\n    0xFF,0x09,0x00,0x2A,0x01,0x1C,0x00,0x02,0x00,0x22,0x00,0x01,0x00,0x02,0x43,0x50,0x55,0x20,0x33,\n    0x31,0x35,0x2D,0x32,0x20,0x50,0x4E,0x2F,0x44,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_011C_IDX_0003[46] = {\n    0xFF,0x09,0x00,0x2A,0x01,0x1C,0x00,0x03,0x00,0x22,0x00,0x01,0x00,0x03,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_011C_IDX_0004[46] = {\n    0xFF,0x09,0x00,0x2A,0x01,0x1C,0x00,0x04,0x00,0x22,0x00,0x01,0x00,0x04,0x4F,0x72,0x69,0x67,0x69,\n    0x6E,0x61,0x6C,0x20,0x53,0x69,0x65,0x6D,0x65,0x6E,0x73,0x20,0x45,0x71,0x75,0x69,0x70,0x6D,0x65,\n    0x6E,0x74,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_011C_IDX_0005[46] = {\n    0xFF,0x09,0x00,0x2A,0x01,0x1C,0x00,0x05,0x00,0x22,0x00,0x01,0x00,0x05,0x53,0x20,0x43,0x2D,0x43,\n    0x32,0x55,0x52,0x32,0x38,0x39,0x32,0x32,0x30,0x31,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_011C_IDX_0007[46] = {\n    0xFF,0x09,0x00,0x2A,0x01,0x1C,0x00,0x07,0x00,0x22,0x00,0x01,0x00,0x07,0x43,0x50,0x55,0x20,0x33,\n    0x31,0x35,0x2D,0x32,0x20,0x50,0x4E,0x2F,0x44,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_011C_IDX_0008[46] = {\n    0xFF,0x09,0x00,0x2A,0x01,0x1C,0x00,0x08,0x00,0x22,0x00,0x01,0x00,0x08,0x4D,0x4D,0x43,0x20,0x32,\n    0x36,0x37,0x46,0x46,0x31,0x31,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_011C_IDX_0009[46] = {\n    0xFF,0x09,0x00,0x2A,0x01,0x1C,0x00,0x09,0x00,0x22,0x00,0x01,0x00,0x09,0x00,0x2A,0xF6,0x00,0x00,\n    0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_011C_IDX_000A[46] = {\n    0xFF,0x09,0x00,0x2A,0x01,0x1C,0x00,0x0A,0x00,0x22,0x00,0x01,0x00,0x0A,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_011C_IDX_000B[46] = {\n    0xFF,0x09,0x00,0x2A,0x01,0x1C,0x00,0x0B,0x00,0x22,0x00,0x01,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0222_IDX_0001[40] = {\n    0xFF,0x09,0x00,0x24,0x02,0x22,0x00,0x01,0x00,0x1C,0x00,0x01,0x11,0x03,0x01,0x01,0xC8,0x58,0x00,\n    0x00,0x00,0x00,0x00,0x01,0x94,0x02,0x05,0x02,0x01,0x56,0x64,0x77,0x00,0x10,0x00,0x08,0x00,0x00,\n    0x00,0x00\n  };\n\n  byte SZL_ID_0222_IDX_000A[40] = {\n    0xFF,0x09,0x00,0x24,0x02,0x22,0x00,0x0A,0x00,0x1C,0x00,0x01,0x10,0x11,0x02,0x0A,0x00,0x50,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00\n  };\n\n  byte SZL_ID_0222_IDX_0014[40] = {\n    0xFF,0x09,0x00,0x24,0x02,0x22,0x00,0x14,0x00,0x1C,0x00,0x01,0x10,0x21,0x03,0x14,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00\n  };\n\n  byte SZL_ID_0222_IDX_0028[40] = {\n    0xFF,0x09,0x00,0x24,0x02,0x22,0x00,0x28,0x00,0x1C,0x00,0x01,0x10,0x41,0x10,0x28,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00\n  };\n\n  byte SZL_ID_0222_IDX_0050[40] = {\n    0xFF,0x09,0x00,0x24,0x02,0x22,0x00,0x50,0x00,0x1C,0x00,0x01,0x35,0x01,0xFE,0x50,0xC8,0x58,0x00,\n    0x00,0x00,0x00,0x00,0x96,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,\n    0x00,0x00\n  };\n\n  byte SZL_ID_0222_IDX_0064[40] = {\n    0xFF,0x09,0x00,0x24,0x02,0x22,0x00,0x64,0x00,0x1C,0x00,0x01,0x13,0x81,0xFE,0x64,0xC7,0x72,0x43,\n    0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x76,0x00,0x00,0x00,0x08,0x00,0x00,\n    0x00,0x00\n  };\n\n  byte SZL_ID_0125_IDX_0000[16] = {\n    0xFF,0x09,0x00,0x0C,0x01,0x25,0x00,0x00,0x00,0x04,0x00,0x01,0x00,0x03,0x01,0x00\n  };\n\n  byte SZL_ID_0125_IDX_0001[16] = {\n    0xFF,0x09,0x00,0x0C,0x01,0x25,0x00,0x01,0x00,0x04,0x00,0x01,0x01,0x0C,0x3D,0x00\n  };\n\n  byte SZL_ID_0225_IDX_0001[16] = {\n    0xFF,0x09,0x00,0x0C,0x02,0x25,0x00,0x01,0x00,0x04,0x00,0x01,0x00,0x03,0x01,0x00\n  };\n\n  byte SZL_ID_0132_IDX_0001[52] = {\n    0xFF,0x09,0x00,0x30,0x01,0x32,0x00,0x01,0x00,0x28,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,\n    0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03\n  };\n\n  byte SZL_ID_0132_IDX_0002[52] = {\n    0xFF,0x09,0x00,0x30,0x01,0x32,0x00,0x02,0x00,0x28,0x00,0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x0E,0x00,0x00,0x00,0x00,0x06,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0132_IDX_0003[52] = {\n    0xFF,0x09,0x00,0x30,0x01,0x32,0x00,0x03,0x00,0x28,0x00,0x01,0x00,0x03,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0132_IDX_0004[52] = {\n    0xFF,0x09,0x00,0x30,0x01,0x32,0x00,0x04,0x00,0x28,0x00,0x01,0x00,0x04,0x00,0x01,0x00,0x00,0x00,\n    0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x56,0x56,0x10,0x01,0x33,0x7B,0x02,0x00,0x75,0xF4,0x02,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0132_IDX_0005[52] = {\n    0xFF,0x09,0x00,0x30,0x01,0x32,0x00,0x05,0x00,0x28,0x00,0x01,0x00,0x05,0x00,0x00,0x00,0x01,0x00,\n    0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0132_IDX_0006[52] = {\n    0xFF,0x09,0x00,0x30,0x01,0x32,0x00,0x06,0x00,0x28,0x00,0x01,0x00,0x06,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0132_IDX_0007[52] = {\n    0xFF,0x09,0x00,0x30,0x01,0x32,0x00,0x07,0x00,0x28,0x00,0x01,0x00,0x07,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0132_IDX_0008[52] = {\n    0xFF,0x09,0x00,0x30,0x01,0x32,0x00,0x08,0x00,0x28,0x00,0x01,0x00,0x08,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x05,0x02,\n    0x01,0x56,0x94,0x57,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0132_IDX_0009[52] = {\n    0xFF,0x09,0x00,0x30,0x01,0x32,0x00,0x09,0x00,0x28,0x00,0x01,0x00,0x09,0x00,0x02,0xDC,0x6C,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0132_IDX_000A[52] = {\n    0xFF,0x09,0x00,0x30,0x01,0x32,0x00,0x0A,0x00,0x28,0x00,0x01,0x00,0x0A,0x00,0x02,0xDC,0x6C,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0132_IDX_000B[52] = {\n    0xFF,0x09,0x00,0x30,0x01,0x32,0x00,0x0B,0x00,0x28,0x00,0x01,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0132_IDX_000C[52] = {\n    0xFF,0x09,0x00,0x30,0x01,0x32,0x00,0x0C,0x00,0x28,0x00,0x01,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0232_IDX_0001[52] = {\n    0xFF,0x09,0x00,0x30,0x02,0x32,0x00,0x01,0x00,0x28,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,\n    0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03\n  };\n\n  byte SZL_ID_0232_IDX_0004[52] = {\n    0xFF,0x09,0x00,0x30,0x02,0x32,0x00,0x04,0x00,0x28,0x00,0x01,0x00,0x04,0x00,0x01,0x00,0x00,0x00,\n    0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x56,0x56,0x10,0x01,0x33,0x7B,0x02,0x00,0x75,0xF4,0x02,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0137_IDX_07FE[60] = {\n    0xFF,0x09,0x00,0x38,0x01,0x37,0x07,0xFE,0x00,0x30,0x00,0x01,0x07,0xFE,0xC0,0xA8,0x01,0x0A,0xFF,\n    0xFF,0xFF,0x00,0xC0,0xA8,0x01,0x0A,0x00,0x1B,0x1B,0x1D,0x1A,0x2D,0x01,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x8F,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0174_IDX_0001[16] = {\n    0xFF,0x09,0x00,0x0C,0x01,0x74,0x00,0x01,0x00,0x04,0x00,0x01,0x00,0x01,0x00,0x00\n  };\n\n  byte SZL_ID_0174_IDX_0004[16] = {\n    0xFF,0x09,0x00,0x0C,0x01,0x74,0x00,0x04,0x00,0x04,0x00,0x01,0x00,0x04,0x01,0x00\n  };\n\n  byte SZL_ID_0174_IDX_0005[16] = {\n    0xFF,0x09,0x00,0x0C,0x01,0x74,0x00,0x05,0x00,0x04,0x00,0x01,0x00,0x05,0x00,0x00\n  };\n\n  byte SZL_ID_0174_IDX_0006[16] = {\n    0xFF,0x09,0x00,0x0C,0x01,0x74,0x00,0x06,0x00,0x04,0x00,0x01,0x00,0x06,0x00,0x00\n  };\n\n  byte SZL_ID_0174_IDX_000B[16] = {\n    0xFF,0x09,0x00,0x0C,0x01,0x74,0x00,0x0B,0x00,0x04,0x00,0x01,0x00,0x0B,0x00,0x00\n  };\n\n  byte SZL_ID_0174_IDX_000C[16] = {\n    0xFF,0x09,0x00,0x0C,0x01,0x74,0x00,0x0C,0x00,0x04,0x00,0x01,0x00,0x0C,0x00,0x00\n  };\n\n  byte SZL_ID_0194_IDX_0064[270] = {\n    0xFF,0x09,0x01,0x0A,0x01,0x94,0x00,0x64,0x01,0x02,0x00,0x01,0x00,0x64,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0694_IDX_0064[270] = {\n    0xFF,0x09,0x01,0x0A,0x06,0x94,0x00,0x64,0x01,0x02,0x00,0x01,0x00,0x64,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_01A0_IDX_0000[12] = {\n    0xFF,0x09,0x00,0x08,0x01,0xA0,0x00,0x00,0x00,0x14,0x00,0x00\n  };\n\n  byte SZL_ID_01A0_IDX_0001[32] = {\n    0xFF,0x09,0x00,0x1C,0x01,0xA0,0x00,0x00,0x00,0x14,0x00,0x01,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,\n    0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x86\n  };\n\n  byte SZL_ID_01A0_IDX_0002[52] = {\n    0xFF,0x09,0x00,0x30,0x01,0xA0,0x00,0x00,0x00,0x14,0x00,0x02,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,\n    0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x86,0x13,0x81,0xFE,0x64,0xC7,0x72,\n    0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x76\n  };\n\n  byte SZL_ID_01A0_IDX_0003[72] = {\n    0xFF,0x09,0x00,0x44,0x01,0xA0,0x00,0x00,0x00,0x14,0x00,0x03,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,\n    0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x86,0x13,0x81,0xFE,0x64,0xC7,0x72,\n    0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x76,0x43,0x01,0xFF,0x46,0xC7,\n    0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x29,0x66\n  };\n\n  byte SZL_ID_01A0_IDX_0004[92] = {\n    0xFF,0x09,0x00,0x58,0x01,0xA0,0x00,0x00,0x00,0x14,0x00,0x04,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,\n    0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x86,0x13,0x81,0xFE,0x64,0xC7,0x72,\n    0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x76,0x43,0x01,0xFF,0x46,0xC7,\n    0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x29,0x66,0x43,0x04,0xFF,0x84,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x52,0x13,0x90,0x16\n  };\n\n  byte SZL_ID_01A0_IDX_0005[112] = {\n    0xFF,0x09,0x00,0x6C,0x01,0xA0,0x00,0x00,0x00,0x14,0x00,0x05,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,\n    0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x86,0x13,0x81,0xFE,0x64,0xC7,0x72,\n    0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x76,0x43,0x01,0xFF,0x46,0xC7,\n    0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x29,0x66,0x43,0x04,0xFF,0x84,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x52,0x13,0x90,0x16,0x43,0x02,0xFF,\n    0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x56\n  };\n\n  byte SZL_ID_01A0_IDX_0006[132] = {\n    0xFF,0x09,0x00,0x80,0x01,0xA0,0x00,0x00,0x00,0x14,0x00,0x06,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,\n    0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x86,0x13,0x81,0xFE,0x64,0xC7,0x72,\n    0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x76,0x43,0x01,0xFF,0x46,0xC7,\n    0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x29,0x66,0x43,0x04,0xFF,0x84,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x52,0x13,0x90,0x16,0x43,0x02,0xFF,\n    0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x56,0x13,0x81,\n    0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x46\n  };\n\n  byte SZL_ID_01A0_IDX_0007[152] = {\n    0xFF,0x09,0x00,0x94,0x01,0xA0,0x00,0x00,0x00,0x14,0x00,0x07,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,\n    0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x86,0x13,0x81,0xFE,0x64,0xC7,0x72,\n    0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x76,0x43,0x01,0xFF,0x46,0xC7,\n    0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x29,0x66,0x43,0x04,0xFF,0x84,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x52,0x13,0x90,0x16,0x43,0x02,0xFF,\n    0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x56,0x13,0x81,\n    0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x46,0x43,\n    0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x79,0x46\n  };\n\n  byte SZL_ID_01A0_IDX_0008[172] = {\n    0xFF,0x09,0x00,0xA8,0x01,0xA0,0x00,0x00,0x00,0x14,0x00,0x08,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,\n    0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x86,0x13,0x81,0xFE,0x64,0xC7,0x72,\n    0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x76,0x43,0x01,0xFF,0x46,0xC7,\n    0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x29,0x66,0x43,0x04,0xFF,0x84,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x52,0x13,0x90,0x16,0x43,0x02,0xFF,\n    0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x56,0x13,0x81,\n    0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x46,0x43,\n    0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x79,0x46,\n    0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x51,0x19,0x48,\n    0x26\n  };\n\n  byte SZL_ID_01A0_IDX_0009[192] = {\n    0xFF,0x09,0x00,0xBC,0x01,0xA0,0x00,0x00,0x00,0x14,0x00,0x09,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,\n    0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x86,0x13,0x81,0xFE,0x64,0xC7,0x72,\n    0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x76,0x43,0x01,0xFF,0x46,0xC7,\n    0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x29,0x66,0x43,0x04,0xFF,0x84,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x52,0x13,0x90,0x16,0x43,0x02,0xFF,\n    0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x56,0x13,0x81,\n    0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x46,0x43,\n    0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x79,0x46,\n    0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x51,0x19,0x48,\n    0x26,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x50,0x45,\n    0x09,0x96\n  };\n\n  byte SZL_ID_01A0_IDX_000A[212] = {\n    0xFF,0x09,0x00,0xD0,0x01,0xA0,0x00,0x00,0x00,0x14,0x00,0x0A,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,\n    0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x86,0x13,0x81,0xFE,0x64,0xC7,0x72,\n    0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x76,0x43,0x01,0xFF,0x46,0xC7,\n    0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x29,0x66,0x43,0x04,0xFF,0x84,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x52,0x13,0x90,0x16,0x43,0x02,0xFF,\n    0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x56,0x13,0x81,\n    0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x46,0x43,\n    0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x79,0x46,\n    0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x51,0x19,0x48,\n    0x26,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x50,0x45,\n    0x09,0x96,0x13,0x81,0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x50,\n    0x45,0x09,0x86\n  };\n\n  byte SZL_ID_01A0_IDX_000B[232] = {\n    0xFF,0x09,0x00,0xE4,0x01,0xA0,0x00,0x00,0x00,0x14,0x00,0x0B,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,\n    0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x86,0x13,0x81,0xFE,0x64,0xC7,0x72,\n    0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x76,0x43,0x01,0xFF,0x46,0xC7,\n    0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x29,0x66,0x43,0x04,0xFF,0x84,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x52,0x13,0x90,0x16,0x43,0x02,0xFF,\n    0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x56,0x13,0x81,\n    0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x46,0x43,\n    0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x79,0x46,\n    0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x51,0x19,0x48,\n    0x26,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x50,0x45,\n    0x09,0x96,0x13,0x81,0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x50,\n    0x45,0x09,0x86,0x43,0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,\n    0x50,0x45,0x00,0x96\n  };\n\n  byte SZL_ID_01A0_IDX_000C[252] = {\n    0xFF,0x09,0x00,0xF8,0x01,0xA0,0x00,0x00,0x00,0x14,0x00,0x0C,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,\n    0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x86,0x13,0x81,0xFE,0x64,0xC7,0x72,\n    0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x76,0x43,0x01,0xFF,0x46,0xC7,\n    0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x29,0x66,0x43,0x04,0xFF,0x84,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x52,0x13,0x90,0x16,0x43,0x02,0xFF,\n    0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x56,0x13,0x81,\n    0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x46,0x43,\n    0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x79,0x46,\n    0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x51,0x19,0x48,\n    0x26,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x50,0x45,\n    0x09,0x96,0x13,0x81,0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x50,\n    0x45,0x09,0x86,0x43,0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,\n    0x50,0x45,0x00,0x96,0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,\n    0x23,0x50,0x42,0x54,0x66\n  };\n\n  byte SZL_ID_01A0_IDX_000D[272] = {\n    0xFF,0x09,0x01,0x0C,0x01,0xA0,0x00,0x00,0x00,0x14,0x00,0x0D,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,\n    0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x86,0x13,0x81,0xFE,0x64,0xC7,0x72,\n    0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x76,0x43,0x01,0xFF,0x46,0xC7,\n    0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x29,0x66,0x43,0x04,0xFF,0x84,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x52,0x13,0x90,0x16,0x43,0x02,0xFF,\n    0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x56,0x13,0x81,\n    0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x46,0x43,\n    0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x79,0x46,\n    0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x51,0x19,0x48,\n    0x26,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x50,0x45,\n    0x09,0x96,0x13,0x81,0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x50,\n    0x45,0x09,0x86,0x43,0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,\n    0x50,0x45,0x00,0x96,0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,\n    0x23,0x50,0x42,0x54,0x66,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,\n    0x04,0x23,0x50,0x32,0x40,0x46\n  };\n\n  byte SZL_ID_01A0_IDX_000E[292] = {\n    0xFF,0x09,0x01,0x20,0x01,0xA0,0x00,0x00,0x00,0x14,0x00,0x0E,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,\n    0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x86,0x13,0x81,0xFE,0x64,0xC7,0x72,\n    0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x76,0x43,0x01,0xFF,0x46,0xC7,\n    0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x29,0x66,0x43,0x04,0xFF,0x84,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x52,0x13,0x90,0x16,0x43,0x02,0xFF,\n    0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x56,0x13,0x81,\n    0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x46,0x43,\n    0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x79,0x46,\n    0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x51,0x19,0x48,\n    0x26,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x50,0x45,\n    0x09,0x96,0x13,0x81,0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x50,\n    0x45,0x09,0x86,0x43,0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,\n    0x50,0x45,0x00,0x96,0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,\n    0x23,0x50,0x42,0x54,0x66,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,\n    0x04,0x23,0x50,0x32,0x40,0x46,0x13,0x81,0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,\n    0x02,0x04,0x23,0x50,0x32,0x40,0x36\n  };\n\n  byte SZL_ID_01A0_IDX_000F[312] = {\n    0xFF,0x09,0x01,0x34,0x01,0xA0,0x00,0x00,0x00,0x14,0x00,0x0F,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,\n    0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x86,0x13,0x81,0xFE,0x64,0xC7,0x72,\n    0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x76,0x43,0x01,0xFF,0x46,0xC7,\n    0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x29,0x66,0x43,0x04,0xFF,0x84,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x52,0x13,0x90,0x16,0x43,0x02,0xFF,\n    0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x56,0x13,0x81,\n    0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x46,0x43,\n    0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x79,0x46,\n    0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x51,0x19,0x48,\n    0x26,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x50,0x45,\n    0x09,0x96,0x13,0x81,0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x50,\n    0x45,0x09,0x86,0x43,0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,\n    0x50,0x45,0x00,0x96,0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,\n    0x23,0x50,0x42,0x54,0x66,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,\n    0x04,0x23,0x50,0x32,0x40,0x46,0x13,0x81,0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,\n    0x02,0x04,0x23,0x50,0x32,0x40,0x36,0x43,0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,\n    0x94,0x02,0x04,0x23,0x50,0x32,0x31,0x46\n  };\n\n  byte SZL_ID_01A0_IDX_0010[332] = {\n    0xFF,0x09,0x01,0x48,0x01,0xA0,0x00,0x00,0x00,0x14,0x00,0x10,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,\n    0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x86,0x13,0x81,0xFE,0x64,0xC7,0x72,\n    0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x76,0x43,0x01,0xFF,0x46,0xC7,\n    0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x29,0x66,0x43,0x04,0xFF,0x84,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x52,0x13,0x90,0x16,0x43,0x02,0xFF,\n    0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x56,0x13,0x81,\n    0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x46,0x43,\n    0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x79,0x46,\n    0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x51,0x19,0x48,\n    0x26,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x50,0x45,\n    0x09,0x96,0x13,0x81,0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x50,\n    0x45,0x09,0x86,0x43,0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,\n    0x50,0x45,0x00,0x96,0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,\n    0x23,0x50,0x42,0x54,0x66,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,\n    0x04,0x23,0x50,0x32,0x40,0x46,0x13,0x81,0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,\n    0x02,0x04,0x23,0x50,0x32,0x40,0x36,0x43,0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,\n    0x94,0x02,0x04,0x23,0x50,0x32,0x31,0x46,0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x94,0x02,0x04,0x23,0x50,0x29,0x92,0x26\n  };\n\n  byte SZL_ID_01A0_IDX_0011[352] = {\n    0xFF,0x09,0x01,0x5C,0x01,0xA0,0x00,0x00,0x00,0x14,0x00,0x11,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,\n    0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x86,0x13,0x81,0xFE,0x64,0xC7,0x72,\n    0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x76,0x43,0x01,0xFF,0x46,0xC7,\n    0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x29,0x66,0x43,0x04,0xFF,0x84,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x52,0x13,0x90,0x16,0x43,0x02,0xFF,\n    0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x56,0x13,0x81,\n    0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x46,0x43,\n    0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x79,0x46,\n    0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x51,0x19,0x48,\n    0x26,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x50,0x45,\n    0x09,0x96,0x13,0x81,0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x50,\n    0x45,0x09,0x86,0x43,0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,\n    0x50,0x45,0x00,0x96,0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,\n    0x23,0x50,0x42,0x54,0x66,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,\n    0x04,0x23,0x50,0x32,0x40,0x46,0x13,0x81,0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,\n    0x02,0x04,0x23,0x50,0x32,0x40,0x36,0x43,0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,\n    0x94,0x02,0x04,0x23,0x50,0x32,0x31,0x46,0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x94,0x02,0x04,0x23,0x50,0x29,0x92,0x26,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,0x00,0x08,0x14,\n    0x77,0x14,0x94,0x02,0x04,0x23,0x49,0x22,0x26,0x66\n  };\n\n  byte SZL_ID_01A0_IDX_0012[372] = {\n    0xFF,0x09,0x01,0x70,0x01,0xA0,0x00,0x00,0x00,0x14,0x00,0x12,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,\n    0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x86,0x13,0x81,0xFE,0x64,0xC7,0x72,\n    0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x76,0x43,0x01,0xFF,0x46,0xC7,\n    0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x29,0x66,0x43,0x04,0xFF,0x84,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x52,0x13,0x90,0x16,0x43,0x02,0xFF,\n    0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x56,0x13,0x81,\n    0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x46,0x43,\n    0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x79,0x46,\n    0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x51,0x19,0x48,\n    0x26,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x50,0x45,\n    0x09,0x96,0x13,0x81,0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x50,\n    0x45,0x09,0x86,0x43,0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,\n    0x50,0x45,0x00,0x96,0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,\n    0x23,0x50,0x42,0x54,0x66,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,\n    0x04,0x23,0x50,0x32,0x40,0x46,0x13,0x81,0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,\n    0x02,0x04,0x23,0x50,0x32,0x40,0x36,0x43,0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,\n    0x94,0x02,0x04,0x23,0x50,0x32,0x31,0x46,0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x94,0x02,0x04,0x23,0x50,0x29,0x92,0x26,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,0x00,0x08,0x14,\n    0x77,0x14,0x94,0x02,0x04,0x23,0x49,0x22,0x26,0x66,0x13,0x81,0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,\n    0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x49,0x22,0x26,0x56\n  };\n\n  byte SZL_ID_01A0_IDX_0013[392] = {\n    0xFF,0x09,0x01,0x84,0x01,0xA0,0x00,0x00,0x00,0x14,0x00,0x13,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,\n    0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x86,0x13,0x81,0xFE,0x64,0xC7,0x72,\n    0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x76,0x43,0x01,0xFF,0x46,0xC7,\n    0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x29,0x66,0x43,0x04,0xFF,0x84,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x52,0x13,0x90,0x16,0x43,0x02,0xFF,\n    0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x56,0x13,0x81,\n    0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x46,0x43,\n    0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x79,0x46,\n    0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x51,0x19,0x48,\n    0x26,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x50,0x45,\n    0x09,0x96,0x13,0x81,0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x50,\n    0x45,0x09,0x86,0x43,0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,\n    0x50,0x45,0x00,0x96,0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,\n    0x23,0x50,0x42,0x54,0x66,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,\n    0x04,0x23,0x50,0x32,0x40,0x46,0x13,0x81,0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,\n    0x02,0x04,0x23,0x50,0x32,0x40,0x36,0x43,0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,\n    0x94,0x02,0x04,0x23,0x50,0x32,0x31,0x46,0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x94,0x02,0x04,0x23,0x50,0x29,0x92,0x26,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,0x00,0x08,0x14,\n    0x77,0x14,0x94,0x02,0x04,0x23,0x49,0x22,0x26,0x66,0x13,0x81,0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,\n    0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x49,0x22,0x26,0x56,0x43,0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,\n    0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x49,0x22,0x17,0x66\n  };\n\n  byte SZL_ID_01A0_IDX_0014[412] = {\n    0xFF,0x09,0x01,0x98,0x01,0xA0,0x00,0x00,0x00,0x14,0x00,0x14,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,\n    0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x86,0x13,0x81,0xFE,0x64,0xC7,0x72,\n    0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x76,0x43,0x01,0xFF,0x46,0xC7,\n    0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x29,0x66,0x43,0x04,0xFF,0x84,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x52,0x13,0x90,0x16,0x43,0x02,0xFF,\n    0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x56,0x13,0x81,\n    0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x46,0x43,\n    0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x79,0x46,\n    0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x51,0x19,0x48,\n    0x26,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x50,0x45,\n    0x09,0x96,0x13,0x81,0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x50,\n    0x45,0x09,0x86,0x43,0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,\n    0x50,0x45,0x00,0x96,0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,\n    0x23,0x50,0x42,0x54,0x66,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,\n    0x04,0x23,0x50,0x32,0x40,0x46,0x13,0x81,0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,\n    0x02,0x04,0x23,0x50,0x32,0x40,0x36,0x43,0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,\n    0x94,0x02,0x04,0x23,0x50,0x32,0x31,0x46,0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x94,0x02,0x04,0x23,0x50,0x29,0x92,0x26,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,0x00,0x08,0x14,\n    0x77,0x14,0x94,0x02,0x04,0x23,0x49,0x22,0x26,0x66,0x13,0x81,0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,\n    0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x49,0x22,0x26,0x56,0x43,0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,\n    0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x49,0x22,0x17,0x66,0x43,0x04,0xFF,0x84,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x49,0x19,0x75,0x46\n  };\n\n  byte SZL_ID_01A0_IDX_0015[432] = {\n    0xFF,0x09,0x01,0xAC,0x01,0xA0,0x00,0x00,0x00,0x14,0x00,0x15,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,\n    0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x86,0x13,0x81,0xFE,0x64,0xC7,0x72,\n    0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x38,0x76,0x43,0x01,0xFF,0x46,0xC7,\n    0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x52,0x16,0x29,0x66,0x43,0x04,0xFF,0x84,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x52,0x13,0x90,0x16,0x43,0x02,0xFF,\n    0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x56,0x13,0x81,\n    0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x88,0x46,0x43,\n    0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x51,0x21,0x79,0x46,\n    0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x51,0x19,0x48,\n    0x26,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x50,0x45,\n    0x09,0x96,0x13,0x81,0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x50,\n    0x45,0x09,0x86,0x43,0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,\n    0x50,0x45,0x00,0x96,0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,\n    0x23,0x50,0x42,0x54,0x66,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,\n    0x04,0x23,0x50,0x32,0x40,0x46,0x13,0x81,0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,0x94,\n    0x02,0x04,0x23,0x50,0x32,0x40,0x36,0x43,0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,0x08,0x14,0x77,0x14,\n    0x94,0x02,0x04,0x23,0x50,0x32,0x31,0x46,0x43,0x04,0xFF,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x94,0x02,0x04,0x23,0x50,0x29,0x92,0x26,0x43,0x02,0xFF,0x68,0xC7,0x00,0x00,0x00,0x08,0x14,\n    0x77,0x14,0x94,0x02,0x04,0x23,0x49,0x22,0x26,0x66,0x13,0x81,0xFE,0x64,0xC7,0x72,0x43,0x04,0x08,\n    0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x49,0x22,0x26,0x56,0x43,0x01,0xFF,0x46,0xC7,0x72,0x43,0x04,\n    0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x49,0x22,0x17,0x66,0x43,0x04,0xFF,0x84,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x94,0x02,0x04,0x23,0x49,0x19,0x75,0x46,0x43,0x02,0xFF,0x68,0xC7,0x00,\n    0x00,0x00,0x08,0x14,0x77,0x14,0x94,0x02,0x04,0x23,0x48,0x32,0x21,0x16\n  };\n\n  byte SZL_ID_0117_IDX_0000[16] = {\n    0xFF,0x09,0x00,0x0C,0x01,0x17,0x00,0x00,0x00,0x04,0x00,0x01,0x00,0x00,0x00,0x01\n  };\n\n  byte SZL_ID_0117_IDX_0001[16] = {\n    0xFF,0x09,0x00,0x0C,0x01,0x17,0x00,0x01,0x00,0x04,0x00,0x01,0x00,0x01,0x00,0x03\n  };\n\n  byte SZL_ID_0117_IDX_0002[16] = {\n    0xFF,0x09,0x00,0x0C,0x01,0x17,0x00,0x02,0x00,0x04,0x00,0x01,0x00,0x02,0x00,0x02\n  };\n\n  byte SZL_ID_0117_IDX_0003[16] = {\n    0xFF,0x09,0x00,0x0C,0x01,0x17,0x00,0x03,0x00,0x04,0x00,0x01,0x00,0x03,0x00,0x01\n  };\n\n  byte SZL_ID_0117_IDX_0004[16] = {\n    0xFF,0x09,0x00,0x0C,0x01,0x17,0x00,0x04,0x00,0x04,0x00,0x01,0x00,0x04,0x00,0x01\n  };\n\n  byte SZL_ID_0118_IDX_0000[16] = {\n    0xFF,0x09,0x00,0x0C,0x01,0x18,0x00,0x00,0x00,0x04,0x00,0x01,0x00,0x00,0x00,0x08\n  };\n\n  byte SZL_ID_0118_IDX_0001[16] = {\n    0xFF,0x09,0x00,0x0C,0x01,0x18,0x00,0x01,0x00,0x04,0x00,0x01,0x00,0x01,0x00,0x08\n  };\n\n  byte SZL_ID_0118_IDX_0002[16] = {\n    0xFF,0x09,0x00,0x0C,0x01,0x18,0x00,0x02,0x00,0x04,0x00,0x01,0x00,0x02,0x00,0x08\n  };\n\n  byte SZL_ID_0118_IDX_0003[16] = {\n    0xFF,0x09,0x00,0x0C,0x01,0x18,0x00,0x03,0x00,0x04,0x00,0x01,0x00,0x03,0x00,0x08\n  };\n\n  byte SZL_ID_0131_IDX_0001[52] = {\n\t0xFF,0x09,0x00,0x30,0x01,0x31,0x00,0x01,0x00,0x28,0x00,0x01,0x00,0x01,\n    0x08,0x00,   // PDU SIZE        : We expose 2048      00F0\n    0x04,0x00,   // Max Commections : We expose 1024      0010\n    0x00,0xB7,0x1B,0x00,0x00,0x02,0xDC,0x6C,0x05,0xF5,0xE1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0131_IDX_0002[52] = {\n    0xFF,0x09,0x00,0x30,0x01,0x31,0x00,0x02,0x00,0x28,0x00,0x01,0x00,0x02,0xBE,0xFD,0x4F,0x00,0x00,\n    0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x3C,0x01,0x08,0x00,0x00,0x00,0x7D,0x00,0x00,0x05,0x03,0x0F,\n    0x00,0x00,0x08,0x00,0x00,0x0C,0x00,0x0A,0x00,0x00,0x00,0x01,0x00,0x00\n  };\n\n  byte SZL_ID_0131_IDX_0003[52] = {\n\t0xFF,0x09,0x00,0x30,0x01,0x31,0x00,0x03,0x00,0x28,0x00,0x01,0x00,0x03,0x7F,0xFC,0x83,0x01,\n\t0x00,0xF0, // Max size of consistently readable data (will be set = PDU size)\n\t0x00,0x10,0x00,0x01,0x02,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0131_IDX_0004[52] = {\n    0xFF,0x09,0x00,0x30,0x01,0x31,0x00,0x04,0x00,0x28,0x00,0x01,0x00,0x04,0xFE,0x01,0x62,0x41,0x63,\n    0x00,0x1E,0x00,0x10,0x10,0x10,0x04,0x02,0x00,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0131_IDX_0005[52] = {\n    0xFF,0x09,0x00,0x30,0x01,0x31,0x00,0x05,0x00,0x28,0x00,0x01,0x00,0x05,0x3E,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x10,0x01,0xF4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0131_IDX_0006[52] = {\n    0xFF,0x09,0x00,0x30,0x01,0x31,0x00,0x06,0x00,0x28,0x00,0x01,0x00,0x06,0xF3,0x00,0x00,0xF8,0x01,\n    0xF0,0xFF,0x4E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x20,\n    0x01,0x00,0x00,0x0E,0x00,0x4C,0xFF,0xFF,0x05,0xC0,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0131_IDX_0007[52] = {\n    0xFF,0x09,0x00,0x30,0x01,0x31,0x00,0x07,0x00,0x28,0x00,0x01,0x00,0x07,0x01,0x00,0x3F,0x00,0x20,\n    0x01,0x01,0x00,0x00,0x00,0x01,0x08,0x01,0x08,0x01,0x08,0x20,0x08,0x02,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0131_IDX_0008[52] = {\n    0xFF,0x09,0x00,0x30,0x01,0x31,0x00,0x08,0x00,0x28,0x00,0x01,0x00,0x08,0x70,0x03,0x70,0x02,0x70,\n    0x02,0x40,0x32,0x40,0x32,0x40,0x32,0x40,0x64,0x40,0x32,0x40,0x32,0x40,0x64,0x40,0x64,0x40,0x64,\n    0x40,0x64,0x40,0x64,0x40,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0131_IDX_0009[52] = {\n    0xFF,0x09,0x00,0x30,0x01,0x31,0x00,0x09,0x00,0x28,0x00,0x01,0x00,0x09,0x04,0x06,0x01,0x00,0x01,\n    0xF7,0x01,0xF7,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n  byte SZL_ID_0C91_IDX_07FE[28] = {\n    0xFF,0x09,0x00,0x18,0x0C,0x91,0x07,0xFE,0x00,0x10,0x00,0x01,0x00,0x00,0x02,0x02,0x07,0xFE,0xA7,\n    0xC4,0xA7,0xC4,0x00,0x00,0xB4,0x02,0x00,0x11\n  };\n\n\n#endif\n\n"
  },
  {
    "path": "deps/snap7/src/core/s7_isotcp.cpp",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.3.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|=============================================================================*/\n#include \"s7_isotcp.h\"\n//---------------------------------------------------------------------------\nTIsoTcpSocket::TIsoTcpSocket()\n{\n\tRecvTimeout = 3000; // Some old equipments are a bit slow to answer....\n\tRemotePort  = isoTcpPort;\n\t// These fields should be $0000 and in any case RFC says that they are not considered.\n\t// But some equipment...need a non zero value for the source reference.\n\tDstRef = 0x0000;\n\tSrcRef = 0x0100;\n\t// PDU size requested\n\tIsoPDUSize =1024;\n    IsoMaxFragments=MaxIsoFragments;\n    LastIsoError=0;\n}\n//---------------------------------------------------------------------------\nTIsoTcpSocket::~TIsoTcpSocket()\n{\n}\n//---------------------------------------------------------------------------\nint TIsoTcpSocket::CheckPDU(void *pPDU, u_char PduTypeExpected)\n{\n\tPIsoHeaderInfo Info;\n\tint Size;\n    ClrIsoError();\n\tif (pPDU!=0)\n\t{\n\t\tInfo = PIsoHeaderInfo(pPDU);\n\t\tSize = PDUSize(pPDU);\n\t\t// Performs check\n\t\tif (( Size<7 ) || ( Size>IsoPayload_Size ) ||  // Checks RFC 1006 header length\n\t\t\t( Info->HLength<sizeof( TCOTP_DT )-1 ) ||  // Checks ISO 8073 header length\n\t\t\t( Info->PDUType!=PduTypeExpected))         // Checks PDU Type\n\t\t  return SetIsoError(errIsoInvalidPDU);\n\t\telse\n\t\t  return noError;\n\t}\n\telse\n\t\treturn SetIsoError(errIsoNullPointer);\n}\n//---------------------------------------------------------------------------\nint TIsoTcpSocket::SetIsoError(int Error)\n{\n\tLastIsoError = Error | LastTcpError;\n\treturn LastIsoError;\n}\n//---------------------------------------------------------------------------\nvoid TIsoTcpSocket::ClrIsoError()\n{\n    LastIsoError=0;\n    LastTcpError=0;\n}\n//---------------------------------------------------------------------------\nint TIsoTcpSocket::BuildControlPDU()\n{\n\tint ParLen, IsoLen;\n\n    ClrIsoError();\n\tFControlPDU.COTP.Params.PduSizeCode=0xC0; // code that identifies TPDU size\n\tFControlPDU.COTP.Params.PduSizeLen =0x01; // 1 byte this field\n\tswitch(IsoPDUSize)\n\t{\n\t\tcase 128:\n\t\t\tFControlPDU.COTP.Params.PduSizeVal =0x07;\n\t\t\tbreak;\n\t\tcase 256:\n\t\t\tFControlPDU.COTP.Params.PduSizeVal =0x08;\n\t\t\tbreak;\n\t\tcase 512:\n\t\t\tFControlPDU.COTP.Params.PduSizeVal =0x09;\n\t\t\tbreak;\n\t\tcase 1024:\n\t\t\tFControlPDU.COTP.Params.PduSizeVal =0x0A;\n\t\t\tbreak;\n\t\tcase 2048:\n\t\t\tFControlPDU.COTP.Params.PduSizeVal =0x0B;\n\t\t\tbreak;\n\t\tcase 4096:\n\t\t\tFControlPDU.COTP.Params.PduSizeVal =0x0C;\n\t\t\tbreak;\n\t\tcase 8192:\n\t\t\tFControlPDU.COTP.Params.PduSizeVal =0x0D;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tFControlPDU.COTP.Params.PduSizeVal =0x0B;  // Our Default\n\t};\n\t// Build TSAPs\n\tFControlPDU.COTP.Params.TSAP[0]=0xC1;   // code that identifies source TSAP\n\tFControlPDU.COTP.Params.TSAP[1]=2;      // source TSAP Len\n\tFControlPDU.COTP.Params.TSAP[2]=(SrcTSap>>8) & 0xFF; // HI part\n\tFControlPDU.COTP.Params.TSAP[3]=SrcTSap & 0xFF; // LO part\n\n\tFControlPDU.COTP.Params.TSAP[4]=0xC2; // code that identifies dest TSAP\n\tFControlPDU.COTP.Params.TSAP[5]=2;    // dest TSAP Len\n\tFControlPDU.COTP.Params.TSAP[6]=(DstTSap>>8) & 0xFF; // HI part\n\tFControlPDU.COTP.Params.TSAP[7]=DstTSap & 0xFF; // LO part\n\n\t// Params length\n\tParLen=11;            // 2 Src TSAP (Code+field Len)      +\n\t\t\t\t\t\t  // 2 Src TSAP len                   +\n\t\t\t\t\t\t  // 2 Dst TSAP (Code+field Len)      +\n\t\t\t\t\t\t  // 2 Src TSAP len                   +\n\t\t\t\t\t\t  // 3 PDU size (Code+field Len+Val)  = 11\n\t// Telegram length\n\tIsoLen=sizeof(TTPKT)+ // TPKT Header\n\t\t\t7 +           // COTP Header Size without params\n\t\t\tParLen;       // COTP params\n\n\tFControlPDU.TPKT.Version  =isoTcpVersion;\n\tFControlPDU.TPKT.Reserved =0;\n\tFControlPDU.TPKT.HI_Lenght=0; // Connection Telegram size cannot exced 255 bytes, so\n\t\t\t\t\t\t\t\t  // this field is always 0\n\tFControlPDU.TPKT.LO_Lenght=IsoLen;\n\n\tFControlPDU.COTP.HLength  =ParLen + 6;  // <-- 6 = 7 - 1 (COTP Header size - 1)\n\tFControlPDU.COTP.PDUType  =pdu_type_CR; // Connection Request\n\tFControlPDU.COTP.DstRef   =DstRef;      // Destination reference\n\tFControlPDU.COTP.SrcRef   =SrcRef;      // Source reference\n\tFControlPDU.COTP.CO_R     =0x00;        // Class + Option : RFC0983 states that it must be always 0x40\n\t\t\t\t\t\t\t\t\t\t\t// but for some equipment (S7) must be 0 in disaccord of specifications !!!\n\treturn noError;\n}\n//---------------------------------------------------------------------------\nint TIsoTcpSocket::PDUSize(void *pPDU)\n{\n\treturn PIsoHeaderInfo(pPDU)->TPKT.HI_Lenght*256+PIsoHeaderInfo( pPDU )->TPKT.LO_Lenght;\n}\n//---------------------------------------------------------------------------\nvoid TIsoTcpSocket::IsoParsePDU(TIsoControlPDU pdu)\n{\n// Currently we accept a connection with any kind of src/dst tsap\n// Override to implement special filters.\n}\n//---------------------------------------------------------------------------\nint TIsoTcpSocket::IsoConfirmConnection(u_char PDUType)\n{\n    PIsoControlPDU CPDU = PIsoControlPDU(&PDU);\n\tu_short TempRef;\n\n\tClrIsoError();\n\tPDU.COTP.PDUType=PDUType;\n\t// Exchange SrcRef<->DstRef, not strictly needed by COTP 8073 but S7PLC as client needs it.\n\tTempRef=CPDU->COTP.DstRef;\n\tCPDU->COTP.DstRef=CPDU->COTP.SrcRef;\n\tCPDU->COTP.SrcRef=0x0100;//TempRef;\n\n\treturn SendPacket(&PDU,PDUSize(&PDU));\n}\n//---------------------------------------------------------------------------\nvoid TIsoTcpSocket::FragmentSkipped(int Size)\n{\n// override for log purpose\n}\n//---------------------------------------------------------------------------\nint TIsoTcpSocket::isoConnect()\n{\n\tpbyte TmpControlPDU;\n    PIsoControlPDU ControlPDU;\n\tu_int Length;\n\tint Result;\n\n\t// Build the default connection telegram\n\tBuildControlPDU();\n    ControlPDU =&FControlPDU;\n\n\t// Checks the format\n\tResult =CheckPDU(ControlPDU, pdu_type_CR);\n\tif (Result!=0)\n\t\treturn Result;\n\n\tResult =SckConnect();\n\tif (Result==noError)\n\t{\n\t\t// Calcs the length\n\t\tLength =PDUSize(ControlPDU);\n\t\t// Send connection telegram\n\t\tSendPacket(ControlPDU, Length);\n\t\tif (LastTcpError==0)\n\t\t{\n\t\t\tTmpControlPDU = pbyte(ControlPDU);\n\t\t\t// Receives TPKT header (4 bytes)\n\t\t\tRecvPacket(TmpControlPDU, sizeof(TTPKT));\n\t\t\tif (LastTcpError==0)\n\t\t\t{\n\t\t\t\t// Calc the packet length\n\t\t\t\tLength =PDUSize(TmpControlPDU);\n\t\t\t\t// Check if it fits in the buffer and if it's greater then TTPKT size\n\t\t\t\tif ((Length<=sizeof(TIsoControlPDU)) && (Length>sizeof(TTPKT)))\n\t\t\t\t{\n\t\t\t\t\t// Points to COTP\n\t\t\t\t\tTmpControlPDU+=sizeof(TTPKT);\n\t\t\t\t\tLength -= sizeof(TTPKT);\n\t\t\t\t\t// Receives remainin bytes 4 bytes after\n\t\t\t\t\tRecvPacket(TmpControlPDU, Length);\n\t\t\t\t\tif (LastTcpError==0)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Finally checks the Connection Confirm telegram\n\t\t\t\t\t\tResult =CheckPDU(ControlPDU, pdu_type_CC);\n\t\t\t\t\t\tif (Result!=0)\n\t\t\t\t\t\t\tLastIsoError=Result;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tResult =SetIsoError(errIsoRecvPacket);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tResult =SetIsoError(errIsoInvalidPDU);\n\t\t\t}\n\t\t\telse\n\t\t\t\tResult =SetIsoError(errIsoRecvPacket);\n\t\t\t// Flush buffer\n\t\t\tif (Result!=0)\n\t\t\t\tPurge();\n\t\t}\n\t\telse\n\t\t\tResult =SetIsoError(errIsoSendPacket);\n\n\t\tif (Result!=0)\n\t\t\tSckDisconnect();\n\t}\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nint TIsoTcpSocket::isoSendBuffer(void *Data, int Size)\n{\n\tint Result;\n\tu_int IsoSize;\n\n    ClrIsoError();\n\t// Total Size = Size + Header Size\n\tIsoSize =Size+DataHeaderSize;\n\t// Checks the length\n\tif ((IsoSize>0) && (IsoSize<=IsoFrameSize))\n\t{\n\t\t// Builds the header\n\t\tResult =0;\n\t\t// TPKT\n\t\tPDU.TPKT.Version  = isoTcpVersion;\n\t\tPDU.TPKT.Reserved = 0;\n\t\tPDU.TPKT.HI_Lenght= (u_short(IsoSize)>> 8) & 0xFF;\n\t\tPDU.TPKT.LO_Lenght= u_short(IsoSize) & 0xFF;\n\t\t// COPT\n\t\tPDU.COTP.HLength   =sizeof(TCOTP_DT)-1;\n\t\tPDU.COTP.PDUType   =pdu_type_DT;\n\t\tPDU.COTP.EoT_Num   =pdu_EoT;\n\t\t// Fill payload\n\t\tif (Data!=0) // Data=null ==> use internal buffer PDU.Payload\n            memcpy(&PDU.Payload, Data, Size);\n        // Send over TCP/IP\n        SendPacket(&PDU, IsoSize);\n\n        if (LastTcpError!=0)\n            Result =SetIsoError(errIsoSendPacket);\n\t}\n\telse\n\t\tResult =SetIsoError(errIsoInvalidDataSize );\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nint TIsoTcpSocket::isoRecvBuffer(void *Data, int & Size)\n{\n\tint Result;\n\n    ClrIsoError();\n\tSize =0;\n\tResult =isoRecvPDU(&PDU);\n\tif (Result==0)\n\t{\n\t\tSize =PDUSize( &PDU )-DataHeaderSize;\n\t\tif (Data!=0)  // Data=NULL ==> a child will consume directly PDY.Payload\n            memcpy(Data, &PDU.Payload, Size);\n\t}\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nint TIsoTcpSocket::isoExchangeBuffer(void *Data, int &Size)\n{\n\tint Result;\n\n    ClrIsoError();\n\tResult =isoSendBuffer(Data, Size);\n\tif (Result==0)\n\t\tResult =isoRecvBuffer(Data, Size);\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nbool TIsoTcpSocket::IsoPDUReady()\n{\n    ClrIsoError();\n\treturn PacketReady(sizeof(TCOTP_DT));\n}\n//---------------------------------------------------------------------------\nint TIsoTcpSocket::isoDisconnect(bool OnlyTCP)\n{\n\tint Result;\n\n    ClrIsoError();\n\tif (Connected)\n\t\tPurge(); // Flush pending\n\tLastIsoError=0;\n\t// OnlyTCP true -> Disconnect Request telegram is not required : only TCP disconnection\n\tif (!OnlyTCP)\n\t{\n\t\t// if we are connected -> we have a valid connection telegram\n\t\tif (Connected)\n\t\t\tFControlPDU.COTP.PDUType =pdu_type_DR;\n\t\t// Checks the format\n\t\tResult =CheckPDU(&FControlPDU, pdu_type_DR);\n\t\tif (Result!=0)\n\t\t\treturn Result;\n\t\t// Sends Disconnect request\n\t\tSendPacket(&FControlPDU, PDUSize(&FControlPDU));\n\t\tif (LastTcpError!=0)\n\t\t{\n\t\t\tResult =SetIsoError(errIsoSendPacket);\n\t\t\treturn Result;\n\t\t}\n\t}\n\t// TCP disconnect\n\tSckDisconnect();\n\tif (LastTcpError!=0)\n\t\tResult =SetIsoError(errIsoDisconnect);\n\telse\n\t\tResult =0;\n\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nint TIsoTcpSocket::isoSendPDU(PIsoDataPDU Data)\n{\n\tint Result;\n\n    ClrIsoError();\n\tResult=CheckPDU(Data,pdu_type_DT);\n\tif (Result==0)\n\t{\n\t\tSendPacket(Data,PDUSize(Data));\n\t\tif (LastTcpError!=0)\n\t\t\tResult=SetIsoError(errIsoSendPacket);\n\t}\n    return Result;\n}\n//------------------------------------------------------------------------------\nint TIsoTcpSocket::isoRecvFragment(void *From, int Max, int &Size, bool &EoT)\n{\n\tint DataLength;\n\n\tSize =0;\n\tEoT =false;\n    byte PDUType;\n    ClrIsoError();\n\t// header is received always from beginning\n\tRecvPacket(&PDU, DataHeaderSize); // TPKT + COPT_DT\n\tif (LastTcpError==0)\n\t{\n        PDUType=PDU.COTP.PDUType;\n        switch (PDUType)\n        {\n\t\t\tcase pdu_type_CR:\n\t\t\tcase pdu_type_DR:\n\t\t\t\tEoT=true;\n\t\t\t\tbreak;\n\t\t\tcase pdu_type_DT:\n                EoT = (PDU.COTP.EoT_Num & 0x80) == 0x80;  // EoT flag\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn SetIsoError(errIsoInvalidPDU);\n        }\n\n\t\tDataLength = PDUSize(&PDU) - DataHeaderSize;\n\t\tif (CheckPDU(&PDU, PDUType)!=0)\n\t\t\treturn LastIsoError;\n\t\t// Checks for data presence\n\t\tif (DataLength>0)  // payload present\n\t\t{\n\t\t\t// Check if the data fits in the buffer\n\t\t\tif(DataLength<=Max)\n\t\t\t{\n\t\t\t\tRecvPacket(From, DataLength);\n\t\t\t\tif (LastTcpError!=0)\n\t\t\t\t\treturn SetIsoError(errIsoRecvPacket);\n\t\t\t\telse\n\t\t\t\t\tSize =DataLength;\n\t\t\t}\n\t\t\telse\n\t\t\t\treturn SetIsoError(errIsoPduOverflow);\n\t\t}\n\t}\n\telse\n\t\treturn SetIsoError(errIsoRecvPacket);\n\n\treturn LastIsoError;\n}\n//---------------------------------------------------------------------------\n// Fragments Recv schema\n//------------------------------------------------------------------------------\n//\n//         packet 1                 packet 2                 packet 3\n// +--------+------------+  +--------+------------+  +--------+------------+\n// | HEADER | FRAGMENT 1 |  | HEADER | FRAGMENT 2 |  | HEADER | FRAGMENT 3 |\n// +--------+------------+  +--------+------------+  +--------+------------+\n//                |                         |                        |\n//                |             +-----------+                        |\n//                |             |                                    |\n//                |             |           +------------------------+\n//                |             |           |      (Packet 3 has EoT Flag set)\n//                V             V           V\n// +--------+------------+------------+------------+\n// | HEADER | FRAGMENT 1 : FRAGMENT 2 : FRAGMENT 3 |\n// +--------+------------+------------+------------+\n//     ^\n//     |\n//     +-- A new header is built with updated info\n//\n//------------------------------------------------------------------------------\nint TIsoTcpSocket::isoRecvPDU(PIsoDataPDU Data)\n{\n\tint Result;\n\tint Size;\n\tpbyte pData;\n\tint max;\n\tint Offset;\n\tint Received;\n\tint NumParts;\n\tbool Complete;\n\n\tNumParts =1;\n\tOffset =0;\n\tComplete =false;\n    ClrIsoError();\n\tpData = pbyte(&PDU.Payload);\n\tdo {\n\t\tpData=pData+Offset;\n\t\tmax =IsoPayload_Size-Offset; // Maximum packet allowed\n\t\tif (max>0)\n\t\t{\n\t\t\tResult =isoRecvFragment(pData, max, Received, Complete);\n\t\t\tif((Result==0) &&  !Complete)\n\t\t\t{\n\t\t\t\t++NumParts;\n\t\t\t\tOffset += Received;\n\t\t\t\tif (NumParts>IsoMaxFragments)\n\t\t\t\t\tResult =SetIsoError(errIsoTooManyFragments);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t\tResult =SetIsoError(errIsoTooManyFragments);\n\t} while ((!Complete) && (Result==0));\n\n\n\tif (Result==0)\n\t{\n\t\t// Add to offset the header size\n\t\tSize =Offset+Received+DataHeaderSize;\n\t\t// Adjust header\n\t\tPDU.TPKT.HI_Lenght =(u_short(Size)>>8) & 0xFF;\n\t\tPDU.TPKT.LO_Lenght =u_short(Size) & 0xFF;\n\t\t// Copies data if target is not the local PDU\n\t\tif (Data!=&PDU)\n            memcpy(Data, &PDU, Size);\n\t}\n\telse\n        if (LastTcpError!=WSAECONNRESET)\n            Purge();\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nint TIsoTcpSocket::isoExchangePDU(PIsoDataPDU Data)\n{\n    int Result;\n    ClrIsoError();\n\tResult=isoSendPDU(Data);\n\tif (Result==0)\n\t\tResult=isoRecvPDU(Data);\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nvoid TIsoTcpSocket::IsoPeek(void *pPDU, TPDUKind &PduKind)\n{\n\tPIsoHeaderInfo Info;\n\tu_int IsoLen;\n\n    Info=PIsoHeaderInfo(pPDU);\n    IsoLen=PDUSize(Info);\n\n    // Check for empty fragment : size of PDU = size of header and nothing else\n    if (IsoLen==DataHeaderSize )\n    {\n        // We don't need to check the EoT flag since the PDU is empty....\n        PduKind=pkEmptyFragment;\n        return;\n    };\n    // Check for invalid packet : size of PDU < size of header\n    if (IsoLen<DataHeaderSize )\n    {\n        PduKind=pkInvalidPDU;\n        return;\n    };\n    // Here IsoLen>DataHeaderSize : check the PDUType\n    switch (Info->PDUType)\n    {\n        case pdu_type_CR:\n            PduKind=pkConnectionRequest;\n            break;\n        case pdu_type_DR:\n            PduKind=pkDisconnectRequest;\n            break;\n        case pdu_type_DT:\n            PduKind=pkValidData;\n            break;\n        default:\n            PduKind=pkUnrecognizedType;\n    };\n}\n\n\n\n"
  },
  {
    "path": "deps/snap7/src/core/s7_isotcp.h",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.3.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|=============================================================================*/\n#ifndef s7_isotcp_h\n#define s7_isotcp_h\n//---------------------------------------------------------------------------\n#include \"snap_msgsock.h\"\n//---------------------------------------------------------------------------\n#pragma pack(1)\n\n#define isoTcpVersion    \t3      // RFC 1006\n#define isoTcpPort    \t\t102    // RFC 1006\n#define isoInvalidHandle        0\n#define MaxTSAPLength    \t16     // Max Lenght for Src and Dst TSAP\n#define MaxIsoFragments         64     // Max fragments\n#define IsoPayload_Size    \t4096   // Iso telegram Buffer size\n\n#define noError    \t\t\t0\n\nconst longword errIsoMask    \t        = 0x000F0000;\nconst longword errIsoBase               = 0x0000FFFF;\n\nconst longword errIsoConnect            = 0x00010000; // Connection error\nconst longword errIsoDisconnect         = 0x00020000; // Disconnect error\nconst longword errIsoInvalidPDU         = 0x00030000; // Bad format\nconst longword errIsoInvalidDataSize    = 0x00040000; // Bad Datasize passed to send/recv : buffer is invalid\nconst longword errIsoNullPointer    \t= 0x00050000; // Null passed as pointer\nconst longword errIsoShortPacket    \t= 0x00060000; // A short packet received\nconst longword errIsoTooManyFragments   = 0x00070000; // Too many packets without EoT flag\nconst longword errIsoPduOverflow    \t= 0x00080000; // The sum of fragments data exceded maximum packet size\nconst longword errIsoSendPacket         = 0x00090000; // An error occurred during send\nconst longword errIsoRecvPacket         = 0x000A0000; // An error occurred during recv\nconst longword errIsoInvalidParams    \t= 0x000B0000; // Invalid TSAP params\nconst longword errIsoResvd_1    \t    = 0x000C0000; // Unassigned\nconst longword errIsoResvd_2    \t    = 0x000D0000; // Unassigned\nconst longword errIsoResvd_3    \t    = 0x000E0000; // Unassigned\nconst longword errIsoResvd_4    \t    = 0x000F0000; // Unassigned\n\nconst longword ISO_OPT_TCP_NODELAY   \t= 0x00000001; // Disable Nagle algorithm\nconst longword ISO_OPT_INSIDE_MTU    \t= 0x00000002; // Max packet size < MTU ethernet card\n\n// TPKT Header - ISO on TCP - RFC 1006 (4 bytes)\ntypedef struct{\n\tu_char Version;    // Always 3 for RFC 1006\n\tu_char Reserved;   // 0\n\tu_char HI_Lenght;  // High part of packet lenght (entire frame, payload and TPDU included)\n\tu_char LO_Lenght;  // Low part of packet lenght (entire frame, payload and TPDU included)\n} TTPKT;               // Packet length : min 7 max 65535\n\ntypedef struct {\n\tu_char PduSizeCode;\n\tu_char PduSizeLen;\n\tu_char PduSizeVal;\n\tu_char TSAP[245]; // We don't know in advance these fields....\n} TCOPT_Params ;\n\n// PDU Type constants - ISO 8073, not all are mentioned in RFC 1006\n// For our purposes we use only those labeled with **\n// These constants contains 4 low bit order 0 (credit nibble)\n//\n//     $10 ED : Expedited Data\n//     $20 EA : Expedited Data Ack\n//     $40 UD : CLTP UD\n//     $50 RJ : Reject\n//     $70 AK : Ack data\n// **  $80 DR : Disconnect request (note : S7 doesn't use it)\n// **  $C0 DC : Disconnect confirm (note : S7 doesn't use it)\n// **  $D0 CC : Connection confirm\n// **  $E0 CR : Connection request\n// **  $F0 DT : Data\n//\n\n// COTP Header for CONNECTION REQUEST/CONFIRM - DISCONNECT REQUEST/CONFIRM\ntypedef struct {\n\tu_char  HLength;     // Header length : initialized to 6 (length without params - 1)\n\t\t\t\t\t\t // descending classes that add values in params field must update it.\n\tu_char  PDUType;     // 0xE0 Connection request\n\t\t\t\t\t\t // 0xD0 Connection confirm\n\t\t\t\t\t\t // 0x80 Disconnect request\n\t\t\t\t\t\t // 0xDC Disconnect confirm\n\tu_short DstRef;      // Destination reference : Always 0x0000\n\tu_short SrcRef;      // Source reference : Always 0x0000\n\tu_char  CO_R;        // If the telegram is used for Connection request/Confirm,\n\t\t\t\t\t\t // the meaning of this field is CLASS+OPTION :\n\t\t\t\t\t\t //   Class (High 4 bits) + Option (Low 4 bits)\n\t\t\t\t\t\t //   Class : Always 4 (0100) but is ignored in input (RFC States this)\n\t\t\t\t\t\t //   Option : Always 0, also this in ignored.\n\t\t\t\t\t\t // If the telegram is used for Disconnect request,\n\t\t\t\t\t\t // the meaning of this field is REASON :\n\t\t\t\t\t\t //    1     Congestion at TSAP\n\t\t\t\t\t\t //    2     Session entity not attached to TSAP\n\t\t\t\t\t\t //    3     Address unknown (at TCP connect time)\n\t\t\t\t\t\t //  128+0   Normal disconnect initiated by the session\n\t\t\t\t\t\t //          entity.\n\t\t\t\t\t\t //  128+1   Remote transport entity congestion at connect\n\t\t\t\t\t\t //          request time\n\t\t\t\t\t\t //  128+3   Connection negotiation failed\n\t\t\t\t\t\t //  128+5   Protocol Error\n\t\t\t\t\t\t //  128+8   Connection request refused on this network\n\t\t\t\t\t\t //          connection\n\t// Parameter data : depending on the protocol implementation.\n\t// ISO 8073 define several type of parameters, but RFC 1006 recognizes only\n\t// TSAP related parameters and PDU size.  See RFC 0983 for more details.\n\tTCOPT_Params Params;\n\t/* Other params not used here, list only for completeness\n\t\tACK_TIME     \t   = 0x85,  1000 0101 Acknowledge Time\n\t\tRES_ERROR    \t   = 0x86,  1000 0110 Residual Error Rate\n\t\tPRIORITY           = 0x87,  1000 0111 Priority\n\t\tTRANSIT_DEL  \t   = 0x88,  1000 1000 Transit Delay\n\t\tTHROUGHPUT   \t   = 0x89,  1000 1001 Throughput\n\t\tSEQ_NR       \t   = 0x8A,  1000 1010 Subsequence Number (in AK)\n\t\tREASSIGNMENT \t   = 0x8B,  1000 1011 Reassignment Time\n\t\tFLOW_CNTL    \t   = 0x8C,  1000 1100 Flow Control Confirmation (in AK)\n\t\tTPDU_SIZE    \t   = 0xC0,  1100 0000 TPDU Size\n\t\tSRC_TSAP     \t   = 0xC1,  1100 0001 TSAP-ID / calling TSAP ( in CR/CC )\n\t\tDST_TSAP     \t   = 0xC2,  1100 0010 TSAP-ID / called TSAP\n\t\tCHECKSUM     \t   = 0xC3,  1100 0011 Checksum\n\t\tVERSION_NR   \t   = 0xC4,  1100 0100 Version Number\n\t\tPROTECTION   \t   = 0xC5,  1100 0101 Protection Parameters (user defined)\n\t\tOPT_SEL            = 0xC6,  1100 0110 Additional Option Selection\n\t\tPROTO_CLASS  \t   = 0xC7,  1100 0111 Alternative Protocol Classes\n\t\tPREF_MAX_TPDU_SIZE = 0xF0,  1111 0000\n\t\tINACTIVITY_TIMER   = 0xF2,  1111 0010\n\t\tADDICC             = 0xe0   1110 0000 Additional Information on Connection Clearing\n\t*/\n} TCOTP_CO ;\ntypedef TCOTP_CO *PCOTP_CO;\n\n// COTP Header for DATA EXCHANGE\ntypedef struct {\n\tu_char HLength;   // Header length : 3 for this header\n\tu_char PDUType;   // 0xF0 for this header\n\tu_char EoT_Num;   // EOT (bit 7) + PDU Number (bits 0..6)\n         \t\t  // EOT = 1 -> End of Trasmission Packet (This packet is complete)\n\t\t\t  // PDU Number : Always 0\n} TCOTP_DT;\ntypedef TCOTP_DT *PCOTP_DT;\n\n// Info part of a PDU, only common parts. We use it to check the consistence\n// of a telegram regardless of it's nature (control or data).\ntypedef struct {\n\tTTPKT TPKT; \t// TPKT Header\n\t\t\t// Common part of any COTP\n\tu_char HLength; // Header length : 3 for this header\n\tu_char PDUType; // Pdu type\n} TIsoHeaderInfo ;\ntypedef TIsoHeaderInfo *PIsoHeaderInfo;\n\n// PDU Type consts (Code + Credit)\nconst byte pdu_type_CR    \t= 0xE0;  // Connection request\nconst byte pdu_type_CC    \t= 0xD0;  // Connection confirm\nconst byte pdu_type_DR    \t= 0x80;  // Disconnect request\nconst byte pdu_type_DC    \t= 0xC0;  // Disconnect confirm\nconst byte pdu_type_DT    \t= 0xF0;  // Data transfer\n\nconst byte pdu_EoT    \t\t= 0x80;  // End of Trasmission Packet (This packet is complete)\n\nconst longword DataHeaderSize  = sizeof(TTPKT)+sizeof(TCOTP_DT);\nconst longword IsoFrameSize    = IsoPayload_Size+DataHeaderSize;\n\ntypedef struct {\n\tTTPKT \t TPKT; // TPKT Header\n\tTCOTP_CO COTP; // COPT Header for CONNECTION stuffs\n} TIsoControlPDU;\ntypedef TIsoControlPDU *PIsoControlPDU;\n\ntypedef u_char TIsoPayload[IsoPayload_Size];\n\ntypedef struct {\n\tTTPKT \t    TPKT; // TPKT Header\n\tTCOTP_DT    COTP; // COPT Header for DATA EXCHANGE\n\tTIsoPayload Payload; // Payload\n} TIsoDataPDU ;\n\ntypedef TIsoDataPDU *PIsoDataPDU;\ntypedef TIsoPayload *PIsoPayload;\n\ntypedef enum {\n\tpkConnectionRequest,\n\tpkDisconnectRequest,\n\tpkEmptyFragment,\n\tpkInvalidPDU,\n\tpkUnrecognizedType,\n\tpkValidData\n} TPDUKind ;\n\n#pragma pack()\n\nvoid ErrIsoText(int Error, char *Msg, int len);\n\nclass TIsoTcpSocket : public TMsgSocket\n{\nprivate:\n\n\tTIsoControlPDU FControlPDU;\n        int IsoMaxFragments; // max fragments allowed for an ISO telegram\n\t// Checks the PDU format\n\tint CheckPDU(void *pPDU, u_char PduTypeExpected);\n\t// Receives the next fragment\n\tint isoRecvFragment(void *From, int Max, int &Size, bool &EoT);\nprotected:\n\tTIsoDataPDU PDU;\n\tint SetIsoError(int Error);\n\t// Builds the control PDU starting from address properties\n\tvirtual int BuildControlPDU();\n\t// Calcs the PDU size\n\tint PDUSize(void *pPDU);\n\t// Parses the connection request PDU to extract TSAP and PDU size info\n\tvirtual void IsoParsePDU(TIsoControlPDU PDU);\n\t// Confirms the connection, override this method for special pourpose\n\t// By default it checks the PDU format and resend it changing the pdu type\n\tint IsoConfirmConnection(u_char PDUType);\n    void ClrIsoError();\n\tvirtual void FragmentSkipped(int Size);\npublic:\n\tword SrcTSap;  // Source TSAP\n\tword DstTSap;  // Destination TSAP\n\tword SrcRef;   // Source Reference\n\tword DstRef;   // Destination Reference\n\tint IsoPDUSize;\n\tint LastIsoError;\n\t//--------------------------------------------------------------------------\n\tTIsoTcpSocket();\n\t~TIsoTcpSocket();\n\t// HIGH Level functions (work on payload hiding the underlying protocol)\n\t// Connects with a peer, the connection PDU is automatically built starting from address scheme (see below)\n\tint isoConnect();\n\t// Disconnects from a peer, if OnlyTCP = true, only a TCP disconnect is performed,\n\t// otherwise a disconnect PDU is built and send.\n\tint isoDisconnect(bool OnlyTCP);\n\t// Sends a buffer, a valid header is created\n\tint isoSendBuffer(void *Data, int Size);\n\t// Receives a buffer\n\tint isoRecvBuffer(void *Data, int & Size);\n\t// Exchange cycle send->receive\n\tint isoExchangeBuffer(void *Data, int & Size);\n\t// A PDU is ready (at least its header) to be read\n\tbool IsoPDUReady();\n\t// Same as isoSendBuffer, but the entire PDU has to be provided (in any case a check is performed)\n\tint isoSendPDU(PIsoDataPDU Data);\n\t// Same as isoRecvBuffer, but it returns the entire PDU, automatically enques the fragments\n\tint isoRecvPDU(PIsoDataPDU Data);\n\t// Same as isoExchangeBuffer, but the entire PDU has to be provided (in any case a check is performed)\n\tint isoExchangePDU(PIsoDataPDU Data);\n\t// Peeks an header info to know which kind of telegram is incoming\n\tvoid IsoPeek(void *pPDU, TPDUKind &PduKind);\n};\n\n#endif // s7_isotcp_h\n"
  },
  {
    "path": "deps/snap7/src/core/s7_micro_client.cpp",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.3.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|=============================================================================*/\n#include \"s7_micro_client.h\"\n//---------------------------------------------------------------------------\n\nTSnap7MicroClient::TSnap7MicroClient()\n{\n\tSrcRef =0x0100; // RFC0983 states that SrcRef and DetRef should be 0\n\t\t\t// and, in any case, they are ignored.\n\t\t\t// S7 instead requires a number != 0\n\t\t\t// Libnodave uses 0x0100\n\t\t\t// S7Manager uses 0x0D00\n                        // TIA Portal V12 uses 0x1D00\n\t\t\t// WinCC     uses 0x0300\n\t\t\t// Seems that every non zero value is good enough...\n\tDstRef  =0x0000;\n\tSrcTSap =0x0100;\n\tDstTSap =0x0000; // It's filled by connection functions\n    ConnectionType = CONNTYPE_PG; // Default connection type\n\tmemset(&Job,0,sizeof(TSnap7Job));\n}\n//---------------------------------------------------------------------------\nTSnap7MicroClient::~TSnap7MicroClient()\n{\n    Destroying = true;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::opReadArea()\n{\n     PReqFunReadParams ReqParams;\n     PResFunReadParams ResParams;\n     PS7ResHeader23    Answer;\n     PResFunReadItem   ResData;\n     word              RPSize; // ReqParams size\n     int WordSize;\n     uintptr_t Offset;\n     pbyte Target;\n     int Address;\n     int IsoSize;\n     int Start;\n     int MaxElements;  // Max elements that we can transfer in a PDU\n     word NumElements; // Num of elements that we are asking for this telegram\n     int TotElements;  // Total elements requested\n     int Size;\n     int Result;\n\n     WordSize=DataSizeByte(Job.WordLen); // The size in bytes of an element that we are asking for\n     if (WordSize==0)\n        return errCliInvalidWordLen;\n     // First check : params bounds\n     if ((Job.Number<0) || (Job.Number>65535) || (Job.Start<0) || (Job.Amount<1))\n        return errCliInvalidParams;\n     // Second check : transport size\n\t if ((Job.WordLen==S7WLBit) && (Job.Amount>1))\n        return errCliInvalidTransportSize;\n     // Request Params size\n     RPSize    =sizeof(TReqFunReadItem)+2; // 1 item + FunRead + ItemsCount\n     // Setup pointers (note : PDUH_out and PDU.Payload are the same pointer)\n     ReqParams =PReqFunReadParams(pbyte(PDUH_out)+sizeof(TS7ReqHeader));\n     Answer    =PS7ResHeader23(&PDU.Payload);\n     ResParams =PResFunReadParams(pbyte(Answer)+ResHeaderSize23);\n     ResData   =PResFunReadItem(pbyte(ResParams)+sizeof(TResFunReadParams));\n     // Each packet cannot exceed the PDU length (in bytes) negotiated, and moreover\n     // we must ensure to transfer a \"finite\" number of item per PDU\n     MaxElements=(PDULength-sizeof(TS7ResHeader23)-sizeof(TResFunReadParams)-4) / WordSize;\n     TotElements=Job.Amount;\n     Start      =Job.Start;\n     Offset     =0;\n     Result     =0;\n     while ((TotElements>0) && (Result==0))\n     {\n          NumElements=TotElements;\n          if (NumElements>MaxElements)\n             NumElements=MaxElements;\n\n          Target=pbyte(Job.pData)+Offset;\n          //----------------------------------------------- Read next slice-----\n          PDUH_out->P = 0x32;                    // Always 0x32\n          PDUH_out->PDUType = PduType_request;   // 0x01\n          PDUH_out->AB_EX = 0x0000;              // Always 0x0000\n          PDUH_out->Sequence = GetNextWord();    // AutoInc\n          PDUH_out->ParLen = SwapWord(RPSize);   // 14 bytes params\n          PDUH_out->DataLen = 0x0000;            // No data\n\n          ReqParams->FunRead = pduFuncRead;      // 0x04\n          ReqParams->ItemsCount = 1;\n          ReqParams->Items[0].ItemHead[0] = 0x12;\n          ReqParams->Items[0].ItemHead[1] = 0x0A;\n          ReqParams->Items[0].ItemHead[2] = 0x10;\n          ReqParams->Items[0].TransportSize = Job.WordLen;\n          ReqParams->Items[0].Length = SwapWord(NumElements);\n          ReqParams->Items[0].Area = Job.Area;\n          if (Job.Area==S7AreaDB)\n               ReqParams->Items[0].DBNumber = SwapWord(Job.Number);\n          else\n               ReqParams->Items[0].DBNumber = 0x0000;\n          // Adjusts the offset\n          if ((Job.WordLen==S7WLBit) || (Job.WordLen==S7WLCounter) || (Job.WordLen==S7WLTimer))\n               Address = Start;\n          else\n               Address = Start*8;\n\n          ReqParams->Items[0].Address[2] = Address & 0x000000FF;\n          Address = Address >> 8;\n          ReqParams->Items[0].Address[1] = Address & 0x000000FF;\n          Address = Address >> 8;\n          ReqParams->Items[0].Address[0] = Address & 0x000000FF;\n\n          IsoSize = sizeof(TS7ReqHeader)+RPSize;\n          Result = isoExchangeBuffer(0,IsoSize);\n          // Get Data\n          if (Result==0)  // 1St level Iso\n          {\n               Size = 0;\n               // Item level error\n                if (ResData->ReturnCode==0xFF) // <-- 0xFF means Result OK\n                {\n                   // Calcs data size in bytes\n                   Size = SwapWord(ResData->DataLength);\n                   // Adjust Size in accord of TransportSize\n                   if ((ResData->TransportSize != TS_ResOctet) && (ResData->TransportSize != TS_ResReal) && (ResData->TransportSize != TS_ResBit))\n                       Size = Size >> 3;\n                   memcpy(Target, &ResData->Data[0], Size);\n                }\n                else\n                     Result = CpuError(ResData->ReturnCode);\n           Offset+=Size;\n          };\n          //--------------------------------------------------------------------\n          TotElements -= NumElements;\n          Start += NumElements*WordSize;\n     }\n     return Result;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::opWriteArea()\n{\n     PReqFunWriteParams   ReqParams;\n     PReqFunWriteDataItem ReqData;  // only 1 item for WriteArea Function\n     PResFunWrite         ResParams;\n     PS7ResHeader23       Answer;\n     word RPSize;  // ReqParams size\n     word RHSize;  // Request headers size\n     bool First = true;\n     pbyte Source;\n     pbyte Target;\n     int Address;\n     int IsoSize;\n     int WordSize;\n     word Size;\n     uintptr_t Offset = 0;\n     int Start;        // where we are starting from for this telegram\n     int MaxElements;  // Max elements that we can transfer in a PDU\n     word NumElements; // Num of elements that we are asking for this telegram\n     int TotElements;  // Total elements requested\n     int Result = 0;\n\n     WordSize=DataSizeByte(Job.WordLen); // The size in bytes of an element that we are pushing\n     if (WordSize==0)\n        return errCliInvalidWordLen;\n     // First check : params bounds\n     if ((Job.Number<0) || (Job.Number>65535) || (Job.Start<0) || (Job.Amount<1))\n        return errCliInvalidParams;\n     // Second check : transport size\n\t if ((Job.WordLen==S7WLBit) && (Job.Amount>1))\n        return errCliInvalidTransportSize;\n\n     RHSize =sizeof(TS7ReqHeader)+    // Request header\n             2+                       // FunWrite+ItemCount (of TReqFunWriteParams)\n             sizeof(TReqFunWriteItem)+// 1 item reference\n             4;                       // ReturnCode+TransportSize+DataLength\n     RPSize =sizeof(TReqFunWriteItem)+2;\n\n     // Setup pointers (note : PDUH_out and PDU.Payload are the same pointer)\n     ReqParams=PReqFunWriteParams(pbyte(PDUH_out)+sizeof(TS7ReqHeader));\n     ReqData  =PReqFunWriteDataItem(pbyte(ReqParams)+sizeof(TReqFunWriteItem)+2); // 2 = FunWrite+ItemsCount\n     Target   =pbyte(ReqData)+4; // 4 = ReturnCode+TransportSize+DataLength\n     Answer   =PS7ResHeader23(&PDU.Payload);\n     ResParams=PResFunWrite(pbyte(Answer)+ResHeaderSize23);\n\n     // Each packet cannot exceed the PDU length (in bytes) negotiated, and moreover\n     // we must ensure to transfer a \"finite\" number of item per PDU\n     MaxElements=(PDULength-RHSize) / WordSize;\n     TotElements=Job.Amount;\n     Start      =Job.Start;\n     while ((TotElements>0) && (Result==0))\n     {\n           NumElements=TotElements;\n           if (NumElements>MaxElements)\n               NumElements=MaxElements;\n           Source=pbyte(Job.pData)+Offset;\n\n           Size=NumElements * WordSize;\n           PDUH_out->P=0x32;                    // Always 0x32\n           PDUH_out->PDUType=PduType_request;   // 0x01\n           PDUH_out->AB_EX=0x0000;              // Always 0x0000\n           PDUH_out->Sequence=GetNextWord();    // AutoInc\n           PDUH_out->ParLen  =SwapWord(RPSize); // 14 bytes params\n           PDUH_out->DataLen =SwapWord(Size+4);\n\n           ReqParams->FunWrite=pduFuncWrite;    // 0x05\n           ReqParams->ItemsCount=1;\n           ReqParams->Items[0].ItemHead[0]=0x12;\n           ReqParams->Items[0].ItemHead[1]=0x0A;\n           ReqParams->Items[0].ItemHead[2]=0x10;\n           ReqParams->Items[0].TransportSize=Job.WordLen;\n           ReqParams->Items[0].Length=SwapWord(NumElements);\n           ReqParams->Items[0].Area=Job.Area;\n           if (Job.Area==S7AreaDB)\n               ReqParams->Items[0].DBNumber=SwapWord(Job.Number);\n           else\n               ReqParams->Items[0].DBNumber=0x0000;\n\n           // Adjusts the offset\n           if ((Job.WordLen==S7WLBit) || (Job.WordLen==S7WLCounter) || (Job.WordLen==S7WLTimer))\n               Address=Start;\n           else\n               Address=Start*8;\n\n           ReqParams->Items[0].Address[2]=Address & 0x000000FF;\n           Address=Address >> 8;\n           ReqParams->Items[0].Address[1]=Address & 0x000000FF;\n           Address=Address >> 8;\n           ReqParams->Items[0].Address[0]=Address & 0x000000FF;\n\n           ReqData->ReturnCode=0x00;\n\n           switch(Job.WordLen)\n           {\n               case S7WLBit:\n                   ReqData->TransportSize=TS_ResBit;\n                   break;\n               case S7WLInt:\n               case S7WLDInt:\n                   ReqData->TransportSize=TS_ResInt;\n                   break;\n               case S7WLReal:\n                   ReqData->TransportSize=TS_ResReal;\n                   break;\n               case S7WLChar   :\n               case S7WLCounter:\n               case S7WLTimer:\n                   ReqData->TransportSize=TS_ResOctet;\n\t\t\t\t   break;\n\t\t\t   default:\n                   ReqData->TransportSize=TS_ResByte;\n                   break;\n           };\n\n           if ((ReqData->TransportSize!=TS_ResOctet) && (ReqData->TransportSize!=TS_ResReal) && (ReqData->TransportSize!=TS_ResBit))\n               ReqData->DataLength=SwapWord(Size*8);\n           else\n               ReqData->DataLength=SwapWord(Size);\n\n           memcpy(Target, Source, Size);\n           IsoSize=RHSize + Size;\n           Result=isoExchangeBuffer(0,IsoSize);\n\n           if (Result==0) // 1St check : Iso result\n           {\n               Result=CpuError(SwapWord(Answer->Error)); // 2nd level global error\n               if (Result==0)\n               {     // 2th check : item error\n                   if (ResParams->Data[0] == 0xFF) // <-- 0xFF means Result OK\n                       Result=0;\n                   else\n                       // Now we check the error : if it's the first part we report the cpu error\n                       // otherwise we warn that the function failed but some data were written\n                       if (First)\n                           Result=CpuError(ResParams->Data[0]);\n                       else\n                           Result=errCliPartialDataWritten;\n               };\n               Offset+=Size;\n           };\n           First=false;\n\n           TotElements-=NumElements;\n           Start+=(NumElements*WordSize);\n     }\n     return Result;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::opReadMultiVars()\n{\n    PS7DataItem       Item;\n    PReqFunReadParams ReqParams;\n    PS7ResHeader23    Answer;\n    PResFunReadParams ResParams;\n    TResFunReadData   ResData;\n\n    word       RPSize; // ReqParams size\n    uintptr_t  Offset =0 ;\n    word       Slice;\n    longword   Address;\n    int        IsoSize;\n    pbyte      P;\n    int        ItemsCount, c, Result;\n\n    Item       = PS7DataItem(Job.pData);\n    ItemsCount = Job.Amount;\n\n    // Some useful initial check to detail the errors (Since S7 CPU always answers\n    // with $05 if (something is wrong in params)\n    if (ItemsCount>MaxVars)\n    \treturn errCliTooManyItems;\n\n    // Adjusts Word Length in case of timers and counters and clears results\n    for (c = 0; c < ItemsCount; c++)\n    {\n    \tItem->Result=0;\n        if (Item->Area==S7AreaCT)\n          Item->WordLen=S7WLCounter;\n        if (Item->Area==S7AreaTM)\n          Item->WordLen=S7WLTimer;\n        Item++;\n    };\n\n    // Let's build the PDU\n    RPSize    = word(2 + ItemsCount * sizeof(TReqFunReadItem));\n    ReqParams = PReqFunReadParams(pbyte(PDUH_out)+sizeof(TS7ReqHeader));\n    Answer    = PS7ResHeader23(&PDU.Payload);\n    ResParams = PResFunReadParams(pbyte(Answer)+ResHeaderSize23);\n    // Fill Header\n    PDUH_out->P=0x32;                    // Always 0x32\n    PDUH_out->PDUType=PduType_request;   // 0x01\n    PDUH_out->AB_EX=0x0000;              // Always 0x0000\n    PDUH_out->Sequence=GetNextWord();    // AutoInc\n    PDUH_out->ParLen=SwapWord(RPSize);   // Request params size\n    PDUH_out->DataLen=0x0000;            // No data in output\n\n    // Fill Params\n    ReqParams->FunRead=pduFuncRead;      // 0x04\n    ReqParams->ItemsCount=ItemsCount;\n\n    Item = PS7DataItem(Job.pData);\n    for (c = 0; c < ItemsCount; c++)\n    {\n        ReqParams->Items[c].ItemHead[0]=0x12;\n        ReqParams->Items[c].ItemHead[1]=0x0A;\n        ReqParams->Items[c].ItemHead[2]=0x10;\n\n        ReqParams->Items[c].TransportSize=Item->WordLen;\n        ReqParams->Items[c].Length=SwapWord(Item->Amount);\n        ReqParams->Items[c].Area=Item->Area;\n        // Automatically drops DBNumber if (Area is not DB\n        if (Item->Area==S7AreaDB)\n\t        ReqParams->Items[c].DBNumber=SwapWord(Item->DBNumber);\n        else\n    \t    ReqParams->Items[c].DBNumber=0x0000;\n        // Adjusts the offset\n        if ((Item->WordLen==S7WLBit) || (Item->WordLen==S7WLCounter) || (Item->WordLen==S7WLTimer))\n        \tAddress=Item->Start;\n        else\n        \tAddress=Item->Start*8;\n        // Builds the offset\n        ReqParams->Items[c].Address[2]=Address & 0x000000FF;\n        Address=Address >> 8;\n        ReqParams->Items[c].Address[1]=Address & 0x000000FF;\n        Address=Address >> 8;\n        ReqParams->Items[c].Address[0]=Address & 0x000000FF;\n        Item++;\n    };\n\n    IsoSize=RPSize+sizeof(TS7ReqHeader);\n\tif (IsoSize>PDULength) \n\t\treturn errCliSizeOverPDU;\n\tResult=isoExchangeBuffer(0,IsoSize);\n\n\tif (Result!=0)\n        return Result;\n\n    // Function level error\n    if (Answer->Error!=0)\n    \treturn CpuError(SwapWord(Answer->Error));\n\n    if (ResParams->ItemCount!=ItemsCount)\n    \treturn errCliInvalidPlcAnswer;\n\n    P=pbyte(ResParams)+sizeof(TResFunReadParams);\n    Item = PS7DataItem(Job.pData);\n    for (c = 0; c < ItemsCount; c++)\n    {\n        ResData[c] =PResFunReadItem(pbyte(P)+Offset);\n        Slice=0;\n        // Item level error\n        if (ResData[c]->ReturnCode==0xFF) // <-- 0xFF means Result OK\n        {\n          // Calcs data size in bytes\n          Slice=SwapWord(ResData[c]->DataLength);\n          // Adjust Size in accord of TransportSize\n          if ((ResData[c]->TransportSize != TS_ResOctet) && (ResData[c]->TransportSize != TS_ResReal) && (ResData[c]->TransportSize != TS_ResBit))\n            Slice=Slice >> 3;\n\n\t\t  memcpy(Item->pdata, ResData[c]->Data, Slice);\n          Item->Result=0;\n        }\n        else\n          Item->Result=CpuError(ResData[c]->ReturnCode);\n\n        if ((Slice % 2)!=0)\n        \tSlice++; // Skip fill byte for Odd frame\n\n        Offset+=(4+Slice);\n        Item++;\n    };\n    return Result;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::opWriteMultiVars()\n{\n    PS7DataItem        Item;\n    PReqFunWriteParams ReqParams;\n    PResFunWrite       ResParams;\n    TReqFunWriteData   ReqData;\n    PS7ResHeader23     Answer;\n    pbyte              P;\n    uintptr_t          Offset;\n    longword           Address;\n    int                ItemsCount, c, IsoSize;\n    word               RPSize; // ReqParams size\n    word               Size;   // Write data size\n    int                WordSize, Result;\n\n    Item       = PS7DataItem(Job.pData);\n    ItemsCount = Job.Amount;\n\n    // Some useful initial check to detail the errors (Since S7 CPU always answers\n    // with $05 if (something is wrong in params)\n    if (ItemsCount>MaxVars)\n    \treturn errCliTooManyItems;\n\n    // Adjusts Word Length in case of timers and counters and clears results\n    for (c = 0; c < ItemsCount; c++)\n    {\n    \tItem->Result=0;\n        if (Item->Area==S7AreaCT)\n          Item->WordLen=S7WLCounter;\n        if (Item->Area==S7AreaTM)\n          Item->WordLen=S7WLTimer;\n        Item++;\n    };\n\n    // Let's build the PDU : setup pointers\n    RPSize    = word(2 + ItemsCount * sizeof(TReqFunWriteItem));\n    ReqParams = PReqFunWriteParams(pbyte(PDUH_out)+sizeof(TS7ReqHeader));\n    Answer    = PS7ResHeader23(&PDU.Payload);\n    ResParams = PResFunWrite(pbyte(Answer)+ResHeaderSize23);\n    P=pbyte(ReqParams)+RPSize;\n\n    // Fill Header\n    PDUH_out->P=0x32;                    // Always 0x32\n    PDUH_out->PDUType=PduType_request;   // 0x01\n    PDUH_out->AB_EX=0x0000;              // Always 0x0000\n    PDUH_out->Sequence=GetNextWord();    // AutoInc\n    PDUH_out->ParLen=SwapWord(RPSize);   // Request params size\n\n    // Fill Params\n    ReqParams->FunWrite=pduFuncWrite;      // 0x05\n    ReqParams->ItemsCount=ItemsCount;\n\n    Offset=0;\n    Item  = PS7DataItem(Job.pData);\n    for (c = 0; c < ItemsCount; c++)\n    {\n        // Items Params\n        ReqParams->Items[c].ItemHead[0]=0x12;\n        ReqParams->Items[c].ItemHead[1]=0x0A;\n        ReqParams->Items[c].ItemHead[2]=0x10;\n\n        ReqParams->Items[c].TransportSize=Item->WordLen;\n        ReqParams->Items[c].Length=SwapWord(Item->Amount);\n        ReqParams->Items[c].Area=Item->Area;\n\n        if (Item->Area==S7AreaDB)\n            ReqParams->Items[c].DBNumber=SwapWord(Item->DBNumber);\n        else\n            ReqParams->Items[c].DBNumber=0x0000;\n\n        // Adjusts the offset\n        if ((Item->WordLen==S7WLBit) || (Item->WordLen==S7WLCounter) || (Item->WordLen==S7WLTimer))\n        \tAddress=Item->Start;\n        else\n        \tAddress=Item->Start*8;\n        // Builds the offset\n        ReqParams->Items[c].Address[2]=Address & 0x000000FF;\n        Address=Address >> 8;\n        ReqParams->Items[c].Address[1]=Address & 0x000000FF;\n        Address=Address >> 8;\n        ReqParams->Items[c].Address[0]=Address & 0x000000FF;\n\n        // Items Data\n        ReqData[c]=PReqFunWriteDataItem(pbyte(P)+Offset);\n        ReqData[c]->ReturnCode=0x00;\n\n        switch (Item->WordLen)\n        {\n          case S7WLBit     :\n               ReqData[c]->TransportSize=TS_ResBit;\n               break;\n\t\t  case S7WLInt     :\n          case S7WLDInt    :\n               ReqData[c]->TransportSize=TS_ResInt;\n               break;\n          case S7WLReal    :\n               ReqData[c]->TransportSize=TS_ResReal;\n               break;\n          case S7WLChar    :\n          case S7WLCounter :\n          case S7WLTimer   : ReqData[c]->TransportSize=TS_ResOctet;\n\t\t\t   break;\n\t\t  default :\n\t\t\t   ReqData[c]->TransportSize=TS_ResByte; // byte/word/dword etc.\n\t\t\t   break;\n        };\n\n        WordSize=DataSizeByte(Item->WordLen);\n        Size=Item->Amount * WordSize;\n\n\t\tif ((ReqData[c]->TransportSize!=TS_ResOctet) && (ReqData[c]->TransportSize!=TS_ResReal) && (ReqData[c]->TransportSize!=TS_ResBit))\n           ReqData[c]->DataLength=SwapWord(Size*8);\n        else\n           ReqData[c]->DataLength=SwapWord(Size);\n\n        memcpy(ReqData[c]->Data, Item->pdata, Size);\n\n\t\tif ((Size % 2) != 0 && (ItemsCount - c != 1))\n\t\t\tSize++; // Skip fill byte for Odd frame (except for the last one)\n\n        Offset+=(4+Size); // next item\n        Item++;\n    };\n\n    PDUH_out->DataLen=SwapWord(word(Offset));\n\n    IsoSize=RPSize+sizeof(TS7ReqHeader)+int(Offset);\n\tif (IsoSize>PDULength) \n\t\treturn errCliSizeOverPDU;\n    Result=isoExchangeBuffer(0,IsoSize);\n\n\tif (Result!=0)\n\t\treturn Result;\n\n\t// Function level error\n\tif (Answer->Error!=0)\n\t\treturn CpuError(SwapWord(Answer->Error));\n\n    if (ResParams->ItemCount!=ItemsCount)\n        return errCliInvalidPlcAnswer;\n\n    Item  = PS7DataItem(Job.pData);\n    for (c = 0; c < ItemsCount; c++)\n    {\n        // Item level error\n        if (ResParams->Data[c]==0xFF) // <-- 0xFF means Result OK\n           Item->Result=0;\n        else\n           Item->Result=CpuError(ResParams->Data[c]);\n        Item++;\n    };\n    return Result;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::opListBlocks()\n{\n    PReqFunGetBlockInfo ReqParams;\n    PReqDataFunBlocks   ReqData;\n    PResFunGetBlockInfo ResParams;\n    PDataFunListAll     ResData;\n    PS7ResHeader17      Answer;\n    PS7BlocksList       List;\n    int IsoSize, Result;\n\n    // Setup pointers (note : PDUH_out and PDU.Payload are the same pointer)\n    ReqParams=PReqFunGetBlockInfo(pbyte(PDUH_out)+sizeof(TS7ReqHeader));\n    ReqData  =PReqDataFunBlocks(pbyte(ReqParams)+sizeof(TReqFunGetBlockInfo));\n    Answer   =PS7ResHeader17(&PDU.Payload);\n    ResParams=PResFunGetBlockInfo(pbyte(Answer)+ResHeaderSize17);\n    ResData  =PDataFunListAll(pbyte(ResParams)+sizeof(TResFunGetBlockInfo));\n    List     =PS7BlocksList(Job.pData);\n    // Fill Header\n    PDUH_out->P=0x32;                    // Always 0x32\n    PDUH_out->PDUType=PduType_userdata;  // 0x07\n    PDUH_out->AB_EX=0x0000;              // Always 0x0000\n    PDUH_out->Sequence=GetNextWord();    // AutoInc\n    PDUH_out->ParLen=SwapWord(sizeof(TReqFunGetBlockInfo));   // 8 bytes params\n    PDUH_out->DataLen=SwapWord(sizeof(TReqDataFunBlocks));   // 4 bytes data\n    // Fill params (mostly constants)\n    ReqParams->Head[0]=0x00;\n    ReqParams->Head[1]=0x01;\n    ReqParams->Head[2]=0x12;\n    ReqParams->Plen   =0x04;\n    ReqParams->Uk     =0x11;\n    ReqParams->Tg     =grBlocksInfo;\n    ReqParams->SubFun =SFun_ListAll;\n    ReqParams->Seq    =0x00;\n    // Fill data\n    ReqData[0] =0x0A;\n    ReqData[1] =0x00;\n    ReqData[2] =0x00;\n    ReqData[3] =0x00;\n\n    IsoSize=sizeof(TS7ReqHeader)+sizeof(TReqFunGetBlockInfo)+sizeof(TReqDataFunBlocks);\n    Result=isoExchangeBuffer(0,IsoSize);\n    // Get Data\n    if (Result==0)\n    {\n        if (ResParams->ErrNo==0)\n        {\n            if (SwapWord(ResData->Length)!=28)\n              return errCliInvalidPlcAnswer;\n\n            for (int c = 0; c < 7; c++)\n            {\n                switch (ResData->Blocks[c].BType)\n                {\n                  case Block_OB:\n                      List->OBCount=SwapWord(ResData->Blocks[c].BCount);\n                      break;\n                  case Block_DB:\n                      List->DBCount=SwapWord(ResData->Blocks[c].BCount);\n                      break;\n                  case Block_SDB:\n                      List->SDBCount=SwapWord(ResData->Blocks[c].BCount);\n                      break;\n                  case Block_FC:\n                      List->FCCount=SwapWord(ResData->Blocks[c].BCount);\n                      break;\n                  case Block_SFC:\n                      List->SFCCount=SwapWord(ResData->Blocks[c].BCount);\n                      break;\n                  case Block_FB:\n                      List->FBCount=SwapWord(ResData->Blocks[c].BCount);\n                      break;\n                  case Block_SFB:\n                      List->SFBCount=SwapWord(ResData->Blocks[c].BCount);\n                      break;\n                }\n            }\n        }\n        else\n          Result=CpuError(SwapWord(ResParams->ErrNo));\n    }\n    return Result;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::opListBlocksOfType()\n{\n    PReqFunGetBlockInfo ReqParams;\n    PReqDataBlockOfType ReqData;\n\n    PS7ResHeader17      Answer;\n    PResFunGetBlockInfo ResParams;\n    PDataFunGetBot      ResData;\n    longword            *PadData;\n    word                *List;\n    bool                First;\n\tbool                Done = false;\n    byte                BlockType, In_Seq;\n    int                 Count, Last, IsoSize, Result;\n    int                 c, CThis;\n    word                DataLength;\n\tbool                RoomError = false;\n\n    BlockType=Job.Area;\n    List=(word*)(&opData);\n    // Setup pointers (note : PDUH_out and PDU.Payload are the same pointer)\n    ReqParams=PReqFunGetBlockInfo(pbyte(PDUH_out)+sizeof(TS7ReqHeader));\n    Answer   =PS7ResHeader17(&PDU.Payload);\n    ResParams=PResFunGetBlockInfo(pbyte(Answer)+ResHeaderSize17);\n    ResData  =PDataFunGetBot(pbyte(ResParams)+sizeof(TResFunGetBlockInfo));\n    // Get Data\n    First =true;\n    In_Seq=0x00; // first group sequence, next will come from PLC\n    Count =0;\n    Last  =0;\n    do\n    {\n    //<--------------------------------------------------------- Get next slice\n        // Fill Header\n        PDUH_out->P=0x32;                    // Always 0x32\n        PDUH_out->PDUType=PduType_userdata;  // 0x07\n        PDUH_out->AB_EX=0x0000;              // Always 0x0000\n        PDUH_out->Sequence=GetNextWord();    // AutoInc\n        if (First)\n        {\n           PDUH_out->ParLen=SwapWord(8);     // 8 bytes params\n           PDUH_out->DataLen=SwapWord(6);    // 6 bytes data\n           DataLength=14;\n        }\n        else\n        {\n           PDUH_out->ParLen=SwapWord(12);    // 12 bytes params\n           PDUH_out->DataLen=SwapWord(4);    // 4 bytes data\n           DataLength=16;\n        }\n\n        // Fill params (mostly constants)\n        ReqParams->Head[0]=0x00;\n        ReqParams->Head[1]=0x01;\n        ReqParams->Head[2]=0x12;\n\n        if (First)\n            ReqParams->Plen   =0x04;\n\t\telse\n            ReqParams->Plen   =0x08;\n\n\t\tif (First)\n\t\t\tReqParams->Uk = 0x11;\n\t\telse\n\t\t\tReqParams->Uk = 0x12;\n\n        ReqParams->Tg     =grBlocksInfo;\n        ReqParams->SubFun =SFun_ListBoT;\n        ReqParams->Seq    =In_Seq;\n\n        // Fill data\n        if (First)\n        {\n            // overlap resvd and error to avoid another struct...\n            ReqData  =PReqDataBlockOfType(pbyte(ReqParams)+sizeof(TReqFunGetBlockInfo));\n            ReqData->RetVal   =0xFF;\n            ReqData->TSize    =TS_ResOctet;\n            ReqData->Length   =SwapWord(0x0002);\n            ReqData->Zero     =0x30; // zero ascii '0'\n            ReqData->BlkType  =BlockType;\n        }\n        else\n        {\n            PadData  =(longword*)(pbyte(ReqParams)+sizeof(TReqFunGetBlockInfo));\n            ReqData  =PReqDataBlockOfType(pbyte(ReqParams)+sizeof(TReqFunGetBlockInfo)+4);\n            *PadData          =0x00000000;\n            ReqData->RetVal   =0x0A;\n            ReqData->TSize    =0x00;\n            ReqData->Length   =0x0000;\n            ReqData->Zero     =0x00;\n            ReqData->BlkType  =0x00;\n        };\n\n        IsoSize=sizeof(TS7ReqHeader)+DataLength;\n        Result=isoExchangeBuffer(0,IsoSize);\n\n        if (Result==0)\n        {\n            if (ResParams->ErrNo==0)\n            {\n                if (ResData->RetVal==0xFF)\n                {\n                     Done=((ResParams->Rsvd & 0xFF00) == 0); // Low order byte = 0x00 => the sequence is done\n                     In_Seq=ResParams->Seq;  // every next telegram must have this number\n\t\t\t\t\t CThis=((SwapWord(ResData->DataLen) - 4 ) / 4) + 1; // Partial counter\n                     for (c=0; c < CThis+1; c++)\n                     {\n                         *List=SwapWord(ResData->Items[c].BlockNum);\n                         Last++;\n                         List++;\n                         if (Last==0x8000)\n                         {\n                             Done=true;\n                             break;\n                         };\n                     };\n                     Count+=CThis; // Total counter\n                     List--;\n                }\n                else\n                    Result=errCliItemNotAvailable;\n            }\n            else\n                Result=errCliItemNotAvailable;\n        };\n        First=false;\n    //---------------------------------------------------------> Get next slice\n    }\n    while ((!Done) && (Result==0));\n\n\t*Job.pAmount=0;\n\tif (Result==0)\n\t{\n\t\tif (Count>Job.Amount)\n\t\t{\n\t\t\tCount=Job.Amount;\n\t\t\tRoomError=true;\n\t\t}\n\t\tmemcpy(Job.pData, &opData, Count*2);\n\t\t*Job.pAmount=Count;\n\n\t\tif (RoomError) // Result==0 -> override if romerror\n\t\t\tResult=errCliPartialDataRead;\n\t};\n\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nvoid TSnap7MicroClient::FillTime(word SiemensTime, char *PTime)\n{\n\t// SiemensTime -> number of seconds after 1/1/1984\n\t// This is not S7 date and time but is used only internally for block info\n    time_t TheDate = (SiemensTime * 86400)+ DeltaSecs;\n    struct tm * timeinfo = localtime (&TheDate);\n    if (timeinfo!=NULL) {\n        strftime(PTime,11,\"%Y/%m/%d\",timeinfo);\n    }\n    else\n        *PTime='\\0';\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::opAgBlockInfo()\n{\n    PS7BlockInfo BlockInfo;\n    PReqFunGetBlockInfo ReqParams;\n    PReqDataBlockInfo ReqData;\n    PS7ResHeader17 Answer;\n    PResFunGetBlockInfo ResParams;\n    PResDataBlockInfo ResData;\n    byte BlockType;\n    int BlockNum, IsoSize, Result;\n\n    BlockType=Job.Area;\n    BlockNum =Job.Number;\n    BlockInfo=PS7BlockInfo(Job.pData);\n    memset(BlockInfo,0,sizeof(TS7BlockInfo));\n    // Setup pointers (note : PDUH_out and PDU.Payload are the same pointer)\n    ReqParams=PReqFunGetBlockInfo(pbyte(PDUH_out)+sizeof(TS7ReqHeader));\n    ReqData  =PReqDataBlockInfo(pbyte(ReqParams)+sizeof(TReqFunGetBlockInfo));\n    Answer   =PS7ResHeader17(&PDU.Payload);\n    ResParams=PResFunGetBlockInfo(pbyte(Answer)+ResHeaderSize17);\n    ResData  =PResDataBlockInfo(pbyte(ResParams)+sizeof(TResFunGetBlockInfo));\n    // Fill Header\n    PDUH_out->P=0x32;                    // Always 0x32\n    PDUH_out->PDUType=PduType_userdata;  // 0x07\n    PDUH_out->AB_EX=0x0000;              // Always 0x0000\n\tPDUH_out->Sequence=GetNextWord();    // AutoInc\n    PDUH_out->ParLen=SwapWord(sizeof(TReqFunGetBlockInfo));   // 8 bytes params\n    PDUH_out->DataLen=SwapWord(sizeof(TReqDataBlockInfo));   // 4 bytes data\n    // Fill params (mostly constants)\n    ReqParams->Head[0]=0x00;\n    ReqParams->Head[1]=0x01;\n    ReqParams->Head[2]=0x12;\n    ReqParams->Plen   =0x04;\n    ReqParams->Uk     =0x11;\n    ReqParams->Tg     =grBlocksInfo;\n    ReqParams->SubFun =SFun_BlkInfo;\n    ReqParams->Seq    =0x00;\n    // Fill data\n    ReqData->RetVal   =0xFF;\n    ReqData->TSize    =TS_ResOctet;\n    ReqData->DataLen  =SwapWord(0x0008);\n    ReqData->BlkPrfx  =0x30;\n    ReqData->BlkType  =BlockType;\n    ReqData->A        =0x41;\n\n    ReqData->AsciiBlk[0]=(BlockNum / 10000)+0x30;\n    BlockNum=BlockNum % 10000;\n    ReqData->AsciiBlk[1]=(BlockNum / 1000)+0x30;\n    BlockNum=BlockNum % 1000;\n    ReqData->AsciiBlk[2]=(BlockNum / 100)+0x30;\n    BlockNum=BlockNum % 100;\n    ReqData->AsciiBlk[3]=(BlockNum / 10)+0x30;\n    BlockNum=BlockNum % 10;\n    ReqData->AsciiBlk[4]=(BlockNum / 1)+0x30;\n\n    IsoSize=sizeof(TS7ReqHeader)+sizeof(TReqFunGetBlockInfo)+sizeof(TReqDataBlockInfo);\n    Result=isoExchangeBuffer(0,IsoSize);\n\n    // Get Data\n    if (Result==0)\n    {\n        if (ResParams->ErrNo==0)\n        {\n            if (SwapWord(ResData->Length)<40) // 78\n                return errCliInvalidPlcAnswer;\n            if (ResData->RetVal==0xFF) // <-- 0xFF means Result OK\n            {\n               //<----------------------------------------------Fill block info\n                 BlockInfo->BlkType=ResData->SubBlkType;\n                 BlockInfo->BlkNumber=SwapWord(ResData->BlkNumber);\n                 BlockInfo->BlkLang=ResData->BlkLang;\n                 BlockInfo->BlkFlags=ResData->BlkFlags;\n                 BlockInfo->MC7Size=SwapWord(ResData->MC7Len);\n                 BlockInfo->LoadSize=SwapDWord(ResData->LenLoadMem);\n                 BlockInfo->LocalData=SwapWord(ResData->LocDataLen);\n                 BlockInfo->SBBLength=SwapWord(ResData->SbbLen);\n                 BlockInfo->CheckSum=SwapWord(ResData->BlkChksum);\n                 BlockInfo->Version=ResData->Version;\n                 memcpy(BlockInfo->Author, ResData->Author, 8);\n                 memcpy(BlockInfo->Family,ResData->Family,8);\n                 memcpy(BlockInfo->Header,ResData->Header,8);\n                 FillTime(SwapWord(ResData->CodeTime_dy),BlockInfo->CodeDate);\n                 FillTime(SwapWord(ResData->IntfTime_dy),BlockInfo->IntfDate);\n               //---------------------------------------------->Fill block info\n            }\n            else\n                Result=CpuError(ResData->RetVal);\n        }\n        else\n            Result=CpuError(SwapWord(ResParams->ErrNo));\n    };\n    return Result;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::opDBGet()\n{\n    TS7BlockInfo BI;\n    void * usrPData;\n    int * usrPSize;\n    int Result, Room;\n    bool RoomError = false;\n\n    // Stores user pointer\n    usrPData=Job.pData;\n    usrPSize=Job.pAmount;\n    Room    =Job.Amount;\n\n    // 1 Pass : Get block info\n    Job.Area=Block_DB;\n    Job.pData=&BI;\n    Result=opAgBlockInfo();\n\n    // 2 Pass : Read the whole (MC7Size bytes) DB.\n    if (Result==0)\n    {\n        // Check user space\n        if (BI.MC7Size>Room)\n        {\n           Job.Amount=Room;\n           RoomError=true;\n        }\n        else\n            Job.Amount =BI.MC7Size;\n        // The data is read even if the buffer is small (the error is reported).\n        // Imagine that we want to read only a small amount of data at the\n        // beginning of a DB regardless it's size....\n        Job.Area   =S7AreaDB;\n        Job.WordLen=S7WLByte;\n        Job.Start  =0;\n        Job.pData  =usrPData;\n        Result     =opReadArea();\n        if (Result==0)\n           *usrPSize=Job.Amount;\n    }\n\n    if ((Result==0) && RoomError)\n        return errCliBufferTooSmall;\n    else\n        return Result;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::opDBFill()\n{\n    TS7BlockInfo BI;\n    int Result;\n    // new op : get block info\n    Job.Op   =s7opAgBlockInfo;\n    Job.Area =Block_DB;\n    Job.pData=&BI;\n    Result   =opAgBlockInfo();\n    // Restore original op\n    Job.Op   =s7opDBFill;\n    // Fill internal buffer then write it\n    if (Result==0)\n    {\n        Job.Amount =BI.MC7Size;\n        Job.Area   =S7AreaDB;\n        Job.WordLen=S7WLByte;\n        Job.Start  =0;\n        memset(&opData, byte(Job.IParam), Job.Amount);\n        Job.pData  =&opData;\n        Result     =opWriteArea();\n    }\n    return Result;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::opUpload()\n{\n    PS7ResHeader23 Answer;\n    int  IsoSize;\n    byte Upload_ID = 0; // not strictly needed, only to avoid warning\n\tbyte BlockType;\n    int  BlockNum, BlockLength, Result;\n    bool Done, Full; // if full==true, the data will be compatible to full download function\n    uintptr_t Offset;\n    bool RoomError = false;\n\n    BlockType=Job.Area;\n    BlockNum =Job.Number;\n    Full     =Job.IParam==1;\n    // Setup Answer (is the same for all Upload pdus)\n    Answer=  PS7ResHeader23(&PDU.Payload);\n    // Init sequence\n    Done  =false;\n    Offset=0;\n    //<-------------------------------------------------------------StartUpload\n    PReqFunStartUploadParams ReqParams;\n    PResFunStartUploadParams ResParams;\n    // Setup pointers (note : PDUH_out and PDU.Payload are the same pointer)\n    ReqParams=PReqFunStartUploadParams(pbyte(PDUH_out)+sizeof(TS7ReqHeader));\n    ResParams=PResFunStartUploadParams(pbyte(Answer)+ResHeaderSize23);\n    // Init Header\n    PDUH_out->P=0x32;                   // Always 0x32\n    PDUH_out->PDUType=PduType_request;  // 0x01\n    PDUH_out->AB_EX=0x0000;             // Always 0x0000\n    PDUH_out->Sequence=GetNextWord();   // AutoInc\n    PDUH_out->ParLen=SwapWord(sizeof(TReqFunStartUploadParams));// params size\n    PDUH_out->DataLen=0x0000;           // No data\n    // Init Params\n    ReqParams->FunSUpld=pduStartUpload;\n    ReqParams->Uk6[0]=0x00;\n    ReqParams->Uk6[1]=0x00;\n    ReqParams->Uk6[2]=0x00;\n    ReqParams->Uk6[3]=0x00;\n    ReqParams->Uk6[4]=0x00;\n    ReqParams->Uk6[5]=0x00;\n    ReqParams->Upload_ID=Upload_ID;  // At begining is 0) we will put upload id incoming from plc\n    ReqParams->Len_1 =0x09; // 9 bytes from here\n    ReqParams->Prefix=0x5F;\n    ReqParams->BlkPrfx=0x30; // '0'\n    ReqParams->BlkType=BlockType;\n    // Block number\n    ReqParams->AsciiBlk[0]=(BlockNum / 10000)+0x30;\n    BlockNum=BlockNum % 10000;\n    ReqParams->AsciiBlk[1]=(BlockNum / 1000)+0x30;\n    BlockNum=BlockNum % 1000;\n    ReqParams->AsciiBlk[2]=(BlockNum / 100)+0x30;\n    BlockNum=BlockNum % 100;\n    ReqParams->AsciiBlk[3]=(BlockNum / 10)+0x30;\n    BlockNum=BlockNum % 10;\n    ReqParams->AsciiBlk[4]=(BlockNum / 1)+0x30;\n    ReqParams->A=0x41; // 'A'\n\n    IsoSize=sizeof(TS7ReqHeader)+sizeof(TReqFunStartUploadParams);\n    Result=isoExchangeBuffer(0,IsoSize);\n    // Get Upload Infos (only ID now)\n    if (Result==0)\n    {\n      if (Answer->Error==0)\n        Upload_ID=ResParams->Upload_ID;\n      else\n        Result=CpuError(SwapWord(Answer->Error));\n    };\n    //------------------------------------------------------------->StartUpload\n    if (Result==0)\n    {\n         //<--------------------------------------------------------FirstUpload\n        PReqFunUploadParams ReqParams;\n        PResFunUploadParams ResParams;\n        PResFunUploadDataHeaderFirst ResDataHeader;\n        pbyte Source;\n        pbyte Target;\n        int Size;\n\n        // Setup pointers (note : PDUH_out and PDU.Payload are the same pointer)\n        ReqParams=PReqFunUploadParams(pbyte(PDUH_out)+sizeof(TS7ReqHeader));\n        // First upload pdu consists of params, block info header, data.\n        ResParams=PResFunUploadParams(pbyte(Answer)+ResHeaderSize23);\n        ResDataHeader=PResFunUploadDataHeaderFirst(pbyte(ResParams)+sizeof(TResFunUploadParams));\n        if (Full)\n          Source=pbyte(ResDataHeader)+4; // skip only the mini header\n        else\n          Source=pbyte(ResDataHeader)+sizeof(TResFunUploadDataHeaderFirst);  // not full : skip the data header\n        // Init Header\n        PDUH_out->P=0x32;                   // Always 0x32\n        PDUH_out->PDUType=PduType_request;  // 0x01\n        PDUH_out->AB_EX=0x0000;             // Always 0x0000\n        PDUH_out->Sequence=GetNextWord();   // AutoInc\n        PDUH_out->ParLen=SwapWord(sizeof(TReqFunUploadParams));// params size\n        PDUH_out->DataLen=0x0000;           // No data\n        // Init Params\n        ReqParams->FunUpld=pduUpload;\n        ReqParams->Uk6[0]=0x00;\n        ReqParams->Uk6[1]=0x00;\n        ReqParams->Uk6[2]=0x00;\n        ReqParams->Uk6[3]=0x00;\n        ReqParams->Uk6[4]=0x00;\n        ReqParams->Uk6[5]=0x00;\n        ReqParams->Upload_ID=Upload_ID;  // At begining is 0) we will put upload id incoming from plc\n\n        IsoSize=sizeof(TS7ReqHeader)+sizeof(TReqFunUploadParams);\n        Result=isoExchangeBuffer(0,IsoSize);\n        // Get Upload Infos (only ID now)\n        if (Result==0)\n        {\n          if (Answer->Error==0)\n          {\n            Done=ResParams->EoU==0;\n            if (Full)\n                Size=SwapWord(Answer->DataLen)-4; // Full data Size\n            else\n                Size=SwapWord(Answer->DataLen)-sizeof(TResFunUploadDataHeaderFirst); // Size of this data slice\n\n            BlockLength=SwapWord(ResDataHeader->MC7Len); // Full block size in byte\n            Target=pbyte(&opData)+Offset;\n            memcpy(Target, Source, Size);\n            Offset+=Size;\n          }\n          else\n              Result=errCliUploadSequenceFailed;\n        };\n         //-------------------------------------------------------->FirstUpload\n         while (!Done && (Result==0))\n         {\n             //<----------------------------------------------------NextUpload\n            PReqFunUploadParams ReqParams;\n            PResFunUploadParams ResParams;\n            PResFunUploadDataHeaderNext ResDataHeader;\n            pbyte Source;\n            pbyte Target;\n            int Size;\n\n            // Setup pointers (note : PDUH_out and PDU.Payload are the same pointer)\n            ReqParams=PReqFunUploadParams(pbyte(PDUH_out)+sizeof(TS7ReqHeader));\n            // Next upload pdu consists of params, small info header, data.\n            ResParams=PResFunUploadParams(pbyte(Answer)+ResHeaderSize23);\n            ResDataHeader=PResFunUploadDataHeaderNext(pbyte(ResParams)+sizeof(TResFunUploadParams));\n            Source=pbyte(ResDataHeader)+sizeof(TResFunUploadDataHeaderNext);\n            // Init Header\n            PDUH_out->P=0x32;                   // Always 0x32\n            PDUH_out->PDUType=PduType_request;  // 0x01\n            PDUH_out->AB_EX=0x0000;             // Always 0x0000\n            PDUH_out->Sequence=GetNextWord();   // AutoInc\n            PDUH_out->ParLen=SwapWord(sizeof(TReqFunUploadParams));// params size\n            PDUH_out->DataLen=0x0000;           // No data\n            // Init Params\n            ReqParams->FunUpld=pduUpload;\n            ReqParams->Uk6[0]=0x00;\n            ReqParams->Uk6[1]=0x00;\n            ReqParams->Uk6[2]=0x00;\n            ReqParams->Uk6[3]=0x00;\n            ReqParams->Uk6[4]=0x00;\n            ReqParams->Uk6[5]=0x00;\n            ReqParams->Upload_ID=Upload_ID;  // At begining is 0) we will put upload id incoming from plc\n\n            IsoSize=sizeof(TS7ReqHeader)+sizeof(TReqFunUploadParams);\n            Result=isoExchangeBuffer(0,IsoSize);\n            // Get Upload Infos (only ID now)\n            if (Result==0)\n            {\n                if (Answer->Error==0)\n                {\n                    Done=ResParams->EoU==0;\n                    Size=SwapWord(Answer->DataLen)-sizeof(TResFunUploadDataHeaderNext); // Size of this data slice\n                    Target=pbyte(&opData)+Offset;\n                    memcpy(Target, Source, Size);\n                    Offset+=Size;\n                }\n                else\n                    Result=errCliUploadSequenceFailed;\n            };\n             //---------------------------------------------------->NextUpload\n         }\n         if (Result==0)\n         {\n            //<----------------------------------------------------EndUpload;\n            PReqFunEndUploadParams ReqParams;\n            PResFunEndUploadParams ResParams;\n\n            // Setup pointers (note : PDUH_out and PDU.Payload are the same pointer)\n            ReqParams=PReqFunEndUploadParams(pbyte(PDUH_out)+sizeof(TS7ReqHeader));\n            ResParams=PResFunEndUploadParams(pbyte(Answer)+ResHeaderSize23);\n            // Init Header\n            PDUH_out->P=0x32;                   // Always 0x32\n            PDUH_out->PDUType=PduType_request;  // 0x01\n            PDUH_out->AB_EX=0x0000;             // Always 0x0000\n            PDUH_out->Sequence=GetNextWord();   // AutoInc\n            PDUH_out->ParLen=SwapWord(sizeof(TReqFunEndUploadParams));// params size\n            PDUH_out->DataLen=0x0000;           // No data\n            // Init Params\n            ReqParams->FunEUpld=pduEndUpload;\n            ReqParams->Uk6[0]=0x00;\n            ReqParams->Uk6[1]=0x00;\n            ReqParams->Uk6[2]=0x00;\n            ReqParams->Uk6[3]=0x00;\n            ReqParams->Uk6[4]=0x00;\n            ReqParams->Uk6[5]=0x00;\n            ReqParams->Upload_ID=Upload_ID;  // At begining is 0) we will put upload id incoming from plc\n\n            IsoSize=sizeof(TS7ReqHeader)+sizeof(TReqFunEndUploadParams);\n            Result=isoExchangeBuffer(0,IsoSize);\n\n            // Get EndUpload Result\n            if (Result==0)\n            {\n               if ((Answer->Error!=0) || (ResParams->FunEUpld!=pduEndUpload))\n                   Result=errCliUploadSequenceFailed;\n            };\n            //---------------------------------------------------->EndUpload;\n         }\n    };\n\n    *Job.pAmount=0;\n    if (Result==0)\n    {\n        if (Full)\n        {\n            opSize=int(Offset);\n            if (opSize<78)\n                Result=errCliInvalidDataSizeRecvd;\n        }\n        else\n        {\n            opSize=BlockLength;\n            if (opSize<1)\n                Result=errCliInvalidDataSizeRecvd;\n        };\n        if (Result==0)\n        {\n\t\t\t // Checks user space\n             if (Job.Amount<opSize) {\n                 opSize=Job.Amount;\n\t\t\t\t RoomError = true;\n\t\t\t };\n\t\t\t memcpy(Job.pData, &opData, opSize);\n\t\t\t *Job.pAmount=opSize;\n\t\t\t if (RoomError) // Result==0 -> override if romerror\n\t\t\t\tResult=errCliPartialDataRead;\n\t\t};\n    };\n    return Result;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::opDownload()\n{\n    PS7CompactBlockInfo Info;\n    PS7BlockFooter Footer;\n    int BlockNum, StoreBlockNum, BlockAmount;\n    int BlockSize, BlockSizeLd;\n    int BlockType, Remainder;\n    int Result, IsoSize;\n    bool Done  = false;\n    uintptr_t Offset;\n\n    BlockAmount=Job.Amount;\n    BlockNum   =Job.Number;\n    Result=CheckBlock(-1,-1,&opData,BlockAmount);\n    if (Result==0)\n    {\n        Info=PS7CompactBlockInfo(&opData);\n        // Gets blocktype\n        BlockType=SubBlockToBlock(Info->SubBlkType);\n\n        if (BlockNum>=0)\n            Info->BlkNum=SwapWord(BlockNum); // change the number\n        else\n            BlockNum=SwapWord(Info->BlkNum); // use the header's number\n\n        BlockSizeLd=BlockAmount; // load mem needed for this block\n        BlockSize  =SwapWord(Info->MC7Len); // net size\n        Footer=PS7BlockFooter(pbyte(&opData)+BlockSizeLd-sizeof(TS7BlockFooter));\n        Footer->Chksum=0x0000;\n\n        Offset=0;\n        Remainder=BlockAmount;\n        //<---------------------------------------------- Start Download request\n            PReqStartDownloadParams ReqParams;\n            PResStartDownloadParams ResParams;\n            PS7ResHeader23          Answer;\n\n            // Setup pointers (note : PDUH_out and PDU.Payload are the same pointer)\n            ReqParams=PReqStartDownloadParams(pbyte(PDUH_out)+sizeof(TS7ReqHeader));\n            Answer   =PS7ResHeader23(&PDU.Payload);\n            ResParams=PResStartDownloadParams(pbyte(Answer)+ResHeaderSize23);\n            // Init Header\n            PDUH_out->P=0x32;                     // Always 0x32\n            PDUH_out->PDUType=PduType_request;    // 0x01\n            PDUH_out->AB_EX=0x0000;               // Always 0x0000\n            PDUH_out->Sequence=GetNextWord();     // AutoInc\n            PDUH_out->ParLen=SwapWord(sizeof(TReqStartDownloadParams));\n            PDUH_out->DataLen=0x0000;             // No data\n            // Init Params\n            ReqParams->FunSDwnld = pduReqDownload;\n            ReqParams->Uk6[0]=0x00;\n            ReqParams->Uk6[1]=0x01;\n            ReqParams->Uk6[2]=0x00;\n            ReqParams->Uk6[3]=0x00;\n            ReqParams->Uk6[4]=0x00;\n            ReqParams->Uk6[5]=0x00;\n            ReqParams->Dwnld_ID=0x00;\n            ReqParams->Len_1 =0x09;\n            ReqParams->Prefix=0x5F;\n            ReqParams->BlkPrfx=0x30;\n            ReqParams->BlkType=BlockType;\n\t\t\tStoreBlockNum=BlockNum;\n            ReqParams->AsciiBlk[0]=(BlockNum / 10000)+0x30;\n            BlockNum=BlockNum % 10000;\n            ReqParams->AsciiBlk[1]=(BlockNum / 1000)+0x30;\n            BlockNum=BlockNum % 1000;\n            ReqParams->AsciiBlk[2]=(BlockNum / 100)+0x30;\n            BlockNum=BlockNum % 100;\n            ReqParams->AsciiBlk[3]=(BlockNum / 10)+0x30;\n            BlockNum=BlockNum % 10;\n            ReqParams->AsciiBlk[4]=(BlockNum / 1)+0x30;\n            ReqParams->P    =0x50;\n            ReqParams->Len_2=0x0D;\n            ReqParams->Uk1  =0x31; // '1'\n\t\t\tBlockNum=StoreBlockNum;\n            // Load memory\n            ReqParams->AsciiLoad[0]=(BlockSizeLd / 100000)+0x30;\n            BlockSizeLd=BlockSizeLd % 100000;\n            ReqParams->AsciiLoad[1]=(BlockSizeLd / 10000)+0x30;\n            BlockSizeLd=BlockSizeLd % 10000;\n            ReqParams->AsciiLoad[2]=(BlockSizeLd / 1000)+0x30;\n            BlockSizeLd=BlockSizeLd % 1000;\n            ReqParams->AsciiLoad[3]=(BlockSizeLd / 100)+0x30;\n            BlockSizeLd=BlockSizeLd % 100;\n            ReqParams->AsciiLoad[4]=(BlockSizeLd / 10)+0x30;\n            BlockSizeLd=BlockSizeLd % 10;\n            ReqParams->AsciiLoad[5]=(BlockSizeLd / 1)+0x30;\n            // MC7 memory\n            ReqParams->AsciiMC7[0]=(BlockSize / 100000)+0x30;\n            BlockSize=BlockSize % 100000;\n            ReqParams->AsciiMC7[1]=(BlockSize / 10000)+0x30;\n            BlockSize=BlockSize % 10000;\n            ReqParams->AsciiMC7[2]=(BlockSize / 1000)+0x30;\n            BlockSize=BlockSize % 1000;\n            ReqParams->AsciiMC7[3]=(BlockSize / 100)+0x30;\n            BlockSize=BlockSize % 100;\n            ReqParams->AsciiMC7[4]=(BlockSize / 10)+0x30;\n            BlockSize=BlockSize % 10;\n            ReqParams->AsciiMC7[5]=(BlockSize / 1)+0x30;\n\n            IsoSize=sizeof(TS7ReqHeader)+sizeof(TReqStartDownloadParams);\n            Result=isoExchangeBuffer(0,IsoSize);\n\n            // Get Result\n            if (Result==0)\n            {\n                 if (SwapWord(Answer->Error)!=Code7NeedPassword)\n                 {\n                     if ((Answer->Error!=0) || (*ResParams!=pduReqDownload))\n                          Result=errCliDownloadSequenceFailed;\n                 }\n                 else\n                     Result=errCliNeedPassword;\n            }\n        //----------------------------------------------> Start Download request\n        if (Result==0)\n        {\n          do\n          {\n            //<-------------------------------- Download sequence (PLC requests)\n                PReqDownloadParams ReqParams;\n                PS7ResHeader23 Answer;\n                PResDownloadParams ResParams;\n                PResDownloadDataHeader ResData;\n                int Slice, Size, MaxSlice;\n                word Sequence;\n                pbyte Source;\n                pbyte Target;\n\n                ReqParams=PReqDownloadParams(pbyte(PDUH_out)+sizeof(TS7ReqHeader));\n                Answer   =PS7ResHeader23(&PDU.Payload);\n                ResParams=PResDownloadParams(pbyte(Answer)+ResHeaderSize23);\n                ResData  =PResDownloadDataHeader(pbyte(ResParams)+sizeof(TResDownloadParams));\n                Target   =pbyte(ResData)+sizeof(TResDownloadDataHeader);\n                Source   =pbyte(&opData)+Offset;\n\n                Result=isoRecvBuffer(0,Size);\n                if (Result==0)\n                {\n                      if ((u_int(Size)>sizeof(TS7ReqHeader)) && (ReqParams->Fun==pduDownload))\n                      {\n                            Sequence=PDUH_out->Sequence;\n                            // Max data slice that we can fit in this pdu\n                            MaxSlice=PDULength-ResHeaderSize23-sizeof(TResDownloadParams)-sizeof(TResDownloadDataHeader);\n                            Slice=Remainder;\n                            if (Slice>MaxSlice)\n                                Slice=MaxSlice;\n                            Remainder-=Slice;\n                            Offset+=Slice;\n                            Done=Remainder<=0;\n                            // Init Answer\n                            Answer->P=0x32;\n                            Answer->PDUType=PduType_response;\n                            Answer->AB_EX=0x0000;\n                            Answer->Sequence=Sequence;\n                            Answer->ParLen =SwapWord(sizeof(TResDownloadParams));\n                            Answer->DataLen=SwapWord(word(sizeof(TResDownloadDataHeader))+Slice);\n                            Answer->Error  =0x0000;\n\n                            // Init Params\n                            ResParams->FunDwnld=pduDownload;\n                            if (Remainder>0)\n                                ResParams->EoS=0x01;\n                            else\n                                ResParams->EoS=0x00;\n\n                            // Init Data\n                            ResData->DataLen=SwapWord(Slice);\n                            ResData->FB_00=0xFB00;\n                            memcpy(Target, Source, Slice);\n\n                            // Send the slice\n                            IsoSize=ResHeaderSize23+sizeof(TResDownloadParams)+sizeof(TResDownloadDataHeader)+Slice;\n                            Result=isoSendBuffer(0,IsoSize);\n                      }\n                      else\n                          Result=errCliDownloadSequenceFailed;\n                };\n            //--------------------------------> Download sequence (PLC requests)\n          }\n          while (!Done && (Result==0));\n\n          if (Result==0)\n          {\n            //<-------------------------------------------Perform Download Ended\n                PReqDownloadParams ReqParams;\n                PS7ResHeader23 Answer;\n                PResEndDownloadParams ResParams;\n                int Size;\n                word Sequence;\n\n                ReqParams=PReqDownloadParams(pbyte(PDUH_out)+sizeof(TS7ReqHeader));\n                Answer   =PS7ResHeader23(&PDU.Payload);\n                ResParams=PResEndDownloadParams(pbyte(Answer)+ResHeaderSize23);\n\n                Result=isoRecvBuffer(0,Size);\n                if (Result==0)\n                {\n                  if ((u_int(Size)>sizeof(TS7ReqHeader)) && (ReqParams->Fun==pduDownloadEnded))\n                  {\n                    Sequence=PDUH_out->Sequence;\n                    // Init Answer\n                    Answer->P=0x32;\n                    Answer->PDUType=PduType_response;\n                    Answer->AB_EX=0x0000;\n                    Answer->Sequence=Sequence;\n                    Answer->ParLen =SwapWord(sizeof(TResEndDownloadParams));\n                    Answer->DataLen=0x0000;\n                    Answer->Error  =0x0000;\n\n                    // Init Params\n                    *ResParams=pduDownloadEnded;\n                    IsoSize=ResHeaderSize23+sizeof(TResEndDownloadParams);\n                    Result=isoSendBuffer(0,IsoSize);\n                  }\n                  else\n                      Result=errCliDownloadSequenceFailed;\n                };\n            //------------------------------------------->Perform Download Ended\n            if (Result==0)\n            {\n               //<----------------------------------- Insert block into the unit\n                PReqControlBlockParams ReqParams;\n                PS7ResHeader23 Answer;\n                pbyte ResParams;\n\n                // Setup pointers (note : PDUH_out and PDU.Payload are the same pointer)\n                ReqParams=PReqControlBlockParams(pbyte(PDUH_out)+sizeof(TS7ReqHeader));\n                Answer=PS7ResHeader23(&PDU.Payload);\n                ResParams=pbyte(Answer)+ResHeaderSize23;\n                // Init Header\n                PDUH_out->P=0x32;                     // Always 0x32\n                PDUH_out->PDUType=PduType_request;    // 0x01\n                PDUH_out->AB_EX=0x0000;               // Always 0x0000\n                PDUH_out->Sequence=GetNextWord();     // AutoInc\n                PDUH_out->ParLen=SwapWord(sizeof(TReqControlBlockParams));\n                PDUH_out->DataLen=0x0000;             // No data\n                // Init Params\n                ReqParams->Fun = pduControl;\n                ReqParams->Uk7[0]=0x00;\n                ReqParams->Uk7[1]=0x00;\n                ReqParams->Uk7[2]=0x00;\n                ReqParams->Uk7[3]=0x00;\n                ReqParams->Uk7[4]=0x00;\n                ReqParams->Uk7[5]=0x00;\n                ReqParams->Uk7[6]=0xFD;\n                ReqParams->Len_1 =SwapWord(0x0A);\n                ReqParams->NumOfBlocks=0x01;\n                ReqParams->ByteZero   =0x00;\n                ReqParams->AsciiZero  =0x30;\n                ReqParams->BlkType=BlockType;\n                ReqParams->AsciiBlk[0]=(BlockNum / 10000)+0x30;\n                BlockNum=BlockNum % 10000;\n                ReqParams->AsciiBlk[1]=(BlockNum / 1000)+0x30;\n                BlockNum=BlockNum % 1000;\n                ReqParams->AsciiBlk[2]=(BlockNum / 100)+0x30;\n                BlockNum=BlockNum % 100;\n                ReqParams->AsciiBlk[3]=(BlockNum / 10)+0x30;\n                BlockNum=BlockNum % 10;\n                ReqParams->AsciiBlk[4]=(BlockNum / 1)+0x30;\n                ReqParams->SFun =SFun_Insert;\n                ReqParams->Len_2=0x05;\n                ReqParams->Cmd[0]='_';\n                ReqParams->Cmd[1]='I';\n                ReqParams->Cmd[2]='N';\n                ReqParams->Cmd[3]='S';\n                ReqParams->Cmd[4]='E';\n\n                IsoSize=sizeof(TS7ReqHeader)+sizeof(TReqControlBlockParams);\n                Result=isoExchangeBuffer(0,IsoSize);\n\n                if (Result==0)\n                {\n                  if ((Answer->Error!=0) || (*ResParams!=pduControl))\n                     Result=errCliInsertRefused;\n                };\n               //-----------------------------------> Insert block into the unit\n            }\n          };\n        };\n    };\n    return Result;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::opDelete()\n{\n    PReqControlBlockParams ReqParams;\n    PS7ResHeader23 Answer;\n    pbyte ResParams;\n    int IsoSize, BlockType, BlockNum, Result;\n\n    BlockType=Job.Area;\n    BlockNum =Job.Number;\n    // Setup pointers (note : PDUH_out and PDU.Payload are the same pointer)\n    ReqParams=PReqControlBlockParams(pbyte(PDUH_out)+sizeof(TS7ReqHeader));\n    Answer   =PS7ResHeader23(&PDU.Payload);\n    ResParams=pbyte(Answer)+ResHeaderSize23;\n    // Init Header\n    PDUH_out->P=0x32;                     // Always 0x32\n    PDUH_out->PDUType=PduType_request;    // 0x01\n    PDUH_out->AB_EX=0x0000;               // Always 0x0000\n    PDUH_out->Sequence=GetNextWord();     // AutoInc\n    PDUH_out->ParLen=SwapWord(sizeof(TReqControlBlockParams));\n    PDUH_out->DataLen=0x0000;             // No data\n    // Init Params\n    ReqParams->Fun = pduControl;\n    ReqParams->Uk7[0]=0x00;\n    ReqParams->Uk7[1]=0x00;\n    ReqParams->Uk7[2]=0x00;\n    ReqParams->Uk7[3]=0x00;\n    ReqParams->Uk7[4]=0x00;\n    ReqParams->Uk7[5]=0x00;\n    ReqParams->Uk7[6]=0xFD;\n    ReqParams->Len_1 =SwapWord(0x0A);\n    ReqParams->NumOfBlocks=0x01;\n    ReqParams->ByteZero   =0x00;\n    ReqParams->AsciiZero  =0x30;\n    ReqParams->BlkType=BlockType;\n    ReqParams->AsciiBlk[0]=(BlockNum / 10000)+0x30;\n    BlockNum=BlockNum % 10000;\n    ReqParams->AsciiBlk[1]=(BlockNum / 1000)+0x30;\n    BlockNum=BlockNum % 1000;\n    ReqParams->AsciiBlk[2]=(BlockNum / 100)+0x30;\n    BlockNum=BlockNum % 100;\n    ReqParams->AsciiBlk[3]=(BlockNum / 10)+0x30;\n    BlockNum=BlockNum % 10;\n    ReqParams->AsciiBlk[4]=(BlockNum / 1)+0x30;\n    ReqParams->SFun =SFun_Delete;\n    ReqParams->Len_2=0x05;\n    ReqParams->Cmd[0]='_';\n    ReqParams->Cmd[1]='D';\n    ReqParams->Cmd[2]='E';\n    ReqParams->Cmd[3]='L';\n    ReqParams->Cmd[4]='E';\n\n    IsoSize=sizeof(TS7ReqHeader)+sizeof(TReqControlBlockParams);\n    Result=isoExchangeBuffer(0,IsoSize);\n\n    if (Result==0)\n    {\n        if (SwapWord(Answer->Error)!=Code7NeedPassword)\n        {\n            if ((Answer->Error!=0) || (*ResParams!=pduControl))\n              Result=errCliDeleteRefused;\n        }\n        else\n            Result=errCliNeedPassword;\n    }\n    return Result;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::opReadSZL()\n{\n    PS7Answer17         Answer;\n    PReqFunReadSZLFirst ReqParamsFirst;\n    PReqFunReadSZLNext  ReqParamsNext;\n    PS7ReqSZLData       ReqDataFirst;\n    PS7ReqSZLData       ReqDataNext;\n    PS7ResParams7       ResParams;\n    PS7ResSZLDataFirst  ResDataFirst;\n    PS7ResSZLDataNext   ResDataNext;\n    PSZL_HEADER         Header;\n    PS7SZLList          Target;\n    pbyte               PDataFirst;\n    pbyte               PDataNext;\n    word                ID, Index;\n    int                 IsoSize, DataSize, DataSZL, Result;\n    bool                First, Done;\n    bool                NoRoom = false;\n    uintptr_t           Offset =0;\n    byte                Seq_in =0x00;\n\n    ID=Job.ID;\n    Index=Job.Index;\n    opSize=0;\n    // Setup pointers (note : PDUH_out and PDU.Payload are the same pointer)\n    ReqParamsFirst=PReqFunReadSZLFirst(pbyte(PDUH_out)+sizeof(TS7ReqHeader));\n    ReqParamsNext =PReqFunReadSZLNext(pbyte(PDUH_out)+sizeof(TS7ReqHeader));\n    ReqDataFirst  =PS7ReqSZLData(pbyte(ReqParamsFirst)+sizeof(TReqFunReadSZLFirst));\n    ReqDataNext   =PS7ReqSZLData(pbyte(ReqParamsNext)+sizeof(TReqFunReadSZLNext));\n\n    Answer        =PS7Answer17(&PDU.Payload);\n    ResParams     =PS7ResParams7(pbyte(Answer)+ResHeaderSize17);\n    ResDataFirst  =PS7ResSZLDataFirst(pbyte(ResParams)+sizeof(TS7Params7));\n    ResDataNext   =PS7ResSZLDataNext(pbyte(ResParams)+sizeof(TS7Params7));\n    PDataFirst    =pbyte(ResDataFirst)+8; // skip header\n    PDataNext     =pbyte(ResDataNext)+4;  // skip header\n    Header        =PSZL_HEADER(&opData);\n    First=true;\n    Done =false;\n    do\n    {\n    //<------------------------------------------------------- read slices\n        if (First)\n        {\n         //<-------------------------------------------------- prepare first\n            DataSize=sizeof(TS7ReqSZLData);\n            // Fill Header\n            PDUH_out->P=0x32;                    // Always 0x32\n            PDUH_out->PDUType=PduType_userdata;  // 0x07\n            PDUH_out->AB_EX=0x0000;              // Always 0x0000\n            PDUH_out->Sequence=GetNextWord();    // AutoInc\n            PDUH_out->ParLen=SwapWord(sizeof(TReqFunReadSZLFirst)); // 8 bytes params\n            PDUH_out->DataLen=SwapWord(DataSize); // 8/4 bytes data\n            // Fill Params\n            ReqParamsFirst->Head[0]=0x00;\n            ReqParamsFirst->Head[1]=0x01;\n            ReqParamsFirst->Head[2]=0x12;\n            ReqParamsFirst->Plen   =0x04;\n            ReqParamsFirst->Uk     =0x11;\n            ReqParamsFirst->Tg     =grSZL;\n            ReqParamsFirst->SubFun =SFun_ReadSZL; //0x03\n            ReqParamsFirst->Seq    =Seq_in;\n            // Fill Data\n            ReqDataFirst->Ret      =0xFF;\n            ReqDataFirst->TS       =TS_ResOctet;\n            ReqDataFirst->DLen     =SwapWord(0x0004);\n            ReqDataFirst->ID       =SwapWord(ID);\n            ReqDataFirst->Index    =SwapWord(Index);\n            IsoSize=sizeof(TS7ReqHeader)+sizeof(TReqFunReadSZLFirst)+DataSize;\n         //--------------------------------------------------> prepare first\n        }\n        else\n        {\n         //<-------------------------------------------------- prepare next\n            DataSize=sizeof(TS7ReqSZLData)-4;\n            // Fill Header\n            PDUH_out->P=0x32;                    // Always 0x32\n            PDUH_out->PDUType=PduType_userdata;  // 0x07\n            PDUH_out->AB_EX=0x0000;              // Always 0x0000\n            PDUH_out->Sequence=GetNextWord();    // AutoInc\n            PDUH_out->ParLen=SwapWord(sizeof(TReqFunReadSZLNext)); // 8 bytes params\n            PDUH_out->DataLen=SwapWord(DataSize);// 8/4 bytes data\n            // Fill Params\n            ReqParamsNext->Head[0]=0x00;\n            ReqParamsNext->Head[1]=0x01;\n            ReqParamsNext->Head[2]=0x12;\n            ReqParamsNext->Plen   =0x08;\n            ReqParamsNext->Uk     =0x12;\n            ReqParamsNext->Tg     =grSZL;\n            ReqParamsNext->SubFun =SFun_ReadSZL;\n            ReqParamsNext->Seq    =Seq_in;\n            ReqParamsNext->Rsvd   =0x0000;\n            ReqParamsNext->ErrNo  =0x0000;\n            // Fill Data\n            ReqDataNext->Ret      =0x0A;\n            ReqDataNext->TS       =0x00;\n            ReqDataNext->DLen     =0x0000;\n            ReqDataNext->ID       =0x0000;\n            ReqDataNext->Index    =0x0000;\n            IsoSize=sizeof(TS7ReqHeader)+sizeof(TReqFunReadSZLNext)+DataSize;\n         //--------------------------------------------------> prepare next\n        }\n        Result=isoExchangeBuffer(0,IsoSize);\n        // Get Data\n        if (Result==0)\n        {\n            if (First)\n            {\n            //<------------------------------------------ get data first\n                if (ResParams->Err==0)\n                {\n                    if (ResDataFirst->Ret==0xFF)  // <-- 0xFF means Result OK\n                    {\n                        // Gets Amount of this slice\n                        DataSZL=SwapWord(ResDataFirst->DLen)-4;// Skips extra params (ID, Index ...)\n                        // Gets end of Sequence Flag\n                        Done=(ResParams->resvd & 0xFF00) == 0; // Low order byte = 0x00 => the sequence is done\n                        // Gets Unit's function sequence\n                        Seq_in=ResParams->Seq;\n                        Target=PS7SZLList(pbyte(&opData)+Offset);\n                        memcpy(Target, PDataFirst, DataSZL);\n                        Offset+=DataSZL;\n                    }\n                    else\n                        Result=CpuError(ResDataFirst->Ret);\n                }\n                else\n                    Result=CpuError(ResDataFirst->Ret);\n            //------------------------------------------> get data first\n            }\n            else\n            {\n            //<------------------------------------------ get data next\n                if (ResParams->Err==0)\n                {\n                    if (ResDataNext->Ret==0xFF)  // <-- 0xFF means Result OK\n                    {\n                        // Gets Amount of this slice\n                        DataSZL=SwapWord(ResDataNext->DLen);\n                        // Gets end  of Sequence Flag\n                        Done=(ResParams->resvd & 0xFF00) == 0; // Low order byte = 0x00 => the sequence is done\n                        // Gets Unit's function sequence\n                        Seq_in=ResParams->Seq;\n                        Target=PS7SZLList(pbyte(&opData)+Offset);\n                        memcpy(Target, PDataNext, DataSZL);\n                        Offset+=DataSZL;\n                    }\n                    else\n                        Result=CpuError(ResDataNext->Ret);\n                }\n                else\n                    Result=CpuError(ResDataNext->Ret);\n            //------------------------------------------> get data next\n            }\n            First=false;\n        }\n    //-------------------------------------------------------> read slices\n    }\n    while ((!Done) && (Result==0));\n\n    // Check errors and adjust header\n    if (Result==0)\n    {\n        // Adjust big endian header\n        Header->LENTHDR=SwapWord(Header->LENTHDR);\n        Header->N_DR   =SwapWord(Header->N_DR);\n        opSize=int(Offset);\n\n        if (Job.IParam==1)  // if 1 data has to be copied into user buffer\n        {\n              // Check buffer size\n              if (opSize>Job.Amount)\n              {\n                 opSize=Job.Amount;\n                 NoRoom=true;\n              }\n              memcpy(Job.pData, &opData, opSize);\n              *Job.pAmount=opSize;\n        };\n    };\n    if ((Result==0)&& NoRoom)\n        Result=errCliBufferTooSmall;\n\n    return Result;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::opReadSZLList()\n{\n    PS7SZLList usrSZLList, opDataList;\n    int ItemsCount, ItemsCount_in, c, Result;\n    bool NoRoom = false;\n\n    Job.ID       =0x0000;\n    Job.Index    =0x0000;\n    Job.IParam   =0;\n    ItemsCount_in=Job.Amount;     // stores the room\n    Job.Amount   =sizeof(opData); // read into the internal buffer\n\n    Result =opReadSZL();\n    if (Result==0)\n    {\n        opDataList=PS7SZLList(&opData); // Source\n        usrSZLList=PS7SZLList(Job.pData);  // Target\n\n        ItemsCount=(opSize-sizeof(SZL_HEADER)) / 2;\n        // Check input size\n        if (ItemsCount>ItemsCount_in)\n        {\n            ItemsCount=ItemsCount_in; // Trim itemscount\n            NoRoom=true;\n        }\n        for (c = 0; c < ItemsCount; c++)\n          usrSZLList->List[c]=SwapWord(opDataList->List[c]);\n        *Job.pAmount=ItemsCount;\n    }\n    else\n        *Job.pAmount=0;\n\n    if ((Result==0) && NoRoom)\n        Result=errCliBufferTooSmall;\n\n    return Result;\n}\n//---------------------------------------------------------------------------\nbyte TSnap7MicroClient::BCDtoByte(byte B)\n{\n    return ((B >> 4) * 10) + (B & 0x0F);\n}\n//---------------------------------------------------------------------------\nbyte TSnap7MicroClient::WordToBCD(word Value)\n{\n    return ((Value / 10) << 4) | (Value % 10);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::opGetDateTime()\n{\n    PTimeStruct DateTime;\n    PReqFunDateTime ReqParams;\n    PReqDataGetDateTime ReqData;\n    PS7ResParams7 ResParams;\n    PResDataGetTime ResData;\n    PS7ResHeader17 Answer;\n    int IsoSize, Result;\n    word AYear;\n\n    // Setup pointers (note : PDUH_out and PDU.Payload are the same pointer)\n    ReqParams=PReqFunDateTime(pbyte(PDUH_out)+sizeof(TS7ReqHeader));\n    ReqData  =PReqDataGetDateTime(pbyte(ReqParams)+sizeof(TReqFunDateTime));\n    Answer   =PS7ResHeader17(&PDU.Payload);\n    ResParams=PS7ResParams7(pbyte(Answer)+ResHeaderSize17);\n    ResData  =PResDataGetTime(pbyte(ResParams)+sizeof(TS7Params7));\n    DateTime =PTimeStruct(Job.pData);\n    // Fill Header\n    PDUH_out->P=0x32;                    // Always 0x32\n    PDUH_out->PDUType=PduType_userdata;  // 0x07\n    PDUH_out->AB_EX=0x0000;              // Always 0x0000\n    PDUH_out->Sequence=GetNextWord();    // AutoInc\n    PDUH_out->ParLen=SwapWord(sizeof(TReqFunDateTime));   // 8 bytes params\n    PDUH_out->DataLen=SwapWord(sizeof(TReqDataGetDateTime)); // 4 bytes data\n    // Fill params (mostly constants)\n    ReqParams->Head[0]=0x00;\n    ReqParams->Head[1]=0x01;\n    ReqParams->Head[2]=0x12;\n    ReqParams->Plen   =0x04;\n    ReqParams->Uk     =0x11;\n    ReqParams->Tg     =grClock;\n    ReqParams->SubFun =SFun_ReadClock;\n    ReqParams->Seq    =0x00;\n    // Fill Data\n    *ReqData =0x0000000A;\n\n    IsoSize=sizeof(TS7ReqHeader)+sizeof(TReqFunDateTime)+sizeof(TReqDataGetDateTime);\n    Result=isoExchangeBuffer(0,IsoSize);\n\n    // Get Data\n    if (Result==0)\n    {\n        if (ResParams->Err==0)\n        {\n            if (ResData->RetVal==0xFF) // <-- 0xFF means Result OK\n            {\n                // Decode Plc Date and Time\n                AYear=BCDtoByte(ResData->Time[0]);\n                if (AYear<90)\n                  AYear=AYear+100;\n                DateTime->tm_year=AYear;\n                DateTime->tm_mon =BCDtoByte(ResData->Time[1])-1;\n                DateTime->tm_mday=BCDtoByte(ResData->Time[2]);\n                DateTime->tm_hour=BCDtoByte(ResData->Time[3]);\n                DateTime->tm_min =BCDtoByte(ResData->Time[4]);\n                DateTime->tm_sec =BCDtoByte(ResData->Time[5]);\n                DateTime->tm_wday=(ResData->Time[7] & 0x0F)-1;\n            }\n            else\n                Result=CpuError(ResData->RetVal);\n        }\n        else\n            Result=CpuError(ResData->RetVal);\n    }\n    return Result;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::opSetDateTime()\n{\n    PTimeStruct DateTime;\n    PReqFunDateTime ReqParams;\n    PReqDataSetTime ReqData;\n    PS7ResParams7 ResParams;\n    PS7ResHeader17 Answer;\n    word AYear;\n    int IsoSize, Result;\n\n    // Setup pointers (note : PDUH_out and PDU.Payload are the same pointer)\n    ReqParams=PReqFunDateTime(pbyte(PDUH_out)+sizeof(TS7ReqHeader));\n    ReqData  =PReqDataSetTime(pbyte(ReqParams)+sizeof(TReqFunDateTime));\n    Answer   =PS7ResHeader17(&PDU.Payload);\n    ResParams=PS7ResParams7(pbyte(Answer)+ResHeaderSize17);\n    DateTime =PTimeStruct(Job.pData);\n    // Fill Header\n    PDUH_out->P=0x32;                    // Always 0x32\n    PDUH_out->PDUType=PduType_userdata;  // 0x07\n    PDUH_out->AB_EX=0x0000;              // Always 0x0000\n    PDUH_out->Sequence=GetNextWord();    // AutoInc\n    PDUH_out->ParLen=SwapWord(sizeof(TReqFunDateTime));  // 8 bytes params\n    PDUH_out->DataLen=SwapWord(sizeof(TReqDataSetTime)); // 4 bytes data\n    // Fill params (mostly constants)\n    ReqParams->Head[0]=0x00;\n    ReqParams->Head[1]=0x01;\n    ReqParams->Head[2]=0x12;\n    ReqParams->Plen   =0x04;\n    ReqParams->Uk     =0x11;\n    ReqParams->Tg     =grClock;\n    ReqParams->SubFun =SFun_SetClock;\n    ReqParams->Seq    =0x00;\n    // EncodeSiemensDateTime;\n    if (DateTime->tm_year<100)\n        AYear=DateTime->tm_year;\n    else\n        AYear=DateTime->tm_year-100;\n\n    ReqData->RetVal=0xFF;\n    ReqData->TSize =TS_ResOctet;\n    ReqData->Length=SwapWord(0x000A);\n    ReqData->Rsvd  =0x00;\n    ReqData->HiYear=0x19; // *must* be 19 tough it's not the Hi part of the year...\n\n    ReqData->Time[0]=WordToBCD(AYear);\n    ReqData->Time[1]=WordToBCD(DateTime->tm_mon+1);\n    ReqData->Time[2]=WordToBCD(DateTime->tm_mday);\n    ReqData->Time[3]=WordToBCD(DateTime->tm_hour);\n    ReqData->Time[4]=WordToBCD(DateTime->tm_min);\n    ReqData->Time[5]=WordToBCD(DateTime->tm_sec);\n    ReqData->Time[6]=0;\n    ReqData->Time[7]=DateTime->tm_wday+1;\n\n    IsoSize=sizeof(TS7ReqHeader)+sizeof(TReqFunDateTime)+sizeof(TReqDataSetTime);\n    Result=isoExchangeBuffer(0,IsoSize);\n\n    // Get Result\n    if (Result==0)\n    {\n       if (ResParams->Err!=0)\n          Result=CpuError(SwapWord(ResParams->Err));\n    };\n    return Result;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::opGetOrderCode()\n{\n    PS7OrderCode OC;\n    int Result;\n\n    Job.ID     =0x0011;\n    Job.Index  =0x0000;\n    Job.IParam =0;\n    Result     =opReadSZL();\n    if (Result==0)\n    {\n        OC=PS7OrderCode(Job.pData);\n        memset(OC,0,sizeof(TS7OrderCode));\n        memcpy(OC->Code,&opData[6],20);\n        OC->V1=opData[opSize-3];\n        OC->V2=opData[opSize-2];\n        OC->V3=opData[opSize-1];\n    };\n    return Result;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::opGetCpuInfo()\n{\n    PS7CpuInfo Info;\n    int Result;\n\n    // Store Pointer\n    Info=PS7CpuInfo(Job.pData);\n    // Clear data in order to have the end of strings (\\0) correctly setted\n    memset(Info, 0, sizeof(TS7CpuInfo));\n\n    Job.ID    =0x001C;\n    Job.Index =0x0000;\n    Job.IParam=0;\n    Result    =opReadSZL();\n    if (Result==0)\n    {\n        memcpy(Info->ModuleTypeName,&opData[176],32);\n        memcpy(Info->SerialNumber,&opData[142],24);\n\t\tmemcpy(Info->ASName,&opData[6],24);\n        memcpy(Info->Copyright,&opData[108],26);\n        memcpy(Info->ModuleName,&opData[40],24);\n    }\n    return Result;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::opGetCpInfo()\n{\n    PS7CpInfo Info;\n    int Result;\n    // Store Pointer\n    Info=PS7CpInfo(Job.pData);\n    memset(Info,0,sizeof(TS7CpInfo));\n    Job.ID    =0x0131;\n    Job.Index =0x0001;\n    Job.IParam=0;\n    Result    =opReadSZL();\n    if (Result==0)\n    {\n        Info->MaxPduLengt=opData[6]*256+opData[7];\n        Info->MaxConnections=opData[8]*256+opData[9];\n        Info->MaxMpiRate=DWordAt(&opData[10]);\n        Info->MaxBusRate=DWordAt(&opData[14]);\n    };\n    return Result;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::opGetPlcStatus()\n{\n    int *Status;\n    int Result;\n\n    Status =(int*)Job.pData;\n    Job.ID     =0x0424;\n    Job.Index  =0x0000;\n    Job.IParam =0;\n    Result     =opReadSZL();\n    if (Result==0)\n    {\n        switch (opData[7])\n        {\n            case S7CpuStatusUnknown :\n            case S7CpuStatusRun     :\n            case S7CpuStatusStop    : *Status=opData[7];\n            break;\n            default :\n            // Since RUN status is always $08 for all CPUs and CPs, STOP status\n            // sometime can be coded as $03 (especially for old cpu...)\n                *Status=S7CpuStatusStop;\n        }\n    }\n    else\n        *Status=0;\n    return Result;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::opPlcStop()\n{\n    PReqFunPlcStop ReqParams;\n    PResFunCtrl ResParams;\n    PS7ResHeader23 Answer;\n    int IsoSize, Result;\n\n    char p_program[] = {'P','_','P','R','O','G','R','A','M'};\n\n    // Setup pointers (note : PDUH_out and PDU.Payload are the same pointer)\n    ReqParams=PReqFunPlcStop(pbyte(PDUH_out)+sizeof(TS7ReqHeader));\n    Answer   =PS7ResHeader23(&PDU.Payload);\n    ResParams=PResFunCtrl(pbyte(Answer)+ResHeaderSize23);\n    // Fill Header\n    PDUH_out->P=0x32;                    // Always 0x32\n    PDUH_out->PDUType=PduType_request;   // 0x01\n    PDUH_out->AB_EX=0x0000;              // Always 0x0000\n    PDUH_out->Sequence=GetNextWord();    // AutoInc\n    PDUH_out->ParLen=SwapWord(sizeof(TReqFunPlcStop));\n    PDUH_out->DataLen=0x0000;            // No Data\n    // Fill Params\n    ReqParams->Fun=pduStop;\n    memset(ReqParams->Uk_5,0,5);\n    ReqParams->Len_2=0x09;\n    memcpy(ReqParams->Cmd,&p_program,9);\n\n    IsoSize=sizeof(TS7ReqHeader)+sizeof(TReqFunPlcStop);\n    Result=isoExchangeBuffer(0,IsoSize);\n\n    if (Result==0)\n    {\n        if (Answer->Error!=0)\n        {\n          if (ResParams->ResFun!=pduStop)\n             Result=errCliCannotStopPLC;\n          else\n             if (ResParams->para ==0x07)\n                 Result=errCliAlreadyStop;\n             else\n                 Result=errCliCannotStopPLC;\n        };\n    };\n    return Result;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::opPlcHotStart()\n{\n    PReqFunPlcHotStart ReqParams;\n    PResFunCtrl ResParams;\n    PS7ResHeader23 Answer;\n    int IsoSize, Result;\n\n    char p_program[] = {'P','_','P','R','O','G','R','A','M'};\n\n    // Setup pointers (note : PDUH_out and PDU.Payload are the same pointer)\n    ReqParams=PReqFunPlcHotStart(pbyte(PDUH_out)+sizeof(TS7ReqHeader));\n    Answer   =PS7ResHeader23(&PDU.Payload);\n    ResParams=PResFunCtrl(pbyte(Answer)+ResHeaderSize23);\n    // Fill Header\n    PDUH_out->P=0x32;                    // Always 0x32\n    PDUH_out->PDUType=PduType_request;   // 0x01\n    PDUH_out->AB_EX=0x0000;              // Always 0x0000\n    PDUH_out->Sequence=GetNextWord();    // AutoInc\n    PDUH_out->ParLen=SwapWord(sizeof(TReqFunPlcHotStart));   // 16 bytes params\n    PDUH_out->DataLen=0x0000;            // No Data\n    // Fill Params\n    ReqParams->Fun=pduStart;\n    ReqParams->Uk_7[0]=0x00;\n    ReqParams->Uk_7[1]=0x00;\n    ReqParams->Uk_7[2]=0x00;\n    ReqParams->Uk_7[3]=0x00;\n    ReqParams->Uk_7[4]=0x00;\n    ReqParams->Uk_7[5]=0x00;\n    ReqParams->Uk_7[6]=0xFD;\n\n    ReqParams->Len_1=0x0000;\n    ReqParams->Len_2=0x09;\n    memcpy(ReqParams->Cmd,&p_program,9);\n\n    IsoSize=sizeof(TS7ReqHeader)+sizeof(TReqFunPlcHotStart);\n    Result=isoExchangeBuffer(0,IsoSize);\n\n    if (Result==0)\n    {\n        if ((Answer->Error!=0))\n        {\n          if ((ResParams->ResFun!=pduStart))\n              Result=errCliCannotStartPLC;\n          else\n          {\n              if (ResParams->para==0x03)\n                  Result=errCliAlreadyRun;\n              else\n                  if (ResParams->para==0x02)\n                      Result=errCliCannotStartPLC;\n                  else\n                      Result=errCliCannotStartPLC;\n          }\n        }\n    };\n    return Result;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::opPlcColdStart()\n{\n    PReqFunPlcColdStart ReqParams;\n    PResFunCtrl ResParams;\n    PS7ResHeader23 Answer;\n    int IsoSize, Result;\n    char p_program[] = {'P','_','P','R','O','G','R','A','M'};\n\n    // Setup pointers (note : PDUH_out and PDU.Payload are the same pointer)\n    ReqParams=PReqFunPlcColdStart(pbyte(PDUH_out)+sizeof(TS7ReqHeader));\n    Answer   =PS7ResHeader23(&PDU.Payload);\n    ResParams=PResFunCtrl(pbyte(Answer)+ResHeaderSize23);\n    // Fill Header\n    PDUH_out->P=0x32;                     // Always 0x32\n    PDUH_out->PDUType=PduType_request;   // 0x01\n    PDUH_out->AB_EX=0x0000;               // Always 0x0000\n    PDUH_out->Sequence=GetNextWord();      // AutoInc\n    PDUH_out->ParLen=SwapWord(sizeof(TReqFunPlcColdStart));   // 22 bytes params\n    PDUH_out->DataLen=0x0000;             // No Data\n    // Fill Params\n    ReqParams->Fun=pduStart;\n    ReqParams->Uk_7[0]=0x00;\n    ReqParams->Uk_7[1]=0x00;\n    ReqParams->Uk_7[2]=0x00;\n    ReqParams->Uk_7[3]=0x00;\n    ReqParams->Uk_7[4]=0x00;\n    ReqParams->Uk_7[5]=0x00;\n    ReqParams->Uk_7[6]=0xFD;\n\n    ReqParams->Len_1=SwapWord(0x0002);\n    ReqParams->SFun =SwapWord(0x4320); // Cold start\n    ReqParams->Len_2=0x09;\n    memcpy(ReqParams->Cmd,&p_program,9);\n\n    IsoSize=sizeof(TS7ReqHeader)+sizeof(TReqFunPlcColdStart);\n    Result=isoExchangeBuffer(0,IsoSize);\n\n    if (Result==0)\n    {\n        if ((Answer->Error!=0))\n        {\n          if ((ResParams->ResFun!=pduStart))\n              Result=errCliCannotStartPLC;\n          else\n          {\n              if (ResParams->para==0x03)\n                  Result=errCliAlreadyRun;\n              else\n                  if (ResParams->para==0x02)\n                      Result=errCliCannotStartPLC;\n                  else\n                      Result=errCliCannotStartPLC;\n          }\n        }\n    };\n    return Result;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::opCopyRamToRom()\n{\n    PReqFunCopyRamToRom ReqParams;\n    PResFunCtrl ResParams;\n    PS7ResHeader23 Answer;\n    int IsoSize, CurTimeout, Result;\n    char _modu[] = {'_','M','O','D','U'};\n\n    // Setup pointers (note : PDUH_out and PDU.Payload are the same pointer)\n    ReqParams=PReqFunCopyRamToRom(pbyte(PDUH_out)+sizeof(TS7ReqHeader));\n    Answer   =PS7ResHeader23(&PDU.Payload);\n    ResParams=PResFunCtrl(pbyte(Answer)+ResHeaderSize23);\n    // Fill Header\n    PDUH_out->P=0x32;                    // Always 0x32\n    PDUH_out->PDUType=PduType_request;   // 0x01\n    PDUH_out->AB_EX=0x0000;              // Always 0x0000\n    PDUH_out->Sequence=GetNextWord();    // AutoInc\n    PDUH_out->ParLen=SwapWord(sizeof(TReqFunCopyRamToRom));\n    PDUH_out->DataLen=0x0000;             // No Data\n    // Fill Params\n    ReqParams->Fun=pduControl;\n    ReqParams->Uk_7[0]=0x00;\n    ReqParams->Uk_7[1]=0x00;\n    ReqParams->Uk_7[2]=0x00;\n    ReqParams->Uk_7[3]=0x00;\n    ReqParams->Uk_7[4]=0x00;\n    ReqParams->Uk_7[5]=0x00;\n    ReqParams->Uk_7[6]=0xFD;\n\n    ReqParams->Len_1=SwapWord(0x0002);\n    ReqParams->SFun =SwapWord(0x4550);\n    ReqParams->Len_2=0x05;\n    memcpy(ReqParams->Cmd,&_modu,5);\n\n    IsoSize=sizeof(TS7ReqHeader)+sizeof(TReqFunCopyRamToRom);\n    // Changes the timeout\n    CurTimeout=RecvTimeout;\n    RecvTimeout=Job.IParam;\n    Result=isoExchangeBuffer(0,IsoSize);\n    // Restores the timeout\n    RecvTimeout=CurTimeout;\n\n    if (Result==0)\n    {\n        if ((Answer->Error!=0) || (ResParams->ResFun!=pduControl))\n             Result=errCliCannotCopyRamToRom;\n    }\n    return Result;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::opCompress()\n{\n    PReqFunCompress ReqParams;\n    PResFunCtrl ResParams;\n    PS7ResHeader23 Answer;\n    int IsoSize, CurTimeout, Result;\n    char _garb[] = {'_','G','A','R','B'};\n\n    // Setup pointers (note : PDUH_out and PDU.Payload are the same pointer)\n    ReqParams=PReqFunCompress(pbyte(PDUH_out)+sizeof(TS7ReqHeader));\n    Answer   =PS7ResHeader23(&PDU.Payload);\n    ResParams=PResFunCtrl(pbyte(Answer)+ResHeaderSize23);\n    // Fill Header\n    PDUH_out->P=0x32;                    // Always 0x32\n    PDUH_out->PDUType=PduType_request;   // 0x01\n    PDUH_out->AB_EX=0x0000;              // Always 0x0000\n    PDUH_out->Sequence=GetNextWord();    // AutoInc\n    PDUH_out->ParLen=SwapWord(sizeof(TReqFunCompress));\n    PDUH_out->DataLen=0x0000;            // No Data\n    // Fill Params\n    ReqParams->Fun=pduControl;\n    ReqParams->Uk_7[0]=0x00;\n    ReqParams->Uk_7[1]=0x00;\n    ReqParams->Uk_7[2]=0x00;\n    ReqParams->Uk_7[3]=0x00;\n    ReqParams->Uk_7[4]=0x00;\n    ReqParams->Uk_7[5]=0x00;\n    ReqParams->Uk_7[6]=0xFD;\n\n    ReqParams->Len_1=0x0000;\n    ReqParams->Len_2=0x05;\n    memcpy(ReqParams->Cmd,&_garb,5);\n\n    IsoSize=sizeof(TS7ReqHeader)+sizeof(TReqFunCompress);\n    // Changes the timeout\n    CurTimeout=RecvTimeout;\n    RecvTimeout=Job.IParam;\n    Result=isoExchangeBuffer(0,IsoSize);\n    // Restores the timeout\n    RecvTimeout=CurTimeout;\n\n    if (Result==0)\n    {\n         if (((Answer->Error!=0) || (ResParams->ResFun!=pduControl)))\n              Result=errCliCannotCompress;\n    }\n    return Result;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::opGetProtection()\n{\n    PS7Protection Info, usrInfo;\n    int Result;\n\n    // Store Pointer\n    usrInfo=PS7Protection(Job.pData);\n    memset(usrInfo, 0, sizeof(TS7Protection));\n\n    Job.ID    =0x0232;\n    Job.Index =0x0004;\n    Job.IParam=0; // No copy in Usr Data pointed by Job.pData\n    Result    =opReadSZL();\n    if (Result==0)\n    {\n        Info=PS7Protection(pbyte(&opData)+6);\n        usrInfo->sch_schal=SwapWord(Info->sch_schal);\n        usrInfo->sch_par  =SwapWord(Info->sch_par);\n        usrInfo->sch_rel  =SwapWord(Info->sch_rel);\n        usrInfo->bart_sch =SwapWord(Info->bart_sch);\n        usrInfo->anl_sch  =SwapWord(Info->anl_sch);\n    }\n    return Result;\n}\n//******************************************************************************\n//                                     NOTE\n//          PASSWORD HACKING IS VERY FAR FROM THE AIM OF THIS PROJECT\n//  NEXT FUNCTION ONLY ENCODES THE ASCII PASSWORD TO BE DOWNLOADED IN THE PLC.\n//\n//       MOREOVER **YOU NEED TO KNOW** THE CORRECT PASSWORD TO MEET THE CPU\n//                                SECURITY LEVEL\n//******************************************************************************\nint TSnap7MicroClient::opSetPassword()\n{\n    PReqFunSecurity ReqParams;\n    PReqDataSecurity ReqData;\n    PResParamsSecurity ResParams;\n    PS7ResHeader23 Answer;\n    int c, IsoSize, Result;\n\n    // Setup pointers (note : PDUH_out and PDU.Payload are the same pointer)\n    ReqParams=PReqFunSecurity(pbyte(PDUH_out)+sizeof(TS7ReqHeader));\n    ReqData  =PReqDataSecurity(pbyte(ReqParams)+sizeof(TReqFunSecurity));\n    Answer   =PS7ResHeader23(&PDU.Payload);\n    ResParams=PResParamsSecurity(pbyte(Answer)+ResHeaderSize17);\n    // Fill Header\n    PDUH_out->P=0x32;                    // Always 0x32\n    PDUH_out->PDUType=PduType_userdata;  // 0x07\n    PDUH_out->AB_EX=0x0000;              // Always 0x0000\n    PDUH_out->Sequence=GetNextWord();    // AutoInc\n    PDUH_out->ParLen =SwapWord(sizeof(TReqFunSecurity));\n    PDUH_out->DataLen=SwapWord(sizeof(TReqDataSecurity));\n    // Fill params (mostly constants)\n    ReqParams->Head[0]=0x00;\n    ReqParams->Head[1]=0x01;\n    ReqParams->Head[2]=0x12;\n    ReqParams->Plen   =0x04;\n    ReqParams->Uk     =0x11;\n    ReqParams->Tg     =grSecurity;\n    ReqParams->SubFun =SFun_EnterPwd;\n    ReqParams->Seq    =0x00;\n    // Fill Data\n    ReqData->Ret      =0xFF;\n    ReqData->TS       =TS_ResOctet;\n    ReqData->DLen     =SwapWord(0x0008); // 8 bytes data : password\n    // Encode the password\n    ReqData->Pwd[0]=opData[0] ^ 0x55;\n    ReqData->Pwd[1]=opData[1] ^ 0x55;\n    for (c = 2; c < 8; c++){\n      ReqData->Pwd[c]=opData[c] ^ 0x55 ^ ReqData->Pwd[c-2];\n    };\n\n    IsoSize=sizeof(TS7ReqHeader)+sizeof(TReqFunSecurity)+sizeof(TReqDataSecurity);\n    Result=isoExchangeBuffer(0,IsoSize);\n\n    // Get Return\n    if (Result==0)\n    {\n        if (ResParams->Err!=0)\n              Result=CpuError(SwapWord(ResParams->Err));\n    };\n\n    return Result;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::opClearPassword()\n{\n    PReqFunSecurity ReqParams;\n    PReqDataSecurity ReqData;\n    PResParamsSecurity ResParams;\n    PS7ResHeader23 Answer;\n    int IsoSize, Result;\n\n    // Setup pointers (note : PDUH_out and PDU.Payload are the same pointer)\n    ReqParams=PReqFunSecurity(pbyte(PDUH_out)+sizeof(TS7ReqHeader));\n    ReqData  =PReqDataSecurity(pbyte(ReqParams)+sizeof(TReqFunSecurity));\n    Answer   =PS7ResHeader23(&PDU.Payload);\n    ResParams=PResParamsSecurity(pbyte(Answer)+ResHeaderSize17);\n    // Fill Header\n    PDUH_out->P=0x32;                     // Always 0x32\n    PDUH_out->PDUType=PduType_userdata;   // 0x07\n    PDUH_out->AB_EX=0x0000;               // Always 0x0000\n    PDUH_out->Sequence=GetNextWord();     // AutoInc\n    PDUH_out->ParLen =SwapWord(sizeof(TReqFunSecurity));\n    PDUH_out->DataLen=SwapWord(0x0004);   // We need only 4 bytes\n    // Fill params (mostly constants)\n    ReqParams->Head[0]=0x00;\n    ReqParams->Head[1]=0x01;\n    ReqParams->Head[2]=0x12;\n    ReqParams->Plen   =0x04;\n    ReqParams->Uk     =0x11;\n    ReqParams->Tg     =grSecurity;\n    ReqParams->SubFun =SFun_CancelPwd;\n    ReqParams->Seq    =0x00;\n    // Fill Data\n    ReqData->Ret      =0x0A;\n    ReqData->TS       =0x00;\n    ReqData->DLen     =0x0000;\n\n    IsoSize=sizeof(TS7ReqHeader)+sizeof(TReqFunSecurity)+4;\n    Result=isoExchangeBuffer(0,IsoSize);\n\n    // Get Return\n    if (Result==0)\n    {\n       if (ResParams->Err!=0)\n            Result=CpuError(SwapWord(ResParams->Err));\n    };\n    return Result;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::CpuError(int Error)\n{\n  switch(Error)\n  {\n    case 0                          : return 0;\n    case Code7AddressOutOfRange     : return errCliAddressOutOfRange;\n    case Code7InvalidTransportSize  : return errCliInvalidTransportSize;\n    case Code7WriteDataSizeMismatch : return errCliWriteDataSizeMismatch;\n    case Code7ResItemNotAvailable   :\n    case Code7ResItemNotAvailable1  : return errCliItemNotAvailable;\n    case Code7DataOverPDU           : return errCliSizeOverPDU;\n    case Code7InvalidValue          : return errCliInvalidValue;\n    case Code7FunNotAvailable       : return errCliFunNotAvailable;\n    case Code7NeedPassword          : return errCliNeedPassword;\n    case Code7InvalidPassword       : return errCliInvalidPassword;\n    case Code7NoPasswordToSet       :\n    case Code7NoPasswordToClear     : return errCliNoPasswordToSetOrClear;\n  default:\n    return errCliFunctionRefused;\n  };\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::DataSizeByte(int WordLength)\n{\n\tswitch (WordLength){\n\t\tcase S7WLBit     : return 1;  // S7 sends 1 byte per bit\n\t\tcase S7WLByte    : return 1;\n\t\tcase S7WLChar    : return 1;\n\t\tcase S7WLWord    : return 2;\n\t\tcase S7WLDWord   : return 4;\n\t\tcase S7WLInt     : return 2;\n\t\tcase S7WLDInt    : return 4;\n\t\tcase S7WLReal    : return 4;\n\t\tcase S7WLCounter : return 2;\n\t\tcase S7WLTimer   : return 2;\n\t\tdefault          : return 0;\n     }\n}\n//---------------------------------------------------------------------------\nlongword TSnap7MicroClient::DWordAt(void * P)\n{\n     longword DW;\n     DW=*(longword*)P;\n     return SwapDWord(DW);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::CheckBlock(int BlockType, int BlockNum,  void * pBlock,  int Size)\n{\n      PS7CompactBlockInfo Info = PS7CompactBlockInfo(pBlock);\n\n      if (BlockType>=0) // if (BlockType<0 the test is skipped\n      {\n        if ((BlockType!=Block_OB)&&(BlockType!=Block_DB)&&(BlockType!=Block_FB)&&\n           (BlockType!=Block_FC)&&(BlockType!=Block_SDB)&&(BlockType!=Block_SFC)&&\n           (BlockType!=Block_SFB))\n          return errCliInvalidBlockType;\n      }\n\n      if (BlockNum>=0)  // if (BlockNum<0 the test is skipped\n      {\n          if (BlockNum>0xFFFF)\n            return errCliInvalidBlockNumber;\n      };\n\n      if (SwapDWord(Info->LenLoadMem)!=longword(Size))\n          return errCliInvalidBlockSize;\n\n  // Check the presence of the footer\n  if (SwapWord(Info->MC7Len)+sizeof(TS7CompactBlockInfo)>=u_int(Size))\n    return errCliInvalidBlockSize;\n\n  return 0;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::SubBlockToBlock(int SBB)\n{\n  switch (SBB)\n  {\n    case SubBlk_OB  : return Block_OB;\n    case SubBlk_DB  : return Block_DB;\n    case SubBlk_SDB : return Block_SDB;\n    case SubBlk_FC  : return Block_FC;\n    case SubBlk_SFC : return Block_SFC;\n    case SubBlk_FB  : return Block_FB;\n    case SubBlk_SFB : return Block_SFB;\n    default : return 0;\n  };\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::PerformOperation()\n{\n    ClrError();\n    int Operation=Job.Op;\n    switch(Operation)\n    {\n        case s7opNone:\n             Job.Result=errCliInvalidParams;\n             break;\n        case s7opReadArea:\n             Job.Result=opReadArea();\n             break;\n        case s7opWriteArea:\n             Job.Result=opWriteArea();\n             break;\n        case s7opReadMultiVars:\n             Job.Result=opReadMultiVars();\n             break;\n        case s7opWriteMultiVars:\n             Job.Result=opWriteMultiVars();\n             break;\n        case s7opDBGet:\n             Job.Result=opDBGet();\n             break;\n        case s7opDBFill:\n             Job.Result=opDBFill();\n             break;\n        case s7opUpload:\n             Job.Result=opUpload();\n             break;\n        case s7opDownload:\n             Job.Result=opDownload();\n             break;\n        case s7opDelete:\n             Job.Result=opDelete();\n             break;\n        case s7opListBlocks:\n             Job.Result=opListBlocks();\n             break;\n        case s7opAgBlockInfo:\n             Job.Result=opAgBlockInfo();\n             break;\n        case s7opListBlocksOfType:\n             Job.Result=opListBlocksOfType();\n             break;\n        case s7opReadSzlList:\n             Job.Result=opReadSZLList();\n             break;\n        case s7opReadSZL:\n             Job.Result=opReadSZL();\n             break;\n        case s7opGetDateTime:\n             Job.Result=opGetDateTime();\n             break;\n        case s7opSetDateTime:\n             Job.Result=opSetDateTime();\n             break;\n        case s7opGetOrderCode:\n             Job.Result=opGetOrderCode();\n             break;\n        case s7opGetCpuInfo:\n             Job.Result=opGetCpuInfo();\n             break;\n        case s7opGetCpInfo:\n             Job.Result=opGetCpInfo();\n             break;\n        case s7opGetPlcStatus:\n             Job.Result=opGetPlcStatus();\n             break;\n        case s7opPlcHotStart:\n             Job.Result=opPlcHotStart();\n             break;\n        case s7opPlcColdStart:\n             Job.Result=opPlcColdStart();\n             break;\n        case s7opCopyRamToRom:\n             Job.Result=opCopyRamToRom();\n             break;\n        case s7opCompress:\n             Job.Result=opCompress();\n             break;\n        case s7opPlcStop:\n             Job.Result=opPlcStop();\n             break;\n        case s7opGetProtection:\n             Job.Result=opGetProtection();\n             break;\n        case s7opSetPassword:\n             Job.Result=opSetPassword();\n             break;\n        case s7opClearPassword:\n             Job.Result=opClearPassword();\n             break;\n    }\n   Job.Time =SysGetTick()-JobStart;\n   Job.Pending=false;\n   return SetError(Job.Result);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::Disconnect()\n{\n     JobStart=SysGetTick();\n     PeerDisconnect();\n     Job.Time=SysGetTick()-JobStart;\n\t Job.Pending=false;\n     return 0;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::Reset(bool DoReconnect)\n{\n    Job.Pending=false;\n    if (DoReconnect) {\n        Disconnect();\n        return Connect();\n    }\n    else\n        return 0;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::Connect()\n{\n\t int Result;\n\t JobStart=SysGetTick();\n\t Result  =PeerConnect();\n\t Job.Time=SysGetTick()-JobStart;\n\t return Result;\n}\n//---------------------------------------------------------------------------\nvoid TSnap7MicroClient::SetConnectionType(word ConnType)\n{\n    ConnectionType=ConnType;\n}\n//---------------------------------------------------------------------------\nvoid TSnap7MicroClient::SetConnectionParams(const char *RemAddress, word LocalTSAP, word RemoteTSAP)\n{\n     SrcTSap = LocalTSAP;\n     DstTSap = RemoteTSAP;\n     strncpy(RemoteAddress, RemAddress, 16);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::ConnectTo(const char *RemAddress, int Rack, int Slot)\n{\n    word RemoteTSAP = (ConnectionType<<8)+(Rack*0x20)+Slot;\n    SetConnectionParams(RemAddress, SrcTSap, RemoteTSAP);\n    return Connect();\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::GetParam(int ParamNumber, void *pValue)\n{\n    switch (ParamNumber)\n    {\n\tcase p_u16_RemotePort:\n\t\t*Puint16_t(pValue)=RemotePort;\n\t\tbreak;\n\tcase p_i32_PingTimeout:\n\t\t*Pint32_t(pValue)=PingTimeout;\n\t\tbreak;\n\tcase p_i32_SendTimeout:\n\t\t*Pint32_t(pValue)=SendTimeout;\n\t\tbreak;\n\tcase p_i32_RecvTimeout:\n\t\t*Pint32_t(pValue)=RecvTimeout;\n\t\tbreak;\n\tcase p_i32_WorkInterval:\n\t\t*Pint32_t(pValue)=WorkInterval;\n\t\tbreak;\n\tcase p_u16_SrcRef:\n\t\t*Puint16_t(pValue)=SrcRef;\n\t\tbreak;\n\tcase p_u16_DstRef:\n\t\t*Puint16_t(pValue)=DstRef;\n\t\tbreak;\n\tcase p_u16_SrcTSap:\n\t\t*Puint16_t(pValue)=SrcTSap;\n\t\tbreak;\n\tcase p_i32_PDURequest:\n\t\t*Pint32_t(pValue)=PDURequest;\n\t\tbreak;\n\tdefault: return errCliInvalidParamNumber;\n    }\n    return 0;\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::SetParam(int ParamNumber, void *pValue)\n{\n    switch (ParamNumber)\n    {\n\tcase p_u16_RemotePort:\n\t\tif (!Connected)\n            RemotePort=*Puint16_t(pValue);\n\t\telse\n\t\t    return errCliCannotChangeParam;\n\t\tbreak;\n\tcase p_i32_PingTimeout:\n\t\tPingTimeout=*Pint32_t(pValue);\n\t\tbreak;\n\tcase p_i32_SendTimeout:\n\t\tSendTimeout=*Pint32_t(pValue);\n\t\tbreak;\n\tcase p_i32_RecvTimeout:\n\t\tRecvTimeout=*Pint32_t(pValue);\n\t\tbreak;\n\tcase p_i32_WorkInterval:\n\t\tWorkInterval=*Pint32_t(pValue);\n\t\tbreak;\n\tcase p_u16_SrcRef:\n\t\tSrcRef=*Puint16_t(pValue);\n\t\tbreak;\n\tcase p_u16_DstRef:\n\t\tDstRef=*Puint16_t(pValue);\n\t\tbreak;\n\tcase p_u16_SrcTSap:\n\t\tSrcTSap=*Puint16_t(pValue);\n\t\tbreak;\n\tcase p_i32_PDURequest:\n\t\tPDURequest=*Pint32_t(pValue);\n\t\tbreak;\n\tdefault: return errCliInvalidParamNumber;\n    }\n    return 0;\n}\n//---------------------------------------------------------------------------\n// Data I/O functions\nint TSnap7MicroClient::ReadArea(int Area, int DBNumber, int Start, int Amount, int WordLen,  void * pUsrData)\n{\n     if (!Job.Pending)\n     {\n         Job.Pending  = true;\n         Job.Op       = s7opReadArea;\n         Job.Area     = Area;\n         Job.Number   = DBNumber;\n         Job.Start    = Start;\n         Job.Amount   = Amount;\n         Job.WordLen  = WordLen;\n         Job.pData    = pUsrData;\n         JobStart     = SysGetTick();\n         return PerformOperation();\n     }\n     else\n         return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::WriteArea(int Area, int DBNumber, int Start, int Amount, int WordLen,  void * pUsrData)\n{\n     if (!Job.Pending)\n     {\n          Job.Pending  = true;\n          Job.Op       = s7opWriteArea;\n          Job.Area     = Area;\n          Job.Number   = DBNumber;\n          Job.Start    = Start;\n          Job.Amount   = Amount;\n          Job.WordLen  = WordLen;\n          Job.pData    = pUsrData;\n          JobStart     = SysGetTick();\n          return PerformOperation();\n     }\n     else\n          return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::ReadMultiVars(PS7DataItem Item, int ItemsCount)\n{\n    if (!Job.Pending)\n    {\n        Job.Pending  =true;\n        Job.Op       =s7opReadMultiVars;\n        Job.Amount   =ItemsCount;\n        Job.pData    =Item;\n        JobStart     =SysGetTick();\n        return PerformOperation();\n    }\n    else\n    \treturn SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::WriteMultiVars(PS7DataItem Item, int ItemsCount)\n{\n    if (!Job.Pending)\n    {\n        Job.Pending  =true;\n        Job.Op       =s7opWriteMultiVars;\n        Job.Amount   =ItemsCount;\n        Job.pData    =Item;\n        JobStart     =SysGetTick();\n        return PerformOperation();\n    }\n    else\n    \treturn SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::DBRead(int DBNumber, int Start, int Size,  void * pUsrData)\n{\n     return ReadArea(S7AreaDB, DBNumber, Start, Size, S7WLByte, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::DBWrite(int DBNumber, int Start, int Size,  void * pUsrData)\n{\n     return WriteArea(S7AreaDB, DBNumber, Start, Size, S7WLByte, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::MBRead(int Start, int Size,  void * pUsrData)\n{\n     return ReadArea(S7AreaMK, 0, Start, Size, S7WLByte, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::MBWrite(int Start, int Size,  void * pUsrData)\n{\n     return WriteArea(S7AreaMK, 0, Start, Size, S7WLByte, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::EBRead(int Start, int Size,  void * pUsrData)\n{\n    return ReadArea(S7AreaPE, 0, Start, Size, S7WLByte, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::EBWrite(int Start, int Size,  void * pUsrData)\n{\n    return WriteArea(S7AreaPE, 0, Start, Size, S7WLByte, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::ABRead(int Start, int Size,  void * pUsrData)\n{\n    return ReadArea(S7AreaPA, 0, Start, Size, S7WLByte, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::ABWrite(int Start, int Size,  void * pUsrData)\n{\n    return WriteArea(S7AreaPA, 0, Start, Size, S7WLByte, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::TMRead(int Start, int Amount,  void * pUsrData)\n{\n    return ReadArea(S7AreaTM, 0, Start, Amount, S7WLTimer, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::TMWrite(int Start, int Amount,  void * pUsrData)\n{\n    return WriteArea(S7AreaTM, 0, Start, Amount, S7WLTimer, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::CTRead(int Start, int Amount,  void * pUsrData)\n{\n    return ReadArea(S7AreaCT, 0, Start, Amount, S7WLCounter, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::CTWrite(int Start, int Amount,  void * pUsrData)\n{\n    return WriteArea(S7AreaCT, 0, Start, Amount, S7WLCounter, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::ListBlocks(PS7BlocksList pUsrData)\n{\n    if (!Job.Pending)\n    {\n        Job.Pending  =true;\n        Job.Op       =s7opListBlocks;\n        Job.pData    =pUsrData;\n        JobStart     =SysGetTick();\n        return PerformOperation();\n    }\n    else\n    \treturn SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::GetAgBlockInfo(int BlockType, int BlockNum, PS7BlockInfo pUsrData)\n{\n    if (!Job.Pending)\n    {\n        Job.Pending  =true;\n        Job.Op       =s7opAgBlockInfo;\n        Job.Area     =BlockType;\n        Job.Number   =BlockNum;\n        Job.pData    =pUsrData;\n        JobStart     =SysGetTick();\n        return PerformOperation();\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::GetPgBlockInfo(void * pBlock, PS7BlockInfo pUsrData, int Size)\n{\n    PS7CompactBlockInfo Info;\n    PS7BlockFooter Footer;\n\n    int Result=CheckBlock(-1,-1,pBlock,Size);\n    if (Result==0)\n    {\n        Info=PS7CompactBlockInfo(pBlock);\n        pUsrData->BlkType  =Info->SubBlkType;\n        pUsrData->BlkNumber=SwapWord(Info->BlkNum);\n        pUsrData->BlkLang  =Info->BlkLang;\n        pUsrData->BlkFlags =Info->BlkFlags;\n        pUsrData->MC7Size  =SwapWord(Info->MC7Len);\n        pUsrData->LoadSize =SwapDWord(Info->LenLoadMem);\n        pUsrData->LocalData=SwapDWord(Info->LocDataLen);\n        pUsrData->SBBLength=SwapDWord(Info->SbbLen);\n        pUsrData->CheckSum =0; // this info is not available\n        pUsrData->Version  =0; // this info is not available\n        FillTime(SwapWord(Info->CodeTime_dy),pUsrData->CodeDate);\n        FillTime(SwapWord(Info->IntfTime_dy),pUsrData->IntfDate);\n\n        Footer=PS7BlockFooter(pbyte(Info)+pUsrData->LoadSize-sizeof(TS7BlockFooter));\n\n        memcpy(pUsrData->Author,Footer->Author,8);\n        memcpy(pUsrData->Family,Footer->Family,8);\n        memcpy(pUsrData->Header,Footer->Header,8);\n    };\n    return SetError(Result);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::ListBlocksOfType(int BlockType, TS7BlocksOfType *pUsrData, int &ItemsCount)\n{\n    if (!Job.Pending)\n    {\n\tif (ItemsCount<1)\n\t    return SetError(errCliInvalidBlockSize);\n\tJob.Pending  =true;\n\tJob.Op       =s7opListBlocksOfType;\n\tJob.Area     =BlockType;\n\tJob.pData    =pUsrData;\n\tJob.pAmount  =&ItemsCount;\n\tJob.Amount   =ItemsCount;\n\tJobStart     =SysGetTick();\n\treturn PerformOperation();\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::Upload(int BlockType, int BlockNum,  void * pUsrData, int & Size)\n{\n    if (!Job.Pending)\n    {\n        if (Size<=0)\n\t     return SetError(errCliInvalidBlockSize);\n        Job.Pending  =true;\n        Job.Op       =s7opUpload;\n        Job.Area     =BlockType;\n        Job.pData    =pUsrData;\n        Job.pAmount  =&Size;\n        Job.Amount   =Size;\n        Job.Number   =BlockNum;\n        Job.IParam   =0; // not full upload, only data\n        JobStart     =SysGetTick();\n        return PerformOperation();\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::FullUpload(int BlockType, int BlockNum, void * pUsrData, int & Size)\n{\n    if (!Job.Pending)\n    {\n        if (Size<=0)\n            return SetError(errCliInvalidBlockSize);\n        Job.Pending  =true;\n        Job.Op       =s7opUpload;\n        Job.Area     =BlockType;\n        Job.pData    =pUsrData;\n        Job.pAmount  =&Size;\n        Job.Amount   =Size;\n        Job.Number   =BlockNum;\n        Job.IParam   =1; // header + data + footer\n        JobStart     =SysGetTick();\n        return PerformOperation();\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::Download(int BlockNum,  void * pUsrData,  int Size)\n{\n    if (!Job.Pending)\n    {\n        Job.Pending  =true;\n        Job.Op       =s7opDownload;\n        memcpy(&opData, pUsrData, Size);\n        Job.Number   =BlockNum;\n        Job.Amount   =Size;\n        JobStart     =SysGetTick();\n        return PerformOperation();\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::Delete(int BlockType, int BlockNum)\n{\n    if (!Job.Pending)\n    {\n        Job.Pending  =true;\n        Job.Op       =s7opDelete;\n        Job.Area     =BlockType;\n        Job.Number   =BlockNum;\n        JobStart     =SysGetTick();\n        return PerformOperation();\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::DBGet(int DBNumber, void * pUsrData, int & Size)\n{\n    if (!Job.Pending)\n    {\n        if (Size<=0)\n            return SetError(errCliInvalidBlockSize);\n        Job.Pending  =true;\n        Job.Op       =s7opDBGet;\n        Job.Number   =DBNumber;\n        Job.pData    =pUsrData;\n        Job.pAmount  =&Size;\n        Job.Amount   =Size;\n        JobStart     =SysGetTick();\n        return PerformOperation();\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::DBFill(int DBNumber,  int FillChar)\n{\n    if (!Job.Pending)\n    {\n        Job.Pending  =true;\n        Job.Op       =s7opDBFill;\n        Job.Number   =DBNumber;\n        Job.IParam   =FillChar;\n        JobStart     =SysGetTick();\n        return PerformOperation();\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::GetPlcDateTime(tm &DateTime)\n{\n    if (!Job.Pending)\n    {\n        Job.Pending  =true;\n        Job.Op       =s7opGetDateTime;\n        Job.pData    =&DateTime;\n        JobStart     =SysGetTick();\n        return PerformOperation();\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::SetPlcDateTime(tm * DateTime)\n{\n    if (!Job.Pending)\n    {\n        Job.Pending  =true;\n        Job.Op       =s7opSetDateTime;\n        Job.pData    =DateTime;\n        JobStart     =SysGetTick();\n        return PerformOperation();\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::SetPlcSystemDateTime()\n{\n    time_t Now;\n    time(&Now);\n    struct tm * DateTime = localtime (&Now);\n    return SetPlcDateTime(DateTime);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::GetOrderCode(PS7OrderCode pUsrData)\n{\n    if (!Job.Pending)\n    {\n        Job.Pending  =true;\n        Job.Op       =s7opGetOrderCode;\n        Job.pData    =pUsrData;\n        JobStart     =SysGetTick();\n        return PerformOperation();\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::GetCpuInfo(PS7CpuInfo pUsrData)\n{\n    if (!Job.Pending)\n    {\n        Job.Pending  =true;\n        Job.Op       =s7opGetCpuInfo;\n        Job.pData    =pUsrData;\n        JobStart     =SysGetTick();\n        return PerformOperation();\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::GetCpInfo(PS7CpInfo pUsrData)\n{\n    if (!Job.Pending)\n    {\n        Job.Pending  =true;\n        Job.Op       =s7opGetCpInfo;\n        Job.pData    =pUsrData;\n        JobStart     =SysGetTick();\n        return PerformOperation();\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::ReadSZL(int ID, int Index, PS7SZL pUsrData, int &Size)\n{\n    if (!Job.Pending)\n    {\n        Job.Pending  =true;\n        Job.Op       =s7opReadSZL;\n        Job.ID       =ID;\n        Job.Index    =Index;\n        Job.pData    =pUsrData;\n        Job.pAmount  =&Size;\n        Job.Amount   =Size;\n        Job.IParam   =1; // Data has to be copied into user buffer\n        JobStart     =SysGetTick();\n        return PerformOperation();\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::ReadSZLList(PS7SZLList pUsrData, int &ItemsCount)\n{\n    if (!Job.Pending)\n    {\n        Job.Pending  =true;\n        Job.Op       =s7opReadSzlList;\n        Job.pData    =pUsrData;\n        Job.pAmount  =&ItemsCount;\n        Job.Amount   =ItemsCount;\n        JobStart     =SysGetTick();\n        return PerformOperation();\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::PlcHotStart()\n{\n    if (!Job.Pending)\n    {\n        Job.Pending  =true;\n        Job.Op       =s7opPlcHotStart;\n        JobStart     =SysGetTick();\n        return PerformOperation();\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::PlcColdStart()\n{\n    if (!Job.Pending)\n    {\n        Job.Pending  =true;\n        Job.Op       =s7opPlcColdStart;\n        JobStart     =SysGetTick();\n        return PerformOperation();\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::PlcStop()\n{\n    if (!Job.Pending)\n    {\n        Job.Pending  =true;\n        Job.Op       =s7opPlcStop;\n        JobStart     =SysGetTick();\n        return PerformOperation();\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::CopyRamToRom(int Timeout)\n{\n      if (!Job.Pending)\n      {\n          if (Timeout>0)\n          {\n               Job.Pending =true;\n               Job.Op      =s7opCopyRamToRom;\n               Job.IParam  =Timeout;\n               JobStart    =SysGetTick();\n               return PerformOperation();\n          }\n          else\n              return SetError(errCliInvalidParams);\n      }\n      else\n          return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::Compress(int Timeout)\n{\n      if (!Job.Pending)\n      {\n          if (Timeout>0)\n          {\n               Job.Pending =true;\n               Job.Op      =s7opCompress;\n               Job.IParam  =Timeout;\n               JobStart    =SysGetTick();\n               return PerformOperation();\n          }\n          else\n              return SetError(errCliInvalidParams);\n      }\n      else\n          return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::GetPlcStatus(int & Status)\n{\n    if (!Job.Pending)\n    {\n        Job.Pending  =true;\n        Job.Op       =s7opGetPlcStatus;\n        Job.pData    =&Status;\n        JobStart     =SysGetTick();\n        return PerformOperation();\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::GetProtection(PS7Protection pUsrData)\n{\n    if (!Job.Pending)\n    {\n        Job.Pending  =true;\n        Job.Op       =s7opGetProtection;\n        Job.pData    =pUsrData;\n        JobStart     =SysGetTick();\n        return PerformOperation();\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::SetSessionPassword(char *Password)\n{\n    if (!Job.Pending)\n    {\n        size_t L = strlen(Password);\n        // checks the len\n        if ((L<1) || (L>8))\n           return SetError(errCliInvalidParams);\n        Job.Pending  =true;\n        // prepares an 8 char string filled with spaces\n        memset(&opData,0x20,8);\n        // copies\n        strncpy((char*)&opData,Password,L);\n        Job.Op       =s7opSetPassword;\n        JobStart     =SysGetTick();\n        return PerformOperation();\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\nint TSnap7MicroClient::ClearSessionPassword()\n{\n    if (!Job.Pending)\n    {\n        Job.Pending  =true;\n        Job.Op       =s7opClearPassword;\n        JobStart     =SysGetTick();\n        return PerformOperation();\n    }\n    else\n        return SetError(errCliJobPending);\n}\n//---------------------------------------------------------------------------\n\n"
  },
  {
    "path": "deps/snap7/src/core/s7_micro_client.h",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.3.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|=============================================================================*/\n#ifndef s7_micro_client_h\n#define s7_micro_client_h\n//---------------------------------------------------------------------------\n#include \"s7_peer.h\"\n//---------------------------------------------------------------------------\n\nconst longword errCliMask                   = 0xFFF00000;\nconst longword errCliBase                   = 0x000FFFFF;\n\nconst longword errCliInvalidParams          = 0x00200000;\nconst longword errCliJobPending             = 0x00300000;\nconst longword errCliTooManyItems           = 0x00400000;\nconst longword errCliInvalidWordLen         = 0x00500000;\nconst longword errCliPartialDataWritten     = 0x00600000;\nconst longword errCliSizeOverPDU            = 0x00700000;\nconst longword errCliInvalidPlcAnswer       = 0x00800000;\nconst longword errCliAddressOutOfRange      = 0x00900000;\nconst longword errCliInvalidTransportSize   = 0x00A00000;\nconst longword errCliWriteDataSizeMismatch  = 0x00B00000;\nconst longword errCliItemNotAvailable       = 0x00C00000;\nconst longword errCliInvalidValue           = 0x00D00000;\nconst longword errCliCannotStartPLC         = 0x00E00000;\nconst longword errCliAlreadyRun             = 0x00F00000;\nconst longword errCliCannotStopPLC          = 0x01000000;\nconst longword errCliCannotCopyRamToRom     = 0x01100000;\nconst longword errCliCannotCompress         = 0x01200000;\nconst longword errCliAlreadyStop            = 0x01300000;\nconst longword errCliFunNotAvailable        = 0x01400000;\nconst longword errCliUploadSequenceFailed   = 0x01500000;\nconst longword errCliInvalidDataSizeRecvd   = 0x01600000;\nconst longword errCliInvalidBlockType       = 0x01700000;\nconst longword errCliInvalidBlockNumber     = 0x01800000;\nconst longword errCliInvalidBlockSize       = 0x01900000;\nconst longword errCliDownloadSequenceFailed = 0x01A00000;\nconst longword errCliInsertRefused          = 0x01B00000;\nconst longword errCliDeleteRefused          = 0x01C00000;\nconst longword errCliNeedPassword           = 0x01D00000;\nconst longword errCliInvalidPassword        = 0x01E00000;\nconst longword errCliNoPasswordToSetOrClear = 0x01F00000;\nconst longword errCliJobTimeout             = 0x02000000;\nconst longword errCliPartialDataRead        = 0x02100000;\nconst longword errCliBufferTooSmall         = 0x02200000;\nconst longword errCliFunctionRefused        = 0x02300000;\nconst longword errCliDestroying             = 0x02400000;\nconst longword errCliInvalidParamNumber     = 0x02500000;\nconst longword errCliCannotChangeParam      = 0x02600000;\n\nconst time_t DeltaSecs = 441763200; // Seconds between 1970/1/1 (C time base) and 1984/1/1 (Siemens base)\n\n#pragma pack(1)\n\n// Read/Write Multivars\ntypedef struct{\n   int   Area;\n   int   WordLen;\n   int   Result;\n   int   DBNumber;\n   int   Start;\n   int   Amount;\n   void  *pdata;\n} TS7DataItem, *PS7DataItem;\n\ntypedef int TS7ResultItems[MaxVars];\ntypedef TS7ResultItems *PS7ResultItems;\n\ntypedef struct {\n   int OBCount;\n   int FBCount;\n   int FCCount;\n   int SFBCount;\n   int SFCCount;\n   int DBCount;\n   int SDBCount;\n} TS7BlocksList, *PS7BlocksList;\n\ntypedef struct {\n   int BlkType;\n   int BlkNumber;\n   int BlkLang;\n   int BlkFlags;\n   int MC7Size;  // The real size in bytes\n   int LoadSize;\n   int LocalData;\n   int SBBLength;\n   int CheckSum;\n   int Version;\n   // Chars info\n   char CodeDate[11];\n   char IntfDate[11];\n   char Author[9];\n   char Family[9];\n   char Header[9];\n} TS7BlockInfo, *PS7BlockInfo ;\n\ntypedef word TS7BlocksOfType[0x2000];\ntypedef TS7BlocksOfType *PS7BlocksOfType;\n\ntypedef struct {\n   char Code[21]; // Order Code\n   byte V1;       // Version V1.V2.V3\n   byte V2;\n   byte V3;\n} TS7OrderCode, *PS7OrderCode;\n\ntypedef struct {\n   char ModuleTypeName[33];\n   char SerialNumber[25];\n   char ASName[25];\n   char Copyright[27];\n   char ModuleName[25];\n} TS7CpuInfo, *PS7CpuInfo;\n\ntypedef struct {\n   int MaxPduLengt;\n   int MaxConnections;\n   int MaxMpiRate;\n   int MaxBusRate;\n} TS7CpInfo, *PS7CpInfo;\n\n// See §33.1 of \"System Software for S7-300/400 System and Standard Functions\"\n// and see SFC51 description too\ntypedef struct {\n   word LENTHDR;\n   word N_DR;\n} SZL_HEADER, *PSZL_HEADER;\n\ntypedef struct {\n   SZL_HEADER Header;\n   byte Data[0x4000-4];\n} TS7SZL, *PS7SZL;\n\n// SZL List of available SZL IDs : same as SZL but List items are big-endian adjusted\ntypedef struct {\n   SZL_HEADER Header;\n   word List[0x2000-2];\n} TS7SZLList, *PS7SZLList;\n\n// See §33.19 of \"System Software for S7-300/400 System and Standard Functions\"\ntypedef struct {\n   word  sch_schal;\n   word  sch_par;\n   word  sch_rel;\n   word  bart_sch;\n   word  anl_sch;\n} TS7Protection, *PS7Protection;\n\n#define s7opNone               0\n#define s7opReadArea           1\n#define s7opWriteArea          2\n#define s7opReadMultiVars      3\n#define s7opWriteMultiVars     4\n#define s7opDBGet              5\n#define s7opUpload             6\n#define s7opDownload           7\n#define s7opDelete             8\n#define s7opListBlocks         9\n#define s7opAgBlockInfo       10\n#define s7opListBlocksOfType  11\n#define s7opReadSzlList       12\n#define s7opReadSZL           13\n#define s7opGetDateTime       14\n#define s7opSetDateTime       15\n#define s7opGetOrderCode      16\n#define s7opGetCpuInfo        17\n#define s7opGetCpInfo         18\n#define s7opGetPlcStatus      19\n#define s7opPlcHotStart       20\n#define s7opPlcColdStart      21\n#define s7opCopyRamToRom      22\n#define s7opCompress          23\n#define s7opPlcStop           24\n#define s7opGetProtection     25\n#define s7opSetPassword       26\n#define s7opClearPassword     27\n#define s7opDBFill            28\n\n// Param Number (to use with setparam)\n\n// Low level : change them to experiment new connections, their defaults normally work well\nconst int pc_iso_SendTimeout   = 6;\nconst int pc_iso_RecvTimeout   = 7;\nconst int pc_iso_ConnTimeout   = 8;\nconst int pc_iso_SrcRef        = 1;\nconst int pc_iso_DstRef        = 2;\nconst int pc_iso_SrcTSAP       = 3;\nconst int pc_iso_DstTSAP       = 4;\nconst int pc_iso_IsoPduSize    = 5;\n\n// Client Connection Type\nconst word CONNTYPE_PG         = 0x01;  // Connect to the PLC as a PG\nconst word CONNTYPE_OP         = 0x02;  // Connect to the PLC as an OP\nconst word CONNTYPE_BASIC      = 0x03;  // Basic connection \n\n#pragma pack()\n\n// Internal struct for operations\n// Commands are not executed directly in the function such as \"DBRead(...\",\n// but this struct is filled and then PerformOperation() is called.\n// This allow us to implement async function very easily.\n\nstruct TSnap7Job \n{\n    int Op;        // Operation Code\n    int Result;    // Operation result\n    bool Pending;  // A Job is pending\n    longword Time; // Job Execution time\n    // Read/Write\n    int Area;      // Also used for Block type and Block of type\n    int Number;    // Used for DB Number, Block number\n    int Start;     // Offset start\n    int WordLen;   // Word length\n    // SZL\n    int ID;        // SZL ID\n    int Index;     // SZL Index\n    // ptr info\n    void * pData;  // User data pointer\n    int Amount;    // Items amount/Size in input\n    int *pAmount;  // Items amount/Size in output\n    // Generic\n    int IParam;   // Used for full upload and CopyRamToRom extended timeout\n};\n\nclass TSnap7MicroClient: public TSnap7Peer\n{\nprivate:\n    void FillTime(word SiemensTime, char *PTime);\n    byte BCDtoByte(byte B);\n    byte WordToBCD(word Value);\n    int opReadArea();\n    int opWriteArea();\n    int opReadMultiVars();\n    int opWriteMultiVars();\n    int opListBlocks();\n    int opListBlocksOfType();\n    int opAgBlockInfo();\n    int opDBGet();\n    int opDBFill();\n    int opUpload();\n    int opDownload();\n    int opDelete();\n    int opReadSZL();\n    int opReadSZLList();\n    int opGetDateTime();\n    int opSetDateTime();\n    int opGetOrderCode();\n    int opGetCpuInfo();\n    int opGetCpInfo();\n    int opGetPlcStatus();\n    int opPlcStop();\n    int opPlcHotStart();\n    int opPlcColdStart();\n    int opCopyRamToRom();\n    int opCompress();\n    int opGetProtection();\n    int opSetPassword();\n    int opClearPassword();\n    int CpuError(int Error);\n    longword DWordAt(void * P);\n    int CheckBlock(int BlockType, int BlockNum,  void *pBlock,  int Size);\n    int SubBlockToBlock(int SBB);\nprotected:\n    word ConnectionType;\n    longword JobStart;\n    TSnap7Job Job;\n    int DataSizeByte(int WordLength);\n    int opSize; // last operation size\n    int PerformOperation();\npublic:\n    TS7Buffer opData;\n\tTSnap7MicroClient();\n    ~TSnap7MicroClient();\n    int Reset(bool DoReconnect);\n    void SetConnectionParams(const char *RemAddress, word LocalTSAP, word RemoteTsap);\n    void SetConnectionType(word ConnType);\n\tint ConnectTo(const char *RemAddress, int Rack, int Slot);\n    int Connect();\n\tint Disconnect();\n\tint GetParam(int ParamNumber, void *pValue);\n\tint SetParam(int ParamNumber, void *pValue);\n    // Fundamental Data I/O functions\n    int ReadArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void * pUsrData);\n    int WriteArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void * pUsrData);\n    int ReadMultiVars(PS7DataItem Item, int ItemsCount);\n    int WriteMultiVars(PS7DataItem Item, int ItemsCount);\n    // Data I/O Helper functions\n    int DBRead(int DBNumber, int Start, int Size, void * pUsrData);\n    int DBWrite(int DBNumber, int Start, int Size, void * pUsrData);\n    int MBRead(int Start, int Size, void * pUsrData);\n    int MBWrite(int Start, int Size, void * pUsrData);\n    int EBRead(int Start, int Size, void * pUsrData);\n    int EBWrite(int Start, int Size, void * pUsrData);\n    int ABRead(int Start, int Size, void * pUsrData);\n    int ABWrite(int Start, int Size, void * pUsrData);\n    int TMRead(int Start, int Amount, void * pUsrData);\n    int TMWrite(int Start, int Amount, void * pUsrData);\n    int CTRead(int Start, int Amount, void * pUsrData);\n    int CTWrite(int Start, int Amount, void * pUsrData);\n    // Directory functions\n    int ListBlocks(PS7BlocksList pUsrData);\n    int GetAgBlockInfo(int BlockType, int BlockNum, PS7BlockInfo pUsrData);\n    int GetPgBlockInfo(void * pBlock, PS7BlockInfo pUsrData, int Size);\n    int ListBlocksOfType(int BlockType, TS7BlocksOfType *pUsrData, int & ItemsCount);\n    // Blocks functions\n    int Upload(int BlockType, int BlockNum, void * pUsrData, int & Size);\n    int FullUpload(int BlockType, int BlockNum, void * pUsrData, int & Size);\n    int Download(int BlockNum, void * pUsrData, int Size);\n    int Delete(int BlockType, int BlockNum);\n    int DBGet(int DBNumber, void * pUsrData, int & Size);\n    int DBFill(int DBNumber, int FillChar);\n    // Date/Time functions\n    int GetPlcDateTime(tm &DateTime);\n    int SetPlcDateTime(tm * DateTime);\n    int SetPlcSystemDateTime();\n    // System Info functions\n    int GetOrderCode(PS7OrderCode pUsrData);\n    int GetCpuInfo(PS7CpuInfo pUsrData);\n    int GetCpInfo(PS7CpInfo pUsrData);\n    int ReadSZL(int ID, int Index, PS7SZL pUsrData, int &Size);\n    int ReadSZLList(PS7SZLList pUsrData, int &ItemsCount);\n    // Control functions\n    int PlcHotStart();\n    int PlcColdStart();\n    int PlcStop();\n    int CopyRamToRom(int Timeout);\n    int Compress(int Timeout);\n    int GetPlcStatus(int &Status);\n    // Security functions\n    int GetProtection(PS7Protection pUsrData);\n    int SetSessionPassword(char *Password);\n    int ClearSessionPassword();\n    // Properties\n    bool Busy(){ return Job.Pending; };\n    int Time(){ return int(Job.Time);}\n};\n\ntypedef TSnap7MicroClient *PSnap7MicroClient;\n\n//---------------------------------------------------------------------------\n#endif // s7_micro_client_h\n"
  },
  {
    "path": "deps/snap7/src/core/s7_partner.cpp",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.3.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|=============================================================================*/\n#include \"s7_partner.h\"\n//------------------------------------------------------------------------------\n\nstatic PServersManager ServersManager = NULL;\n\n//------------------------------------------------------------------------------\nint ServersManager_GetServer(longword BindAddress, PConnectionServer &Server)\n{\n    if (ServersManager == NULL)\n    {\n        ServersManager = new TServersManager();\n    }\n    return ServersManager->GetServer(BindAddress, Server);\n}\n//------------------------------------------------------------------------------\nvoid ServersManager_RemovePartner(PConnectionServer Server, PSnap7Partner Partner)\n{\n    if (ServersManager != NULL)\n    {\n        ServersManager->RemovePartner(Server, Partner);\n        if (ServersManager->ServersCount==0)\n        {\n            delete ServersManager;\n            ServersManager = NULL;\n        }\n    }\n}\n//------------------------------------------------------------------------------\n// CONNECTION SERVERS MANAGER\n//------------------------------------------------------------------------------\nTServersManager::TServersManager()\n{\n    cs = new TSnapCriticalSection;\n    memset(Servers,0,sizeof(Servers));\n    ServersCount=0;\n}\n//---------------------------------------------------------------------------\nTServersManager::~TServersManager()\n{\n\tint c;\n    Lock();\n    if (ServersCount>0)\n    {\n        for (c = 0; c < MaxAdapters; c++)\n        {\n            if (Servers[c]!=0)\n            {\n                delete Servers[c];\n                Servers[c]=0;\n                ServersCount--;\n            }\n        }\n    }\n    Unlock();\n    delete cs;\n}\n//---------------------------------------------------------------------------\nvoid TServersManager::Lock()\n{\n    cs->Enter();\n}\n//---------------------------------------------------------------------------\nvoid TServersManager::Unlock()\n{\n    cs->Leave();\n}\n//---------------------------------------------------------------------------\nvoid TServersManager::AddServer(PConnectionServer Server)\n{\n    int c;\n    Lock();\n    for (c = 0; c < MaxAdapters; c++)\n    {\n        if (Servers[c]==0)\n        {\n\t    Servers[c]=Server;\n            ServersCount++;\n            break;\n\t\t}\n    }\n    Unlock();\n}\n//---------------------------------------------------------------------------\nint TServersManager::CreateServer(longword BindAddress, PConnectionServer &Server)\n{\n    in_addr sin;\n    sin.s_addr=BindAddress;\n    int Result;\n\n    if (ServersCount<MaxAdapters)\n    {\n        Server = new TConnectionServer();\n        Result=Server->StartTo(inet_ntoa(sin));\n        if (Result!=0)\n        {\n            delete Server;\n            Server=0;\n            return Result;\n        }\n        AddServer(Server);\n        return 0;\n    }\n    else\n        return errServerNoRoom;\n}\n//---------------------------------------------------------------------------\nint TServersManager::GetServer(longword BindAddress, PConnectionServer &Server)\n{\n    int c;\n    Server=0;\n    for (c = 0; c < ServersCount; c++)\n    {\n        if (Servers[c]->LocalBind==BindAddress)\n        {\n            Server=Servers[c];\n            break;\n        }\n\t}\n    if (Server==0)\n        return CreateServer(BindAddress, Server);\n    else\n        return 0;\n}\n//---------------------------------------------------------------------------\nvoid TServersManager::RemovePartner(PConnectionServer Server, PSnap7Partner Partner)\n{\n    int c;\n    Server->RemovePartner(Partner);\n    if (Server->PartnersCount==0)\n    {\n        Lock();\n        for (c = 0; c < MaxAdapters; c++)\n        {\n            if (Servers[c]==Server)\n            {\n                Servers[c]=0;\n                ServersCount--;\n                break;\n            }\n        }\n        Unlock();\n        delete Server;\n    }\n}\n//---------------------------------------------------------------------------\n// CONNECTION SERVER\n//------------------------------------------------------------------------------\nvoid TConnListenerThread::Execute()\n{\n    socket_t Sock;\n    bool Valid;\n\n    while (!Terminated)\n    {\n\tif (FListener->CanRead(FListener->WorkInterval))\n\t{\n\t\tSock=FListener->SckAccept(); // in any case we must accept\n\t    Valid=Sock!=INVALID_SOCKET;\n\t    // check if we are not destroying\n\t    if ((!Terminated) && (!FServer->Destroying))\n\t    {\n\t\tif (Valid)\n\t\t    FServer->Incoming(Sock);\n\t    }\n\t    else\n\t\tif (Valid)\n\t\t    Msg_CloseSocket(Sock);\n\t};\n    }\n}\n//------------------------------------------------------------------------------\nTConnectionServer::TConnectionServer()\n{\n    cs = new TSnapCriticalSection;\n    memset(Partners,0,sizeof(Partners));\n    FRunning = false;\n    PartnersCount = 0;\n}\n//------------------------------------------------------------------------------\nTConnectionServer::~TConnectionServer()\n{\n    Stop();\n    delete cs;\n}\n//---------------------------------------------------------------------------\nvoid TConnectionServer::Lock()\n{\n    cs->Enter();\n}\nvoid TConnectionServer::Unlock()\n{\n    cs->Leave();\n}\n//---------------------------------------------------------------------------\nint TConnectionServer::Start()\n{\n    int Result;\n    // Creates the listener\n    SockListener = new TMsgSocket();\n    strncpy(SockListener->LocalAddress,FLocalAddress,16);\n    SockListener->LocalPort=isoTcpPort;\n    // Binds\n    Result=SockListener->SckBind();\n    if (Result==0)\n    {\n        LocalBind=SockListener->LocalBind;\n        // Listen\n        Result=SockListener->SckListen();\n        if (Result==0)\n        {\n            // Creates the Listener thread\n            ServerThread = new TConnListenerThread(SockListener, this);\n            ServerThread->Start();\n        }\n        else\n            delete SockListener;\n    }\n    else\n        delete SockListener;\n\n    FRunning=Result==0;\n    return Result;\n}\n//---------------------------------------------------------------------------\nint TConnectionServer::StartTo(const char *Address)\n{\n    strncpy(FLocalAddress,Address,16);\n    return Start();\n}\n//---------------------------------------------------------------------------\nvoid TConnectionServer::Stop()\n{\n    if (FRunning)\n    {\n\t\t// Kills the listener thread\n        ServerThread->Terminate();\n        if (ServerThread->WaitFor(csTimeout)!=WAIT_OBJECT_0)\n           ServerThread->Kill();\n        delete ServerThread;\n        // Kills the listener\n        delete SockListener;\n        FRunning = false;\n    }\n}\n//---------------------------------------------------------------------------\nPSnap7Partner TConnectionServer::FindPartner(longword Address)\n{\n    int c;\n    PSnap7Partner Result;\n    for (c = 0; c < MaxPartners; c++)\n    {\n        Result=Partners[c];\n        if (Result!=NULL)\n        {\n           if (Result->PeerAddress==Address)\n               return Result;\n        }\n    }\n    return NULL;\n}\n//------------------------------------------------------------------------------\nint TConnectionServer::FirstFree()\n{\n    int i;\n    for (i = 0; i < MaxPartners; i++)\n    {\n        if (Partners[i]==0)\n\t    return i;\n    }\n    return -1;\n}\n//------------------------------------------------------------------------------\nint TConnectionServer::RegisterPartner(PSnap7Partner Partner)\n{\n    PSnap7Partner aPartner;\n    int idx;\n    // check if already exists a passive partner linked to the same peer address\n    aPartner=FindPartner(Partner->PeerAddress);\n    if (aPartner==NULL)\n    {\n       Lock();\n       idx=FirstFree();\n       if (idx>=0)\n       {\n           Partners[idx]=Partner;\n           PartnersCount++;\n       }\n       Unlock();\n       if (idx>=0)\n           return 0;\n       else\n           return errParNoRoom;\n    }\n    else\n       return errParAddressInUse;\n}\n//------------------------------------------------------------------------------\nvoid TConnectionServer::RemovePartner(PSnap7Partner Partner)\n{\n    int c;\n    Lock();\n\tfor (c = 0; c < MaxPartners; c++)\n    {\n        if (Partners[c]==Partner)\n        {\n            Partners[c]=0;\n            PartnersCount--;\n            break;\n        }\n    }\n    Unlock();\n}\n//------------------------------------------------------------------------------\nvoid TConnectionServer::Incoming(socket_t Sock)\n{\n    longword Address;\n    PSnap7Partner Partner;\n\n    Address=Msg_GetSockAddr(Sock);\n    // Looks for a partner that is waiting for a connection from this address\n    Lock();\n    Partner=FindPartner(Address);\n    Unlock();\n    // if partner exists must not be already connected : a partner can be connected\n    // with only one peer at time\n    if ((Partner!=NULL) && (!Partner->Stopping) && (!Partner->Connected))\n        Partner->SetSocket(Sock);\n    else\n        Msg_CloseSocket(Sock); // we are not interested\n}\n//------------------------------------------------------------------------------\n// PARTHER THREAD\n//------------------------------------------------------------------------------\nvoid TPartnerThread::Execute()\n{\n    longword TheTime;\n\n    FKaElapsed=SysGetTick();\n    while ((!Terminated) && (!FPartner->Destroying))\n    {\n        // Check connection\n        while (!Terminated && !FPartner->Connected && !FPartner->Destroying)\n        {\n            if (!FPartner->ConnectToPeer())\n                SysSleep(FRecoveryTime);\n        }\n        // Execution\n        if ((!Terminated) && (!FPartner->Destroying) && (!FPartner->Execute()))\n\t\t\tSysSleep(FRecoveryTime);\n        // Keep Alive\n        if (!Terminated && (!FPartner->Destroying) && FPartner->Active && FPartner->Connected)\n\t\t{\n             TheTime=SysGetTick();\n             if (TheTime-FKaElapsed>FPartner->KeepAliveTime)\n             {\n                 FKaElapsed=TheTime;\n                 if (!FPartner->Ping(FPartner->RemoteAddress))\n                     FPartner->Disconnect();\n             };\n        };\n    };\n}\n//------------------------------------------------------------------------------\n// S7 PARTNER\n//------------------------------------------------------------------------------\nTSnap7Partner::TSnap7Partner(bool CreateActive)\n{\n    // We skip RFC/ISO header, our PDU is the ISO payload\n    PDUH_in=PS7ReqHeader(&PDU.Payload);\n    FWorkerThread=0;\n    OnBRecv = 0;\n    OnBSend = 0;\n    Active=CreateActive;\n    SendEvt = new TSnapEvent(true);\n    RecvEvt = new TSnapEvent(true);\n    FSendPending = false;\n    FRecvPending = false;\n    memset(&FRecvStatus,0,sizeof(TRecvStatus));\n    memset(&FRecvLast,0,sizeof(TRecvLast));\n    FSendElapsed  = 0;\n\tDestroying    = false;\n    // public\n    Linked        =false;\n    Running       =false;\n    BindError     =false;\n    BRecvTimeout  =3000;\n    BSendTimeout  =3000;\n    RecoveryTime  =500;\n    KeepAliveTime =5000;\n    NextByte      =0;\n    PeerAddress   =0;\n    SendTime      =0;\n    RecvTime      =0;\n    BytesSent     =0;\n    BytesRecv     =0;\n    SendErrors    =0;\n    RecvErrors    =0;\n}\n//------------------------------------------------------------------------------\nTSnap7Partner::~TSnap7Partner()\n{\n    Stop();\n    OnBRecv = 0;\n    OnBSend = 0;\n    delete SendEvt;\n    delete RecvEvt;\n}\n//------------------------------------------------------------------------------\nbyte TSnap7Partner::GetNextByte()\n{\n    NextByte++;\n    if (NextByte==0xFF)\n       NextByte=1;\n    return NextByte;\n}\n//------------------------------------------------------------------------------\nint TSnap7Partner::Start()\n{\n    int Result;\n    PeerAddress=inet_addr(RemoteAddress);\n    SrcAddress =inet_addr(LocalAddress);\n    if (!Running)\n    {\n      if (!Active)\n      {\n          Result=ServersManager_GetServer(SrcAddress,FServer);\n          if (Result==0)\n              FServer->RegisterPartner(this);\n          BindError=Result!=0;\n      }\n      else\n      {\n          Linked=PeerConnect()==0;\n          Result=0; // we need to create the worker thread even tough it's not linked\n      };\n     // if ok create the worker thread\n     if (Result==0)\n     {\n         FWorkerThread = new TPartnerThread(this, RecoveryTime);\n         FWorkerThread->Start();\n     }\n    }\n    else\n        Result=0;\n\n    Running=Result==0;\n\n    return Result;\n}\n//------------------------------------------------------------------------------\nint TSnap7Partner::StartTo(const char *LocAddress, const char *RemAddress, word LocTsap, word RemTsap)\n{\n    SrcTSap=LocTsap;\n    DstTSap=RemTsap;\n\tstrcpy(LocalAddress,LocAddress);\n\tstrcpy(RemoteAddress,RemAddress);\n    return Start();\n}\n//------------------------------------------------------------------------------\nint TSnap7Partner::Stop()\n{\n    if (Running)\n    {\n        Stopping=true; // to prevent incoming connections\n        CloseWorker();\n        if (!Active && (FServer!=0))\n            ServersManager_RemovePartner(FServer, this);\n        if (Connected)\n            Disconnect();\n        Running =false;\n        Stopping=false;\n    };\n    BindError=false;\n    return 0;\n}\n//------------------------------------------------------------------------------\nvoid TSnap7Partner::Disconnect()\n{\n    PeerDisconnect();\n    Linked=false;\n}\n//------------------------------------------------------------------------------\nint TSnap7Partner::GetParam(int ParamNumber, void * pValue)\n{\n\tswitch (ParamNumber)\n\t{\n\t\tcase p_u16_LocalPort:\n\t\t\t*Puint16_t(pValue)=LocalPort;\n\t\t\tbreak;\n\t\tcase p_u16_RemotePort:\n\t\t\t*Puint16_t(pValue)=RemotePort;\n\t\t\tbreak;\n\t\tcase p_i32_PingTimeout:\n\t\t\t*Pint32_t(pValue)=PingTimeout;\n\t\t\tbreak;\n\t\tcase p_i32_SendTimeout:\n\t\t\t*Pint32_t(pValue)=SendTimeout;\n\t\t\tbreak;\n\t\tcase p_i32_RecvTimeout:     \n\t\t\t*Pint32_t(pValue)=RecvTimeout;\n\t\t\tbreak;\n\t\tcase p_i32_WorkInterval:\n\t\t\t*Pint32_t(pValue)=WorkInterval;\n\t\t\tbreak;\n\t\tcase p_u16_SrcRef:\n\t\t\t*Puint16_t(pValue)=SrcRef;\n\t\t\tbreak;\n\t\tcase p_u16_DstRef:\n\t\t\t*Puint16_t(pValue)=DstRef;\n\t\t\tbreak;\n\t\tcase p_u16_SrcTSap:\n\t\t\t*Puint16_t(pValue)=SrcTSap;\n\t\t\tbreak;\n\t\tcase p_i32_PDURequest:\n\t\t\t*Pint32_t(pValue)=PDURequest;\n\t\t\tbreak;\n\t\tcase p_i32_BSendTimeout:\n\t\t\t*Pint32_t(pValue)=BSendTimeout;\n\t\t\tbreak;\n\t\tcase p_i32_BRecvTimeout:    \n\t\t\t*Pint32_t(pValue)=BRecvTimeout;\n\t\t\tbreak;\n\t\tcase p_u32_RecoveryTime:    \n\t\t\t*Puint32_t(pValue)=RecoveryTime;\n\t\t\tbreak;\n\t\tcase p_u32_KeepAliveTime:   \n\t\t\t*Puint32_t(pValue)=KeepAliveTime;\n\t\t\tbreak;\n\t\tdefault: return errParInvalidParamNumber;\n\t}\n\treturn 0;\n}\n//------------------------------------------------------------------------------\nint TSnap7Partner::SetParam(int ParamNumber, void * pValue)\n{\n\tswitch (ParamNumber)\n\t{\n\t\tcase p_u16_RemotePort:\n\t\t\tif (!Connected && Active)\n\t\t\t\tRemotePort=*Puint16_t(pValue);\n\t\t\telse\n\t\t\t\treturn errParCannotChangeParam;\n\t\t\tbreak;\n\t\tcase p_i32_PingTimeout:\n\t\t\tPingTimeout=*Pint32_t(pValue);\n\t\t\tbreak;\n\t\tcase p_i32_SendTimeout:\n\t\t\tSendTimeout=*Pint32_t(pValue);\n\t\t\tbreak;\n\t\tcase p_i32_RecvTimeout:     \n\t\t\tRecvTimeout=*Pint32_t(pValue);\n\t\t\tbreak;\n\t\tcase p_i32_WorkInterval:\n\t\t\tWorkInterval=*Pint32_t(pValue);\n\t\t\tbreak;\n\t\tcase p_u16_SrcRef:\n\t\t\tSrcRef=*Puint16_t(pValue);\n\t\t\tbreak;\n\t\tcase p_u16_DstRef:\n\t\t\tDstRef=*Puint16_t(pValue);\n\t\t\tbreak;\n\t\tcase p_u16_SrcTSap:\n\t\t\tSrcTSap=*Puint16_t(pValue);\n\t\t\tbreak;\n\t\tcase p_i32_PDURequest:\n\t\t\tPDURequest=*Pint32_t(pValue);\n\t\t\tbreak;\n\t\tcase p_i32_BSendTimeout:\n\t\t\tBSendTimeout=*Pint32_t(pValue);\n\t\t\tbreak;\n\t\tcase p_i32_BRecvTimeout:    \n\t\t\tBRecvTimeout=*Pint32_t(pValue);\n\t\t\tbreak;\n\t\tcase p_u32_RecoveryTime:    \n\t\t\tRecoveryTime=*Puint32_t(pValue);\n\t\t\tbreak;\n\t\tcase p_u32_KeepAliveTime:   \n\t\t\tKeepAliveTime=*Puint32_t(pValue);\n\t\t\tbreak;\n\t\tdefault: return errParInvalidParamNumber;\n\t}\n\treturn 0;\n}\n//------------------------------------------------------------------------------\nvoid TSnap7Partner::ClearRecv()\n{\n    memset(&FRecvStatus,0,sizeof(TRecvStatus));\n    FRecvPending=false;\n}\n//------------------------------------------------------------------------------\nbool TSnap7Partner::ConnectToPeer()\n{\n    bool Result;\n    if (Active)\n    {\n        Result=PeerConnect()==0;  // try to Connect\n        Linked=Result;\n    }\n    else\n        Result =false;     // nothing : we are waiting for a connection\n\n    return Result;\n}\n//------------------------------------------------------------------------------\nbool TSnap7Partner::PerformFunctionNegotiate()\n{\n    PReqFunNegotiateParams ReqParams;\n    PResFunNegotiateParams ResParams;\n    TS7Answer23 Answer;\n    int Size;\n\n    // Setup pointers\n    ReqParams=PReqFunNegotiateParams(pbyte(PDUH_in)+sizeof(TS7ReqHeader));\n    ResParams=PResFunNegotiateParams(pbyte(&Answer)+sizeof(TS7ResHeader23));\n    // We are here only because we found a PduType_request, the partner can only\n    // handle Bs} requests and pdu negotiation requests.\n    // So, now we must check the incoming function\n    if (ReqParams->FunNegotiate!=pduNegotiate)\n    {\n        LastError=errParInvalidPDU;\n        return false;\n    };\n    // Prepares the answer\n    Answer.Header.P=0x32;\n    Answer.Header.PDUType =0x03;\n    Answer.Header.AB_EX   =0x0000;\n    Answer.Header.Sequence=PDUH_in->Sequence;\n    Answer.Header.ParLen  =SwapWord(sizeof(TResFunNegotiateParams));\n    Answer.Header.DataLen =0x0000;\n    Answer.Header.Error   =0x0000;\n    // Params point at the } of the header\n    ResParams->FunNegotiate=pduNegotiate;\n    ResParams->Unknown=0x0;\n    // Checks PDU request length\n    if (SwapWord(ResParams->PDULength)>IsoPayload_Size)\n        ResParams->PDULength=SwapWord(IsoPayload_Size);\n    else\n        ResParams->PDULength=ReqParams->PDULength;\n    // We offer the same\n    ResParams->ParallelJobs_1=ReqParams->ParallelJobs_1;\n    ResParams->ParallelJobs_2=ReqParams->ParallelJobs_2;\n    // And store the value\n    PDULength=SwapWord(ResParams->PDULength);\n    // Sends the answer\n    Size=sizeof(TS7ResHeader23) + sizeof(TResFunNegotiateParams);\n    if (isoSendBuffer(&Answer, Size)!=0)\n        SetError(errParNegotiatingPDU);\n\n    Linked=LastError==0;\n    return Linked;\n}\n//------------------------------------------------------------------------------\nvoid TSnap7Partner::CloseWorker()\n{\n     int Timeout;\n     if (FWorkerThread)\n     {\n          FWorkerThread->Terminate();\n          if (FRecvPending || FSendPending)\n             Timeout=3000;\n          else\n             Timeout=1000;\n\n          if (FWorkerThread->WaitFor(Timeout)!=WAIT_OBJECT_0)\n             FWorkerThread->Kill();\n          try {\n             delete FWorkerThread;\n          }\n          catch (...){\n          }\n          FWorkerThread=0;\n     }\n}\n//------------------------------------------------------------------------------\nbool TSnap7Partner::BlockSend()\n{\n    PBSendReqParams ReqParams;\n    PBSendReqParams ResParams;\n    PBsendRequestData DataSendReq;\n    int TotalSize;\n    int SentSize;\n    int Slice;\n    int MaxSlice;\n    uintptr_t Offset;\n    pbyte Source;\n    bool First, Last;\n    byte Seq_IN;\n    int TxIsoSize;\n    pbyte Data;\n    pword TotalPackSize;\n    int DataPtrOffset;\n    word Extra;\n\n    ClrError();\n    TotalSize=TxBuffer.Size;\n    SentSize =TotalSize;\n    Offset=0;\n    First =true;\n    Seq_IN=0x00;\n\n  // With BSend we can transfer up to 32k (S7300) or 64k (S7400), but splitted\n  // into slice that cannot exced the PDU size negotiated (including various headers).\n    MaxSlice=PDULength-sizeof(TS7ReqHeader)-sizeof(TBSendParams)-sizeof(TBsendRequestData)-2;\n\n    ReqParams=PBSendReqParams(pbyte(PDUH_out)+sizeof(TS7ReqHeader));\n    ResParams=ReqParams; // pdu 7 is symmetrical\n\n    while ((TotalSize>0) && (LastError==0))\n    {\n\t\tSource=pbyte(&TxBuffer.Data)+Offset;\n\t\tSlice=TotalSize;\n\n\t\tif (Slice>MaxSlice)\n\t\t\tSlice=MaxSlice;\n\n\t\tTotalSize-=Slice;\n\t\tOffset+=Slice;\n\t\tLast=TotalSize==0;\n\n\t\t// Prepare send\n\t\tDataPtrOffset=sizeof(TS7ReqHeader)+sizeof(TBSendParams);\n\t\t// Header\n\t\tPDUH_out->P=0x32;                     // Always 0x32\n\t\tPDUH_out->PDUType=PduType_userdata;  // 7\n\t\tPDUH_out->AB_EX=0x0000;               // Always 0x0000\n\t\tPDUH_out->Sequence=GetNextWord();      // Autoinc\n\t\tPDUH_out->ParLen=SwapWord(sizeof(TBSendParams)); // 16 bytes\n\n\t\tReqParams->Head[0]=0x00;\n\t\tReqParams->Head[1]=0x01;\n\t\tReqParams->Head[2]=0x12;\n\t\tReqParams->Plen   =0x08; // length from here up the end of the record\n\t\tReqParams->Uk     =0x12;\n\t\tReqParams->Tg     =grBSend; // 0x46\n\t\tReqParams->SubFun =0x01;\n\t\tReqParams->Seq    =Seq_IN;\n\t\tReqParams->Err    =0x0000;\n\t\tif (Last)\n\t\t\tReqParams->EoS  =0x00;\n\t\telse\n\t\t\tReqParams->EoS  =0x01;\n\t\t// Next byte is auto inc and not zero for partial sequences\n\t\t// Is zero for lonely sequences.\n\t\tif (First && Last)\n\t\t\tReqParams->IDSeq=0x00;\n\t\telse\n\t\t\tReqParams->IDSeq=GetNextByte();\n\n\t\tDataSendReq=PBsendRequestData(pbyte(PDUH_out)+DataPtrOffset);\n\t\tif (First)\n\t\t{\n\t\t\t// in the first pdu, after data header there is the whole packet length\n\t\t\tTotalPackSize=pword(pbyte(DataSendReq)+sizeof(TBsendRequestData));\n\t\t\tData=pbyte(TotalPackSize)+sizeof(word);\n\t\t\t*TotalPackSize=SwapWord(word(TxBuffer.Size));\n\t\t\tExtra=2; // extra bytes (total pack size indicator)\n\t\t}\n\t\telse\n\t\t{\n\t\t\tData=pbyte(DataSendReq)+sizeof(TBsendRequestData);\n\t\t\tExtra=0;\n\t\t};\n\n\t\tPDUH_out->DataLen=SwapWord(word(sizeof(TBsendRequestData))+Slice+Extra);\n\t\tDataSendReq->Len =SwapWord(Slice+8+Extra);\n\t\tTxIsoSize=Slice+sizeof(TS7ReqHeader)+sizeof(TBSendParams)+sizeof(TBsendRequestData)+Extra;\n\n\t\tDataSendReq->FF      =0xFF;\n\t\tDataSendReq->TRSize  =TS_ResOctet;\n\t\tDataSendReq->DHead[0]=0x12;\n\t\tDataSendReq->DHead[1]=0x06;\n\t\tDataSendReq->DHead[2]=0x13;\n\t\tDataSendReq->DHead[3]=0x00;\n\t\tDataSendReq->R_ID    =SwapDWord(TxBuffer.R_ID);\n\t\tmemcpy(Data, Source ,Slice);\n\n\t\tif (isoExchangeBuffer(NULL, TxIsoSize)!=0)\n\t\t\tSetError(errParSendingBlock);\n\n\t\tif (LastError==0)\n\t\t{\n\t\t   Seq_IN=ResParams->Seq;\n\t\t   if (SwapWord(ResParams->Err)!=0)\n\t\t\t   LastError=errParSendRefused;\n\t\t}\n\n\t\tif (First)\n\t\t{\n\t\t\tFirst =false;\n\t\t\tMaxSlice+=2; // only in the first frame we have the extra info\n\t\t};\n\t};\n\n\tSendTime=SysGetTick()-FSendElapsed;\n\tif (LastError==0)\n\t\tBytesSent+=SentSize;\n\n\treturn LastError==0;\n}\n//------------------------------------------------------------------------------\nbool TSnap7Partner::PickData()\n{\n\tPBSendReqParams   ReqParams;\n\tPBSendReqParams   ResParams;\n\tPBSendResData     ResData;\n\tPBsendRequestData DataSendReq;\n\tpbyte Source, Target;\n\tpword TotalPackSize;\n\tword Slice;\n\tint AnswerLen;\n\n\tClrError();\n\t// Setup pointers\n\tReqParams  =PBSendReqParams(pbyte(PDUH_in)+sizeof(TS7ReqHeader));\n\tResParams  =ReqParams; // pdu 7 is symmetrical\n\tDataSendReq=PBsendRequestData(pbyte(ReqParams)+sizeof(TBSendParams));\n\n\t// Checks if PDU is a BSend request\n\tif ((PDUH_in->PDUType!=PduType_userdata) || (ReqParams->Tg!=grBSend))\n\t{\n\t\tLastError=errParInvalidPDU;\n\t\treturn false;\n\t}\n\n\tif (FRecvStatus.First)\n\t{\n\t\tTotalPackSize=(word*)(pbyte(DataSendReq)+sizeof(TBsendRequestData));\n\t\tFRecvStatus.TotalLength=SwapWord(*TotalPackSize);\n\t\tSource=pbyte(DataSendReq)+sizeof(TBsendRequestData)+2;\n\t\tFRecvStatus.In_R_ID=SwapDWord(DataSendReq->R_ID);\n\t\tFRecvStatus.Offset=0;\n\t\tSlice=SwapWord(DataSendReq->Len)-10;\n\t}\n\telse {\n\t\tSlice=SwapWord(DataSendReq->Len)-8;\n\t\tSource=pbyte(DataSendReq)+sizeof(TBsendRequestData);\n\t}\n\n\tFRecvStatus.Done=ReqParams->EoS==0x00;\n\n\tTarget=pbyte(&RxBuffer)+FRecvStatus.Offset;\n\tmemcpy(Target, Source, Slice);\n\tFRecvStatus.Offset+=Slice;\n\n\tResData =PBSendResData(pbyte(ResParams)+sizeof(TBSendParams));\n\t// Send Answer\n\tPDUH_out->ParLen  =SwapWord(sizeof(TBSendParams));\n\tPDUH_out->DataLen =SwapWord(sizeof(TBSendResData));\n\n\tResParams->Head[0]=0x00;\n\tResParams->Head[1]=0x01;\n\tResParams->Head[2]=0x12;\n\tResParams->Plen   =0x08; // length from here up the end of the record\n\tResParams->Uk     =0x12;\n\tResParams->Tg     =0x86;\n\tResParams->SubFun =0x01;\n\tResParams->Seq    =FRecvStatus.Seq_Out;\n\tResParams->Err    =0x0000;\n\tResParams->EoS    =0x00;\n\tResParams->IDSeq  =0x00;\n\n\tResData->DHead[0] =0x0A;\n\tResData->DHead[1] =0x00;\n\tResData->DHead[2] =0x00;\n\tResData->DHead[3] =0x00;\n\n\tAnswerLen=sizeof(TS7ReqHeader)+sizeof(TBSendParams)+sizeof(TBSendResData);\n\tif (isoSendBuffer(NULL,AnswerLen)!=0)\n\t\tSetError(errParRecvingBlock);\n\n\treturn LastError==0;\n}\n//------------------------------------------------------------------------------\nbool TSnap7Partner::BlockRecv()\n{\n\tbool Result;\n    if (!FRecvPending) // Start sequence\n    {\n        FRecvPending=true;\n        FRecvStatus.First=true;\n        FRecvStatus.Done =false;\n        FRecvStatus.Seq_Out =GetNextByte();\n        FRecvStatus.Elapsed =SysGetTick();\n        FRecvLast.Done=false;\n        FRecvLast.Result=0;\n        FRecvLast.R_ID=0;\n        FRecvLast.Size=0;\n        RecvTime =0;\n        FRecvLast.Count++;\n        if (FRecvLast.Count==0xFFFFFFFF)\n          FRecvLast.Count=0;\n    };\n\n\tResult=PickData();\n    FRecvStatus.First=false;\n\n    if (!Result || FRecvStatus.Done)\n    {\n        FRecvLast.Result=LastError;\n        if (Result)\n        {\n            BytesRecv+=FRecvStatus.TotalLength;\n            RecvTime=SysGetTick()-FRecvStatus.Elapsed;\n            FRecvLast.R_ID=FRecvStatus.In_R_ID;\n            FRecvLast.Size=FRecvStatus.TotalLength;\n        };\n        RecvEvt->Set();\n        if ((OnBRecv!=NULL) && !Destroying)\n            OnBRecv(FRecvUsrPtr, FRecvLast.Result, FRecvLast.R_ID, &RxBuffer, FRecvLast.Size);\n        FRecvLast.Done=true;\n        ClearRecv();\n    };\n    return Result;\n}\n//------------------------------------------------------------------------------\nbool TSnap7Partner::ConnectionConfirm()\n{\n    if (FRecvPending)\n        ClearRecv();\n    IsoConfirmConnection(pdu_type_CC); // <- Connection confirm\n    return LastTcpError!=WSAECONNRESET;\n}\n//------------------------------------------------------------------------------\nint TSnap7Partner::Status()\n{\n    if (Running)\n    {\n        if (Linked)\n        {\n            if (FRecvPending)\n                return par_receiving;\n            else\n                if (FSendPending)\n                    return par_sending;\n                else\n                    return par_linked;\n        }\n        else\n            if (Active)\n                return par_connecting;\n            else\n                return par_waiting;\n    }\n    else{\n        if ((!Active) && BindError)\n            return par_binderror;\n        else\n            return par_stopped;\n    }\n}\n//------------------------------------------------------------------------------\nbool TSnap7Partner::Execute()\n{\n    TPDUKind PduKind;\n    bool RTimeout;\n    bool Result =true;\n\n    // Checks if there is something to send (and we are not receiving...)\n    if (FSendPending && !FRecvPending)\n    {\n        Result=BlockSend();\n        SendEvt->Set();\n        if ((OnBSend!=NULL) && (!Destroying))\n            OnBSend(FSendUsrPtr, LastError);\n        FSendPending=false;\n    }\n\n\tif (Destroying)\n\t\treturn false;\n\n    // Checks if there is something to recv\n    if (Result && CanRead(WorkInterval))\n    {\n        // Peeks info and returns PDU Kind\n        isoRecvPDU(&PDU);\n        if (LastTcpError==0)\n        {\n            // First check valid data incoming (most likely situation)\n            IsoPeek(&PDU,PduKind);\n            if (PduKind==pkValidData)\n            {\n                if (PDUH_in->PDUType==PduType_request)\n                {\n                    if (FRecvPending)\n                        ClearRecv();\n                    Result=PerformFunctionNegotiate();\n                }\n                else // Pdu type userdata\n                    Result=BlockRecv();\n            }\n            else\n                if (PduKind==pkConnectionRequest)\n                    Result=ConnectionConfirm();\n                else // nothing else\n                    Purge();\n        }\n        else\n            Result=false;\n    };\n\n    if (LastTcpError==WSAECONNRESET)\n    {\n        Result=false;\n        Linked=false;\n    }\n    else\n        if (!Result)\n            Disconnect();\n\n    // Check BRecv sequence timeout\n    RTimeout= FRecvPending && (SysGetTick()-FRecvStatus.Elapsed>longword(BRecvTimeout));\n\n    if (RTimeout)\n    {\n        LastError=errParFrameTimeout;\n        RecvEvt->Set();\n        if ((OnBRecv!=NULL) && !Destroying)\n            OnBRecv(FRecvUsrPtr, LastError, 0, &RxBuffer,0);\n    };\n\n  if (!Result || RTimeout)\n      ClearRecv();   // parframetimeout\n\n  return Result;\n}\n\n//------------------------------------------------------------------------------\nint TSnap7Partner::BSend(longword R_ID, void *pUsrData, int Size)\n{\n    // The block send is managed into the worker thread.\n    // Sync Bsend consists of AsBSend+WaitAsCompletion\n    int Result=AsBSend(R_ID, pUsrData, Size);\n    if (Result==0)\n        Result=WaitAsBSendCompletion(BSendTimeout);\n    return Result;\n}\n//------------------------------------------------------------------------------\nint TSnap7Partner::AsBSend(longword R_ID, void *pUsrData, int Size)\n{\n    SendTime=0;\n    if (Linked)\n    {\n      if (!FSendPending)\n      {\n          memcpy(&TxBuffer.Data, pUsrData, Size);\n          TxBuffer.R_ID=R_ID;\n          TxBuffer.Size=Size;\n          SendEvt->Reset();\n          FSendPending=true;\n          FSendElapsed=SysGetTick();\n          return 0;\n      }\n      else\n          return errParBusy;\n    }\n    else\n        return SetError(errParNotLinked);\n}\n//------------------------------------------------------------------------------\nbool TSnap7Partner::CheckAsBSendCompletion(int &opResult)\n{\n    if (!Destroying)\n\t{\n\t\tif (!FSendPending)\n\t\t\topResult=LastError;\n\t\telse\n\t\t\topResult=errParBusy;\n\n\t\treturn !FSendPending;\n\t}\n\telse\n\t{\n\t\topResult=errParDestroying;\n\t\treturn true;\n    }\n\n}\n//------------------------------------------------------------------------------\nint TSnap7Partner::WaitAsBSendCompletion(longword Timeout)\n{\n   if (SendEvt->WaitFor(BSendTimeout)==WAIT_OBJECT_0)\n   {\n\t\tif (!Destroying)\n\t\t\treturn LastError;\n\t\telse\n\t\t\treturn SetError(errParDestroying);\n   }\n   else\n       return SetError(errParSendTimeout);\n}\n//------------------------------------------------------------------------------\nint TSnap7Partner::SetSendCallback(pfn_ParBSendCompletion pCompletion, void *usrPtr)\n{\n    OnBSend=pCompletion;\n    FSendUsrPtr=usrPtr;\n    return 0;\n}\n//------------------------------------------------------------------------------\nint TSnap7Partner::BRecv(longword &R_ID, void *pData, int &Size, longword Timeout)\n{\n     int Result=0;\n     if (RecvEvt->WaitFor(Timeout)==WAIT_OBJECT_0)\n     {\n         R_ID =FRecvLast.R_ID;\n         Size =FRecvLast.Size;\n         if (FRecvLast.Result==0)\n         {\n             if (pData!=NULL)\n                 memcpy(pData, &RxBuffer, Size);\n             else\n                 Result=errParInvalidParams;\n         }\n         else\n             Result=FRecvLast.Result;\n         RecvEvt->Reset();\n     }\n     else\n         Result=errParRecvTimeout;\n\n     return SetError(Result);\n}\n//------------------------------------------------------------------------------\nbool TSnap7Partner::CheckAsBRecvCompletion(int &opResult, longword &R_ID,\n    void *pData, int &Size)\n{\n    if (Destroying)\n\t{\n\t\tSize=0;\n\t\topResult=errParDestroying;\n\t\treturn true;\n\t}\n\t\n\tbool Result=FRecvLast.Done;\n    if (Result)\n    {\n        Size=FRecvLast.Size;\n        R_ID=FRecvLast.R_ID;\n        opResult=FRecvLast.Result;\n        if ((pData!=NULL) && (Size>0) && (opResult==0))\n           memcpy(pData, &RxBuffer, Size);\n        FRecvLast.Done=false;\n    }\n    return Result;\n}\n//------------------------------------------------------------------------------\nint TSnap7Partner::SetRecvCallback(pfn_ParBRecvCallBack pCompletion, void *usrPtr)\n{\n    OnBRecv=pCompletion;\n    FRecvUsrPtr=usrPtr;\n    return 0;\n}\n//------------------------------------------------------------------------------\n\n"
  },
  {
    "path": "deps/snap7/src/core/s7_partner.h",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.3.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|=============================================================================*/\n#ifndef s7_partner_h\n#define s7_partner_h\n//---------------------------------------------------------------------------\n#include \"snap_threads.h\"\n#include \"s7_peer.h\"\n//---------------------------------------------------------------------------\nusing namespace std;\n//---------------------------------------------------------------------------\n\n#define MaxPartners 256\n#define MaxAdapters 256\n#define csTimeout   1500 // Connection server destruction timeout\n\nconst int par_stopped         = 0;   // stopped\nconst int par_connecting      = 1;   // running and active connecting\nconst int par_waiting         = 2;   // running and waiting for a connection\nconst int par_linked          = 3;   // running and connected\nconst int par_sending         = 4;   // sending data\nconst int par_receiving       = 5;   // receiving data\nconst int par_binderror       = 6;   // error starting passive partner\n\nconst longword errParMask               = 0xFFF00000;\nconst longword errParBase               = 0x000FFFFF;\n\nconst longword errParAddressInUse       = 0x00200000;\nconst longword errParNoRoom             = 0x00300000;\nconst longword errServerNoRoom          = 0x00400000;\nconst longword errParInvalidParams      = 0x00500000;\nconst longword errParNotLinked          = 0x00600000;\nconst longword errParBusy               = 0x00700000;\nconst longword errParFrameTimeout       = 0x00800000;\nconst longword errParInvalidPDU         = 0x00900000;\nconst longword errParSendTimeout        = 0x00A00000;\nconst longword errParRecvTimeout        = 0x00B00000;\nconst longword errParSendRefused        = 0x00C00000;\nconst longword errParNegotiatingPDU     = 0x00D00000;\nconst longword errParSendingBlock       = 0x00E00000;\nconst longword errParRecvingBlock       = 0x00F00000;\nconst longword errParBindError          = 0x01000000;\nconst longword errParDestroying         = 0x01100000;\nconst longword errParInvalidParamNumber = 0x01200000; // Invalid param (par_get/set_param)\nconst longword errParCannotChangeParam  = 0x01300000; // Cannot change because running\nconst longword errParBufferTooSmall     = 0x01400000; // Raised by LabVIEW wrapper\n\nclass TSnap7Partner;\ntypedef TSnap7Partner *PSnap7Partner;\n\nclass TConnectionServer;\ntypedef TConnectionServer *PConnectionServer;\n\n//------------------------------------------------------------------------------\n// CONNECTION SERVERS MANAGER\n//------------------------------------------------------------------------------\nclass TServersManager\n{\nprivate:\n    PConnectionServer Servers[MaxAdapters];\n    TSnapCriticalSection *cs;\n    void Lock();\n    void Unlock();\n    int CreateServer(longword BindAddress, PConnectionServer &Server);\n    void AddServer(PConnectionServer Server);\npublic:\n    int ServersCount;\n    TServersManager();\n    ~TServersManager();\n\n    int GetServer(longword BindAddress, PConnectionServer &Server);\n    void RemovePartner(PConnectionServer Server, PSnap7Partner Partner);\n\n};\ntypedef TServersManager *PServersManager;\n\n//------------------------------------------------------------------------------\n// CONNECTION SERVER (Don't inherit from TcpSrv to avoid dependence)\n//------------------------------------------------------------------------------\n\nclass TConnListenerThread : public TSnapThread\n{\nprivate:\n\tTMsgSocket *FListener;\n\tTConnectionServer *FServer;\npublic:\n\tTConnListenerThread(TMsgSocket *Listener, TConnectionServer *Server)\n    {\n        FServer=Server;\n        FListener=Listener;\n        FreeOnTerminate=false;\n    };\n\tvoid Execute();\n};\ntypedef TConnListenerThread *PConnListenerThread;\n\n\nclass TConnectionServer\n{\nprivate:\n    TSnapCriticalSection *cs;\n    bool FRunning;\n    // Bind Address\n\tchar FLocalAddress[16];\n\t// Server listener\n\tPConnListenerThread ServerThread;\n\t// Socket listener\n\tPMsgSocket SockListener;\n    // Finds a partner bound to the address\n    PSnap7Partner FindPartner(longword Address);\n    // Locks the Partner list\n    void Lock();\n    // Unlocks the Partner list\n    void Unlock();\nprotected:\n\t// Workers list\n\tPSnap7Partner Partners[MaxPartners];\n    bool Destroying;\n    void Incoming(socket_t Sock);\n    int Start();\n    int FirstFree();\npublic:\n    int PartnersCount;\n    longword LocalBind;\n    TConnectionServer();\n    ~TConnectionServer();\n\n    int StartTo(const char *Address);\n    void Stop();\n    int RegisterPartner(PSnap7Partner Partner);\n    void RemovePartner(PSnap7Partner Partner);\n    friend class TConnListenerThread;\n};\ntypedef TConnectionServer * PConnectionServer;\n\n//------------------------------------------------------------------------------\n// PARTNER THREAD\n//------------------------------------------------------------------------------\nclass TPartnerThread : public TSnapThread\n{\nprivate:\n    TSnap7Partner *FPartner;\n    longword FRecoveryTime;\n    longword FKaElapsed;\nprotected:\n    void Execute();\npublic:\n    TPartnerThread(TSnap7Partner *Partner, longword RecoveryTime)\n    {\n        FPartner = Partner;\n        FRecoveryTime =RecoveryTime;\n        FreeOnTerminate =false;\n    };\n    ~TPartnerThread(){};\n};\ntypedef TPartnerThread *PPartnerThread;\n//------------------------------------------------------------------------------\n// S7 PARTNER\n//------------------------------------------------------------------------------\n\ntypedef struct{\n    bool      First;\n    bool      Done;\n    uintptr_t Offset;\n    longword  TotalLength;\n    longword  In_R_ID;\n    longword  Elapsed;\n    byte      Seq_Out;\n}TRecvStatus;\n\ntypedef struct{\n    bool     Done;\n    int      Size;\n    int      Result;\n    longword R_ID;\n    longword Count;\n}TRecvLast;\n\nextern \"C\" {\ntypedef void (S7API *pfn_ParBRecvCallBack)(void * usrPtr, int opResult, longword R_ID, void *pdata, int Size);\ntypedef void (S7API *pfn_ParBSendCompletion)(void * usrPtr, int opResult);\n}\n\nclass TSnap7Partner : public TSnap7Peer\n{\nprivate:\n    PS7ReqHeader PDUH_in;\n    void *FRecvUsrPtr;\n    void *FSendUsrPtr;\n    PSnapEvent SendEvt;\n    PSnapEvent RecvEvt;\n    PConnectionServer FServer;\n    PPartnerThread FWorkerThread;\n    bool FSendPending;\n    bool FRecvPending;\n    TRecvStatus FRecvStatus;\n    TRecvLast FRecvLast;\n    TPendingBuffer TxBuffer;\n    TPendingBuffer RxBuffer;\n    longword FSendElapsed;\n    bool BindError;\n    byte NextByte;\n    pfn_ParBRecvCallBack OnBRecv;\n    pfn_ParBSendCompletion OnBSend;\n    void ClearRecv();\n    byte GetNextByte();\n    void CloseWorker();\n    bool BlockSend();\n    bool PickData();\n    bool BlockRecv();\n    bool ConnectionConfirm();\nprotected:\n    bool Stopping;\n    bool Execute();\n    void Disconnect();\n    bool ConnectToPeer();\n    bool PerformFunctionNegotiate();\npublic:\n    bool Active;\n    bool Running;\n    longword PeerAddress;\n    longword SrcAddress;\n    int BRecvTimeout;\n    int BSendTimeout;\n    longword SendTime;\n    longword RecvTime;\n    longword RecoveryTime;\n    longword KeepAliveTime;\n    longword BytesSent;\n    longword BytesRecv;\n    longword SendErrors;\n    longword RecvErrors;\n    // The partner is linked when the init sequence is terminated\n    //(TCP connection + ISO connection + PDU Length negotiation)\n    bool Linked;\n    TSnap7Partner(bool CreateActive);\n    ~TSnap7Partner();\n    // Control\n    int Start();\n    int StartTo(const char *LocAddress, const char *RemAddress, word LocTsap, word RemTsap);\n    int Stop();\n    int Status();\n\tint GetParam(int ParamNumber, void * pValue);\n\tint SetParam(int ParamNumber, void * pValue);\n    // Block send\n    int BSend(longword R_ID, void *pUsrData, int Size);\n    int AsBSend(longword R_ID, void *pUsrData, int Size);\n    bool CheckAsBSendCompletion(int &opResult);\n    int WaitAsBSendCompletion(longword Timeout);\n    int SetSendCallback(pfn_ParBSendCompletion pCompletion, void *usrPtr);\n    // Block recv\n    int BRecv(longword &R_ID, void *pData, int &Size, longword Timeout);\n    bool CheckAsBRecvCompletion(int &opResult, longword &R_ID,\n        void *pData, int &Size);\n    int SetRecvCallback(pfn_ParBRecvCallBack pCompletion, void *usrPtr);\n\n    friend class TConnectionServer;\n    friend class TPartnerThread;\n};\n\n\n#endif // s7_partner_h\n"
  },
  {
    "path": "deps/snap7/src/core/s7_peer.cpp",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.3.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|=============================================================================*/\n#include \"s7_peer.h\"\n//---------------------------------------------------------------------------\n\nTSnap7Peer::TSnap7Peer()\n{\n    PDUH_out=PS7ReqHeader(&PDU.Payload);\n    PDURequest=480; // Our request, FPDULength will contain the CPU answer\n    LastError=0;\n    Destroying = false;\n}\n//---------------------------------------------------------------------------\nTSnap7Peer::~TSnap7Peer()\n{\n    Destroying = true;\n}\n//---------------------------------------------------------------------------\nint TSnap7Peer::SetError(int Error)\n{\n    if (Error==0)\n       ClrError();\n    else\n       LastError=Error | LastIsoError | LastTcpError;\n    return Error;\n}\n//---------------------------------------------------------------------------\nvoid TSnap7Peer::ClrError()\n{\n    LastError=0;\n    LastIsoError=0;\n    LastTcpError=0;\n}\n//---------------------------------------------------------------------------\nword TSnap7Peer::GetNextWord()\n{\n     if (cntword==0xFFFF)\n        cntword=0;\n     return cntword++;\n}\n//---------------------------------------------------------------------------\nint TSnap7Peer::NegotiatePDULength( )\n{\n    int Result, IsoSize = 0;\n    PReqFunNegotiateParams ReqNegotiate;\n    PResFunNegotiateParams ResNegotiate;\n    PS7ResHeader23 Answer;\n    ClrError();\n    // Setup Pointers\n    ReqNegotiate = PReqFunNegotiateParams(pbyte(PDUH_out) + sizeof(TS7ReqHeader));\n    // Header\n    PDUH_out->P        = 0x32;            // Always $32\n    PDUH_out->PDUType  = PduType_request; // $01\n    PDUH_out->AB_EX    = 0x0000;          // Always $0000\n    PDUH_out->Sequence = GetNextWord();   // AutoInc\n    PDUH_out->ParLen   = SwapWord(sizeof(TReqFunNegotiateParams)); // 8 bytes\n    PDUH_out->DataLen  = 0x0000;\n    // Params\n    ReqNegotiate->FunNegotiate = pduNegotiate;\n    ReqNegotiate->Unknown = 0x00;\n    ReqNegotiate->ParallelJobs_1 = 0x0100;\n    ReqNegotiate->ParallelJobs_2 = 0x0100;\n    ReqNegotiate->PDULength = SwapWord(PDURequest);\n    IsoSize = sizeof( TS7ReqHeader ) + sizeof( TReqFunNegotiateParams );\n    Result = isoExchangeBuffer(NULL, IsoSize);\n    if ((Result == 0) && (IsoSize == int(sizeof(TS7ResHeader23) + sizeof(TResFunNegotiateParams))))\n    {\n        // Setup pointers\n        Answer = PS7ResHeader23(&PDU.Payload);\n        ResNegotiate = PResFunNegotiateParams(pbyte(Answer) + sizeof(TS7ResHeader23));\n        if ( Answer->Error != 0 )\n\t    Result = SetError(errNegotiatingPDU);\n        if ( Result == 0 )\n\t    PDULength = SwapWord(ResNegotiate->PDULength);\n    }\n    return Result;\n}\n//---------------------------------------------------------------------------\nvoid TSnap7Peer::PeerDisconnect( )\n{\n    ClrError();\n    isoDisconnect(true);\n}\n//---------------------------------------------------------------------------\nint TSnap7Peer::PeerConnect( )\n{\n    int Result;\n\n    ClrError();\n\tResult = isoConnect();\n\tif (Result == 0)\n\t{\n\t\tResult = NegotiatePDULength();\n\t\tif (Result != 0)\n\t\t\tPeerDisconnect();\n\t}\n    return Result;\n}\n"
  },
  {
    "path": "deps/snap7/src/core/s7_peer.h",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.3.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|=============================================================================*/\n#ifndef s7_peer_h\n#define s7_peer_h\n//---------------------------------------------------------------------------\n#include \"s7_types.h\"\n#include \"s7_isotcp.h\"\n//---------------------------------------------------------------------------\n\nconst longword errPeerMask \t     = 0xFFF00000;\nconst longword errPeerBase       = 0x000FFFFF;\nconst longword errNegotiatingPDU = 0x00100000;\n\nclass TSnap7Peer: public TIsoTcpSocket\n{\nprivate:\n    word cntword;\nprotected:\n    bool Destroying;\n    PS7ReqHeader PDUH_out;\n    word GetNextWord();\n    int SetError(int Error);\n    int NegotiatePDULength();\n    void ClrError();\npublic:\n    int LastError;\n    int PDULength;\n    int PDURequest;\n    TSnap7Peer();\n    ~TSnap7Peer();\n    void PeerDisconnect();\n    int PeerConnect();\n};\n//---------------------------------------------------------------------------\n#endif\n"
  },
  {
    "path": "deps/snap7/src/core/s7_server.cpp",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.3.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|=============================================================================*/\n#include \"s7_server.h\"\n#include \"s7_firmware.h\"\n\nconst byte BitMask[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};\n\n//------------------------------------------------------------------------------\n// ISO/TCP WORKER  CLASS\n//------------------------------------------------------------------------------\nbool TIsoTcpWorker::IsoPerformCommand(int &Size)\n{\n    return true;\n}\n//---------------------------------------------------------------------------\nbool TIsoTcpWorker::ExecuteSend()\n{\n    return true;\n}\n//---------------------------------------------------------------------------\nbool TIsoTcpWorker::ExecuteRecv()\n{\n    TPDUKind PduKind;\n    int PayloadSize;\n\n    if (CanRead(WorkInterval)) // should be Small to avoid time wait during the close\n    {\n        isoRecvPDU(&PDU);\n        if (LastTcpError==0)\n        {\n            IsoPeek(&PDU,PduKind);\n            // First check valid data incoming (most likely situation)\n            if (PduKind==pkValidData)\n            {\n                PayloadSize=PDUSize(&PDU)-DataHeaderSize;\n                return IsoPerformCommand(PayloadSize);\n            };\n            // Connection request incoming\n            if (PduKind==pkConnectionRequest)\n            {\n                IsoConfirmConnection(pdu_type_CC); // <- Connection confirm\n                return LastTcpError!=WSAECONNRESET;\n            };\n            // Disconnect request incoming (only for isotcp full complient equipment, not S7)\n            if (PduKind==pkDisconnectRequest)\n            {\n                IsoConfirmConnection(pdu_type_DC); // <- Disconnect confirm\n                return false;\n            };\n            // Empty fragment, maybe an ACK\n            if (PduKind==pkEmptyFragment)\n            {\n                PayloadSize=0;\n                return IsoPerformCommand(PayloadSize);\n            };\n            // Valid PDU format but we have to discard it\n            if (PduKind==pkUnrecognizedType)\n            {\n                return LastTcpError!=WSAECONNRESET;\n            };\n            // Here we have an Invalid PDU\n            Purge();\n            return true;\n        }\n        else\n            return LastTcpError!=WSAECONNRESET;\n    }\n    else\n        return true;\n}\n//---------------------------------------------------------------------------\nbool TIsoTcpWorker::Execute()\n{\n    return ExecuteSend() && ExecuteRecv();\n}\n//------------------------------------------------------------------------------\n// S7 WORKER CLASS\n//------------------------------------------------------------------------------\nTS7Worker::TS7Worker()\n{\n    // We skip RFC/ISO header, our PDU is the payload\n    PDUH_in   =PS7ReqHeader(&PDU.Payload);\n    FPDULength=2048;\n    DBCnt     =0;\n    LastBlk   =Block_DB;\n}\n\nbool TS7Worker::ExecuteRecv()\n{\n    WorkInterval=FServer->WorkInterval;\n    return TIsoTcpWorker::ExecuteRecv();\n}\n//------------------------------------------------------------------------------\nbool TS7Worker::CheckPDU_in(int PayloadSize)\n{\n    // Checks the size : packet size must match with header infos\n    int Size=SwapWord(PDUH_in->ParLen)+SwapWord(PDUH_in->DataLen)+ReqHeaderSize;\n    if (Size!=PayloadSize)\n        return false;\n    // Checks PDUType : must be 1 or 7\n    if ((PDUH_in->PDUType!=PduType_request) &&\n        (PDUH_in->PDUType!=PduType_userdata))\n        return false;\n    else\n        return true;\n}\n//------------------------------------------------------------------------------\nbyte TS7Worker::BCD(word Value)\n{\n    return ((Value / 10) << 4) + (Value % 10);\n}\n//------------------------------------------------------------------------------\nvoid TS7Worker::FillTime(PS7Time PTime)\n{\n    time_t Now;\n    time(&Now);\n    struct tm *DT = localtime (&Now);\n\n    PTime->bcd_year=BCD(DT->tm_year-100);\n    PTime->bcd_mon =BCD(DT->tm_mon+1);\n    PTime->bcd_day =BCD(DT->tm_mday);\n    PTime->bcd_hour=BCD(DT->tm_hour);\n    PTime->bcd_min =BCD(DT->tm_min);\n    PTime->bcd_sec =BCD(DT->tm_sec);\n    PTime->bcd_himsec=0;\n    PTime->bcd_dow =BCD(DT->tm_wday);\n}\n//------------------------------------------------------------------------------\nvoid TS7Worker::DoEvent(longword Code, word RetCode, word Param1, word Param2,\n  word Param3, word Param4)\n{\n    FServer->DoEvent(ClientHandle,Code,RetCode,Param1,Param2,Param3,Param4);\n}\n//------------------------------------------------------------------------------\nvoid TS7Worker::DoReadEvent(longword Code, word RetCode, word Param1, word Param2,\n  word Param3, word Param4)\n{\n    FServer->DoReadEvent(ClientHandle,Code,RetCode,Param1,Param2,Param3,Param4);\n}\n//------------------------------------------------------------------------------\nvoid TS7Worker::FragmentSkipped(int Size)\n{\n// do nothing could be used for debug purpose\n}\n//------------------------------------------------------------------------------\nbool TS7Worker::IsoPerformCommand(int &Size)\n{\n    // Checks for Ack fragment\n    if (Size==0)\n        return PerformPDUAck(Size);\n    // First checks PDU consistence\n    if (CheckPDU_in(Size))\n    {\n        switch (PDUH_in->PDUType)\n        {\n            case PduType_request    : return PerformPDURequest(Size);\n            case PduType_userdata   : return PerformPDUUsrData(Size);\n        }\n    }\n    else\n        DoEvent(evcPDUincoming, evrMalformedPDU, Size, 0, 0, 0);\n    return false;\n}\n//------------------------------------------------------------------------------\nbool TS7Worker::PerformPDUAck(int &Size)\n{\n    // here we could keep track of ack empty fragment for debug purpose\n    return true;\n}\n//------------------------------------------------------------------------------\nbool TS7Worker::PerformPDURequest(int &Size)\n{\n    pbyte P;\n    byte PDUFun;\n    bool Result = true;\n\n    // We have to store PDUfun since it will be overwritten\n    P = pbyte(PDUH_in)+ReqHeaderSize;\n    PDUFun=*P;\n    // Watches the function\n    switch (PDUFun)\n    {\n        case pduFuncRead    : Result=PerformFunctionRead();\n             break;\n        case pduFuncWrite   : Result=PerformFunctionWrite();\n             break;\n\t\tcase pduNegotiate   : Result=PerformFunctionNegotiate();\n             break;\n        case pduStart       :\n        case pduStop        : Result=PerformFunctionControl(PDUFun);\n             break;\n\t\tcase pduStartUpload :\n        case pduUpload      :\n        case pduEndUpload   : Result=PerformFunctionUpload();\n             break;\n        case pduReqDownload : Result=PerformFunctionDownload();\n             break;\n        // <-- Further (custom) functions can be added here\n        default:\n             DoEvent(evcPDUincoming, evrCannotHandlePDU, Size, 0, 0, 0);\n    };\n    return Result;\n}\n//------------------------------------------------------------------------------\nbool TS7Worker::PerformPDUUsrData(int &Size)\n{\n    PS7ReqParams7 ReqParams;\n    byte Tg, SubFun;\n    bool Result = true;\n    // Set Pointer to request params\n    ReqParams=PS7ReqParams7(pbyte(PDUH_in)+ReqHeaderSize);\n    Tg=ReqParams->Tg;\n    SubFun=ReqParams->SubFun;\n    // Switch type_group\n    switch (Tg)\n    {\n      case grProgrammer : Result=PerformGroupProgrammer();\n          break;\n      case grCyclicData : Result=PerformGroupCyclicData();\n          break;\n      case grBlocksInfo : Result=PerformGroupBlockInfo();\n          break;\n      case grSZL        : Result=PerformGroupSZL();\n          break;\n      case grPassword   : Result=PerformGroupSecurity();\n          break;\n      case grClock      : switch (SubFun)\n                         {\n                             case 0x01 : Result=PerformGetClock();\n                                 break;\n                             case 0x02 : Result=PerformSetClock();\n                                 break;\n                         };\n                         break;\n      default:\n          DoEvent(evcPDUincoming, evrInvalidGroupUData, Tg, 0, 0, 0);\n    };\n    return Result;\n}\n//------------------------------------------------------------------------------\nint TS7Worker::DataSizeByte(int WordLength)\n{\n\tswitch (WordLength){\n\t\tcase S7WLBit     : return 1;  // S7 sends 1 byte per bit\n\t\tcase S7WLByte    : return 1;\n\t\tcase S7WLChar    : return 1;\n\t\tcase S7WLWord    : return 2;\n\t\tcase S7WLDWord   : return 4;\n\t\tcase S7WLInt     : return 2;\n\t\tcase S7WLDInt    : return 4;\n\t\tcase S7WLReal    : return 4;\n\t\tcase S7WLCounter : return 2;\n\t\tcase S7WLTimer   : return 2;\n\t\tdefault          : return 0;\n     }\n}\n//==============================================================================\n// FUNCTION READ\n//==============================================================================\nword TS7Worker::RA_NotFound(PResFunReadItem ResItem, TEv &EV)\n{\n    ResItem->DataLength=SwapWord(0x0004);\n    ResItem->ReturnCode=Code7ResItemNotAvailable;\n    ResItem->TransportSize=0x00;\n    EV.EvRetCode=evrErrAreaNotFound;\n    return 0;\n}\n//------------------------------------------------------------------------------\nword TS7Worker::RA_OutOfRange(PResFunReadItem ResItem, TEv &EV)\n{\n    ResItem->DataLength=SwapWord(0x0004);\n    ResItem->ReturnCode=Code7AddressOutOfRange;\n    ResItem->TransportSize=0x00;\n    EV.EvRetCode=evrErrOutOfRange;\n    return 0;\n}\n//------------------------------------------------------------------------------\nword TS7Worker::RA_SizeOverPDU(PResFunReadItem ResItem, TEv &EV)\n{\n    ResItem->DataLength=SwapWord(0x0004);\n    ResItem->ReturnCode=byte(SwapWord(Code7DataOverPDU));\n    ResItem->TransportSize=0x00;\n    EV.EvRetCode=evrErrOverPDU;\n    return 0;\n}\n//------------------------------------------------------------------------------\nPS7Area TS7Worker::GetArea(byte S7Code, word index)\n{\n\tswitch(S7Code)\n    {\n\tcase S7AreaPE : return FServer->HA[srvAreaPE];\n\tcase S7AreaPA : return FServer->HA[srvAreaPA];\n\tcase S7AreaMK : return FServer->HA[srvAreaMK];\n\tcase S7AreaCT : return FServer->HA[srvAreaCT];\n\tcase S7AreaTM : return FServer->HA[srvAreaTM];\n\tcase S7AreaDB : return FServer->FindDB(index);\n\tdefault       : return NULL;\n    };\n}\n//------------------------------------------------------------------------------\nword TS7Worker::ReadArea(PResFunReadItem ResItemData, PReqFunReadItem ReqItemPar,\n     int &PDURemainder, TEv &EV)\n{\n    PS7Area P;\n\tword DBNum = 0;\n\tword Elements;\n    longword Start, Size, ASize, AStart;\n    longword *PAdd;\n    byte BitIndex, ByteVal;\n\tint Multiplier;\n    void *Source = NULL;\n    PSnapCriticalSection pcs;\n\n    P=NULL;\n    EV.EvStart   =0;\n    EV.EvSize    =0;\n    EV.EvRetCode =0;\n    EV.EvIndex   =0;\n\n    EV.EvArea=ReqItemPar->Area;\n    // Get Pointer to selected Area\n\n\tif (ReqItemPar->Area==S7AreaDB)\n\t{\n        DBNum=SwapWord(ReqItemPar->DBNumber);\n        EV.EvIndex=DBNum;\n\t};\n\n\tif (!FServer->ResourceLess)\n\t{\n\t\tP = GetArea(ReqItemPar->Area, DBNum);\n\t\tif (P == NULL)\n\t\t\treturn RA_NotFound(ResItemData, EV);\n\t}\n\n    // Calcs the amount\n\tMultiplier = DataSizeByte(ReqItemPar->TransportSize);\n\tif (Multiplier==0)\n\t\treturn RA_OutOfRange(ResItemData, EV);\n\n    // Checks timers/counters coherence\n    if ((ReqItemPar->Area==S7AreaTM) ^ (ReqItemPar->TransportSize==S7WLTimer))\n        return RA_OutOfRange(ResItemData, EV);\n\n    if ((ReqItemPar->Area==S7AreaCT) ^ (ReqItemPar->TransportSize==S7WLCounter))\n        return RA_OutOfRange(ResItemData, EV);\n\n    // Calcs size\n\tElements = SwapWord(ReqItemPar->Length);\n\tSize=Multiplier*Elements;   \n\tEV.EvSize=Size;\n\n    // The sum of the items must not exceed the PDU size negotiated\n    if (PDURemainder-Size<=0)\n        return RA_SizeOverPDU(ResItemData, EV);\n    else\n        PDURemainder-=Size;\n\n    // More then 1 bit is not supported by S7 CPU \n    if ((ReqItemPar->TransportSize==S7WLBit) && (Size>1))\n        return RA_OutOfRange(ResItemData, EV);\n\n\t// Calcs the start point\n    PAdd=(longword*)(&ReqItemPar->Area);   // points to area since we need 4 bytes for a pointer\n    Start=SwapDWord(*PAdd & 0xFFFFFF00);\n\n    // Checks if the address is not multiple of 8 when transport size is neither bit nor timer nor counter\n    if (\n\t\t(ReqItemPar->TransportSize!=S7WLBit) &&\n\t\t(ReqItemPar->TransportSize!=S7WLTimer) &&\n\t\t(ReqItemPar->TransportSize!=S7WLCounter) &&\n\t\t((Start % 8) !=0)\n\t   )\n\t\treturn RA_OutOfRange(ResItemData, EV);\n\n    // AStart is only for callback\n\tif ((ReqItemPar->TransportSize != S7WLBit) && (ReqItemPar->TransportSize != S7WLCounter) && (ReqItemPar->TransportSize != S7WLTimer))\n\t\tAStart = Start >> 3;\n\telse\n\t\tAStart = Start;\n\n\tif ((ReqItemPar->TransportSize == S7WLCounter) || (ReqItemPar->TransportSize == S7WLTimer))\n\t{\n\t\tStart = Start >> 1;   // 1 Timer or Counter = 2 bytes\n\t}\n\telse\n\t{\n\t\tBitIndex  =Start & 0x07; // start bit\n\t\tStart     =Start >> 3;   // start byte\n\t}\n\t\n\tEV.EvStart=Start;\n\n\t// Checks bounds\n\tif (!FServer->ResourceLess)\n\t{\n\t\tASize = P->Size; // Area size\n\t\tif (Start + Size > ASize)\n\t\t\treturn RA_OutOfRange(ResItemData, EV);\n\t\tSource = P->PData + Start;\n\t}\n\n\t// Read Event (before copy data)\n    DoReadEvent(evcDataRead,0,EV.EvArea,EV.EvIndex,EV.EvStart,EV.EvSize);\t\n\n\tif (FServer->ResourceLess)\n\t{\n\t\tmemset(&ResItemData->Data, 0, Size);\n\t\tif (!FServer->DoReadArea(ClientHandle, EV.EvArea, EV.EvIndex, AStart, Elements, ReqItemPar->TransportSize, &ResItemData->Data))\n\t\t\treturn RA_NotFound(ResItemData, EV);\n\t}\n\telse\n\t{\n\t\t// Lock the area\n\t\tpcs = P->cs;\n\t\tpcs->Enter();\n\t\t// Get Data\n\t\tmemcpy(&ResItemData->Data, Source, Size);\n\t\t// Unlock the area\n\t\tpcs->Leave();\n\t}\n\n    ResItemData->ReturnCode=0xFF;\n    // Set Result transport size and, for bit, performs the mask\n    switch (ReqItemPar->TransportSize)\n    {\n      case S7WLBit:\n        {\n          ByteVal=ResItemData->Data[0];\n\n          if ((ByteVal & BitMask[BitIndex])!=0)\n              ResItemData->Data[0]=0x01;\n          else\n              ResItemData->Data[0]=0x00;\n\n          ResItemData->TransportSize=TS_ResBit;\n          ResItemData->DataLength=SwapWord(Size);\n        };break;\n      case S7WLByte:\n\t  case S7WLWord:\n\t  case S7WLDWord:\n        {\n          ResItemData->TransportSize=TS_ResByte;\n          ResItemData->DataLength=SwapWord(Size*8);\n        };break;\n\t  case S7WLInt:\n\t  case S7WLDInt:\n        {\n          ResItemData->TransportSize=TS_ResInt;\n          ResItemData->DataLength=SwapWord(Size*8);\n        };break;\n      case S7WLReal:\n        {\n          ResItemData->TransportSize=TS_ResReal;\n          ResItemData->DataLength=SwapWord(Size);\n        };break;\n      case S7WLChar:\n      case S7WLTimer:\n      case S7WLCounter:\n        {\n          ResItemData->TransportSize=TS_ResOctet;\n\t\t  ResItemData->DataLength=SwapWord(Size);\n        };break;\n      default : \n        {\n          ResItemData->TransportSize=TS_ResByte;\n          ResItemData->DataLength=SwapWord(Size*8);\n        };break;\n    }\n    EV.EvRetCode=evrNoError;\n    return Size;\n}\n//------------------------------------------------------------------------------\nbool TS7Worker::PerformFunctionRead()\n{\n    PReqFunReadParams ReqParams;\n    PResFunReadParams ResParams;\n    TResFunReadData   ResData;\n    TS7Answer23       Answer;\n    uintptr_t         Offset;\n    word ItemSize;\n    int ItemsCount, c,\n    TotalSize,\n    PDURemainder;\n    TEv EV;\n\n\tPDURemainder=FPDULength;\n    // Stage 1 : Setup pointers and initial check\n\tReqParams=PReqFunReadParams(pbyte(PDUH_in)+sizeof(TS7ReqHeader));\n    ResParams=PResFunReadParams(pbyte(&Answer)+ResHeaderSize23);        // Params after the header\n\n    // trunk to 20 max items.\n    if (ReqParams->ItemsCount>MaxVars)\n        ReqParams->ItemsCount=MaxVars;\n\n    ItemsCount=ReqParams->ItemsCount;\n\n    // Stage 2 : gather data\n    Offset=sizeof(TResFunReadParams);      // = 2\n\n    for (c = 0; c < ItemsCount; c++)\n\t{\n\t\tResData[c]=PResFunReadItem(pbyte(ResParams)+Offset);\n\t\tItemSize=ReadArea(ResData[c],&ReqParams->Items[c],PDURemainder, EV);\n\n        // S7 doesn't xfer odd byte amount\n        if ((c<ItemsCount-1) && (ItemSize % 2 != 0))\n\t      ItemSize++;\n\t\t\n        Offset+=(ItemSize+4);\n        // For multiple items we have to create multiple events\n        if (ItemsCount>1)\n            DoEvent(evcDataRead,EV.EvRetCode,EV.EvArea,EV.EvIndex,EV.EvStart,EV.EvSize);\n    }\n    // Stage 3 : finalize the answer and send the packet\n    Answer.Header.P=0x32;\n    Answer.Header.PDUType=0x03;\n    Answer.Header.AB_EX=0x0000;\n    Answer.Header.Sequence=PDUH_in->Sequence;\n    Answer.Header.ParLen=SwapWord(sizeof(TResFunReadParams));\n    Answer.Header.Error=0x0000; // this is zero, we will find the error in ResData.ReturnCode\n    Answer.Header.DataLen=SwapWord(word(Offset)-2);\n\n    ResParams->FunRead  =ReqParams->FunRead;\n    ResParams->ItemCount=ReqParams->ItemsCount;\n\n    TotalSize=ResHeaderSize23+int(Offset);\n    isoSendBuffer(&Answer, TotalSize);\n\n    // For single item (most likely case) it's better to work with the event after\n    // we sent the answer\n    if (ItemsCount==1)\n        DoEvent(evcDataRead,EV.EvRetCode,EV.EvArea,EV.EvIndex,EV.EvStart,EV.EvSize);\n\n    return true;\n}\n//==============================================================================\n// FUNCTION WRITE\n//==============================================================================\nbyte TS7Worker::WA_NotFound(TEv &EV)\n{\n\tEV.EvRetCode=evrErrAreaNotFound;\n    return Code7ResItemNotAvailable;\n}\n//------------------------------------------------------------------------------\nbyte TS7Worker::WA_InvalidTransportSize(TEv &EV)\n{\n    EV.EvRetCode=evrErrTransportSize;\n    return Code7InvalidTransportSize;\n}\n//------------------------------------------------------------------------------\nbyte TS7Worker::WA_OutOfRange(TEv &EV)\n{\n    EV.EvRetCode=evrErrOutOfRange;\n    return Code7AddressOutOfRange;\n}\n//------------------------------------------------------------------------------\nbyte TS7Worker::WA_DataSizeMismatch(TEv &EV)\n{\n    EV.EvRetCode=evrDataSizeMismatch;\n    return Code7WriteDataSizeMismatch;\n}\n//------------------------------------------------------------------------------\nbyte TS7Worker::WriteArea(PReqFunWriteDataItem ReqItemData, PReqFunWriteItem ReqItemPar,\n     TEv &EV)\n{\n\tint Multiplier;\n    PS7Area P = NULL;\n\tword DBNum = 0;\n\tword Elements;\n    longword *PAdd;\n\tPSnapCriticalSection pcs;\n\tlongword Start, Size, ASize, DataLen, AStart;\n\tpbyte Target = NULL;\n\tbyte BitIndex;\n\n    EV.EvStart   =0;\n\tEV.EvSize    =0;\n    EV.EvRetCode =evrNoError;\n    EV.EvIndex   =0;\n\n    EV.EvArea=ReqItemPar->Area;\n    // Get Pointer to selected Area\n\tif (ReqItemPar->Area==S7AreaDB)\n\t{\n\t\tDBNum=SwapWord(ReqItemPar->DBNumber);\n\t\tEV.EvIndex=DBNum;\n\t};\n\t\n\tif (!FServer->ResourceLess)\n\t{\n\t\tP=GetArea(ReqItemPar->Area, DBNum);\n\t\tif (P==NULL)\n\t\t\treturn WA_NotFound(EV);\n\t}\n\n    // Calcs the amount\n\tMultiplier = DataSizeByte(ReqItemPar->TransportSize);\n\tif (Multiplier==0)\n\t\treturn WA_InvalidTransportSize(EV);\n\n    // Checks timers/counters coherence\n    if ((ReqItemPar->Area==S7AreaTM) ^ (ReqItemPar->TransportSize==S7WLTimer))\n        return WA_OutOfRange(EV);\n\n\tif ((ReqItemPar->Area==S7AreaCT) ^ (ReqItemPar->TransportSize==S7WLCounter))\n        return WA_OutOfRange(EV);\n\n\t// Calcs size\n\tElements = SwapWord(ReqItemPar->Length);\n\tSize = Multiplier*Elements;\n    EV.EvSize=Size;\n\n    // More) 1 bit is not supported by S7 CPU\n    if ((ReqItemPar->TransportSize==S7WLBit) && (Size>1))\n        return WA_OutOfRange(EV);\n\n    // Calcs the start point ??\n    PAdd=(longword*)&ReqItemPar->Area;   // points to area since we need 4 bytes for a pointer\n    Start=SwapDWord(*PAdd & 0xFFFFFF00);\n\n    // Checks if the address is not multiple of 8 when transport size is neither bit nor timer nor counter\n    if (\n\t\t(ReqItemPar->TransportSize!=S7WLBit) && \n\t\t(ReqItemPar->TransportSize!=S7WLTimer) && \n\t\t(ReqItemPar->TransportSize!=S7WLCounter) && \n\t\t((Start % 8) !=0)\n\t   )\n\t\treturn WA_OutOfRange(EV);\n\n\t// AStart is only for callback\n\tif ((ReqItemPar->TransportSize != S7WLBit) && (ReqItemPar->TransportSize != S7WLCounter) && (ReqItemPar->TransportSize != S7WLTimer))\n\t\tAStart = Start >> 3;\n\telse\n\t\tAStart = Start;\n\n\tif ((ReqItemPar->TransportSize == S7WLCounter) || (ReqItemPar->TransportSize == S7WLTimer))\n\t{\n\t\tStart = Start >> 1;   // 1 Timer or Counter = 2 bytes\n\t}\n\telse\n\t{\n\t\tBitIndex = Start & 0x07; // start bit\n\t\tStart = Start >> 3;   // start byte\n\t}\n\tEV.EvStart =Start;\n\t\n\tif (!FServer->ResourceLess)\n\t{\n\t\t// Checks bounds\n\t\tASize = P->Size; // Area size\n\t\tif (Start + Size > ASize)\n\t\t\treturn WA_OutOfRange(EV);\n\t\tTarget = pbyte(P->PData + Start);\n\t}\n    // Checks data size coherence\n    DataLen=SwapWord(ReqItemData->DataLength);\n\n\tif ((ReqItemData->TransportSize!=TS_ResOctet) && (ReqItemData->TransportSize!=TS_ResReal) && (ReqItemData->TransportSize!=TS_ResBit))\n\t\tDataLen=DataLen / 8;\n\n\tif (DataLen!=Size)\n        return WA_DataSizeMismatch(EV);\n\n\tif (FServer->ResourceLess)\n\t{\n\t\tif (!FServer->DoWriteArea(ClientHandle, EV.EvArea, EV.EvIndex, AStart, Elements, ReqItemPar->TransportSize, &ReqItemData->Data[0]))\n\t\t\treturn WA_NotFound(EV);\n\t}\n\telse\n\t{\n\t\tif (ReqItemPar->TransportSize==S7WLBit)\n\t\t{\n\t\t  if ((ReqItemData->Data[0] & 0x01) != 0)   // bit set\n\t\t\t  *Target=*Target | BitMask[BitIndex];\n\t\t  else                                      // bit reset\n\t\t\t  *Target=*Target & (~BitMask[BitIndex]);\n\t\t}\n\t\telse {\n\t\t  // Lock the area\n\t\t\tpcs = P->cs;\n\t\t\tpcs->Enter();\n\t\t\t// Write Data\n\t\t\tmemcpy(Target, &ReqItemData->Data[0], Size);\n\t\t\tpcs->Leave();\n\t\t};\n\t}\n\t\n\treturn 0xFF;\n}\n//------------------------------------------------------------------------------\nbool TS7Worker::PerformFunctionWrite()\n{\n    PReqFunWriteParams ReqParams;\n    TReqFunWriteData ReqData;\n    PResFunWrite ResData;\n    TS7Answer23 Answer;\n\tint L;\n\n\tuintptr_t StartData;\n\tint c, ItemsCount;\n\tint ResDSize;\n\tTEv EV;\n\n\t// Stage 1 : Setup pointers and initial check\n\tReqParams=PReqFunWriteParams(pbyte(PDUH_in)+sizeof(TS7ReqHeader));\n\tResData  =PResFunWrite(pbyte(&Answer)+ResHeaderSize23);\n\n\tStartData=sizeof(TS7ReqHeader)+SwapWord(PDUH_in->ParLen);\n\n\tItemsCount=ReqParams->ItemsCount;\n\tResDSize  =ResHeaderSize23+2+ItemsCount;\n\tfor (c = 0; c < ItemsCount; c++)\n\t{\n\t\tReqData[c]=PReqFunWriteDataItem(pbyte(PDUH_in)+StartData);\n\t\t\n\t\tif ((ReqParams->Items[c].TransportSize == S7WLTimer) || (ReqParams->Items[c].TransportSize == S7WLCounter) || (ReqParams->Items[c].TransportSize == S7WLBit))\n\t\t\tL = SwapWord(ReqData[c]->DataLength);\n\t\telse\n\t\t\tL = (SwapWord(ReqData[c]->DataLength) / 8);\n\n\t\tStartData+=L+4;\n\t\t// the datalength is always even\n\t\tif ( L % 2 != 0) StartData++;\n\t}\n\n\tResData->FunWrite =pduFuncWrite;\n\tResData->ItemCount=ReqParams->ItemsCount;\n\n\t// Stage 2 : Write data\n\tfor (c = 0; c < ItemsCount; c++)\n\t{\n\t  ResData->Data[c]=WriteArea(ReqData[c],&ReqParams->Items[c], EV);\n      // For multiple items we have to create multiple events\n      if (ItemsCount>1)\n           DoEvent(evcDataWrite,EV.EvRetCode,EV.EvArea,EV.EvIndex,EV.EvStart,EV.EvSize);\n    }\n\n    // Stage 3 : finalize the answer\n    Answer.Header.P=0x32;\n    Answer.Header.PDUType=0x03;\n    Answer.Header.AB_EX=0x0000;\n    Answer.Header.Sequence=PDUH_in->Sequence;\n    Answer.Header.ParLen=SwapWord(0x02);\n    Answer.Header.Error=0x0000; // this is zero, we will find the error in ResData.ReturnCode if any\n    Answer.Header.DataLen=SwapWord(ItemsCount);\n\n    isoSendBuffer(&Answer,ResDSize);\n    // For single item (most likely case) it's better to fire the event after\n    // we sent the answer\n    if (ItemsCount==1)\n        DoEvent(evcDataWrite,EV.EvRetCode,EV.EvArea,EV.EvIndex,EV.EvStart,EV.EvSize);\n    return true;\n}\n//==============================================================================\n// FUNCTION NEGOTIATE\n//==============================================================================\nbool TS7Worker::PerformFunctionNegotiate()\n{\n\tPReqFunNegotiateParams ReqParams;\n\tPResFunNegotiateParams ResParams;\n\tword ReqLen;\n\tTS7Answer23 Answer;\n\tint Size;\n\n\t// Setup pointers\n\tReqParams=PReqFunNegotiateParams(pbyte(PDUH_in)+sizeof(TS7ReqHeader));\n\tResParams=PResFunNegotiateParams(pbyte(&Answer)+sizeof(TS7ResHeader23));\n\t// Prepares the answer\n\tAnswer.Header.P=0x32;\n\tAnswer.Header.PDUType=0x03;\n\tAnswer.Header.AB_EX=0x0000;\n\tAnswer.Header.Sequence=PDUH_in->Sequence;\n\tAnswer.Header.ParLen=SwapWord(sizeof(TResFunNegotiateParams));\n\tAnswer.Header.DataLen=0x0000;\n\tAnswer.Header.Error=0x0000;\n\t// Params point at the end of the header\n\tResParams->FunNegotiate=pduNegotiate;\n\tResParams->Unknown=0x0;\n\t// We offer the same\n\tResParams->ParallelJobs_1=ReqParams->ParallelJobs_1;\n\tResParams->ParallelJobs_2=ReqParams->ParallelJobs_2;\n\n\tif (FServer->ForcePDU == 0)\n\t{\n\t\tReqLen = SwapWord(ReqParams->PDULength);\n\t\tif (ReqLen<MinPduSize)\n\t\t\tResParams->PDULength = SwapWord(MinPduSize);\n\t\telse\n\t\t\tif (ReqLen>IsoPayload_Size)\n\t\t\t\tResParams->PDULength = SwapWord(IsoPayload_Size);\n\t\t\telse\n\t\t\t\tResParams->PDULength = ReqParams->PDULength;\n\t}\n\telse\n\t\tResParams->PDULength = SwapWord(FServer->ForcePDU);\n\n\tFPDULength=SwapWord(ResParams->PDULength); // Stores the value\n\t// Sends the answer\n\tSize=sizeof(TS7ResHeader23) + sizeof(TResFunNegotiateParams);\n\tisoSendBuffer(&Answer, Size);\n\t// Store the event\n\tDoEvent(evcNegotiatePDU, evrNoError, FPDULength, 0, 0, 0);\n\treturn true;\n}\n//==============================================================================\n// FUNCTION CONTROL\n//==============================================================================\nbool TS7Worker::PerformFunctionControl(byte PduFun)\n{\n    TS7Answer23 Answer;\n    PResFunCtrl ResParams;\n    word ParLen;\n    word CtrlCode;\n\n    // Setup pointer\n    ResParams=PResFunCtrl(pbyte(&Answer)+sizeof(TS7ResHeader23));\n    // Prepares the answer\n    Answer.Header.P=0x32;\n    Answer.Header.PDUType=0x03;\n    Answer.Header.AB_EX=0x0000;\n    Answer.Header.Sequence=PDUH_in->Sequence;\n    Answer.Header.ParLen=SwapWord(0x0001); // We send only Res fun without para\n    Answer.Header.DataLen=0x0000;\n    Answer.Header.Error=0x0000;\n    ResParams->ResFun=PduFun;\n    ResParams->para  =0x00;\n\n    ParLen=SwapWord(PDUH_in->ParLen);\n    if (PduFun==pduStop)\n      CtrlCode=CodeControlStop;\n    else\n    {\n      switch (ParLen)\n      {\n        case 16 : CtrlCode=CodeControlCompress;  break;\n        case 18 : CtrlCode=CodeControlCpyRamRom; break;\n        case 20 : CtrlCode=CodeControlWarmStart; break;\n        case 22 : CtrlCode=CodeControlColdStart; break;\n        case 26 : CtrlCode=CodeControlInsDel;    break;\n        default : CtrlCode=CodeControlUnknown;\n      }\n    }\n    // Sends the answer\n    isoSendBuffer(&Answer,sizeof(TS7ResHeader23)+1);\n    // Stores the event\n    DoEvent(evcControl,0,CtrlCode,0,0,0);\n\n    if ((CtrlCode==CodeControlWarmStart) || (CtrlCode==CodeControlColdStart))\n        FServer->CpuStatus=S7CpuStatusRun;\n\n    if (CtrlCode==CodeControlStop)\n        FServer->CpuStatus=S7CpuStatusStop;\n\n    return true;\n}\n//==============================================================================\n// FUNCTION UPLOAD\n//==============================================================================\nbool TS7Worker::PerformFunctionUpload()\n{\n    TS7Answer23 Answer;\n\n    // Upload is not implemented, however to avoid that S7 manager hangs\n    // we simulate a cpu read/write protected.\n    // We can see the directory but can't upload/download anything\n\n    // Prepares the answer\n    Answer.Header.P=0x32;\n    Answer.Header.PDUType =pduResponse;\n    Answer.Header.AB_EX=0x0000;\n    Answer.Header.Sequence=PDUH_in->Sequence;\n    Answer.Header.ParLen=0;\n    Answer.Header.DataLen=0;\n    Answer.Header.Error=SwapWord(Code7NeedPassword);\n    // Sends the answer\n    isoSendBuffer(&Answer,sizeof(TS7ResHeader23));\n\n    DoEvent(evcUpload,evrCannotUpload,evsStartUpload,0,0,0);\n    return true;\n}\n//==============================================================================\n// FUNCTION DOWNLOAD\n//==============================================================================\nbool TS7Worker::PerformFunctionDownload()\n{\n    TS7Answer23 Answer;\n\n    // Download is not implemented, however to avoid that S7 manager hangs\n    // we simulate a cpu read/write protected.\n    // We can see the directory but can't upload/download anything\n\n    // Prepares the answer\n    Answer.Header.P=0x32;\n    Answer.Header.PDUType =pduResponse;\n    Answer.Header.AB_EX=0x0000;\n    Answer.Header.Sequence=PDUH_in->Sequence;\n    Answer.Header.ParLen=0;\n    Answer.Header.DataLen=0;\n    Answer.Header.Error=SwapWord(Code7NeedPassword);\n    // Sends the answer\n    isoSendBuffer(&Answer,sizeof(TS7ResHeader23));\n\n    DoEvent(evcUpload,evrCannotDownload, evsStartDownload,0,0,0);\n    return true;\n}\n//==============================================================================\n// FUNCTIONS PROGRAMMER AND CYCLIC DATA (NOT IMPLEMENTED...yet)\n//==============================================================================\nbool TS7Worker::PerformGroupProgrammer()\n{\n    DoEvent(evcPDUincoming,evrNotImplemented,grProgrammer,0,0,0);\n    return true;\n}\n//------------------------------------------------------------------------------\nbool TS7Worker::PerformGroupCyclicData()\n{\n    DoEvent(evcPDUincoming,evrNotImplemented,grCyclicData,0,0,0);\n    return true;\n}\n//==============================================================================\n// BLOCK(S) INFO FUNCTIONS\n//==============================================================================\nvoid TS7Worker::BLK_ListAll(TCB &CB)\n{\n    PDataFunListAll Data;\n    int TotalSize;\n\n    TotalSize = ResHeaderSize17+sizeof(TResFunGetBlockInfo)+sizeof(TDataFunListAll);\n    // Prepares the answer\n    CB.Answer.Header.P=0x32;\n    CB.Answer.Header.PDUType=PduType_userdata;\n    CB.Answer.Header.AB_EX=0x0000;\n    CB.Answer.Header.Sequence=PDUH_in->Sequence;\n    CB.Answer.Header.ParLen =SwapWord(sizeof(TResFunGetBlockInfo));\n    CB.Answer.Header.DataLen=SwapWord(sizeof(TDataFunListAll));\n\n    CB.ResParams->Head[0]=CB.ReqParams->Head[0];\n    CB.ResParams->Head[1]=CB.ReqParams->Head[1];\n    CB.ResParams->Head[2]=CB.ReqParams->Head[2];\n    CB.ResParams->Plen  =0x08;\n    CB.ResParams->Uk    =0x12;\n    CB.ResParams->Tg    =0x83; // Type response, group functions info\n    CB.ResParams->SubFun=SFun_ListAll;\n\n    CB.ResParams->Seq   =CB.ReqParams->Seq;\n    CB.ResParams->Rsvd  =0x0000;\n    CB.ResParams->ErrNo =0x0000;\n\n    Data=PDataFunListAll(pbyte(&CB.Answer)+ResHeaderSize17+sizeof(TResFunGetBlockInfo));\n    Data->RetVal=0xFF;\n    Data->TRSize=TS_ResOctet;\n    Data->Length=SwapWord(28); // 28 = Size of TDataFunListAll.Blocks\n    // Fill elements, only DB will have a valid number\n    Data->Blocks[0].Zero=0x30;\n    Data->Blocks[0].BType=Block_OB;\n    Data->Blocks[0].BCount=0x0000;    // We don't have OBs\n    Data->Blocks[1].Zero=0x30;\n    Data->Blocks[1].BType=Block_FB;\n    Data->Blocks[1].BCount=0x0000;    // We don't have FBs\n    Data->Blocks[2].Zero=0x30;\n    Data->Blocks[2].BType=Block_FC;\n    Data->Blocks[2].BCount=0x0000;    // We don't have FCs\n    Data->Blocks[3].Zero=0x30;\n    Data->Blocks[3].BType=Block_DB;\n    Data->Blocks[3].BCount=SwapWord(FServer->DBCount); // Most likely we HAVE DBs\n    Data->Blocks[4].Zero=0x30;\n    Data->Blocks[4].BType=Block_SDB;\n    Data->Blocks[4].BCount=0x0000;    // We don't have SDBs\n    Data->Blocks[5].Zero=0x30;\n    Data->Blocks[5].BType=Block_SFC;\n    Data->Blocks[5].BCount=0x0000;    // We don't have SFCs\n    Data->Blocks[6].Zero=0x30;\n    Data->Blocks[6].BType=Block_SFB;\n    Data->Blocks[6].BCount=0x0000;    // We don't have SFBs\n    // Sends\n    isoSendBuffer(&CB.Answer,TotalSize);\n    DoEvent(evcDirectory, 0, evsGetBlockList, 0, 0, 0);\n}\n//------------------------------------------------------------------------------\nvoid TS7Worker::BLK_NoResource_ListBoT(PDataFunGetBot Data, TCB &CB)\n{\n    CB.DataLength    =4;\n    DBCnt            =0; // Reset counter\n    CB.Answer.Header.DataLen=SwapWord(CB.DataLength);\n    CB.ResParams->ErrNo =0x0ED2; // function in error\n    Data->RetVal     =0x0A;   // No resource available\n    Data->TSize      =0x00;   // No transport size;\n    Data->DataLen    =0x0000; // No data;\n    CB.evError       =evrResNotFound;\n}\n//------------------------------------------------------------------------------\nvoid TS7Worker::BLK_ListBoT(byte BlockType, bool Start, TCB &CB)\n{\n    PDataFunGetBot Data;\n    int MaxItems, TotalSize, cnt;\n    int HiBound = FServer->DBLimit+1;\n\n    CB.evError=0;\n    MaxItems=(FPDULength - 32) / 4;\n    // Prepares the answer\n    CB.Answer.Header.P=0x32;\n    CB.Answer.Header.PDUType=PduType_userdata;\n    CB.Answer.Header.AB_EX=0x0000;\n    CB.Answer.Header.Sequence=PDUH_in->Sequence;\n    CB.Answer.Header.ParLen =SwapWord(sizeof(TResFunGetBlockInfo));\n\n    CB.ResParams->Head[0]=CB.ReqParams->Head[0];\n    CB.ResParams->Head[1]=CB.ReqParams->Head[1];\n    CB.ResParams->Head[2]=CB.ReqParams->Head[2];\n    CB.ResParams->Plen  =0x08;\n    CB.ResParams->Uk    =0x12;\n    CB.ResParams->Tg    =0x83; // Type response, group functions info\n    CB.ResParams->SubFun=SFun_ListBoT;\n    CB.ResParams->Seq   =CB.ReqParams->Seq;\n    CB.ResParams->Rsvd  =0x0000;\n    Data=PDataFunGetBot(pbyte(&CB.Answer)+ResHeaderSize17+sizeof(TResFunGetBlockInfo));\n\n    if (BlockType==Block_DB)\n    {\n      cnt =0;  // Local couter\n      if (Start)\n\t      DBCnt=-1; // Global counter\n\n      if (FServer->DBCount>0)\n      {\n\t      while ((cnt<MaxItems) && (DBCnt<HiBound))\n\t      {\n\t\t      DBCnt++;\n\t\t      if (FServer->DB[DBCnt]!=NULL)\n\t\t      {\n\t\t\t      Data->Items[cnt].BlockNum=SwapWord(FServer->DB[DBCnt]->Number);\n\t\t\t      Data->Items[cnt].Unknown  =0x22;\n\t\t\t      Data->Items[cnt].BlockLang=0x05;\n\t\t\t      cnt++;\n\t\t      };\n\t      };\n\n\t      if ((cnt<MaxItems) || (DBCnt==HiBound))\n\t      {\n\t\t      DBCnt=0; // Finished\n\t\t      CB.ResParams->Rsvd=0x0023;\n\t      }\n\t      else\n\t\t      CB.ResParams->Rsvd=0x0123;\n\n\t      if (cnt>0)\n\t      {\n\t\t      CB.ResParams->ErrNo =0x0000;\n\t\t      Data->TSize =TS_ResOctet;\n\t\t      Data->RetVal=0xFF;\n\t\t      CB.DataLength=4+(cnt*word(sizeof(TDataFunGetBotItem)));\n\t\t      CB.Answer.Header.DataLen=SwapWord(CB.DataLength);\n\t\t      Data->DataLen=SwapWord(CB.DataLength-4);\n\t      }\n\t      else\n\t\t      BLK_NoResource_ListBoT(Data, CB);\n      }\n      else\n\t      BLK_NoResource_ListBoT(Data, CB);\n    }\n    else // we store only DBs\n\t    BLK_NoResource_ListBoT(Data, CB);\n\n    TotalSize = ResHeaderSize17+sizeof(TResFunGetBlockInfo)+CB.DataLength;\n    isoSendBuffer(&CB.Answer,TotalSize);\n    if (Start)\n        DoEvent(evcDirectory, CB.evError, evsStartListBoT, BlockType, 0, 0);\n    else\n        DoEvent(evcDirectory, CB.evError, evsListBoT, BlockType, 0, 0);\n}\n//------------------------------------------------------------------------------\nvoid TS7Worker::BLK_NoResource_GetBlkInfo(PResDataBlockInfo Data, TCB &CB)\n{\n    CB.DataLength  =4;\n    CB.Answer.Header.DataLen=SwapWord(CB.DataLength);\n    CB.ResParams->ErrNo =0x09D2; // function in error\n    Data->RetVal        =0x0A;   // No resource available\n    Data->TSize         =0x00;   // No transport size;\n    Data->Length        =0x0000; // No data;\n    CB.evError          =evrResNotFound;\n}\n//------------------------------------------------------------------------------\nvoid TS7Worker::BLK_GetBlockNum_GetBlkInfo(int &BlkNum, PReqDataBlockInfo ReqData)\n{\n    BlkNum = (ReqData->AsciiBlk[4] - 0x30) +\n             (ReqData->AsciiBlk[3] - 0x30) * 10 +\n             (ReqData->AsciiBlk[2] - 0x30) * 100 +\n             (ReqData->AsciiBlk[1] - 0x30) * 1000 +\n             (ReqData->AsciiBlk[0] - 0x30) * 10000;\n\n    if (BlkNum>65535)\n      BlkNum=-1;\n}\n//------------------------------------------------------------------------------\nvoid TS7Worker::BLK_DoBlockInfo_GetBlkInfo(PS7Area DB, PResDataBlockInfo Data, TCB &CB)\n{\n    // Prepares the answer\n    CB.Answer.Header.P=0x32;\n    CB.Answer.Header.PDUType=PduType_userdata;\n    CB.Answer.Header.AB_EX=0x0000;\n    CB.Answer.Header.Sequence=PDUH_in->Sequence;\n    CB.Answer.Header.ParLen =SwapWord(sizeof(TResFunGetBlockInfo));\n\n    CB.ResParams->Head[0]=CB.ReqParams->Head[0];\n    CB.ResParams->Head[1]=CB.ReqParams->Head[1];\n    CB.ResParams->Head[2]=CB.ReqParams->Head[2];\n    CB.ResParams->Plen  =0x08;\n    CB.ResParams->Uk    =0x12;\n    CB.ResParams->Tg    =0x83; // Type response, group functions info\n    CB.ResParams->SubFun=SFun_BlkInfo;\n    CB.ResParams->Seq   =CB.ReqParams->Seq;\n    CB.ResParams->Rsvd  =0x0000;\n    CB.ResParams->ErrNo =0x0000;\n\n    CB.DataLength =sizeof(TResDataBlockInfo);\n    CB.Answer.Header.DataLen=SwapWord(CB.DataLength);\n    CB.ResParams->ErrNo =0x0000;\n\n    Data->RetVal       =0xFF;\n    Data->TSize        =TS_ResOctet;\n    Data->Length       =SwapWord(78); // this struct - RetValData->Tsize and length\n    Data->Cst_b        =0x01;\n    Data->BlkType      =0x00;\n    Data->Cst_w1       =0x4A00;\n    Data->Cst_w2       =0x0022;\n    Data->Cst_pp       =0x7070;\n    Data->Unknown_1    =0x01;\n    Data->BlkFlags     =0x01;\n    Data->BlkLang      =BlockLangDB;\n    Data->SubBlkType   =0x0A;\n    Data->CodeTime_dy  =SwapWord(5800);// Nov/18/1999 my princess's birthdate\n    Data->IntfTime_dy  =Data->CodeTime_dy;\n    Data->LocDataLen   =0x0000;\n    Data->BlkNumber    =SwapWord(DB->Number);\n    Data->SbbLen       =0x1400;\n    Data->AddLen       =0x0000;\n    Data->MC7Len       =SwapWord(DB->Size);\n    Data->LenLoadMem   =SwapDWord(DB->Size+92);\n    Data->Version      =0x01;\n    Data->Unknown_2    =0x00;\n    Data->BlkChksum    =0x0000;\n}\n//------------------------------------------------------------------------------\nvoid TS7Worker::BLK_GetBlkInfo(TCB &CB)\n{\n    PReqDataBlockInfo ReqData;\n    PResDataBlockInfo Data;\n    int BlkNum;\n    PS7Area BlkDB;\n    byte BlkTypeInfo;\n    int TotalSize;\n\n    CB.evError=0;\n    Data   =PResDataBlockInfo(pbyte(&CB.Answer)+ResHeaderSize17+sizeof(TResFunGetBlockInfo));\n    ReqData=PReqDataBlockInfo(pbyte(PDUH_in)+ReqHeaderSize+sizeof(TReqFunGetBlockInfo));\n    memset(Data,0,sizeof(TResDataBlockInfo)); // many fields are 0\n\n    BLK_GetBlockNum_GetBlkInfo(BlkNum, ReqData);\n    BlkTypeInfo=ReqData->BlkType;\n    if (BlkTypeInfo==Block_DB)\n    {\n      if (BlkNum>=0)\n      {\n\t    BlkDB=FServer->FindDB(BlkNum);\n\t    if (BlkDB!=NULL)\n                BLK_DoBlockInfo_GetBlkInfo(BlkDB, Data, CB);\n\t    else\n                BLK_NoResource_GetBlkInfo(Data, CB);\n      }\n      else\n          BLK_NoResource_GetBlkInfo(Data, CB);\n    }\n    else\n        BLK_NoResource_GetBlkInfo(Data, CB);\n\n    TotalSize = ResHeaderSize17+sizeof(TResFunGetBlockInfo)+sizeof(TResDataBlockInfo);\n    isoSendBuffer(&CB.Answer, TotalSize);\n    DoEvent(evcDirectory,CB.evError,evsGetBlockInfo,BlkTypeInfo,BlkNum,0);\n}\n//------------------------------------------------------------------------------\nbool TS7Worker::PerformGroupBlockInfo()\n{\n    TCB CB;\n    pbyte BlockType;\n\n    // Setup pointers\n    CB.ReqParams=PReqFunGetBlockInfo(pbyte(PDUH_in)+ReqHeaderSize);\n    CB.ResParams=PResFunGetBlockInfo(pbyte(&CB.Answer)+ResHeaderSize17);\n    BlockType   =pbyte(PDUH_in)+23;\n\n    switch (CB.ReqParams->SubFun)\n    {\n      case SFun_ListAll : BLK_ListAll(CB); break;            // List all blocks\n      case SFun_ListBoT :\n      {\n          if (CB.ReqParams->Plen==4)\n          {\n              LastBlk=*BlockType;\n              BLK_ListBoT(*BlockType, true, CB); // start sequence from beginning\n          }\n          else\n              BLK_ListBoT(LastBlk, false, CB);  // Continue sequence\n      }; break;\n      case SFun_BlkInfo : BLK_GetBlkInfo(CB); // Get Block info\n    }\n    return true;\n}\n//==============================================================================\n// FUNCTION SZL\n//==============================================================================\nvoid TS7Worker::SZLNotAvailable()\n{\n    SZL.Answer.Header.DataLen=SwapWord(sizeof(SZLNotAvail));\n\tSZL.ResParams->Err = 0x02D4;\n    memcpy(SZL.ResData, &SZLNotAvail, sizeof(SZLNotAvail));\n    isoSendBuffer(&SZL.Answer,26);\n    SZL.SZLDone=false;\n}\nvoid TS7Worker::SZLSystemState()\n{\n    SZL.Answer.Header.DataLen=SwapWord(sizeof(SZLSysState));\n    SZL.ResParams->Err =0x0000;\n    memcpy(SZL.ResData,&SZLNotAvail,sizeof(SZLSysState));\n    isoSendBuffer(&SZL.Answer,28);\n\tSZL.SZLDone=true;\n\n}\nvoid TS7Worker::SZLData(void *P, int len)\n{\n\tint MaxSzl=FPDULength-22;\n\n\tif (len>MaxSzl) {\n\t\tlen=MaxSzl;\n\t}\n\n\tSZL.Answer.Header.DataLen=SwapWord(word(len));\n\tSZL.ResParams->Err  =0x0000;\n\tSZL.ResParams->resvd=0x0000; // this is the end, no more packets\n\tmemcpy(SZL.ResData, P, len);\n\n\tSZL.ResData[2]=((len-4)>>8) & 0xFF;\n\tSZL.ResData[3]=(len-4) & 0xFF;\n\n\tisoSendBuffer(&SZL.Answer,22+len);\n\tSZL.SZLDone=true;\n}\n// this block is dynamic (contains date/time and cpu status)\nvoid TS7Worker::SZL_ID424()\n{\n\tPS7Time PTime;\n\tpbyte PStatus;\n\n\tSZL.Answer.Header.DataLen=SwapWord(sizeof(SZL_ID_0424_IDX_XXXX));\n\tSZL.ResParams->Err  =0x0000;\n\tPTime=PS7Time(pbyte(SZL.ResData)+24);\n\tPStatus =pbyte(SZL.ResData)+15;\n\tmemcpy(SZL.ResData,&SZL_ID_0424_IDX_XXXX,sizeof(SZL_ID_0424_IDX_XXXX));\n\tFillTime(PTime);\n\t*PStatus=FServer->CpuStatus;\n\tSZL.SZLDone=true;\n\tisoSendBuffer(&SZL.Answer,22+sizeof(SZL_ID_0424_IDX_XXXX));\n}\n\nvoid TS7Worker::SZL_ID131_IDX003()\n{\n\tword len = sizeof(SZL_ID_0131_IDX_0003);\n\tSZL.Answer.Header.DataLen=SwapWord(len);\n\tSZL.ResParams->Err  =0x0000;\n\tSZL.ResParams->resvd=0x0000; // this is the end, no more packets\n\tmemcpy(SZL.ResData, &SZL_ID_0131_IDX_0003, len);\n    // Set the max consistent data window to PDU size\n\tSZL.ResData[18]=((FPDULength)>>8) & 0xFF;\n\tSZL.ResData[19]=(FPDULength) & 0xFF;\n\n\tisoSendBuffer(&SZL.Answer,22+len);\n\tSZL.SZLDone=true;\n}\n\nbool TS7Worker::PerformGroupSZL()\n{\n  SZL.SZLDone=false;\n  // Setup pointers\n  SZL.ReqParams=PReqFunReadSZLFirst(pbyte(PDUH_in)+ReqHeaderSize);\n  SZL.ResParams=PS7ResParams7(pbyte(&SZL.Answer)+ResHeaderSize17);\n  SZL.ResData  =pbyte(&SZL.Answer)+ResHeaderSize17+sizeof(TS7Params7);\n  // Prepare Answer header\n  SZL.Answer.Header.P=0x32;\n  SZL.Answer.Header.PDUType=PduType_userdata;\n  SZL.Answer.Header.AB_EX=0x0000;\n  SZL.Answer.Header.Sequence=PDUH_in->Sequence;\n  SZL.Answer.Header.ParLen =SwapWord(sizeof(TS7Params7));\n\n  SZL.ResParams->Head[0]=SZL.ReqParams->Head[0];\n  SZL.ResParams->Head[1]=SZL.ReqParams->Head[1];\n  SZL.ResParams->Head[2]=SZL.ReqParams->Head[2];\n  SZL.ResParams->Plen  =0x08;\n  SZL.ResParams->Uk    =0x12;\n  SZL.ResParams->Tg    =0x84; // Type response + group szl\n  SZL.ResParams->SubFun=SZL.ReqParams->SubFun;\n  SZL.ResParams->Seq   =SZL.ReqParams->Seq;\n  SZL.ResParams->resvd=0x0000; // this is the end, no more packets\n\n  // only two subfunction are defined : 0x01 read, 0x02 system state\n  if (SZL.ResParams->SubFun==0x02)   // 0x02 = subfunction system state\n  {\n      SZLSystemState();\n      return true;\n  };\n  if (SZL.ResParams->SubFun!=0x01)\n  {\n      SZLNotAvailable();\n      return true;\n  };\n  // From here we assume subfunction = 0x01\n  SZL.ReqData=PS7ReqSZLData(pbyte(PDUH_in)+ReqHeaderSize+sizeof(TReqFunReadSZLFirst));// Data after params\n\n  SZL.ID=SwapWord(SZL.ReqData->ID);\n  SZL.Index=SwapWord(SZL.ReqData->Index);\n\n  // Switch prebuilt Data Bank (they come from a physical CPU)\n  switch (SZL.ID)\n  {\n    case 0x0000 : SZLData(&SZL_ID_0000_IDX_XXXX,sizeof(SZL_ID_0000_IDX_XXXX));break;\n    case 0x0F00 : SZLData(&SZL_ID_0F00_IDX_XXXX,sizeof(SZL_ID_0F00_IDX_XXXX));break;\n    case 0x0002 : SZLData(&SZL_ID_0002_IDX_XXXX,sizeof(SZL_ID_0002_IDX_XXXX));break;\n    case 0x0011 : SZLData(&SZL_ID_0011_IDX_XXXX,sizeof(SZL_ID_0011_IDX_XXXX));break;\n    case 0x0012 : SZLData(&SZL_ID_0012_IDX_XXXX,sizeof(SZL_ID_0012_IDX_XXXX));break;\n    case 0x0013 : SZLData(&SZL_ID_0013_IDX_XXXX,sizeof(SZL_ID_0013_IDX_XXXX));break;\n    case 0x0014 : SZLData(&SZL_ID_0014_IDX_XXXX,sizeof(SZL_ID_0014_IDX_XXXX));break;\n    case 0x0015 : SZLData(&SZL_ID_0015_IDX_XXXX,sizeof(SZL_ID_0015_IDX_XXXX));break;\n    case 0x0F14 : SZLData(&SZL_ID_0F14_IDX_XXXX,sizeof(SZL_ID_0F14_IDX_XXXX));break;\n    case 0x0019 : SZLData(&SZL_ID_0019_IDX_XXXX,sizeof(SZL_ID_0019_IDX_XXXX));break;\n    case 0x0F19 : SZLData(&SZL_ID_0F19_IDX_XXXX,sizeof(SZL_ID_0F19_IDX_XXXX));break;\n    case 0x001C : SZLData(&SZL_ID_001C_IDX_XXXX,sizeof(SZL_ID_001C_IDX_XXXX));break;\n    case 0x0F1C : SZLData(&SZL_ID_0F1C_IDX_XXXX,sizeof(SZL_ID_0F1C_IDX_XXXX));break;\n    case 0x0036 : SZLData(&SZL_ID_0036_IDX_XXXX,sizeof(SZL_ID_0036_IDX_XXXX));break;\n    case 0x0F36 : SZLData(&SZL_ID_0F36_IDX_XXXX,sizeof(SZL_ID_0F36_IDX_XXXX));break;\n    case 0x0025 : SZLData(&SZL_ID_0025_IDX_XXXX,sizeof(SZL_ID_0025_IDX_XXXX));break;\n    case 0x0F25 : SZLData(&SZL_ID_0F25_IDX_XXXX,sizeof(SZL_ID_0F25_IDX_XXXX));break;\n    case 0x0037 : SZLData(&SZL_ID_0037_IDX_XXXX,sizeof(SZL_ID_0037_IDX_XXXX));break;\n    case 0x0F37 : SZLData(&SZL_ID_0F37_IDX_XXXX,sizeof(SZL_ID_0F37_IDX_XXXX));break;\n    case 0x0074 : SZLData(&SZL_ID_0074_IDX_XXXX,sizeof(SZL_ID_0074_IDX_XXXX));break;\n    case 0x0F74 : SZLData(&SZL_ID_0F74_IDX_XXXX,sizeof(SZL_ID_0F74_IDX_XXXX));break;\n    case 0x0591 : SZLData(&SZL_ID_0591_IDX_XXXX,sizeof(SZL_ID_0591_IDX_XXXX));break;\n    case 0x0A91 : SZLData(&SZL_ID_0A91_IDX_XXXX,sizeof(SZL_ID_0A91_IDX_XXXX));break;\n    case 0x0F92 : SZLData(&SZL_ID_0F92_IDX_XXXX,sizeof(SZL_ID_0F92_IDX_XXXX));break;\n    case 0x0294 : SZLData(&SZL_ID_0294_IDX_XXXX,sizeof(SZL_ID_0294_IDX_XXXX));break;\n    case 0x0794 : SZLData(&SZL_ID_0794_IDX_XXXX,sizeof(SZL_ID_0794_IDX_XXXX));break;\n    case 0x0F94 : SZLData(&SZL_ID_0F94_IDX_XXXX,sizeof(SZL_ID_0F94_IDX_XXXX));break;\n    case 0x0095 : SZLData(&SZL_ID_0095_IDX_XXXX,sizeof(SZL_ID_0095_IDX_XXXX));break;\n    case 0x0F95 : SZLData(&SZL_ID_0F95_IDX_XXXX,sizeof(SZL_ID_0F95_IDX_XXXX));break;\n    case 0x00A0 : SZLData(&SZL_ID_00A0_IDX_XXXX,sizeof(SZL_ID_00A0_IDX_XXXX));break;\n    case 0x0FA0 : SZLData(&SZL_ID_0FA0_IDX_XXXX,sizeof(SZL_ID_0FA0_IDX_XXXX));break;\n\tcase 0x0017 : SZLData(&SZL_ID_0017_IDX_XXXX,sizeof(SZL_ID_0017_IDX_XXXX));break;\n    case 0x0F17 : SZLData(&SZL_ID_0F17_IDX_XXXX,sizeof(SZL_ID_0F17_IDX_XXXX));break;\n    case 0x0018 : SZLData(&SZL_ID_0018_IDX_XXXX,sizeof(SZL_ID_0018_IDX_XXXX));break;\n    case 0x0F18 : SZLData(&SZL_ID_0F18_IDX_XXXX,sizeof(SZL_ID_0F18_IDX_XXXX));break;\n    case 0x001A : SZLData(&SZL_ID_001A_IDX_XXXX,sizeof(SZL_ID_001A_IDX_XXXX));break;\n    case 0x0F1A : SZLData(&SZL_ID_0F1A_IDX_XXXX,sizeof(SZL_ID_0F1A_IDX_XXXX));break;\n    case 0x001B : SZLData(&SZL_ID_001B_IDX_XXXX,sizeof(SZL_ID_001B_IDX_XXXX));break;\n    case 0x0F1B : SZLData(&SZL_ID_0F1B_IDX_XXXX,sizeof(SZL_ID_0F1B_IDX_XXXX));break;\n    case 0x0021 : SZLData(&SZL_ID_0021_IDX_XXXX,sizeof(SZL_ID_0021_IDX_XXXX));break;\n    case 0x0A21 : SZLData(&SZL_ID_0A21_IDX_XXXX,sizeof(SZL_ID_0A21_IDX_XXXX));break;\n    case 0x0F21 : SZLData(&SZL_ID_0F21_IDX_XXXX,sizeof(SZL_ID_0F21_IDX_XXXX));break;\n    case 0x0023 : SZLData(&SZL_ID_0023_IDX_XXXX,sizeof(SZL_ID_0023_IDX_XXXX));break;\n    case 0x0F23 : SZLData(&SZL_ID_0F23_IDX_XXXX,sizeof(SZL_ID_0F23_IDX_XXXX));break;\n    case 0x0024 : SZLData(&SZL_ID_0024_IDX_XXXX,sizeof(SZL_ID_0024_IDX_XXXX));break;\n    case 0x0124 : SZLData(&SZL_ID_0124_IDX_XXXX,sizeof(SZL_ID_0124_IDX_XXXX));break;\n    case 0x0424 : SZL_ID424();break;\n    case 0x0038 : SZLData(&SZL_ID_0038_IDX_XXXX,sizeof(SZL_ID_0038_IDX_XXXX));break;\n    case 0x0F38 : SZLData(&SZL_ID_0F38_IDX_XXXX,sizeof(SZL_ID_0F38_IDX_XXXX));break;\n    case 0x003A : SZLData(&SZL_ID_003A_IDX_XXXX,sizeof(SZL_ID_003A_IDX_XXXX));break;\n    case 0x0F3A : SZLData(&SZL_ID_0F3A_IDX_XXXX,sizeof(SZL_ID_0F3A_IDX_XXXX));break;\n    case 0x0F9A : SZLData(&SZL_ID_0F9A_IDX_XXXX,sizeof(SZL_ID_0F9A_IDX_XXXX));break;\n    case 0x0D91 : switch(SZL.Index){\n                    case 0x0000 : SZLData(&SZL_ID_0D91_IDX_0000,sizeof(SZL_ID_0D91_IDX_0000));break;\n                    default: SZLNotAvailable();break;\n                  };\n                  break;\n    case 0x0092 : switch(SZL.Index){\n                    case 0x0000 : SZLData(&SZL_ID_0092_IDX_0000,sizeof(SZL_ID_0092_IDX_0000));break;\n                    default     : SZLNotAvailable();break;\n                  };break;\n    case 0x0292 : switch(SZL.Index){\n                    case 0x0000 : SZLData(&SZL_ID_0292_IDX_0000,sizeof(SZL_ID_0292_IDX_0000));break;\n                    default     : SZLNotAvailable();break;\n                  };break;\n    case 0x0692 : switch(SZL.Index){\n                    case 0x0000 : SZLData(&SZL_ID_0692_IDX_0000,sizeof(SZL_ID_0692_IDX_0000));break;\n                    default     : SZLNotAvailable();break;\n                  };break;\n\tcase 0x0094 : switch(SZL.Index){\n                    case 0x0000 : SZLData(&SZL_ID_0094_IDX_0000,sizeof(SZL_ID_0094_IDX_0000));break;\n                    default     : SZLNotAvailable();break;\n                  };break;\n    case 0x0D97 : switch(SZL.Index){\n                    case 0x0000 : SZLData(&SZL_ID_0D97_IDX_0000,sizeof(SZL_ID_0D97_IDX_0000));break;\n                    default     : SZLNotAvailable();break;\n                  };break;\n    case 0x0111 : switch(SZL.Index){\n                    case 0x0001 : SZLData(&SZL_ID_0111_IDX_0001,sizeof(SZL_ID_0111_IDX_0001));break;\n                    case 0x0006 : SZLData(&SZL_ID_0111_IDX_0006,sizeof(SZL_ID_0111_IDX_0006));break;\n                    case 0x0007 : SZLData(&SZL_ID_0111_IDX_0007,sizeof(SZL_ID_0111_IDX_0007));break;\n                    default     : SZLNotAvailable();break;\n                  };break;\n    case 0x0F11 : switch(SZL.Index){\n                    case 0x0001 : SZLData(&SZL_ID_0F11_IDX_0001,sizeof(SZL_ID_0F11_IDX_0001));break;\n                    case 0x0006 : SZLData(&SZL_ID_0F11_IDX_0006,sizeof(SZL_ID_0F11_IDX_0006));break;\n                    case 0x0007 : SZLData(&SZL_ID_0F11_IDX_0007,sizeof(SZL_ID_0F11_IDX_0007));break;\n                    default     : SZLNotAvailable();break;\n                  };break;\n    case 0x0112 : switch(SZL.Index){\n                    case 0x0000 : SZLData(&SZL_ID_0112_IDX_0000,sizeof(SZL_ID_0112_IDX_0000));break;\n                    case 0x0100 : SZLData(&SZL_ID_0112_IDX_0100,sizeof(SZL_ID_0112_IDX_0100));break;\n                    case 0x0200 : SZLData(&SZL_ID_0112_IDX_0200,sizeof(SZL_ID_0112_IDX_0200));break;\n                    case 0x0400 : SZLData(&SZL_ID_0112_IDX_0400,sizeof(SZL_ID_0112_IDX_0400));break;\n                    default     : SZLNotAvailable();break;\n                  };break;\n    case 0x0F12 : switch(SZL.Index){\n                   case 0x0000 : SZLData(&SZL_ID_0F12_IDX_0000,sizeof(SZL_ID_0F12_IDX_0000));break;\n                   case 0x0100 : SZLData(&SZL_ID_0F12_IDX_0100,sizeof(SZL_ID_0F12_IDX_0100));break;\n                   case 0x0200 : SZLData(&SZL_ID_0F12_IDX_0200,sizeof(SZL_ID_0F12_IDX_0200));break;\n                   case 0x0400 : SZLData(&SZL_ID_0F12_IDX_0400,sizeof(SZL_ID_0F12_IDX_0400));break;\n                   default     : SZLNotAvailable();break;\n                  };break;\n    case 0x0113 : switch(SZL.Index){\n                    case 0x0001 : SZLData(&SZL_ID_0113_IDX_0001,sizeof(SZL_ID_0113_IDX_0001));break;\n                    default     : SZLNotAvailable();break;\n                  };break;\n\tcase 0x0115 : switch(SZL.Index){\n                    case 0x0800 : SZLData(&SZL_ID_0115_IDX_0800,sizeof(SZL_ID_0115_IDX_0800));break;\n                    default     : SZLNotAvailable();break;\n                  };break;\n    case 0x011C : switch(SZL.Index){\n                    case 0x0001 : SZLData(&SZL_ID_011C_IDX_0001,sizeof(SZL_ID_011C_IDX_0001));break;\n                    case 0x0002 : SZLData(&SZL_ID_011C_IDX_0002,sizeof(SZL_ID_011C_IDX_0002));break;\n                    case 0x0003 : SZLData(&SZL_ID_011C_IDX_0003,sizeof(SZL_ID_011C_IDX_0003));break;\n                    case 0x0004 : SZLData(&SZL_ID_011C_IDX_0004,sizeof(SZL_ID_011C_IDX_0004));break;\n                    case 0x0005 : SZLData(&SZL_ID_011C_IDX_0005,sizeof(SZL_ID_011C_IDX_0005));break;\n                    case 0x0007 : SZLData(&SZL_ID_011C_IDX_0007,sizeof(SZL_ID_011C_IDX_0007));break;\n                    case 0x0008 : SZLData(&SZL_ID_011C_IDX_0008,sizeof(SZL_ID_011C_IDX_0008));break;\n                    case 0x0009 : SZLData(&SZL_ID_011C_IDX_0009,sizeof(SZL_ID_011C_IDX_0009));break;\n                    case 0x000A : SZLData(&SZL_ID_011C_IDX_000A,sizeof(SZL_ID_011C_IDX_000A));break;\n                    case 0x000B : SZLData(&SZL_ID_011C_IDX_000B,sizeof(SZL_ID_011C_IDX_000B));break;\n                    default     : SZLNotAvailable();break;\n                  };break;\n    case 0x0222 : switch(SZL.Index){\n                    case 0x0001 : SZLData(&SZL_ID_0222_IDX_0001,sizeof(SZL_ID_0222_IDX_0001));break;\n                    case 0x000A : SZLData(&SZL_ID_0222_IDX_000A,sizeof(SZL_ID_0222_IDX_000A));break;\n                    case 0x0014 : SZLData(&SZL_ID_0222_IDX_0014,sizeof(SZL_ID_0222_IDX_0014));break;\n                    case 0x0028 : SZLData(&SZL_ID_0222_IDX_0028,sizeof(SZL_ID_0222_IDX_0028));break;\n                    case 0x0050 : SZLData(&SZL_ID_0222_IDX_0050,sizeof(SZL_ID_0222_IDX_0050));break;\n                    case 0x0064 : SZLData(&SZL_ID_0222_IDX_0064,sizeof(SZL_ID_0222_IDX_0064));break;\n                    default     : SZLNotAvailable();break;\n                  };break;\n    case 0x0125 : switch(SZL.Index){\n                    case 0x0000 : SZLData(&SZL_ID_0125_IDX_0000,sizeof(SZL_ID_0125_IDX_0000));break;\n                    case 0x0001 : SZLData(&SZL_ID_0125_IDX_0001,sizeof(SZL_ID_0125_IDX_0001));break;\n                    default     : SZLNotAvailable();break;\n                  };break;\n    case 0x0225 : switch(SZL.Index){\n                    case 0x0001 : SZLData(&SZL_ID_0225_IDX_0001,sizeof(SZL_ID_0225_IDX_0001));break;\n                    default     : SZLNotAvailable();break;\n                  };break;\n    case 0x0131 : switch(SZL.Index){\n\t\t\t\t\tcase 0x0001 : SZLData(&SZL_ID_0131_IDX_0001,sizeof(SZL_ID_0131_IDX_0001));break;\n\t\t\t\t\tcase 0x0002 : SZLData(&SZL_ID_0131_IDX_0002,sizeof(SZL_ID_0131_IDX_0002));break;\n\t\t\t\t\tcase 0x0003 : SZL_ID131_IDX003();break;\n                    case 0x0004 : SZLData(&SZL_ID_0131_IDX_0004,sizeof(SZL_ID_0131_IDX_0004));break;\n                    case 0x0005 : SZLData(&SZL_ID_0131_IDX_0005,sizeof(SZL_ID_0131_IDX_0005));break;\n                    case 0x0006 : SZLData(&SZL_ID_0131_IDX_0006,sizeof(SZL_ID_0131_IDX_0006));break;\n                    case 0x0007 : SZLData(&SZL_ID_0131_IDX_0007,sizeof(SZL_ID_0131_IDX_0007));break;\n                    case 0x0008 : SZLData(&SZL_ID_0131_IDX_0008,sizeof(SZL_ID_0131_IDX_0008));break;\n                    case 0x0009 : SZLData(&SZL_ID_0131_IDX_0009,sizeof(SZL_ID_0131_IDX_0009));break;\n                    default     : SZLNotAvailable();break;\n                  };break;\n    case 0x0117 : switch(SZL.Index){\n                     case 0x0000 : SZLData(&SZL_ID_0117_IDX_0000,sizeof(SZL_ID_0117_IDX_0000));break;\n                     case 0x0001 : SZLData(&SZL_ID_0117_IDX_0001,sizeof(SZL_ID_0117_IDX_0001));break;\n                     case 0x0002 : SZLData(&SZL_ID_0117_IDX_0002,sizeof(SZL_ID_0117_IDX_0002));break;\n                     case 0x0003 : SZLData(&SZL_ID_0117_IDX_0003,sizeof(SZL_ID_0117_IDX_0003));break;\n                     case 0x0004 : SZLData(&SZL_ID_0117_IDX_0004,sizeof(SZL_ID_0117_IDX_0004));break;\n                     default     : SZLNotAvailable();break;\n                   };break;\n    case 0x0118 : switch(SZL.Index){\n                     case 0x0000 : SZLData(&SZL_ID_0118_IDX_0000,sizeof(SZL_ID_0118_IDX_0000));break;\n                     case 0x0001 : SZLData(&SZL_ID_0118_IDX_0001,sizeof(SZL_ID_0118_IDX_0001));break;\n                     case 0x0002 : SZLData(&SZL_ID_0118_IDX_0002,sizeof(SZL_ID_0118_IDX_0002));break;\n                     case 0x0003 : SZLData(&SZL_ID_0118_IDX_0003,sizeof(SZL_ID_0118_IDX_0003));break;\n                     default     : SZLNotAvailable();break;\n                   };break;\n    case 0x0132 : switch(SZL.Index){\n                     case 0x0001 : SZLData(&SZL_ID_0132_IDX_0001,sizeof(SZL_ID_0132_IDX_0001));break;\n                     case 0x0002 : SZLData(&SZL_ID_0132_IDX_0002,sizeof(SZL_ID_0132_IDX_0002));break;\n                     case 0x0003 : SZLData(&SZL_ID_0132_IDX_0003,sizeof(SZL_ID_0132_IDX_0003));break;\n                     case 0x0004 : SZLData(&SZL_ID_0132_IDX_0004,sizeof(SZL_ID_0132_IDX_0004));break;\n                     case 0x0005 : SZLData(&SZL_ID_0132_IDX_0005,sizeof(SZL_ID_0132_IDX_0005));break;\n                     case 0x0006 : SZLData(&SZL_ID_0132_IDX_0006,sizeof(SZL_ID_0132_IDX_0006));break;\n                     case 0x0007 : SZLData(&SZL_ID_0132_IDX_0007,sizeof(SZL_ID_0132_IDX_0007));break;\n                     case 0x0008 : SZLData(&SZL_ID_0132_IDX_0008,sizeof(SZL_ID_0132_IDX_0008));break;\n                     case 0x0009 : SZLData(&SZL_ID_0132_IDX_0009,sizeof(SZL_ID_0132_IDX_0009));break;\n                     case 0x000A : SZLData(&SZL_ID_0132_IDX_000A,sizeof(SZL_ID_0132_IDX_000A));break;\n                     case 0x000B : SZLData(&SZL_ID_0132_IDX_000B,sizeof(SZL_ID_0132_IDX_000B));break;\n                     case 0x000C : SZLData(&SZL_ID_0132_IDX_000C,sizeof(SZL_ID_0132_IDX_000C));break;\n                     default     : SZLNotAvailable();break;\n                   };break;\n    case 0x0137 : switch(SZL.Index){\n                    case 0x07FE : SZLData(&SZL_ID_0137_IDX_07FE,sizeof(SZL_ID_0137_IDX_07FE));break;\n                    default     : SZLNotAvailable();break;\n                  };break;\n    case 0x01A0 : switch(SZL.Index){\n                     case 0x0000 : SZLData(&SZL_ID_01A0_IDX_0000,sizeof(SZL_ID_01A0_IDX_0000));break;\n                     case 0x0001 : SZLData(&SZL_ID_01A0_IDX_0001,sizeof(SZL_ID_01A0_IDX_0001));break;\n                     case 0x0002 : SZLData(&SZL_ID_01A0_IDX_0002,sizeof(SZL_ID_01A0_IDX_0002));break;\n                     case 0x0003 : SZLData(&SZL_ID_01A0_IDX_0003,sizeof(SZL_ID_01A0_IDX_0003));break;\n                     case 0x0004 : SZLData(&SZL_ID_01A0_IDX_0004,sizeof(SZL_ID_01A0_IDX_0004));break;\n                     case 0x0005 : SZLData(&SZL_ID_01A0_IDX_0005,sizeof(SZL_ID_01A0_IDX_0005));break;\n                     case 0x0006 : SZLData(&SZL_ID_01A0_IDX_0006,sizeof(SZL_ID_01A0_IDX_0006));break;\n                     case 0x0007 : SZLData(&SZL_ID_01A0_IDX_0007,sizeof(SZL_ID_01A0_IDX_0007));break;\n                     case 0x0008 : SZLData(&SZL_ID_01A0_IDX_0008,sizeof(SZL_ID_01A0_IDX_0008));break;\n                     case 0x0009 : SZLData(&SZL_ID_01A0_IDX_0009,sizeof(SZL_ID_01A0_IDX_0009));break;\n                     case 0x000A : SZLData(&SZL_ID_01A0_IDX_000A,sizeof(SZL_ID_01A0_IDX_000A));break;\n                     case 0x000B : SZLData(&SZL_ID_01A0_IDX_000B,sizeof(SZL_ID_01A0_IDX_000B));break;\n                     case 0x000C : SZLData(&SZL_ID_01A0_IDX_000C,sizeof(SZL_ID_01A0_IDX_000C));break;\n                     case 0x000D : SZLData(&SZL_ID_01A0_IDX_000D,sizeof(SZL_ID_01A0_IDX_000D));break;\n                     case 0x000E : SZLData(&SZL_ID_01A0_IDX_000E,sizeof(SZL_ID_01A0_IDX_000E));break;\n                     case 0x000F : SZLData(&SZL_ID_01A0_IDX_000F,sizeof(SZL_ID_01A0_IDX_000F));break;\n                     case 0x0010 : SZLData(&SZL_ID_01A0_IDX_0010,sizeof(SZL_ID_01A0_IDX_0010));break;\n                     case 0x0011 : SZLData(&SZL_ID_01A0_IDX_0011,sizeof(SZL_ID_01A0_IDX_0011));break;\n                     case 0x0012 : SZLData(&SZL_ID_01A0_IDX_0012,sizeof(SZL_ID_01A0_IDX_0012));break;\n                     case 0x0013 : SZLData(&SZL_ID_01A0_IDX_0013,sizeof(SZL_ID_01A0_IDX_0013));break;\n                     case 0x0014 : SZLData(&SZL_ID_01A0_IDX_0014,sizeof(SZL_ID_01A0_IDX_0014));break;\n                     case 0x0015 : SZLData(&SZL_ID_01A0_IDX_0015,sizeof(SZL_ID_01A0_IDX_0015));break;\n                     default     : SZLNotAvailable();break;\n                   };break;\n    case 0x0174 : switch(SZL.Index){\n                    case 0x0001 : SZLData(&SZL_ID_0174_IDX_0001,sizeof(SZL_ID_0174_IDX_0001));break;\n                    case 0x0004 : SZLData(&SZL_ID_0174_IDX_0004,sizeof(SZL_ID_0174_IDX_0004));break;\n                    case 0x0005 : SZLData(&SZL_ID_0174_IDX_0005,sizeof(SZL_ID_0174_IDX_0005));break;\n                    case 0x0006 : SZLData(&SZL_ID_0174_IDX_0006,sizeof(SZL_ID_0174_IDX_0006));break;\n                    case 0x000B : SZLData(&SZL_ID_0174_IDX_000B,sizeof(SZL_ID_0174_IDX_000B));break;\n                    case 0x000C : SZLData(&SZL_ID_0174_IDX_000C,sizeof(SZL_ID_0174_IDX_000C));break;\n                    default     : SZLNotAvailable();break;\n                  };break;\n    case 0x0194 : switch(SZL.Index){\n                    case 0x0064 : SZLData(&SZL_ID_0194_IDX_0064,sizeof(SZL_ID_0194_IDX_0064));break;\n                    default     : SZLNotAvailable();break;\n                  };break;\n    case 0x0694 : switch(SZL.Index){\n                    case 0x0064 : SZLData(&SZL_ID_0694_IDX_0064,sizeof(SZL_ID_0694_IDX_0064));break;\n                    default     : SZLNotAvailable();break;\n                  };break;\n    case 0x0232 : switch(SZL.Index){\n                     case 0x0001 : SZLData(&SZL_ID_0232_IDX_0001,sizeof(SZL_ID_0232_IDX_0001));break;\n                     case 0x0004 : SZLData(&SZL_ID_0232_IDX_0004,sizeof(SZL_ID_0232_IDX_0004));break;\n                     default     : SZLNotAvailable();break;\n                   };break;\n    case 0x0C91 : switch(SZL.Index){\n                    case 0x07FE : SZLData(&SZL_ID_0C91_IDX_07FE,sizeof(SZL_ID_0C91_IDX_07FE));break;\n                    default     : SZLNotAvailable();break;\n                  };break;\n    default : SZLNotAvailable();break;\n  }\n  // Event\n  if (SZL.SZLDone)\n      DoEvent(evcReadSZL,evrNoError,SZL.ID,SZL.Index,0,0);\n  else\n      DoEvent(evcReadSZL,evrInvalidSZL,SZL.ID,SZL.Index,0,0);\n  return true;\n}\n//------------------------------------------------------------------------------\nbool TS7Worker::PerformGroupSecurity()\n{\n    PReqFunSecurity ReqParams;\n    PResParamsSecurity ResParams;\n    PResDataSecurity ResData;\n    TS7Answer17 Answer;\n    int TotalSize;\n\n    ReqParams=PReqFunSecurity(pbyte(PDUH_in)+ReqHeaderSize);\n    ResParams=PResParamsSecurity(pbyte(&Answer)+ResHeaderSize17);\n    ResData  =PResDataSecurity(pbyte(ResParams)+sizeof(TResParamsSecurity));\n\n    // Prepares the answer\n    Answer.Header.P=0x32;\n    Answer.Header.PDUType=PduType_userdata;\n    Answer.Header.AB_EX=0x0000;\n    Answer.Header.Sequence=PDUH_in->Sequence;\n    Answer.Header.ParLen =SwapWord(sizeof(TResParamsSecurity));\n    Answer.Header.DataLen=SwapWord(0x0004);\n    // Params\n    ResParams->Head[0]=ReqParams->Head[0];\n    ResParams->Head[1]=ReqParams->Head[1];\n    ResParams->Head[2]=ReqParams->Head[2];\n    ResParams->Plen  =0x08;\n    ResParams->Uk    =0x12;\n    ResParams->Tg    =0x85; // Type response, group functions info\n    ResParams->SubFun=ReqParams->SubFun;\n    ResParams->Seq   =ReqParams->Seq;\n    ResParams->resvd =0x0000;\n    ResParams->Err   =0x0000;\n    // Data\n    ResData->Ret =0x0A;\n    ResData->TS  =0x00;\n    ResData->DLen=0x0000;\n\n    TotalSize=26;\n    isoSendBuffer(&Answer,TotalSize);\n\n    switch (ReqParams->SubFun)\n    {\n      case SFun_EnterPwd  : DoEvent(evcSecurity,evrNoError,evsSetPassword,0,0,0); break;\n      case SFun_CancelPwd : DoEvent(evcSecurity,evrNoError,evsClrPassword,0,0,0); break;\n      default             : DoEvent(evcSecurity,evrNoError,evsUnknown,0,0,0);\n    };\n\n    return true;\n}\n//------------------------------------------------------------------------------\nbool TS7Worker::PerformGetClock()\n{\n    PS7ReqParams7 ReqParams;\n    PS7ResParams7 ResParams;\n    TS7Answer17 Answer;\n    PResDataGetTime Data;\n    PS7Time PTime;\n    int TotalSize;\n\n    ReqParams=PS7ReqParams7(pbyte(PDUH_in)+ReqHeaderSize);\n    ResParams=PS7ResParams7(pbyte(&Answer)+ResHeaderSize17);\n    Data     =PResDataGetTime(pbyte(&Answer)+ResHeaderSize17+sizeof(TS7Params7));\n    PTime    =PS7Time(pbyte(Data)+6);\n\n    // Prepares the answer\n    Answer.Header.P=0x32;\n    Answer.Header.PDUType=PduType_userdata;\n    Answer.Header.AB_EX=0x0000;\n    Answer.Header.Sequence=PDUH_in->Sequence;\n    Answer.Header.ParLen =SwapWord(sizeof(TS7Params7));\n    Answer.Header.DataLen=SwapWord(sizeof(TResDataGetTime));\n\n    ResParams->Head[0]=ReqParams->Head[0];\n    ResParams->Head[1]=ReqParams->Head[1];\n    ResParams->Head[2]=ReqParams->Head[2];\n    ResParams->Plen  =0x08;\n    ResParams->Uk    =0x12;\n    ResParams->Tg    =0x87; // Type response, group functions info\n    ResParams->SubFun=ReqParams->SubFun;\n    ResParams->Seq   =ReqParams->Seq;\n    ResParams->resvd =0x0000;\n    ResParams->Err   =0x0000;\n\n    Data->RetVal     =0xFF;\n    Data->TSize      =TS_ResOctet;\n    Data->Length     =SwapWord(10);\n    Data->Rsvd       =0x00;\n    Data->HiYear     =0x20; // Year 2000 +\n    FillTime(PTime);\n\n    TotalSize=36;\n    isoSendBuffer(&Answer,TotalSize);\n    DoEvent(evcClock,evrNoError,evsGetClock,0,0,0);\n    return true;\n}\n//------------------------------------------------------------------------------\nbool TS7Worker::PerformSetClock()\n{\n    PS7ReqParams7 ReqParams;\n    PS7ResParams7 ResParams;\n    PResDataSetTime Data;\n    TS7Answer17 Answer;\n    int TotalSize;\n\n    ReqParams=PS7ReqParams7(pbyte(PDUH_in)+ReqHeaderSize);\n    ResParams=PS7ResParams7(pbyte(&Answer)+ResHeaderSize17);\n    Data     =PResDataSetTime(pbyte(&Answer)+ResHeaderSize17+sizeof(TS7Params7));\n\n    // Prepares the answer\n    Answer.Header.P=0x32;\n    Answer.Header.PDUType=PduType_userdata;\n    Answer.Header.AB_EX=0x0000;\n    Answer.Header.Sequence=PDUH_in->Sequence;\n    Answer.Header.ParLen =SwapWord(sizeof(TS7Params7));\n    Answer.Header.DataLen=SwapWord(sizeof(TResDataSetTime));\n\n    ResParams->Head[0]=ReqParams->Head[0];\n    ResParams->Head[1]=ReqParams->Head[1];\n    ResParams->Head[2]=ReqParams->Head[2];\n    ResParams->Plen  =0x08;\n    ResParams->Uk    =0x12;\n    ResParams->Tg    =0x87; // Type response, group functions info\n    ResParams->SubFun=ReqParams->SubFun;\n    ResParams->Seq   =ReqParams->Seq;\n    ResParams->resvd =0x0000;\n    ResParams->Err   =0x0000;\n\n    Data->RetVal     =0x0A;\n    Data->TSize      =0x00;\n    Data->Length     =0x0000;\n\n    TotalSize=26;\n    isoSendBuffer(&Answer,TotalSize);\n    DoEvent(evcClock,evrNoError,evsSetClock,0,0,0);\n    return true;\n}\n//------------------------------------------------------------------------------\n// S7 SERVER CLASS\n//------------------------------------------------------------------------------\nTSnap7Server::TSnap7Server()\n{\n\tCSRWHook = new TSnapCriticalSection();\n\tOnReadEvent=NULL;\n\tmemset(&DB,0,sizeof(DB));\n    memset(&HA,0,sizeof(HA));\n    DBCount=0;\n    DBLimit=0;\n\tForcePDU = 0;\n\tResourceLess = false;\n    LocalPort=isoTcpPort;\n    CpuStatus=S7CpuStatusRun;\n    WorkInterval=100;\n}\n//------------------------------------------------------------------------------\nTSnap7Server::~TSnap7Server()\n{\n    DisposeAll();\n\tdelete CSRWHook;\n}\n//------------------------------------------------------------------------------\nPWorkerSocket TSnap7Server::CreateWorkerSocket(socket_t Sock)\n{\n    PWorkerSocket Result;\n    Result = new TS7Worker();\n    Result->SetSocket(Sock);\n    PS7Worker(Result)->FServer=this;\n    return Result;\n}\n//------------------------------------------------------------------------------\nPS7Area TSnap7Server::FindDB(word DBNumber)\n{\n    int c;\n    int max=DBLimit+1;\n\n    for (c=0; c<max; c++)\n    {\n        if (DB[c]!=NULL)\n        {\n\t        if (DB[c]->Number==DBNumber)\n\t        {\n                return DB[c];\n\t        }\n\t    }\n    }\n    return NULL;\n}\n//------------------------------------------------------------------------------\nint TSnap7Server::IndexOfDB(word DBNumber)\n{\n    int c;\n    int max=DBLimit+1;\n\n    for (c=0; c<max; c++)\n    {\n\t\tif (DB[c]!=NULL)\n\t\t{\n\t\t\tif (DB[c]->Number==DBNumber)\n\t\t\t{\n\t\t\t\treturn c;\n\t\t\t}\n\t\t}\n    }\n    return -1;\n}\n//------------------------------------------------------------------------------\nint TSnap7Server::FindFirstFreeDB()\n{\n    int c;\n    for (c=0; c < MaxDB; c++)\n    {\n        if (DB[c]==NULL)\n\t        return c;\n    }\n    return -1;\n}\n//------------------------------------------------------------------------------\nint TSnap7Server::RegisterDB(word Number, void *pUsrData, word Size)\n{\n    PS7Area TheArea;\n    int index;\n\n    if (pUsrData==0)\n        return errSrvDBNullPointer;\n\n    if (FindDB(Number)!=NULL)\n        return errSrvAreaAlreadyExists;\n\n    index=FindFirstFreeDB();\n    if (index==-1)\n        return errSrvTooManyDB;\n\n    TheArea =new TS7Area;\n    TheArea->Number=Number;\n    TheArea->cs=new TSnapCriticalSection();\n    TheArea->PData=pbyte(pUsrData);\n    TheArea->Size=Size;\n    DB[index]=TheArea;\n    DBCount++;\n    if (DBLimit<index)\n        DBLimit=index;\n    return 0;\n}\n//------------------------------------------------------------------------------\nvoid TSnap7Server::DisposeAll()\n{\n    PS7Area TheDB;\n    int c;\n    // Unregister DBs\n    for (c = 0; c < MaxDB; c++)\n    {\n\t\tif (DB[c]!=NULL)\n\t\t{\n\t\t\t// Unregister should be done with the server in stop mode\n\t\t\t// however we can minimize the risk...\n\t\t\tTheDB=DB[c];\n\t\t\tDB[c]=NULL;\n\t\t\tif (TheDB->cs!=0)\n\t\t\t\t\tdelete TheDB->cs;\n\t\t\tdelete TheDB;\n\t\t}\n    }\n    DBCount=0;\n    // Unregister other\n    for (c = srvAreaPE; c < srvAreaDB; c++)\n        UnregisterSys(c);\n}\n//------------------------------------------------------------------------------\nint TSnap7Server::RegisterSys(int AreaCode, void *pUsrData, word Size)\n{\n    PS7Area TheArea;\n\n    if (pUsrData==0)\n        return errSrvDBNullPointer;\n\n    if ((AreaCode<srvAreaPE) || (AreaCode>srvAreaTM))\n        return errSrvUnknownArea;\n\n    if (HA[AreaCode]==0)\n    {\n\tTheArea=new TS7Area;\n\tTheArea->cs=new TSnapCriticalSection();\n\tTheArea->PData=pbyte(pUsrData);\n\tTheArea->Size=Size;\n\tHA[AreaCode]=TheArea;\n\treturn 0;\n    }\n    else\n        return errSrvAreaAlreadyExists;\n}\n//------------------------------------------------------------------------------\nint TSnap7Server::UnregisterDB(word DBNumber)\n{\n    PS7Area TheDB;\n    int index = IndexOfDB(DBNumber);\n    if (index==-1)\n        return errSrvInvalidParams;\n\n    // Unregister should be done with the server in stop mode\n    // however we can minimize the risk...\n    TheDB=DB[index];\n    DB[index]=NULL;\n    if (TheDB->cs!=NULL)\n        delete TheDB->cs;\n    delete TheDB;\n    DBCount--;\n\n    return 0;\n}\n//------------------------------------------------------------------------------\nint TSnap7Server::UnregisterSys(int AreaCode)\n{\n    PS7Area TheArea;\n    if (HA[AreaCode]!=NULL)\n    {\n\t\t// Unregister should be done with the server in stop mode\n\t\t// however we can minimize the risk...\n\t\tTheArea=HA[AreaCode];\n\t\tHA[AreaCode]=NULL;\n\t\tif (TheArea->cs!=NULL)\n\t\t\t delete TheArea->cs;\n\t\tdelete TheArea;\n    }\n    return 0;\n}\n//------------------------------------------------------------------------------\nint TSnap7Server::StartTo(const char *Address)\n{\n    return TCustomMsgServer::StartTo(Address, LocalPort);\n}\n//------------------------------------------------------------------------------\nint TSnap7Server::GetParam(int ParamNumber, void *pValue)\n{\n    switch (ParamNumber)\n    {\n\tcase p_u16_LocalPort:\n            *Puint16_t(pValue)=LocalPort;\n\t    break;\n\tcase p_i32_WorkInterval:\n\t    *Pint32_t(pValue)=WorkInterval;\n\t    break;\n\tcase p_i32_MaxClients:\n\t    *Pint32_t(pValue)=MaxClients;\n\t    break;\n\tcase p_i32_PDURequest:\n\t\t*Pint32_t(pValue) = ForcePDU;\n\t\tbreak;\n\tdefault: return errSrvInvalidParamNumber;\n    }\n    return 0;\n}\n//------------------------------------------------------------------------------\nint TSnap7Server::SetParam(int ParamNumber, void *pValue)\n{\n\tswitch (ParamNumber)\n\t{\n\tcase p_u16_LocalPort:\n\t\tif (Status == SrvStopped)\n\t\t\tLocalPort = *Puint16_t(pValue);\n\t\telse\n\t\t\treturn errSrvCannotChangeParam;\n\t\tbreak;\n\tcase p_i32_PDURequest:\n\t\tif (Status == SrvStopped)\n\t\t{\n\t\t\tint PDU = *Pint32_t(pValue);\n\t\t\tif (PDU == 0)\n\t\t\t\tForcePDU = 0; // ForcePDU=0 --> The server accepts the client's proposal\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif ((PDU < MinPduSize) || (PDU>IsoPayload_Size))\n\t\t\t\t\t\treturn errSrvInvalidParams; // Wrong value\n\t\t\t\t\telse\n\t\t\t\t\t\tForcePDU = PDU; // The server imposes ForcePDU as PDU size\n\t\t\t\t}\n\t    }\n\t\telse\n            return errSrvCannotChangeParam;\n\t\tbreak;\n\tcase p_i32_WorkInterval:\n         WorkInterval=*Pint32_t(pValue);\n\t     break;\n\tcase p_i32_MaxClients:\n\t     if (ClientsCount==0 && Status==SrvStopped)\n\t         MaxClients=*Pint32_t(pValue);\n         else\n\t         return errSrvCannotChangeParam;\n         break;\n\tdefault: return errSrvInvalidParamNumber;\n    }\n    return 0;\n}\n//------------------------------------------------------------------------------\nint TSnap7Server::RegisterArea(int AreaCode, word Index, void *pUsrData, word Size)\n{\n    if (AreaCode==srvAreaDB)\n        return RegisterDB(Index, pUsrData, Size);\n    else\n        return RegisterSys(AreaCode,pUsrData, Size);\n}\n//------------------------------------------------------------------------------\nint TSnap7Server::UnregisterArea(int AreaCode, word Index)\n{\n    if (AreaCode==srvAreaDB)\n        return UnregisterDB(Index);\n    else\n        if ((AreaCode>=srvAreaPE) && (AreaCode<=srvAreaTM))\n            return UnregisterSys(AreaCode);\n\telse\n        return errSrvInvalidParams;\n}\n//------------------------------------------------------------------------------\nint TSnap7Server::LockArea(int AreaCode, word DBNumber)\n{\n  int index;\n\n  if ((AreaCode>=srvAreaPE) && (AreaCode<=srvAreaTM))\n  {\n      if (HA[AreaCode]!=0)\n      {\n\t\t  HA[AreaCode]->cs->Enter();\n\t\t  return 0;\n      }\n      else\n\t\t  return errSrvInvalidParams;\n  }\n  else\n      if (AreaCode==srvAreaDB)\n      {\n\t\t  index=IndexOfDB(DBNumber);\n\t\t  if (index!=-1)\n\t  {\n\t      DB[index]->cs->Enter();\n\t      return 0;\n\t  }\n\t  else\n\t      return errSrvInvalidParams;\n      }\n      else\n\t\t  return errSrvInvalidParams;\n}\n//------------------------------------------------------------------------------\nint TSnap7Server::UnlockArea(int AreaCode, word DBNumber)\n{\n  int index;\n\n  if ((AreaCode>=srvAreaPE) && (AreaCode<=srvAreaTM))\n  {\n      if (HA[AreaCode]!=0)\n      {\n\t\t  HA[AreaCode]->cs->Leave();\n\t\t  return 0;\n      }\n      else\n\t\t  return errSrvInvalidParams;\n  }\n  else\n      if (AreaCode==srvAreaDB)\n      {\n\t\t  index=IndexOfDB(DBNumber);\n\t\t  if (index!=-1)\n\t  {\n\t      DB[index]->cs->Leave();\n\t      return 0;\n\t  }\n\t  else\n\t      return errSrvInvalidParams;\n      }\n      else\n\t\t  return errSrvInvalidParams;\n}\n//------------------------------------------------------------------------------\nint TSnap7Server::SetReadEventsCallBack(pfn_SrvCallBack PCallBack, void *UsrPtr) \n{\n    OnReadEvent = PCallBack;\n    FReadUsrPtr = UsrPtr;\n    return 0;\n}\n//---------------------------------------------------------------------------\nint TSnap7Server::SetRWAreaCallBack(pfn_RWAreaCallBack PCallBack, void *UsrPtr)\n{\n\tOnRWArea = PCallBack;\n\tFRWAreaUsrPtr = UsrPtr;\n\tResourceLess = OnRWArea != NULL;\n\treturn 0;\n}\n//---------------------------------------------------------------------------\nvoid TSnap7Server::DoReadEvent(int Sender, longword Code, word RetCode, word Param1,\n  word Param2, word Param3, word Param4)\n{\n    TSrvEvent SrvReadEvent;\n    if (!Destroying && (OnReadEvent != NULL))\n    {\n        CSEvent->Enter();\n\n        time(&SrvReadEvent.EvtTime);\n        SrvReadEvent.EvtSender = Sender;\n        SrvReadEvent.EvtCode = Code;\n        SrvReadEvent.EvtRetCode = RetCode;\n        SrvReadEvent.EvtParam1 = Param1;\n        SrvReadEvent.EvtParam2 = Param2;\n        SrvReadEvent.EvtParam3 = Param3;\n        SrvReadEvent.EvtParam4 = Param4;\n\n        try\n        { // callback is outside here, we have to shield it\n            OnReadEvent(FReadUsrPtr, &SrvReadEvent, sizeof (TSrvEvent));\n        } catch (...)\n        {\n        };\n        CSEvent->Leave();\n    };\n}\n//---------------------------------------------------------------------------\nbool TSnap7Server::DoReadArea(int Sender, int Area, int DBNumber, int Start, int Size, int WordLen, void *pUsrData)\n{\n\tTS7Tag Tag;\n\tbool Result = false;\n\tif (!Destroying && (OnRWArea != NULL))\n\t{\n\t\tCSRWHook->Enter();\n\t\ttry\n\t\t{ \n\t\t\tTag.Area = Area;\n\t\t\tTag.DBNumber = DBNumber;\n\t\t\tTag.Start = Start;\n\t\t\tTag.Size = Size;\n\t\t\tTag.WordLen = WordLen;\n\t\t\t// callback is outside here, we have to shield it\n\t\t\tResult = OnRWArea(FRWAreaUsrPtr, Sender, OperationRead, &Tag, pUsrData) == 0;\n\t\t}\n\t\tcatch (...)\n\t\t{\n\t\t\tResult = false;\n\t\t};\n\t\tCSRWHook->Leave();\n\t}\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nbool TSnap7Server::DoWriteArea(int Sender, int Area, int DBNumber, int Start, int Size, int WordLen, void *pUsrData)\n{\n\tTS7Tag Tag;\n\tbool Result = false;\n\tif (!Destroying && (OnRWArea != NULL))\n\t{\n\t\tCSRWHook->Enter();\n\t\ttry\n\t\t{ \n\t\t\tTag.Area = Area;\n\t\t\tTag.DBNumber = DBNumber;\n\t\t\tTag.Start = Start;\n\t\t\tTag.Size = Size;\n\t\t\tTag.WordLen = WordLen;\n\t\t\t// callback is outside here, we have to shield it\n\t\t\tResult = OnRWArea(FRWAreaUsrPtr, Sender, OperationWrite, &Tag, pUsrData) == 0;\n\t\t}\n\t\tcatch (...)\n\t\t{\n\t\t\tResult = false;\n\t\t};\n\t\tCSRWHook->Leave();\n\t}\n\treturn Result;\n}\n\n\n"
  },
  {
    "path": "deps/snap7/src/core/s7_server.h",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.3.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|=============================================================================*/\n#ifndef s7_server_h\n#define s7_server_h\n//---------------------------------------------------------------------------\n#include \"snap_tcpsrvr.h\"\n#include \"s7_types.h\"\n#include \"s7_isotcp.h\"\n//---------------------------------------------------------------------------\n\n// Maximum number of DB, change it to increase/decrease the limit.\n// The DB table size is 12*MaxDB bytes\n\n#define MaxDB 2048    // Like a S7 318\n#define MinPduSize 240\n#define CPU315PduSize 240\n//---------------------------------------------------------------------------\n// Server Interface errors\nconst longword errSrvDBNullPointer      = 0x00200000; // Pssed null as PData\nconst longword errSrvAreaAlreadyExists  = 0x00300000; // Area Re-registration\nconst longword errSrvUnknownArea        = 0x00400000; // Unknown area\nconst longword errSrvInvalidParams      = 0x00500000; // Invalid param(s) supplied\nconst longword errSrvTooManyDB          = 0x00600000; // Cannot register DB\nconst longword errSrvInvalidParamNumber = 0x00700000; // Invalid param (srv_get/set_param)\nconst longword errSrvCannotChangeParam  = 0x00800000; // Cannot change because running\n\n// Server Area ID  (use with Register/unregister - Lock/unlock Area)\nconst int srvAreaPE = 0;\nconst int srvAreaPA = 1;\nconst int srvAreaMK = 2;\nconst int srvAreaCT = 3;\nconst int srvAreaTM = 4;\nconst int srvAreaDB = 5;\n\ntypedef struct{\n\tword   Number; // Number (only for DB)\n\tword   Size;   // Area size (in bytes)\n\tpbyte  PData;  // Pointer to area\n\tPSnapCriticalSection cs;\n}TS7Area, *PS7Area;\n\n//------------------------------------------------------------------------------\n// ISOTCP WORKER CLASS\n//------------------------------------------------------------------------------\nclass TIsoTcpWorker : public TIsoTcpSocket\n{\nprotected:\n\tvirtual bool IsoPerformCommand(int &Size);\n\tvirtual bool ExecuteSend();\n\tvirtual bool ExecuteRecv();\npublic:\n\tTIsoTcpWorker(){};\n\t~TIsoTcpWorker(){};\n\t// Worker execution\n\tbool Execute();\n};\n//------------------------------------------------------------------------------\n// S7 WORKER CLASS\n//------------------------------------------------------------------------------\n\n// SZL frame\ntypedef struct{\n    TS7Answer17         Answer;\n    PReqFunReadSZLFirst ReqParams;\n    PS7ReqSZLData       ReqData;\n    PS7ResParams7       ResParams;\n    pbyte               ResData;\n    int                 ID;\n    int                 Index;\n    bool                SZLDone;\n}TSZL;\n\n// Current Event Info\ntypedef struct{\n    word EvRetCode;\n    word EvArea;\n    word EvIndex;\n    word EvStart;\n    word EvSize;\n}TEv;\n\n// Current Block info\ntypedef struct{\n  PReqFunGetBlockInfo ReqParams;\n  PResFunGetBlockInfo ResParams;\n  TS7Answer17         Answer;\n  word                evError;\n  word                DataLength;\n}TCB;\n\nclass TSnap7Server; // forward declaration\n\nclass TS7Worker : public TIsoTcpWorker\n{\nprivate:\n    PS7ReqHeader PDUH_in;\n\tint DBCnt;\n    byte LastBlk;\n    TSZL SZL;\n    byte BCD(word Value);\n    // Checks the consistence of the incoming PDU\n    bool CheckPDU_in(int PayloadSize);\n    void FillTime(PS7Time PTime);\nprotected:\n    int DataSizeByte(int WordLength);\n    bool ExecuteRecv();\n    void DoEvent(longword Code, word RetCode, word Param1, word Param2,\n      word Param3, word Param4);\n    void DoReadEvent(longword Code, word RetCode, word Param1, word Param2,\n      word Param3, word Param4);\n    void FragmentSkipped(int Size);\n    // Entry parse\n    bool IsoPerformCommand(int &Size);\n    // First stage parse\n    bool PerformPDUAck(int &Size);\n    bool PerformPDURequest(int &Size);\n    bool PerformPDUUsrData(int &Size);\n    // Second stage parse : PDU Request\n    PS7Area GetArea(byte S7Code, word index);\n    // Group Read Area\n    bool PerformFunctionRead();\n    // Subfunctions Read Data\n    word ReadArea(PResFunReadItem ResItemData, PReqFunReadItem ReqItemPar,\n    int &PDURemainder,TEv &EV);\n    word RA_NotFound(PResFunReadItem ResItem, TEv &EV);\n    word RA_OutOfRange(PResFunReadItem ResItem, TEv &EV);\n    word RA_SizeOverPDU(PResFunReadItem ResItem, TEv &EV);\n    // Group Write Area\n    bool PerformFunctionWrite();\n    // Subfunctions Write Data\n    byte WriteArea(PReqFunWriteDataItem ReqItemData, PReqFunWriteItem ReqItemPar,\n         TEv &EV);\n    byte WA_NotFound(TEv &EV);\n    byte WA_InvalidTransportSize(TEv &EV);\n    byte WA_OutOfRange(TEv &EV);\n    byte WA_DataSizeMismatch(TEv &EV);\n    // Negotiate PDU Length\n    bool PerformFunctionNegotiate();\n    // Control\n    bool PerformFunctionControl(byte PduFun);\n    // Up/Download\n\tbool PerformFunctionUpload();\n    bool PerformFunctionDownload();\n    // Second stage parse : PDU User data\n    bool PerformGroupProgrammer();\n    bool PerformGroupCyclicData();\n    bool PerformGroupSecurity();\n    // Group Block(s) Info\n    bool PerformGroupBlockInfo();\n    // Subfunctions Block info\n    void BLK_ListAll(TCB &CB);\n    void BLK_ListBoT(byte BlockType, bool Start, TCB &CB);\n    void BLK_NoResource_ListBoT(PDataFunGetBot Data, TCB &CB);\n    void BLK_GetBlkInfo(TCB &CB);\n    void BLK_NoResource_GetBlkInfo(PResDataBlockInfo Data, TCB &CB);\n    void BLK_GetBlockNum_GetBlkInfo(int &BlkNum, PReqDataBlockInfo ReqData);\n    void BLK_DoBlockInfo_GetBlkInfo(PS7Area DB, PResDataBlockInfo Data, TCB &CB);\n    // Clock Group\n    bool PerformGetClock();\n    bool PerformSetClock();\n    // SZL Group\n    bool PerformGroupSZL();\n    // Subfunctions (called by PerformGroupSZL)\n    void SZLNotAvailable();\n\tvoid SZLSystemState();\n\tvoid SZLData(void *P, int len);\n\tvoid SZL_ID424();\n\tvoid SZL_ID131_IDX003();\npublic:\n    TSnap7Server *FServer;\n    int FPDULength;\n    TS7Worker();\n    ~TS7Worker(){};\n};\n\ntypedef TS7Worker *PS7Worker;\n//------------------------------------------------------------------------------\n// S7 SERVER CLASS\n//------------------------------------------------------------------------------\nextern \"C\"\n{\n\ttypedef int (S7API *pfn_RWAreaCallBack)(void *usrPtr, int Sender, int Operation, PS7Tag PTag, void *pUsrData);\n}\nconst int OperationRead  = 0;\nconst int OperationWrite = 1;\n\nclass TSnap7Server : public TCustomMsgServer\n{\nprivate:\n    // Read Callback related\n    pfn_SrvCallBack OnReadEvent;\n\tpfn_RWAreaCallBack OnRWArea;\n\t// Critical section to lock Read/Write Hook Area\n\tPSnapCriticalSection CSRWHook;\n\tvoid *FReadUsrPtr;\n\tvoid *FRWAreaUsrPtr;\n\tvoid DisposeAll();\n    int FindFirstFreeDB();\n    int IndexOfDB(word DBNumber);\nprotected:\n    int DBCount;\n    int DBLimit;\n    PS7Area DB[MaxDB]; // DB\n    PS7Area HA[5];     // MK,PE,PA,TM,CT\n    PS7Area FindDB(word DBNumber);\n    PWorkerSocket CreateWorkerSocket(socket_t Sock);\n\tbool ResourceLess;\n\tword ForcePDU;\n    int RegisterDB(word Number, void *pUsrData, word Size);\n    int RegisterSys(int AreaCode, void *pUsrData, word Size);\n    int UnregisterDB(word DBNumber);\n    int UnregisterSys(int AreaCode);\n    // The Read event\n    void DoReadEvent(int Sender, longword Code, word RetCode, word Param1,\n      word Param2, word Param3, word Param4);\n\tbool DoReadArea(int Sender, int Area, int DBNumber, int Start, int Size, int WordLen, void *pUsrData);\n\tbool DoWriteArea(int Sender, int Area, int DBNumber, int Start, int Size, int WordLen, void *pUsrData);\npublic:\n    int WorkInterval;\n    byte CpuStatus;\n    TSnap7Server();\n    ~TSnap7Server();\n    int StartTo(const char *Address);\n    int GetParam(int ParamNumber, void *pValue);\n    int SetParam(int ParamNumber, void *pValue);\n    int RegisterArea(int AreaCode, word Index, void *pUsrData, word Size);\n    int UnregisterArea(int AreaCode, word Index);\n    int LockArea(int AreaCode, word DBNumber);\n    int UnlockArea(int AreaCode, word DBNumber);\n    // Sets Event callback\n    int SetReadEventsCallBack(pfn_SrvCallBack PCallBack, void *UsrPtr);\n\tint SetRWAreaCallBack(pfn_RWAreaCallBack PCallBack, void *UsrPtr);\n    friend class TS7Worker;\n};\ntypedef TSnap7Server *PSnap7Server;\n\n#endif // s7_server_h\n\n"
  },
  {
    "path": "deps/snap7/src/core/s7_text.cpp",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.3.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|=============================================================================*/\n#include \"s7_text.h\"\n//---------------------------------------------------------------------------\n#ifndef OS_WINDOWS\nstatic char* itoa(int value, char* result, int base) {\n\t// check that the base if valid\n\tif (base < 2 || base > 36){\n\t\t*result = '\\0'; return result;\n\n\t}\n\tchar* ptr = result, *ptr1 = result, tmp_char;\n\tint tmp_value;\n\n\tdo {\n\t\ttmp_value = value;\n\t\tvalue /= base;\n\t\t*ptr++ = \"zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz\" [35 + (tmp_value - value * base)];\n\t} while ( value );\n\n\t// Apply negative sign\n\tif (tmp_value < 0) *ptr++ = '-';\n\t*ptr-- = '\\0';\n\twhile(ptr1 < ptr) {\n\t\ttmp_char = *ptr;\n\t\t*ptr--= *ptr1;\n\t\t*ptr1++ = tmp_char;\n\t}\n\treturn result;\n}\n#endif\n//---------------------------------------------------------------------------\nchar* NumToString(int Value, int Base, int Len, char* Result)\n{\n\tchar CNumber[64];\n\tchar Pad[65] = \"0000000000000000000000000000000000000000000000000000000000000000\";\n\titoa(Value, CNumber, Base);\n\t\n\tif (Len > 0)\n\t{\n\t\tint Delta = Len - strlen(CNumber); // Len is max 8 in this program\n\t\tif (Delta > 0)\n\t\t{\n\t\t\tstrncpy(Result, Pad, Delta);\n\t\t\tResult[Delta] = '\\0';\n\t\t\tstrcat(Result, CNumber);\n\t\t}\n\t\telse\n\t\t\tstrcpy(Result, CNumber);\n\t}\n\telse\n\t\tstrcpy(Result, CNumber);\n\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nchar* IntToString(int Value, char* Result)\n{\n\treturn NumToString(Value, 10, 0, Result);\n}\n//---------------------------------------------------------------------------\nchar* TimeToString(time_t dt, char* Result)\n{\n\tstruct tm * DateTime = localtime(&dt);\n\tif (DateTime != NULL) \n\t\tstrftime(Result, 50, \"%Y-%m-%d %H:%M:%S\", DateTime);\n\telse\n\t\t*Result = '\\0';\n\treturn Result;\n}\n\n//---------------------------------------------------------------------------\nchar* IpAddressToString(int IP, char* Result)\n{\n\tin_addr Addr;\n\tAddr.s_addr = IP;\n\tstrcpy(Result, inet_ntoa(Addr));\n\treturn Result;\n}\n//---------------------------------------------------------------------------\n#define WSAEINVALIDADDRESS   12001\n\nchar* TcpTextOf(int Error, char* Result)\n{\n\tswitch (Error)\n\t{\n\tcase 0:                   *Result='\\0';break;\n\tcase WSAEINTR:            strcpy(Result,\" TCP : Interrupted system call\\0\");break;\n\tcase WSAEBADF:            strcpy(Result,\" TCP : Bad file number\\0\");break;\n\tcase WSAEACCES:           strcpy(Result,\" TCP : Permission denied\\0\");break;\n\tcase WSAEFAULT:           strcpy(Result,\" TCP : Bad address\\0\");break;\n\tcase WSAEINVAL:           strcpy(Result,\" TCP : Invalid argument\\0\");break;\n\tcase WSAEMFILE:           strcpy(Result,\" TCP : Too many open files\\0\");break;\n\tcase WSAEWOULDBLOCK:      strcpy(Result,\" TCP : Operation would block\\0\");break;\n\tcase WSAEINPROGRESS:      strcpy(Result,\" TCP : Operation now in progress\\0\");break;\n\tcase WSAEALREADY:         strcpy(Result,\" TCP : Operation already in progress\\0\");break;\n\tcase WSAENOTSOCK:         strcpy(Result,\" TCP : Socket operation on non socket\\0\");break;\n\tcase WSAEDESTADDRREQ:     strcpy(Result,\" TCP : Destination address required\\0\");break;\n\tcase WSAEMSGSIZE:         strcpy(Result,\" TCP : Message too long\\0\");break;\n\tcase WSAEPROTOTYPE:       strcpy(Result,\" TCP : Protocol wrong type for Socket\\0\");break;\n\tcase WSAENOPROTOOPT:      strcpy(Result,\" TCP : Protocol not available\\0\");break;\n\tcase WSAEPROTONOSUPPORT:  strcpy(Result,\" TCP : Protocol not supported\\0\");break;\n\tcase WSAESOCKTNOSUPPORT:  strcpy(Result,\" TCP : Socket not supported\\0\");break;\n\tcase WSAEOPNOTSUPP:       strcpy(Result,\" TCP : Operation not supported on Socket\\0\");break;\n\tcase WSAEPFNOSUPPORT:     strcpy(Result,\" TCP : Protocol family not supported\\0\");break;\n\tcase WSAEAFNOSUPPORT:     strcpy(Result,\" TCP : Address family not supported\\0\");break;\n\tcase WSAEADDRINUSE:       strcpy(Result,\" TCP : Address already in use\\0\");break;\n\tcase WSAEADDRNOTAVAIL:    strcpy(Result,\" TCP : Can't assign requested address\\0\");break;\n\tcase WSAENETDOWN:         strcpy(Result,\" TCP : Network is down\\0\");break;\n\tcase WSAENETUNREACH:      strcpy(Result,\" TCP : Network is unreachable\\0\");break;\n\tcase WSAENETRESET:        strcpy(Result,\" TCP : Network dropped connection on reset\\0\");break;\n\tcase WSAECONNABORTED:     strcpy(Result,\" TCP : Software caused connection abort\\0\");break;\n\tcase WSAECONNRESET:       strcpy(Result,\" TCP : Connection reset by peer\\0\");break;\n\tcase WSAENOBUFS:          strcpy(Result,\" TCP : No Buffer space available\\0\");break;\n\tcase WSAEISCONN:          strcpy(Result,\" TCP : Socket is already connected\\0\");break;\n\tcase WSAENOTCONN:         strcpy(Result,\" TCP : Socket is not connected\\0\");break;\n\tcase WSAESHUTDOWN:        strcpy(Result,\" TCP : Can't send after Socket shutdown\\0\");break;\n\tcase WSAETOOMANYREFS:     strcpy(Result,\" TCP : Too many references:can't splice\\0\");break;\n\tcase WSAETIMEDOUT:        strcpy(Result,\" TCP : Connection timed out\\0\");break;\n\tcase WSAECONNREFUSED:     strcpy(Result,\" TCP : Connection refused\\0\");break;\n\tcase WSAELOOP:            strcpy(Result,\" TCP : Too many levels of symbolic links\\0\");break;\n\tcase WSAENAMETOOLONG:     strcpy(Result,\" TCP : File name is too long\\0\");break;\n\tcase WSAEHOSTDOWN:        strcpy(Result,\" TCP : Host is down\\0\");break;\n\tcase WSAEHOSTUNREACH:     strcpy(Result,\" TCP : Unreachable peer\\0\");break;\n\tcase WSAENOTEMPTY:        strcpy(Result,\" TCP : Directory is not empty\\0\");break;\n\tcase WSAEUSERS:           strcpy(Result,\" TCP : Too many users\\0\");break;\n\tcase WSAEDQUOT:           strcpy(Result,\" TCP : Disk quota exceeded\\0\");break;\n\tcase WSAESTALE:           strcpy(Result,\" TCP : Stale NFS file handle\\0\");break;\n\tcase WSAEREMOTE:          strcpy(Result,\" TCP : Too many levels of remote in path\\0\");break;\n\t#ifdef OS_WINDOWS\n\tcase WSAEPROCLIM:         strcpy(Result,\" TCP : Too many processes\\0\");break;\n\tcase WSASYSNOTREADY:      strcpy(Result,\" TCP : Network subsystem is unusable\\0\");break;\n\tcase WSAVERNOTSUPPORTED:  strcpy(Result,\" TCP : Winsock DLL cannot support this application\\0\");break;\n\tcase WSANOTINITIALISED:   strcpy(Result,\" TCP : Winsock not initialized\\0\");break;\n\tcase WSAEDISCON:          strcpy(Result,\" TCP : Disconnect\\0\");break;\n\tcase WSAHOST_NOT_FOUND:   strcpy(Result,\" TCP : Host not found\\0\");break;\n\tcase WSATRY_AGAIN:        strcpy(Result,\" TCP : Non authoritative - host not found\\0\");break;\n\tcase WSANO_RECOVERY:      strcpy(Result,\" TCP : Non recoverable error\\0\");break;\n\tcase WSANO_DATA:          strcpy(Result,\" TCP : Valid name, no data record of requested type\\0\");break;\n\t#endif\n\tcase WSAEINVALIDADDRESS:  strcpy(Result,\" TCP : Invalid address\\0\");break;\n\tdefault:\n\t\t{\n\t\t\tchar CNumber[16];\n\t\t\tstrcpy(Result, \" TCP : Other Socket error (\");\n\t\t\tstrcat(Result, IntToString(Error, CNumber));\n\t\t\tstrcat(Result, \")\");\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nchar* IsoTextOf(int Error, char* Result)\n{\n\tswitch (Error)\n\t{\n\t\tcase 0 :                     *Result='\\0';break;\n\t\tcase errIsoConnect:          strcpy(Result,\" ISO : Connection error\\0\");break;\n\t\tcase errIsoDisconnect:       strcpy(Result,\" ISO : Disconnect error\\0\");break;\n\t\tcase errIsoInvalidPDU:       strcpy(Result,\" ISO : Bad PDU format\\0\");break;\n\t\tcase errIsoInvalidDataSize:  strcpy(Result,\" ISO : Datasize passed to send/recv buffer is invalid\\0\");break;\n\t\tcase errIsoNullPointer:      strcpy(Result,\" ISO : Null passed as pointer\\0\");break;\n\t\tcase errIsoShortPacket:      strcpy(Result,\" ISO : A short packet received\\0\");break;\n\t\tcase errIsoTooManyFragments: strcpy(Result,\" ISO : Too many packets without EoT flag\\0\");break;\n\t\tcase errIsoPduOverflow:      strcpy(Result,\" ISO : The sum of fragments data exceded maximum packet size\\0\");break;\n\t\tcase errIsoSendPacket:       strcpy(Result,\" ISO : An error occurred during send\\0\");break;\n\t\tcase errIsoRecvPacket:       strcpy(Result,\" ISO : An error occurred during recv\\0\");break;\n\t\tcase errIsoInvalidParams:    strcpy(Result,\" ISO : Invalid connection params (wrong TSAPs)\\0\");break;\n\t\tdefault:\n\t\t{\n\t\t\tchar CNumber[16];\n\t\t\tstrcpy(Result, \" ISO : Unknown error (0x\");\n\t\t\tstrcat(Result, NumToString(Error, 16, 8, CNumber));\n\t\t\tstrcat(Result, \")\");\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nchar* CliTextOf(int Error, char* Result)\n{\n\tswitch (Error)\n\t{\n\t  case 0 :                            *Result='\\0';break;\n\t  case errNegotiatingPDU            : strcpy(Result,\"CPU : Error in PDU negotiation\\0\");break;\n\t  case errCliInvalidParams          : strcpy(Result,\"CLI : invalid param(s) supplied\\0\");break;\n\t  case errCliJobPending             : strcpy(Result,\"CLI : Job pending\\0\");break;\n\t  case errCliTooManyItems           : strcpy(Result,\"CLI : too may items (>20) in multi read/write\\0\");break;\n\t  case errCliInvalidWordLen         : strcpy(Result,\"CLI : invalid WordLength\\0\");break;\n\t  case errCliPartialDataWritten     : strcpy(Result,\"CLI : Partial data written\\0\");break;\n\t  case errCliSizeOverPDU            : strcpy(Result,\"CPU : total data exceeds the PDU size\\0\");break;\n\t  case errCliInvalidPlcAnswer       : strcpy(Result,\"CLI : invalid CPU answer\\0\");break;\n\t  case errCliAddressOutOfRange      : strcpy(Result,\"CPU : Address out of range\\0\");break;\n\t  case errCliInvalidTransportSize   : strcpy(Result,\"CPU : Invalid Transport size\\0\");break;\n\t  case errCliWriteDataSizeMismatch  : strcpy(Result,\"CPU : Data size mismatch\\0\");break;\n\t  case errCliItemNotAvailable       : strcpy(Result,\"CPU : Item not available\\0\");break;\n\t  case errCliInvalidValue           : strcpy(Result,\"CPU : Invalid value supplied\\0\");break;\n\t  case errCliCannotStartPLC         : strcpy(Result,\"CPU : Cannot start PLC\\0\");break;\n\t  case errCliAlreadyRun             : strcpy(Result,\"CPU : PLC already RUN\\0\");break;\n\t  case errCliCannotStopPLC          : strcpy(Result,\"CPU : Cannot stop PLC\\0\");break;\n\t  case errCliCannotCopyRamToRom     : strcpy(Result,\"CPU : Cannot copy RAM to ROM\\0\");break;\n\t  case errCliCannotCompress         : strcpy(Result,\"CPU : Cannot compress\\0\");break;\n\t  case errCliAlreadyStop            : strcpy(Result,\"CPU : PLC already STOP\\0\");break;\n\t  case errCliFunNotAvailable        : strcpy(Result,\"CPU : Function not available\\0\");break;\n\t  case errCliUploadSequenceFailed   : strcpy(Result,\"CPU : Upload sequence failed\\0\");break;\n\t  case errCliInvalidDataSizeRecvd   : strcpy(Result,\"CLI : Invalid data size received\\0\");break;\n\t  case errCliInvalidBlockType       : strcpy(Result,\"CLI : Invalid block type\\0\");break;\n\t  case errCliInvalidBlockNumber     : strcpy(Result,\"CLI : Invalid block number\\0\");break;\n\t  case errCliInvalidBlockSize       : strcpy(Result,\"CLI : Invalid block size\\0\");break;\n\t  case errCliDownloadSequenceFailed : strcpy(Result,\"CPU : Download sequence failed\\0\");break;\n\t  case errCliInsertRefused          : strcpy(Result,\"CPU : block insert refused\\0\");break;\n\t  case errCliDeleteRefused          : strcpy(Result,\"CPU : block delete refused\\0\");break;\n\t  case errCliNeedPassword           : strcpy(Result,\"CPU : Function not authorized for current protection level\\0\");break;\n\t  case errCliInvalidPassword        : strcpy(Result,\"CPU : Invalid password\\0\");break;\n\t  case errCliNoPasswordToSetOrClear : strcpy(Result,\"CPU : No password to set or clear\\0\");break;\n\t  case errCliJobTimeout             : strcpy(Result,\"CLI : Job Timeout\\0\");break;\n\t  case errCliFunctionRefused        : strcpy(Result,\"CLI : function refused by CPU (Unknown error)\\0\");break;\n\t  case errCliPartialDataRead        : strcpy(Result,\"CLI : Partial data read\\0\");break;\n\t  case errCliBufferTooSmall         : strcpy(Result,\"CLI : The buffer supplied is too small to accomplish the operation\\0\");break;\n\t  case errCliDestroying             : strcpy(Result,\"CLI : Cannot perform (destroying)\\0\");break;\n\t  case errCliInvalidParamNumber     : strcpy(Result,\"CLI : Invalid Param Number\\0\");break;\n\t  case errCliCannotChangeParam      : strcpy(Result,\"CLI : Cannot change this param now\\0\");break;\n\t  default                           :\n\t  {\n\t\t  char CNumber[16];\n\t\t  strcpy(Result, \"CLI : Unknown error (0x\");\n\t\t  strcat(Result, NumToString(Error, 16, 8, CNumber));\n\t\t  strcat(Result, \")\");\n\t\t  break;\n\t  }\n\t};\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nchar* SrvTextOf(int Error, char* Result)\n{\n\tswitch (Error)\n\t{\n\tcase 0:                        *Result = '\\0'; break;\n\tcase errSrvCannotStart:        strcpy(Result, \"SRV : Server cannot start\\0\"); break;\n\tcase errSrvDBNullPointer:      strcpy(Result, \"SRV : Null passed as area pointer\\0\"); break;\n\tcase errSrvAreaAlreadyExists:  strcpy(Result, \"SRV : Cannot register area since already exists\\0\"); break;\n\tcase errSrvUnknownArea:        strcpy(Result, \"SRV : Unknown Area code\\0\"); break;\n\tcase errSrvInvalidParams:      strcpy(Result, \"SRV : Invalid param(s) supplied\\0\"); break;\n\tcase errSrvTooManyDB:          strcpy(Result, \"SRV : DB Limit reached\\0\"); break;\n\tcase errSrvInvalidParamNumber: strcpy(Result, \"SRV : Invalid Param Number\\0\"); break;\n\tcase errSrvCannotChangeParam:  strcpy(Result, \"SRV : Cannot change this param now\\0\");break;\n\tdefault: \n\t\t{\n\t\t\tchar CNumber[16];\n\t\t\tstrcpy(Result, \"SRV : Unknown error (0x\");\n\t\t\tstrcat(Result, NumToString(Error, 16, 8, CNumber));\n\t\t\tstrcat(Result, \")\");\n\t\t\tbreak;\n\t\t}\n\t};\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nchar* ParTextOf(int Error, char* Result)\n{\n\tswitch(Error)\n\t{\n\t\tcase 0: *Result = '\\0'; break;\n\t\tcase errParAddressInUse      : strcpy(Result, \"PAR : Local address already in use\");break;\n\t\tcase errParNoRoom            : strcpy(Result, \"PAR : No more partners available\");break;\n\t\tcase errServerNoRoom         : strcpy(Result, \"PAR : No more servers available\");break;\n\t\tcase errParInvalidParams     : strcpy(Result, \"PAR : Invalid parameter supplied\");break;\n\t\tcase errParNotLinked         : strcpy(Result, \"PAR : Cannot perform, Partner not linked\");break;\n\t\tcase errParBusy              : strcpy(Result, \"PAR : Cannot perform, Partner Busy\");break;\n\t\tcase errParFrameTimeout      : strcpy(Result, \"PAR : Frame timeout\");break;\n\t\tcase errParInvalidPDU        : strcpy(Result, \"PAR : Invalid PDU received\");break;\n\t\tcase errParSendTimeout       : strcpy(Result, \"PAR : Send timeout\");break;\n\t\tcase errParRecvTimeout       : strcpy(Result, \"PAR : Recv timeout\");break;\n\t\tcase errParSendRefused       : strcpy(Result, \"PAR : Send refused by peer\");break;\n\t\tcase errParNegotiatingPDU    : strcpy(Result, \"PAR : Error negotiating PDU\");break;\n\t\tcase errParSendingBlock      : strcpy(Result, \"PAR : Error Sending Block\");break;\n\t\tcase errParRecvingBlock      : strcpy(Result, \"PAR : Error Receiving Block\");break;\n\t\tcase errParBindError         : strcpy(Result, \"PAR : Error Binding\");break;\n\t\tcase errParDestroying        : strcpy(Result, \"PAR : Cannot perform (destroying)\");break;\n\t\tcase errParInvalidParamNumber: strcpy(Result, \"PAR : Invalid Param Number\");break;\n\t\tcase errParCannotChangeParam : strcpy(Result, \"PAR : Cannot change this param now\");break;\n\t\tcase errParBufferTooSmall    : strcpy(Result, \"PAR : The buffer supplied is too small to accomplish the operation\");break;\n\t\tdefault:\n\t\t{\n\t\t\tchar CNumber[16];\n\t\t\tstrcpy(Result, \"PAR : Unknown error (0x\");\n\t\t\tstrcat(Result, NumToString(Error, 16, 8, CNumber));\n\t\t\tstrcat(Result, \")\");\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nchar* ErrCliText(int Error, char * Result, int TextLen)\n{\n\tchar TcpError[128];\n\tchar IsoError[128];\n\tchar CliError[256];\n\tif (Error != 0)\n\t{\n\t\tswitch (Error)\n\t\t{\n\t\t\tcase errLibInvalidParam  : strncpy(Result,\"LIB : Invalid param supplied\\0\",TextLen);break;\n\t\t\tcase errLibInvalidObject: strncpy(Result, \"LIB : Invalid object supplied\\0\", TextLen); break;\n\t\t\tdefault :\n\t\t\t{\n\t\t\t\tCliTextOf(Error & ErrS7Mask, CliError);\n\t\t\t\tstrcat(CliError, IsoTextOf(Error & ErrIsoMask, IsoError));\n\t\t\t\tstrcat(CliError, TcpTextOf(Error & ErrTcpMask, TcpError));\n\t\t\t\tstrncpy(Result, CliError, TextLen);\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t\tstrncpy(Result, \"OK\\0\", TextLen);\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nchar* ErrSrvText(int Error, char* Result, int TextLen)\n{\n\tchar TcpError[128];\n\tchar IsoError[128];\n\tchar SrvError[256];\n\tif (Error != 0)\n\t{\n\t\tswitch (Error)\n\t\t{\n\t\tcase errLibInvalidParam: strncpy(Result, \"LIB : Invalid param supplied\\0\", TextLen); break;\n\t\tcase errLibInvalidObject: strncpy(Result, \"LIB : Invalid object supplied\\0\", TextLen); break;\n\t\tdefault:\n\t\t{\n\t\t\tSrvTextOf(Error & ErrS7Mask, SrvError);\n\t\t\tstrcat(SrvError, IsoTextOf(Error & ErrIsoMask, IsoError));\n\t\t\tstrcat(SrvError, TcpTextOf(Error & ErrTcpMask, TcpError));\n\t\t\tstrncpy(Result, SrvError, TextLen);\n\t\t}\n\t\t}\n\t}\n\telse\n\t\tstrncpy(Result, \"OK\\0\", TextLen);\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nchar* ErrParText(int Error, char* Result, int TextLen)\n{\n\tchar TcpError[128];\n\tchar IsoError[128];\n\tchar ParError[256];\n\tif (Error != 0)\n\t{\n\t\tswitch (Error)\n\t\t{\n\t\tcase errLibInvalidParam: strncpy(Result, \"LIB : Invalid param supplied\\0\", TextLen); break;\n\t\tcase errLibInvalidObject: strncpy(Result, \"LIB : Invalid object supplied\\0\", TextLen); break;\n\t\tdefault:\n\t\t{\n\t\t\tParTextOf(Error & ErrS7Mask, ParError);\n\t\t\tstrcat(ParError, IsoTextOf(Error & ErrIsoMask, IsoError));\n\t\t\tstrcat(ParError, TcpTextOf(Error & ErrTcpMask, TcpError));\n\t\t\tstrncpy(Result, ParError, TextLen);\n\t\t}\n\t\t}\n\t}\n\telse\n\t\tstrncpy(Result, \"OK\\0\", TextLen);\n\treturn Result;\n}\n//---------------------------------------------------------------------------\n//                               SERVER EVENTS TEXT\n//---------------------------------------------------------------------------\nchar* SenderText(TSrvEvent &Event, char* Result)\n{\n\tchar Buf[64];\n\tchar Add[16];\n\tTimeToString(Event.EvtTime, Buf);\n\tif (Event.EvtSender != 0)\n\t{\n\t\tstrcat(Buf, \" [\");\n\t\tstrcat(Buf, IpAddressToString(Event.EvtSender, Add));\n\t\tstrcat(Buf, \"] \");\n\t}\n\telse\n\t\tstrcat(Buf, \" Server \");\n\tstrcpy(Result, Buf);\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nchar* TcpServerEventText(TSrvEvent &Event, char* Result)\n{\n    char S[256];\n\tchar Buf[128];\n\t\n\tstrcpy(S, SenderText(Event, Buf));\n\n\tswitch (Event.EvtCode)\n    {\n      case evcServerStarted       : strcat(S,\"started\");break;\n      case evcServerStopped       : strcat(S,\"stopped\");break;\n\t  case evcListenerCannotStart:\n\t\t  strcat(S, \"Cannot start listener - Socket Error : \");\n\t\t  strcat(S, TcpTextOf(Event.EvtRetCode,Buf));  \n\t\t  break;\n      case evcClientAdded         : strcat(S,\"Client added\");break;\n      case evcClientRejected      : strcat(S,\"Client refused\");break;\n      case evcClientNoRoom        : strcat(S,\"A client was refused due to maximum connections number\");break;\n      case evcClientException     : strcat(S,\"Client exception\");break;\n      case evcClientDisconnected  : strcat(S,\"Client disconnected by peer\");break;\n      case evcClientTerminated    : strcat(S,\"Client terminated\");break;\n\t  case evcClientsDropped:\n\t\t  strcat(S, IntToString(Event.EvtParam1, Buf));\n\t\t  strcat(S, \" clients have been dropped bacause unresponsive\");\n\t\t  break;\n\t  default:\n\t\t  strcat(S, \"Unknown event (\");\n\t\t  strcat(S, IntToString(Event.EvtCode, Buf));\n\t\t  strcat(S,\")\"); \n\t\t  break;\n    };\n\tstrcpy(Result, S);\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nchar* PDUText(TSrvEvent &Event, char* Result)\n{\n\tchar S[256];\n\tchar Buf[128];\n\tswitch (Event.EvtRetCode)\n\t{\n\t\tcase evrFragmentRejected:\n\t\t\tstrcpy(S, \"Fragment of \");\n\t\t\tstrcat(S, IntToString(Event.EvtParam1, Buf));\n\t\t\tstrcat(S, \" bytes rejected\");\n\t\t\tbreak;\n\t\tcase evrMalformedPDU:\n\t\t\tstrcpy(S, \"Malformed PDU of \");\n\t\t\tstrcat(S, IntToString(Event.EvtParam1, Buf));\n\t\t\tstrcat(S, \" bytes rejected\");\n\t\t\tbreak;\n\t\tcase evrSparseBytes:\n\t\t\tstrcpy(S, \"Message of sparse \");\n\t\t\tstrcat(S, IntToString(Event.EvtParam1, Buf));\n\t\t\tstrcat(S, \" bytes rejected\");\n\t\t\tbreak;\n\t\tcase evrCannotHandlePDU:\n\t\t\tstrcpy(S, \"Cannot handle this PDU\");\n\t\t\tbreak;\n\t\tcase evrNotImplemented:\n\t\t\tswitch (Event.EvtParam1)\n\t\t\t{\n\t\t\t\tcase grCyclicData:\n\t\t\t\t\tstrcpy(S, \"Function group cyclic data not yet implemented\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase grProgrammer:\n\t\t\t\t\tstrcpy(S, \"Function group programmer not yet implemented\");\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tstrcpy(S, \"Unknown Return code (\");\n\t\t\tstrcat(S, IntToString(Event.EvtRetCode, Buf));\n\t\t\tstrcat(S, \")\");\n\t\t\tbreak;\n\t}\n\tstrcpy(Result, S);\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nchar* TxtArea(TSrvEvent &Event, char* Result)\n{\n\tchar S[64];\n\tchar Buf[32];\n\tswitch (Event.EvtParam1)\n    {\n\t\tcase S7AreaPE: strcpy(S, \"Area : PE, \"); break;\n\t\tcase S7AreaPA: strcpy(S, \"Area : PA, \"); break;\n\t\tcase S7AreaMK: strcpy(S, \"Area : MK, \"); break;\n\t\tcase S7AreaCT: strcpy(S, \"Area : CT, \"); break;\n\t\tcase S7AreaTM: strcpy(S, \"Area : TM, \"); break;\n\t\tcase S7AreaDB: \n\t\t\tstrcpy(S, \"Area : DB\");\n\t\t\tstrcat(S, IntToString(Event.EvtParam2, Buf));\n\t\t\tstrcat(S,\", \"); \n\t\t\tbreak;\n\t\tdefault: \n\t\t\tstrcpy(S, \"Unknown area (\");\n\t\t\tstrcat(S, IntToString(Event.EvtParam2, Buf));\n\t\t\tstrcat(S,\")\");\n\t\t\tbreak;\n    }\n\tstrcpy(Result, S);\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nchar* TxtStartSize(TSrvEvent &Event, char* Result)\n{\n\tchar N[32];\n\tstrcpy(Result, \"Start : \");\n\tstrcat(Result, IntToString(Event.EvtParam3, N));\n\tstrcat(Result, \", Size : \");\n\tstrcat(Result, IntToString(Event.EvtParam4, N));\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nchar* TxtDataResult(TSrvEvent &Event, char* Result)\n{\n\tchar N[32];\n\tswitch (Event.EvtRetCode)\n    {\n        case evrNoError:\n\t\t\tstrcpy(Result,\" --> OK\");\n\t\t\tbreak;\n\t\tcase evrErrException: \n\t\t\tstrcpy(Result, \" --> Exception error\");\n\t\t\tbreak;\n\t\tcase evrErrAreaNotFound: \n\t\t\tstrcpy(Result, \" --> Area not found\");\n\t\t\tbreak;\n        case evrErrOutOfRange: \n\t\t\tstrcpy(Result, \" --> Out of range\");\n\t\t\tbreak;\n        case evrErrOverPDU:\n\t\t\tstrcpy(Result, \" --> Data size exceeds PDU size\");\n\t\t\tbreak;\n\t\tcase evrErrTransportSize: \n\t\t\tstrcpy(Result, \" --> Invalid transport size\");\n\t\t\tbreak;\n\t\tcase evrDataSizeMismatch: \n\t\t\tstrcpy(Result, \" --> Data size mismatch\");\n\t\t\tbreak;\n\t\tdefault: \n\t\t\tstrcpy(Result, \" --> Unknown error code (\");\n\t\t\tstrcat(Result, IntToString(Event.EvtRetCode, N));\n\t\t\tstrcat(Result,\")\");\n\t\t\tbreak;\n    };\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nchar* ControlText(word Code, char* Result)\n{\n\tchar N[64];\n\tstrcpy(Result, \"CPU Control request : \");\n    switch (Code)\n    {\n        case CodeControlUnknown: \n\t\t\tstrcat(Result,\"Unknown\");\n\t\t\tbreak;\n\t\tcase CodeControlColdStart: \n\t\t\tstrcat(Result, \"Cold START --> OK\");\n\t\t\tbreak;\n\t\tcase CodeControlWarmStart: \n\t\t\tstrcat(Result, \"Warm START --> OK\");\n\t\t\tbreak;\n\t\tcase CodeControlStop: \n\t\t\tstrcat(Result, \"STOP --> OK\");\n\t\t\tbreak;\n\t\tcase CodeControlCompress: \n\t\t\tstrcat(Result, \"Memory compress --> OK\");\n\t\t\tbreak;\n\t\tcase CodeControlCpyRamRom: \n\t\t\tstrcat(Result, \"Copy Ram to Rom --> OK\");\n\t\t\tbreak;\n\t\tcase CodeControlInsDel: \n\t\t\tstrcat(Result, \"Block Insert or Delete --> OK\");\n\t\t\tbreak;\n        default : \n\t\t\tstrcat(Result, \"Unknown control code (\");\n\t\t\tstrcat(Result, IntToString(Code, N));\n\t\t\tstrcat(Result,\")\");\n    }\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nchar* ClockText(word Code, char* Result)\n{\n    if (Code==evsGetClock)\n        strcpy(Result,\"System clock read requested\");\n    else\n\t\tstrcpy(Result, \"System clock write requested\");\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nchar* ReadSZLText(TSrvEvent &Event, char* Result)\n{\n\tchar S[128];\n\tchar N[64];\n\tstrcpy(S, \"Read SZL request, ID:0x\");\n\tstrcat(S, NumToString(Event.EvtParam1, 16, 4, N));\n\tstrcat(S, \" INDEX:0x\");\n\tstrcat(S, NumToString(Event.EvtParam2, 16, 4, N));\n\t\n\tif (Event.EvtRetCode == evrNoError)\n\t\tstrcat(S, \" --> OK\");\n    else\n\t\tstrcat(S, \" --> NOT AVAILABLE\");\n\tstrcpy(Result, S);\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nchar* UploadText(TSrvEvent &Event, char* Result)\n{\n   strcpy(Result,\"Block upload requested --> NOT PERFORMED (due to invalid security level)\");\n   return Result;\n}\n//---------------------------------------------------------------------------\nchar* DownloadText(TSrvEvent &Event, char* Result)\n{\n\tstrcpy(Result, \"Block download requested --> NOT PERFORMED (due to invalid security level)\");\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nchar* StrBlockType(word Code, char* Result)\n{\n\tchar N[64];\n\tswitch (Code)\n    {\n\t\tcase Block_OB: \n\t\t\tstrcpy(Result, \"OB\");\n\t\t\tbreak;\n\t\tcase Block_DB: \n\t\t\tstrcpy(Result, \"DB\");\n\t\t\tbreak;\n\t\tcase Block_SDB: \n\t\t\tstrcpy(Result, \"SDB\");\n\t\t\tbreak;\n\t\tcase Block_FC: \n\t\t\tstrcpy(Result, \"FC\");\n\t\t\tbreak;\n\t\tcase Block_SFC: \n\t\t\tstrcpy(Result, \"SFC\");\n\t\t\tbreak;\n\t\tcase Block_FB: \n\t\t\tstrcpy(Result, \"FB\");\n\t\t\tbreak;\n\t\tcase Block_SFB: \n\t\t\tstrcpy(Result, \"SFB\");\n\t\t\tbreak;\n\t\tdefault: \n\t\t\tstrcpy(Result, \"[Unknown 0x\");\n\t\t\tstrcat(Result, NumToString(Code, 16, 4, N));\n\t\t\tstrcat(Result,\"]\");\n\t\t\tbreak;\n    };\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nchar* BlockInfoText(TSrvEvent &Event, char* Result)\n{\n\tchar S[64];\n\tswitch (Event.EvtParam1)\n    {\n\t\tcase evsGetBlockList: \n\t\t\tstrcpy(Result, \"Block list requested\");\n\t\t\tbreak;\n\t\tcase evsStartListBoT:\n\t\t\tstrcpy(Result, \"Block of type \");\n\t\t\tstrcat(Result, StrBlockType(Event.EvtParam2,S));\n\t\t\tstrcat(Result, \" list requested (start sequence)\");\n\t\t\tbreak;\n\t\tcase evsListBoT: \n\t\t\tstrcpy(Result, \"Block of type \");\n\t\t\tstrcat(Result, StrBlockType(Event.EvtParam2, S));\n\t\t\tstrcat(Result, \" list requested (next part)\");\n\t\t\tbreak;\n\t\tcase evsGetBlockInfo: \n\t\t\tstrcpy(Result, \"Block info requested \");\n\t\t\tstrcat(Result, StrBlockType(Event.EvtParam2, S));\n\t\t\tstrcat(Result, \" \");\n\t\t\tstrcat(Result, IntToString(Event.EvtParam3,S));\n\t\t\tbreak;\n    };\n    if (Event.EvtRetCode == evrNoError)\n\t\tstrcat(Result, \" --> OK\");\n    else\n\t\tstrcat(Result, \" --> NOT AVAILABLE\");\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nchar* SecurityText(TSrvEvent &Event, char* Result)\n{\n    switch (Event.EvtParam1)\n    {\n        case evsSetPassword:\n\t\t\tstrcpy(Result,\"Security request : Set session password --> OK\");\n\t\t\tbreak;\n\t\tcase evsClrPassword: \n\t\t\tstrcpy(Result, \"Security request : Clear session password --> OK\");\n\t\t\tbreak;\n\t\tdefault: \n\t\t\tstrcpy(Result, \"Security request : Unknown Subfunction\");\n\t\t\tbreak;\n    };\n\treturn Result;\n}\n//---------------------------------------------------------------------------\nchar* EvtSrvText(TSrvEvent &Event, char* Result, int TextLen)\n{\n\tchar S[256];\n\tchar C[128];\n\n\tif (Event.EvtCode > evcSnap7Base)\n    {\n\t\tstrcpy(S, SenderText(Event, C));\n\t\tswitch (Event.EvtCode)\n        {\n            case evcPDUincoming:\n\t\t\t\tstrcat(S, \"PDU incoming : \");\n\t\t\t\tstrcat(S,PDUText(Event,C));\n\t\t\t\tbreak;\n\t\t\tcase evcDataRead: \n\t\t\t\tstrcat(S, \"Read request, \");\n\t\t\t\tstrcat(S, TxtArea(Event, C));\n\t\t\t\tstrcat(S, TxtStartSize(Event, C));\n\t\t\t\tstrcat(S, TxtDataResult(Event, C));\n\t\t\t\tbreak;\n\t\t\tcase evcDataWrite: \n\t\t\t\tstrcat(S, \"Write request, \");\n\t\t\t\tstrcat(S, TxtArea(Event, C));\n\t\t\t\tstrcat(S, TxtStartSize(Event, C));\n\t\t\t\tstrcat(S, TxtDataResult(Event, C));\n\t\t\t\tbreak;\n\t\t\tcase evcNegotiatePDU:\n\t\t\t\tstrcat(S, \"The client requires a PDU size of \");\n\t\t\t\tstrcat(S, IntToString(Event.EvtParam1, C));\n\t\t\t\tstrcat(S,\" bytes\");\n\t\t\t\tbreak;\n\t\t\tcase evcControl: \n\t\t\t\tstrcat(S, ControlText(Event.EvtParam1,C));\n\t\t\t\tbreak;\n\t\t\tcase evcReadSZL: \n\t\t\t\tstrcat(S, ReadSZLText(Event,C));\n\t\t\t\tbreak;\n\t\t\tcase evcClock: \n\t\t\t\tstrcat(S, ClockText(Event.EvtParam1,C));\n\t\t\t\tbreak;\n\t\t\tcase evcUpload: \n\t\t\t\tstrcat(S, UploadText(Event,C));\n\t\t\t\tbreak;\n\t\t\tcase evcDownload: \n\t\t\t\tstrcat(S, DownloadText(Event,C));\n\t\t\t\tbreak;\n\t\t\tcase evcDirectory: \n\t\t\t\tstrcat(S, BlockInfoText(Event,C));\n\t\t\t\tbreak;\n\t\t\tcase evcSecurity: \n\t\t\t\tstrcat(S, SecurityText(Event,C));\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tstrcat(S, \"Unknown event (\");\n\t\t\t\tstrcat(S, IntToString(Event.EvtCode, C));\n\t\t\t\tstrcat(S,\")\");\n\t\t\t\tbreak;\n        }\n    }\n    else\n        strcpy(S,TcpServerEventText(Event,C));\n\n\tstrncpy(Result, S, TextLen);\n\treturn Result;\n}\n\n"
  },
  {
    "path": "deps/snap7/src/core/s7_text.h",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.3.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|=============================================================================*/\n#ifndef s7_text_h\n#define s7_text_h\n//---------------------------------------------------------------------------\n#include \"s7_micro_client.h\"\n#include \"s7_server.h\"\n#include \"s7_partner.h\"\n//---------------------------------------------------------------------------\n\nconst int errLibInvalidParam  = -1;\nconst int errLibInvalidObject = -2;\n// Errors areas definition\nconst longword ErrTcpMask = 0x0000FFFF;\nconst longword ErrIsoMask = 0x000F0000;\nconst longword ErrS7Mask  = 0xFFF00000;\n\nchar* ErrCliText(int Error, char* Result, int TextLen);\nchar* ErrSrvText(int Error, char* Result, int TextLen);\nchar* ErrParText(int Error, char* Result, int TextLen);\nchar* EvtSrvText(TSrvEvent &Event, char* Result, int TextLen);\n\n\n#endif\n\n\n"
  },
  {
    "path": "deps/snap7/src/core/s7_types.h",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.3.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|=============================================================================*/\n#ifndef s7_types_h\n#define s7_types_h\n//------------------------------------------------------------------------------\n#include \"s7_isotcp.h\"\n//------------------------------------------------------------------------------\n//                               EXPORT CONSTANTS\n// Everything added in this section has to be copied into wrappers interface\n//------------------------------------------------------------------------------\n\n#ifdef OS_WINDOWS\n#define SM7API __stdcall\n#else\n#define SM7API\n#endif\n\n  // Area ID\nconst byte S7AreaPE   =\t0x81;\nconst byte S7AreaPA   =\t0x82;\nconst byte S7AreaMK   =\t0x83;\nconst byte S7AreaDB   =\t0x84;\nconst byte S7AreaCT   =\t0x1C;\nconst byte S7AreaTM   =\t0x1D;\n\nconst int MaxVars     = 20;\n\nconst int S7WLBit     = 0x01;\nconst int S7WLByte    = 0x02;\nconst int S7WLChar    = 0x03;\nconst int S7WLWord    = 0x04;\nconst int S7WLInt     = 0x05;\nconst int S7WLDWord   = 0x06;\nconst int S7WLDInt    = 0x07;\nconst int S7WLReal    = 0x08;\nconst int S7WLCounter = 0x1C;\nconst int S7WLTimer   = 0x1D;\n\n  // Block type\nconst byte Block_OB   = 0x38;\nconst byte Block_DB   = 0x41;\nconst byte Block_SDB  = 0x42;\nconst byte Block_FC   = 0x43;\nconst byte Block_SFC  = 0x44;\nconst byte Block_FB   = 0x45;\nconst byte Block_SFB  = 0x46;\n\n  // Sub Block Type\nconst byte SubBlk_OB  = 0x08;\nconst byte SubBlk_DB  = 0x0A;\nconst byte SubBlk_SDB = 0x0B;\nconst byte SubBlk_FC  = 0x0C;\nconst byte SubBlk_SFC = 0x0D;\nconst byte SubBlk_FB  = 0x0E;\nconst byte SubBlk_SFB = 0x0F;\n\n  // Block languages\nconst byte BlockLangAWL       = 0x01;\nconst byte BlockLangKOP       = 0x02;\nconst byte BlockLangFUP       = 0x03;\nconst byte BlockLangSCL       = 0x04;\nconst byte BlockLangDB        = 0x05;\nconst byte BlockLangGRAPH     = 0x06;\n\n  // CPU status\nconst byte S7CpuStatusUnknown = 0x00;\nconst byte S7CpuStatusRun     = 0x08;\nconst byte S7CpuStatusStop    = 0x04;\n\nconst longword evcSnap7Base           = 0x00008000;\n// S7 Server Event Code\nconst longword evcPDUincoming  \t      = 0x00010000;\nconst longword evcDataRead            = 0x00020000;\nconst longword evcDataWrite    \t      = 0x00040000;\nconst longword evcNegotiatePDU        = 0x00080000;\nconst longword evcReadSZL             = 0x00100000;\nconst longword evcClock               = 0x00200000;\nconst longword evcUpload              = 0x00400000;\nconst longword evcDownload            = 0x00800000;\nconst longword evcDirectory           = 0x01000000;\nconst longword evcSecurity            = 0x02000000;\nconst longword evcControl             = 0x04000000;\nconst longword evcReserved_08000000   = 0x08000000;\nconst longword evcReserved_10000000   = 0x10000000;\nconst longword evcReserved_20000000   = 0x20000000;\nconst longword evcReserved_40000000   = 0x40000000;\nconst longword evcReserved_80000000   = 0x80000000;\n// Event SubCodes\nconst word evsUnknown                 = 0x0000;\nconst word evsStartUpload             = 0x0001;\nconst word evsStartDownload           = 0x0001;\nconst word evsGetBlockList            = 0x0001;\nconst word evsStartListBoT            = 0x0002;\nconst word evsListBoT                 = 0x0003;\nconst word evsGetBlockInfo            = 0x0004;\nconst word evsGetClock                = 0x0001;\nconst word evsSetClock                = 0x0002;\nconst word evsSetPassword             = 0x0001;\nconst word evsClrPassword             = 0x0002;\n// Event Result\nconst word evrNoError                 = 0;\nconst word evrFragmentRejected        = 0x0001;\nconst word evrMalformedPDU            = 0x0002;\nconst word evrSparseBytes             = 0x0003;\nconst word evrCannotHandlePDU         = 0x0004;\nconst word evrNotImplemented          = 0x0005;\nconst word evrErrException            = 0x0006;\nconst word evrErrAreaNotFound         = 0x0007;\nconst word evrErrOutOfRange           = 0x0008;\nconst word evrErrOverPDU              = 0x0009;\nconst word evrErrTransportSize        = 0x000A;\nconst word evrInvalidGroupUData       = 0x000B;\nconst word evrInvalidSZL              = 0x000C;\nconst word evrDataSizeMismatch        = 0x000D;\nconst word evrCannotUpload            = 0x000E;\nconst word evrCannotDownload          = 0x000F;\nconst word evrUploadInvalidID         = 0x0010;\nconst word evrResNotFound             = 0x0011;\n\n  // Async mode\nconst int amPolling   = 0;\nconst int amEvent     = 1;\nconst int amCallBack  = 2;\n\n//------------------------------------------------------------------------------\n//                                  PARAMS LIST            \n// Notes for Local/Remote Port\n//   If the local port for a server and remote port for a client is != 102 they\n//   will be *no more compatible with S7 IsoTCP*\n//   A good reason to change them could be inside a debug session under Unix.\n//   Increasing the port over 1024 avoids the need of be root. \n//   Obviously you need to work with the couple Snap7Client/Snap7Server and change\n//   both, or, use iptable and nat the port.\n//------------------------------------------------------------------------------\nconst int p_u16_LocalPort  \t    = 1;\nconst int p_u16_RemotePort \t    = 2;\nconst int p_i32_PingTimeout\t    = 3;\nconst int p_i32_SendTimeout     = 4;\nconst int p_i32_RecvTimeout     = 5;\nconst int p_i32_WorkInterval    = 6;\nconst int p_u16_SrcRef          = 7;\nconst int p_u16_DstRef          = 8;\nconst int p_u16_SrcTSap         = 9;\nconst int p_i32_PDURequest      = 10;\nconst int p_i32_MaxClients      = 11;\nconst int p_i32_BSendTimeout    = 12;\nconst int p_i32_BRecvTimeout    = 13;\nconst int p_u32_RecoveryTime    = 14;\nconst int p_u32_KeepAliveTime   = 15;\n\n// Bool param is passed as int32_t : 0->false, 1->true\n// String param (only set) is passed as pointer\n\ntypedef int16_t   *Pint16_t;     \ntypedef uint16_t  *Puint16_t;     \ntypedef int32_t   *Pint32_t;     \ntypedef uint32_t  *Puint32_t;     \ntypedef int64_t   *Pint64_t;     \ntypedef uint64_t  *Puint64_t;     \ntypedef uintptr_t *Puintptr_t;\n//-----------------------------------------------------------------------------\n//                               INTERNALS CONSTANTS\n//------------------------------------------------------------------------------\n\nconst word DBMaxName = 0xFFFF; // max number (name) of DB\n\nconst longword errS7Mask         = 0xFFF00000;\nconst longword errS7Base         = 0x000FFFFF;\nconst longword errS7notConnected = errS7Base+0x0001; // Client not connected\nconst longword errS7InvalidMode  = errS7Base+0x0002; // Requested a connection to...\nconst longword errS7InvalidPDUin = errS7Base+0x0003; // Malformed input PDU\n\n// S7 outcoming Error code\nconst word Code7Ok                      = 0x0000;\nconst word Code7AddressOutOfRange       = 0x0005;\nconst word Code7InvalidTransportSize    = 0x0006;\nconst word Code7WriteDataSizeMismatch   = 0x0007;\nconst word Code7ResItemNotAvailable   \t= 0x000A;\nconst word Code7ResItemNotAvailable1    = 0xD209;\nconst word Code7InvalidValue   \t        = 0xDC01;\nconst word Code7NeedPassword            = 0xD241;\nconst word Code7InvalidPassword         = 0xD602;\nconst word Code7NoPasswordToClear   \t= 0xD604;\nconst word Code7NoPasswordToSet         = 0xD605;\nconst word Code7FunNotAvailable         = 0x8104;\nconst word Code7DataOverPDU             = 0x8500;\n\n// Result transport size\nconst byte TS_ResBit   = 0x03;\nconst byte TS_ResByte  = 0x04;\nconst byte TS_ResInt   = 0x05;\nconst byte TS_ResReal  = 0x07;\nconst byte TS_ResOctet = 0x09;\n\n// Client Job status (lib internals, not S7)\nconst int JobComplete  = 0;\nconst int JobPending   = 1;\n\n// Control codes\nconst word CodeControlUnknown   = 0;\nconst word CodeControlColdStart = 1;      // Cold start\nconst word CodeControlWarmStart = 2;      // Warm start\nconst word CodeControlStop      = 3;      // Stop\nconst word CodeControlCompress  = 4;      // Compress\nconst word CodeControlCpyRamRom = 5;      // Copy Ram to Rom\nconst word CodeControlInsDel    = 6;      // Insert in working ram the block downloaded\n\t\t\t\t\t  // Delete from working ram the block selected\n// PDU Type\nconst byte PduType_request      = 1;      // family request\nconst byte PduType_response     = 3;      // family response\nconst byte PduType_userdata     = 7;      // family user data\n\n// PDU Functions\nconst byte pduResponse    \t= 0x02;   // Response (when error)\nconst byte pduFuncRead    \t= 0x04;   // Read area\nconst byte pduFuncWrite   \t= 0x05;   // Write area\nconst byte pduNegotiate   \t= 0xF0;   // Negotiate PDU length\nconst byte pduStart         = 0x28;   // CPU start\nconst byte pduStop          = 0x29;   // CPU stop\nconst byte pduStartUpload   = 0x1D;   // Start Upload\nconst byte pduUpload        = 0x1E;   // Upload\nconst byte pduEndUpload     = 0x1F;   // EndUpload\nconst byte pduReqDownload   = 0x1A;   // Start Download request\nconst byte pduDownload      = 0x1B;   // Download request\nconst byte pduDownloadEnded = 0x1C;   // Download end request\nconst byte pduControl   \t= 0x28;   // Control (insert/delete..)\n\n// PDU SubFunctions\nconst byte SFun_ListAll   \t= 0x01;   // List all blocks\nconst byte SFun_ListBoT   \t= 0x02;   // List Blocks of type\nconst byte SFun_BlkInfo   \t= 0x03;   // Get Block info\nconst byte SFun_ReadSZL   \t= 0x01;   // Read SZL \nconst byte SFun_ReadClock   = 0x01;   // Read Clock (Date and Time)\nconst byte SFun_SetClock  \t= 0x02;   // Set Clock (Date and Time)\nconst byte SFun_EnterPwd    = 0x01;   // Enter password    for this session\nconst byte SFun_CancelPwd   = 0x02;   // Cancel password    for this session\nconst byte SFun_Insert   \t= 0x50;   // Insert block\nconst byte SFun_Delete   \t= 0x42;   // Delete block\n\ntypedef tm *PTimeStruct;\n\n//==============================================================================\n//                                   HEADERS\n//==============================================================================\n#pragma pack(1)\n\n// Tag Struct\ntypedef struct{\n\tint Area;\n\tint DBNumber;\n\tint Start;\n\tint Size;\n\tint WordLen;\n}TS7Tag, *PS7Tag;\n\n// Incoming header, it will be mapped onto IsoPDU payload\ntypedef struct {\n\tbyte    P;        // Telegram ID, always 32\n\tbyte    PDUType;  // Header type 1 or 7\n\tword    AB_EX;    // AB currently unknown, maybe it can be used for long numbers.\n\tword    Sequence; // Message ID. This can be used to make sure a received answer\n\tword    ParLen;   // Length of parameters which follow this header\n\tword    DataLen;  // Length of data which follow the parameters\n}TS7ReqHeader;\n\ntypedef TS7ReqHeader* PS7ReqHeader;\n\n// Outcoming 12 bytes header , response for Request type 1\ntypedef struct{\n\tbyte    P;        // Telegram ID, always 32\n\tbyte    PDUType;  // Header type 2 or 3\n\tword    AB_EX;    // AB currently unknown, maybe it can be used for long numbers.\n\tword    Sequence; // Message ID. This can be used to make sure a received answer\n\tword    ParLen;   // Length of parameters which follow this header\n\tword    DataLen;  // Length of data which follow the parameters\n\tword    Error;    // Error code\n} TS7ResHeader23;\n\ntypedef TS7ResHeader23* PS7ResHeader23;\n\n// Outcoming 10 bytes header , response for Request type 7\ntypedef struct{\n\tbyte    P;        // Telegram ID, always 32\n\tbyte    PDUType;  // Header type 1 or 7\n\tword    AB_EX;    // AB currently unknown, maybe it can be used for long numbers.\n\tword    Sequence; // Message ID. This can be used to make sure a received answer\n\tword    ParLen;   // Length of parameters which follow this header\n\tword    DataLen;  // Length of data which follow the parameters\n}TS7ResHeader17;\n\ntypedef TS7ResHeader17* PS7ResHeader17;\n\n// Outcoming 10 bytes header , response for Request type 8 (server control)\ntypedef struct {\n\tbyte    P;        // Telegram ID, always 32\n\tbyte    PDUType;  // Header type 8\n\tword    AB_EX;    // Zero\n\tword    Sequence; // Message ID. This can be used to make sure a received answer\n\tword    DataLen;  // Length of data which follow this header\n\tword    Error;    // Error code\n} TS7ResHeader8;\n\ntypedef TS7ResHeader8* PS7ResHeader8;\n\n// Outcoming answer buffer header type 2 or header type 3\ntypedef struct{\n\tTS7ResHeader23 Header;\n\tbyte   ResData [IsoPayload_Size - sizeof(TS7ResHeader23)];\n} TS7Answer23;\n\ntypedef TS7Answer23* PS7Answer23;\n\n// Outcoming buffer header type 1 or header type 7\ntypedef struct {\n\tTS7ResHeader17 Header;\n\tbyte   ResData [IsoPayload_Size - sizeof(TS7ResHeader17)];\n} TS7Answer17;\n\ntypedef TS7Answer17* PS7Answer17;\n\ntypedef byte   TTimeBuffer[8];\ntypedef byte   *PTimeBuffer[8];\n\ntypedef struct{\n   byte bcd_year;\n   byte bcd_mon;\n   byte bcd_day;\n   byte bcd_hour;\n   byte bcd_min;\n   byte bcd_sec;\n   byte bcd_himsec;\n   byte bcd_dow;\n}TS7Time, *PS7Time;\n\ntypedef byte   TS7Buffer[65536];\ntypedef byte   *PS7Buffer;\n\nconst int ReqHeaderSize   = sizeof(TS7ReqHeader);\nconst int ResHeaderSize23 = sizeof(TS7ResHeader23);\nconst int ResHeaderSize17 = sizeof(TS7ResHeader17);\n\n// Most used request type parameters record\ntypedef struct {\n\tbyte   Head[3];// 0x00 0x01 0x12\n\tbyte   Plen;   // par len 0x04\n\tbyte   Uk;     // unknown\n\tbyte   Tg;     // type and group  (4 bits type and 4 bits group)\n\tbyte   SubFun; // subfunction\n\tbyte   Seq;    // sequence\n}TReqFunTypedParams;\n\n//==============================================================================\n//                            FUNCTION NEGOTIATE\n//==============================================================================\ntypedef struct {\n\tbyte    FunNegotiate;\n\tbyte    Unknown;\n\tword    ParallelJobs_1;\n\tword    ParallelJobs_2;\n\tword    PDULength;\n}TReqFunNegotiateParams;\n\ntypedef TReqFunNegotiateParams* PReqFunNegotiateParams;\n\ntypedef struct {\n\tbyte    FunNegotiate;\n\tbyte    Unknown;\n\tword    ParallelJobs_1;\n\tword    ParallelJobs_2;\n\tword    PDULength;\n}TResFunNegotiateParams;\n\ntypedef TResFunNegotiateParams* PResFunNegotiateParams;\n\n//==============================================================================\n//                               FUNCTION READ\n//==============================================================================\ntypedef struct {\n\tbyte    ItemHead[3];\n\tbyte    TransportSize;\n\tword    Length;\n\tword    DBNumber;\n\tbyte    Area;\n\tbyte    Address[3];\n}TReqFunReadItem, * PReqFunReadItem;\n\n//typedef TReqFunReadItem;\n\ntypedef struct {\n\tbyte   FunRead;\n\tbyte   ItemsCount;\n\tTReqFunReadItem Items[MaxVars];\n}TReqFunReadParams;\n\ntypedef TReqFunReadParams* PReqFunReadParams;\n\ntypedef struct {\n\tbyte   FunRead;\n\tbyte   ItemCount;\n}TResFunReadParams;\n\ntypedef TResFunReadParams* PResFunReadParams;\n\ntypedef struct {\n\tbyte    ReturnCode;\n\tbyte    TransportSize;\n\tword    DataLength;\n\tbyte    Data[IsoPayload_Size - 17]; // 17 = header + params + data header - 1\n}TResFunReadItem, *PResFunReadItem;\n\ntypedef PResFunReadItem TResFunReadData[MaxVars];\n\n//==============================================================================\n//                               FUNCTION WRITE\n//==============================================================================\ntypedef struct {\n\tbyte    ItemHead[3];\n\tbyte    TransportSize;\n\tword    Length;\n\tword    DBNumber;\n\tbyte    Area;\n\tbyte    Address[3];\n}TReqFunWriteItem, * PReqFunWriteItem;\n\ntypedef struct {\n\tbyte   FunWrite;\n\tbyte   ItemsCount;\n\tTReqFunWriteItem Items[MaxVars];\n}TReqFunWriteParams;\n\ntypedef TReqFunWriteParams* PReqFunWriteParams;\n\ntypedef struct {\n\tbyte    ReturnCode;\n\tbyte    TransportSize;\n\tword    DataLength;\n\tbyte    Data [IsoPayload_Size - 17]; // 17 = header + params + data header -1\n}TReqFunWriteDataItem, *PReqFunWriteDataItem;\n\ntypedef PReqFunWriteDataItem TReqFunWriteData[MaxVars];\n\ntypedef struct {\n\tbyte   FunWrite;\n\tbyte   ItemCount;\n\tbyte   Data[MaxVars];\n}TResFunWrite;\n\ntypedef TResFunWrite* PResFunWrite;\n\n//==============================================================================\n//                                 GROUP UPLOAD\n//==============================================================================\ntypedef struct {\n\tbyte   FunSUpld;    // function start upload 0x1D\n\tbyte   Uk6 [6];     // Unknown 6 bytes\n\tbyte   Upload_ID;\n\tbyte   Len_1;\n\tbyte   Prefix;\n\tbyte   BlkPrfx;     // always 0x30\n\tbyte   BlkType;\n\tbyte   AsciiBlk[5]; // BlockNum in ascii\n\tbyte   A;           // always 0x41 ('A')\n}TReqFunStartUploadParams;\n\ntypedef TReqFunStartUploadParams* PReqFunStartUploadParams;\n\ntypedef struct {\n\tbyte   FunSUpld;  // function start upload 0x1D\n\tbyte   Data_1[6];\n\tbyte   Upload_ID;\n\tbyte   Uk[3];\n\tbyte   LenLoad[5];\n}TResFunStartUploadParams;\n\ntypedef TResFunStartUploadParams* PResFunStartUploadParams;\n\ntypedef struct {\n\tbyte   FunUpld;  // function upload 0x1E\n\tbyte   Uk6[6];   // Unknown 6 bytes\n\tbyte   Upload_ID;\n}TReqFunUploadParams;\n\ntypedef TReqFunUploadParams* PReqFunUploadParams;\n\ntypedef struct {\n\tbyte   FunUpld; // function upload 0x1E\n\tbyte   EoU;     // 0 = End Of Upload, 1 = Upload in progress\n}TResFunUploadParams;\n\ntypedef TResFunUploadParams* PResFunUploadParams;\n\ntypedef struct {\n\tword    Length;   // Payload length - 4\n\tbyte    Uk_00;    // Unknown 0x00\n\tbyte    Uk_FB;    // Unknown 0xFB\n\t// from here is the same of TS7CompactBlockInfo\n\tword    Cst_pp;\n\tbyte    Uk_01;    // Unknown 0x01\n\tbyte    BlkFlags;\n\tbyte    BlkLang;\n\tbyte    SubBlkType;\n\tword    BlkNum;\n\tu_int   LenLoadMem;\n\tu_int   BlkSec;\n\tu_int   CodeTime_ms;\n\tword    CodeTime_dy;\n\tu_int   IntfTime_ms;\n\tword    IntfTime_dy;\n\tword    SbbLen;\n\tword    AddLen;\n\tword    LocDataLen;\n\tword    MC7Len;\n}TResFunUploadDataHeaderFirst;\n\ntypedef TResFunUploadDataHeaderFirst* PResFunUploadDataHeaderFirst;\n\ntypedef struct {\n\tword    Length;// Payload length - 4\n\tbyte    Uk_00; // Unknown 0x00\n\tbyte    Uk_FB; // Unknown 0xFB\n}TResFunUploadDataHeaderNext;\n\ntypedef TResFunUploadDataHeaderNext* PResFunUploadDataHeaderNext;\n\ntypedef struct {\n\tword    Length;// Payload length - 4\n\tbyte    Uk_00; // Unknown 0x00\n\tbyte    Uk_FB; // Unknown 0xFB\n}TResFunUploadDataHeader;\n\ntypedef TResFunUploadDataHeader* PResFunUploadDataHeader;\n\ntypedef struct {\n\tbyte    ID;  // 0x65\n\tword    Seq; // Sequence\n\tbyte    Const_1[10];\n\tword    Lo_bound;\n\tword    Hi_Bound;\n\tbyte    u_shortLen;// 0x02 byte\n\t\t\t   // 0x04 word\n\t\t\t   // 0x05 int\n\t\t\t   // 0x06 dword\n\t\t\t   // 0x07 dint\n\t\t\t   // 0x08 real\n\tbyte    c1, c2;\n\tchar    Author[8];\n\tchar    Family[8];\n\tchar    Header[8];\n\tbyte    B1; // 0x11\n\tbyte    B2; // 0x00\n\tword    Chksum;\n\tbyte    Uk_8[8];\n}TArrayUpldFooter;\n\ntypedef TArrayUpldFooter* PArrayUpldFooter;\n\ntypedef struct {\n\tbyte   FunEUpld; // function end upload 0x1F\n\tbyte   Uk6[6];   // Unknown 6 bytes\n\tbyte   Upload_ID;\n}TReqFunEndUploadParams;\n\ntypedef TReqFunEndUploadParams* PReqFunEndUploadParams;\n\ntypedef struct {\n\tbyte   FunEUpld;  // function end upload 0x1F\n}TResFunEndUploadParams;\n\ntypedef TResFunEndUploadParams* PResFunEndUploadParams;\n\n//==============================================================================\n//                               GROUP DOWNLOAD\n//==============================================================================\ntypedef struct {\n\tbyte   FunSDwnld;   // function start Download 0x1A\n\tbyte   Uk6[6];      // Unknown 6 bytes\n\tbyte   Dwnld_ID;\n\tbyte   Len_1;       // 0x09\n\tbyte   Prefix;      // 0x5F\n\tbyte   BlkPrfx;     // always 0x30\n\tbyte   BlkType;\n\tbyte   AsciiBlk[5]; // BlockNum in ascii\n\tbyte   P;           // 0x50 ('P')\n\tbyte   Len_2;       // 0x0D\n\tbyte   Uk1;         // 0x01\n\tbyte   AsciiLoad[6];// load memory size (MC7 size + 92)\n\tbyte   AsciiMC7[6]; // Block size in bytes\n}TReqStartDownloadParams;\n\ntypedef TReqStartDownloadParams* PReqStartDownloadParams;\ntypedef byte  TResStartDownloadParams;\ntypedef TResStartDownloadParams* PResStartDownloadParams;\n\ntypedef struct {\n\tbyte   Fun;         // pduDownload or pduDownloadEnded\n\tbyte   Uk7[7];\n\tbyte   Len_1;       // 0x09\n\tbyte   Prefix;      // 0x5F\n\tbyte   BlkPrfx;     // always 0x30\n\tbyte   BlkType;\n\tbyte   AsciiBlk[5]; // BlockNum in ascii\n\tbyte   P;           // 0x50 ('P')\n}TReqDownloadParams;\n\ntypedef TReqDownloadParams* PReqDownloadParams;\n\ntypedef struct {\n\tbyte   FunDwnld; // 0x1B\n\tbyte   EoS;      // End of sequence : 0x00 - Sequence in progress : 0x01\n}TResDownloadParams;\n\ntypedef TResDownloadParams* PResDownloadParams;\n\ntypedef struct {\n\tword    DataLen;\n\tword    FB_00;   // 0x00 0xFB\n}TResDownloadDataHeader;\n\ntypedef TResDownloadDataHeader* PResDownloadDataHeader;\ntypedef byte   TResEndDownloadParams;\ntypedef TResEndDownloadParams* PResEndDownloadParams;\n\ntypedef struct {\n\tword    Cst_pp;\n\tbyte    Uk_01; // Unknown 0x01\n\tbyte    BlkFlags;\n\tbyte    BlkLang;\n\tbyte    SubBlkType;\n\tword    BlkNum;\n\tu_int   LenLoadMem;\n\tu_int   BlkSec;\n\tu_int   CodeTime_ms;\n\tword    CodeTime_dy;\n\tu_int   IntfTime_ms;\n\tword    IntfTime_dy;\n\tword    SbbLen;\n\tword    AddLen;\n\tword    LocDataLen;\n\tword    MC7Len;\n}TS7CompactBlockInfo;\n\ntypedef TS7CompactBlockInfo* PS7CompactBlockInfo;\n\ntypedef struct {\n\tbyte    Uk_20[20];\n\tbyte    Author[8];\n\tbyte    Family[8];\n\tbyte    Header[8];\n\tbyte    B1; // 0x11\n\tbyte    B2; // 0x00\n\tword    Chksum;\n\tbyte    Uk_12[8];\n}TS7BlockFooter;\n\ntypedef TS7BlockFooter* PS7BlockFooter;\n\n//==============================================================================\n//                          FUNCTION INSERT/DELETE\n//==============================================================================\ntypedef struct {\n\tbyte    Fun;         // plc control 0x28\n\tbyte    Uk7[7];      // unknown 7\n\tword    Len_1;       // Length part 1 : 10\n\tbyte    NumOfBlocks; // number of blocks to insert\n\tbyte    ByteZero;    // 0x00\n\tbyte    AsciiZero;   // 0x30 '0'\n\tbyte    BlkType;\n\tbyte    AsciiBlk[5]; // BlockNum in ascii\n\tbyte    SFun;        // 0x50 or 0x42\n\tbyte    Len_2;       // Length part 2 : 0x05 bytes\n\tchar    Cmd[5];      // ascii '_INSE' or '_DELE'\n}TReqControlBlockParams;\n\ntypedef TReqControlBlockParams* PReqControlBlockParams;\n\n//==============================================================================\n//                FUNCTIONS START/STOP/COPY RAM TO ROM/COMPRESS\n//==============================================================================\ntypedef struct {\n\tbyte   Fun;     // stop 0x29\n\tbyte   Uk_5[5]; // unknown 5 bytes 0x00\n\tbyte   Len_2;   // Length part 2 : 0x09\n\tchar   Cmd[9];  // ascii 'P_PROGRAM'\n}TReqFunPlcStop;\n\ntypedef TReqFunPlcStop* PReqFunPlcStop;\n\ntypedef struct {\n\tbyte    Fun;     // start 0x28\n\tbyte    Uk_7[7]; // unknown 7\n\tword    Len_1;   // Length part 1 : 0x0000\n\tbyte    Len_2;   // Length part 2 : 0x09\n\tchar    Cmd [9]; // ascii 'P_PROGRAM'\n}TReqFunPlcHotStart;\n\ntypedef TReqFunPlcHotStart* PReqFunPlcHotStart;\n\ntypedef struct {\n\tbyte    Fun;     // start 0x28\n\tbyte    Uk_7[7]; // unknown 7\n\tword    Len_1;   // Length part 1 : 0x0002\n\tword    SFun;    // 'C ' 0x4320\n\tbyte    Len_2;   // Length part 2 : 0x09\n\tchar    Cmd[9];  // ascii 'P_PROGRAM'\n}TReqFunPlcColdStart;\n\ntypedef TReqFunPlcColdStart* PReqFunPlcColdStart;\n\ntypedef struct {\n\tbyte    Fun;     // pduControl 0x28\n\tbyte    Uk_7[7]; // unknown 7\n\tword    Len_1;   // Length part 1 : 0x0002\n\tword    SFun;    // 'EP' 0x4550\n\tbyte    Len_2;   // Length part 2 : 0x05\n\tchar    Cmd[5];  // ascii '_MODU'\n}TReqFunCopyRamToRom;\n\ntypedef TReqFunCopyRamToRom* PReqFunCopyRamToRom;\n\ntypedef struct {\n\tbyte    Fun;     // pduControl 0x28\n\tbyte    Uk_7[7]; // unknown 7\n\tword    Len_1;   // Length part 1 : 0x00\n\tbyte    Len_2;   // Length part 2 : 0x05\n\tchar    Cmd[5];  // ascii '_GARB'\n}TReqFunCompress;\n\ntypedef TReqFunCompress* PReqFunCompress;\n\ntypedef struct {\n\tbyte   ResFun;\n\tbyte   para;\n}TResFunCtrl;\n\ntypedef TResFunCtrl* PResFunCtrl;\n\n//==============================================================================\n//                            FUNCTIONS USERDATA\n//==============================================================================\ntypedef struct {\n\tbyte    Head[3]; // Always 0x00 0x01 0x12\n\tbyte    Plen;    // par len 0x04 or 0x08\n\tbyte    Uk;      // unknown\n\tbyte    Tg;      // type and group  (4 bits type and 4 bits group)\n\tbyte    SubFun;  // subfunction\n\tbyte    Seq;     // sequence\n\tword    resvd;   // present if plen=0x08 (S7 manager online functions)\n\tword    Err;     // present if plen=0x08 (S7 manager online functions)\n}TS7Params7;\n\ntypedef TS7Params7* PS7ReqParams7;\ntypedef TS7Params7* PS7ResParams7;\n\n// for convenience Hi order bit of type are included (0x4X)\nconst byte   grProgrammer  = 0x41;\nconst byte   grCyclicData  = 0x42;\nconst byte   grBlocksInfo  = 0x43;\nconst byte   grSZL         = 0x44;\nconst byte   grPassword    = 0x45;\nconst byte   grBSend       = 0x46;\nconst byte   grClock       = 0x47;\nconst byte   grSecurity    = 0x45;\n\n//==============================================================================\n//                             GROUP SECURITY\n//==============================================================================\ntypedef TReqFunTypedParams TReqFunSecurity;\ntypedef TReqFunSecurity* PReqFunSecurity;\n\ntypedef char TS7Password[8];\n\ntypedef struct {\n\tbyte    Ret;    // 0xFF for request\n\tbyte    TS;     // 0x09 Transport size\n\tword    DLen;   // Data len  : 8 bytes\n\tbyte    Pwd[8]; // Password encoded into \"AG\" format\n}TReqDataSecurity;\n\ntypedef TReqDataSecurity* PReqDataSecurity;\ntypedef TS7Params7 TResParamsSecurity;\ntypedef TResParamsSecurity* PResParamsSecurity;\n\ntypedef struct {\n\tbyte    Ret;\n\tbyte    TS;\n\tword    DLen;\n}TResDataSecurity;\n\ntypedef TResDataSecurity* PResDataSecurity;\n\n//==============================================================================\n//                             GROUP BLOCKS SZL\n//==============================================================================\ntypedef TReqFunTypedParams TReqFunReadSZLFirst;\ntypedef TReqFunReadSZLFirst* PReqFunReadSZLFirst;\n\ntypedef struct {\n\tbyte    Head[3]; // 0x00 0x01 0x12\n\tbyte    Plen;    // par len 0x04\n\tbyte    Uk;      // unknown\n\tbyte    Tg;      // type and group (4 bits type and 4 bits group)\n\tbyte    SubFun;  // subfunction\n\tbyte    Seq;     // sequence\n\tword    Rsvd;    // Reserved 0x0000\n\tword    ErrNo;   // Error Code\n}TReqFunReadSZLNext;\n\ntypedef TReqFunReadSZLNext* PReqFunReadSZLNext;\n\ntypedef struct {\n\tbyte    Ret;  // 0xFF for request\n\tbyte    TS;   // 0x09 Transport size\n\tword    DLen; // Data len\n\tword    ID;   // SZL-ID\n\tword    Index;// SZL-Index\n}TS7ReqSZLData;\n\ntypedef TS7ReqSZLData* PS7ReqSZLData;\n\ntypedef struct {\n\tbyte    Ret;\n\tbyte    TS;\n\tword    DLen;\n\tword    ID;\n\tword    Index;\n\tword    ListLen;\n\tword    ListCount;\n\tword    Data[32747];\n}TS7ResSZLDataFirst;\n\ntypedef TS7ResSZLDataFirst* PS7ResSZLDataFirst;\n\ntypedef struct {\n\tbyte    Ret;\n\tbyte    TS;\n\tword    DLen;\n\tword    Data[32751];\n}TS7ResSZLDataNext;\n\ntypedef TS7ResSZLDataNext* PS7ResSZLDataNext;\n\ntypedef struct {\n\tbyte    Ret;\n\tbyte    OtherInfo[9];\n\tword    Count;\n\tword    Items[32747];\n}TS7ResSZLData_0;\n\ntypedef TS7ResSZLData_0* PS7ResSZLData_0;\n\n//==============================================================================\n//                               GROUP CLOCK\n//==============================================================================\ntypedef TReqFunTypedParams TReqFunDateTime;\ntypedef TReqFunDateTime* PReqFunDateTime;\n\ntypedef byte   TReqDataGetDateTime[4];\n\ntypedef longword *PReqDataGetDateTime;\n\ntypedef struct {\n\tbyte    RetVal;\n\tbyte    TSize;\n\tword    Length;\n\tbyte    Rsvd;\n\tbyte    HiYear;\n\tTTimeBuffer Time;\n}TResDataGetTime;\n\ntypedef TResDataGetTime* PResDataGetTime;\ntypedef TResDataGetTime TReqDataSetTime;\ntypedef TReqDataSetTime* PReqDataSetTime;\n\ntypedef struct {\n\tbyte    RetVal;\n\tbyte    TSize;\n\tword    Length;\n}TResDataSetTime;\n\ntypedef TResDataSetTime* PResDataSetTime;\n\n//==============================================================================\n//                            GROUP BLOCKS INFO\n//==============================================================================\ntypedef TReqFunTypedParams TReqFunGetBlockInfo;\ntypedef TReqFunGetBlockInfo* PReqFunGetBlockInfo;\n\ntypedef byte   TReqDataFunBlocks[4];\ntypedef u_char* PReqDataFunBlocks;\n\ntypedef struct {\n\tbyte    Head[3]; // 0x00 0x01 0x12\n\tbyte    Plen;    // par len 0x04\n\tbyte    Uk;      // unknown\n\tbyte    Tg;      // type and group  (4 bits type and 4 bits group)\n\tbyte    SubFun;  // subfunction\n\tbyte    Seq;     // sequence\n\tword    Rsvd;    // Reserved 0x0000\n\tword    ErrNo;   // Error Code\n}TResFunGetBlockInfo;\n\ntypedef TResFunGetBlockInfo* PResFunGetBlockInfo;\n\ntypedef struct {\n\tbyte    Zero;   // always 0x30 -> Ascii 0\n\tbyte    BType;  // Block Type\n\tword    BCount; // Block count\n}TResFunGetBlockItem;\n\ntypedef struct {\n\tbyte    RetVal;\n\tbyte    TRSize;\n\tword    Length;\n\tTResFunGetBlockItem Blocks[7];\n}TDataFunListAll;\n\ntypedef TDataFunListAll* PDataFunListAll;\n\ntypedef struct {\n\tword    BlockNum;\n\tbyte    Unknown;\n\tbyte    BlockLang;\n}TDataFunGetBotItem;\n\ntypedef struct {\n\tbyte    RetVal;\n\tbyte    TSize;\n\tword    DataLen;\n\tTDataFunGetBotItem Items[(IsoPayload_Size - 29 ) / 4];\n}TDataFunGetBot;\n// Note : 29 is the size of headers iso, COPT, S7 header, params, data\n\ntypedef TDataFunGetBot* PDataFunGetBot;\n\ntypedef struct {\n\tbyte   RetVal;  // 0xFF\n\tbyte   TSize;   // Octet (0x09)\n\tword   Length;  // 0x0002\n\tbyte   Zero;    // Ascii '0' (0x30)\n\tbyte   BlkType;\n}TReqDataBlockOfType;\n\ntypedef TReqDataBlockOfType* PReqDataBlockOfType;\n\ntypedef struct {\n\tbyte    RetVal;\n\tbyte    TSize;\n\tword    DataLen;\n\tbyte    BlkPrfx;     // always 0x30\n\tbyte    BlkType;\n\tbyte    AsciiBlk[5]; // BlockNum in ascii\n\tbyte    A;           // always 0x41 ('A')\n}TReqDataBlockInfo;\n\ntypedef TReqDataBlockInfo* PReqDataBlockInfo;\n\ntypedef struct {\n\tbyte    RetVal;\n\tbyte    TSize;\n\tword    Length;\n\tbyte    Cst_b;\n\tbyte    BlkType;\n\tword    Cst_w1;\n\tword    Cst_w2;\n\tword    Cst_pp;\n\tbyte    Unknown_1;\n\tbyte    BlkFlags;\n\tbyte    BlkLang;\n\tbyte    SubBlkType;\n\tword    BlkNumber;\n\tu_int   LenLoadMem;\n\tbyte    BlkSec[4];\n\tu_int   CodeTime_ms;\n\tword    CodeTime_dy;\n\tu_int   IntfTime_ms;\n\tword    IntfTime_dy;\n\tword    SbbLen;\n\tword    AddLen;\n\tword    LocDataLen;\n\tword    MC7Len;\n\tbyte    Author[8];\n\tbyte    Family[8];\n\tbyte    Header[8];\n\tbyte    Version;\n\tbyte    Unknown_2;\n\tword    BlkChksum;\n\tbyte    Resvd1[4];\n\tbyte    Resvd2[4];\n}TResDataBlockInfo;\n\ntypedef TResDataBlockInfo* PResDataBlockInfo;\n\n//==============================================================================\n//                                 BSEND / BRECV\n//==============================================================================\ntypedef struct {\n\tint       Size;\n\tlongword  R_ID;\n\tbyte      Data[65536];\n}TPendingBuffer;\n\ntypedef struct {\n\tTTPKT    TPKT;\n\tTCOTP_DT COTP;\n\tbyte     P;\n\tbyte     PDUType;\n}TPacketInfo;\n\ntypedef struct {\n\tbyte    Head[3];// Always 0x00 0x01 0x12\n\tbyte    Plen;   // par len 0x04 or 0x08\n\tbyte    Uk;     // unknown  (0x12)\n\tbyte    Tg;     // type and group, 4 bits type and 4 bits group  (0x46)\n\tbyte    SubFun; // subfunction (0x01)\n\tbyte    Seq;    // sequence\n\tbyte    IDSeq;  // ID Sequence (come from partner)\n\tbyte    EoS;    // End of Sequence = 0x00 Sequence in progress = 0x01;\n\tword    Err;    //\n}TBSendParams;\n\ntypedef TBSendParams* PBSendReqParams;\ntypedef TBSendParams* PBSendResParams;\n\n// Data frame\n\ntypedef struct {\n\tbyte    FF;      // 0xFF\n\tbyte    TRSize;  // Transport Size 0x09 (octet)\n\tword    Len;     // This Telegram Length\n\tbyte    DHead[4];// sequence 0x12 0x06 0x13 0x00\n\tu_int   R_ID;    // R_ID\n}TBsendRequestData;\n\ntypedef TBsendRequestData* PBsendRequestData;\n\ntypedef struct {\n\tbyte   DHead[4]; // sequence 0x0A 0x00 0x00 0x00\n}TBSendResData;\n\ntypedef TBSendResData* PBSendResData;\n\n#pragma pack()\n#endif // s7_types_h\n"
  },
  {
    "path": "deps/snap7/src/lib/snap7.def",
    "content": "LIBRARY SNAP7.DLL\nEXPORTS\n  Cli_Create\n  Cli_Destroy\n  Cli_ConnectTo\n  Cli_SetConnectionParams\n  Cli_SetConnectionType\n  Cli_Connect\n  Cli_Disconnect\n  Cli_GetParam\n  Cli_SetParam\n  Cli_SetAsCallback\n  Cli_ReadArea\n  Cli_WriteArea\n  Cli_ReadMultiVars\n  Cli_WriteMultiVars\n  Cli_DBRead\n  Cli_DBWrite\n  Cli_MBRead\n  Cli_MBWrite\n  Cli_EBRead\n  Cli_EBWrite\n  Cli_ABRead\n  Cli_ABWrite\n  Cli_TMRead\n  Cli_TMWrite\n  Cli_CTRead\n  Cli_CTWrite\n  Cli_ListBlocks\n  Cli_GetAgBlockInfo\n  Cli_GetPgBlockInfo\n  Cli_ListBlocksOfType\n  Cli_Upload\n  Cli_FullUpload\n  Cli_Download\n  Cli_Delete\n  Cli_DBGet\n  Cli_DBFill\n  Cli_GetPlcDateTime\n  Cli_SetPlcDateTime\n  Cli_SetPlcSystemDateTime\n  Cli_GetOrderCode\n  Cli_GetCpuInfo\n  Cli_GetCpInfo\n  Cli_ReadSZL\n  Cli_ReadSZLList\n  Cli_PlcHotStart\n  Cli_PlcColdStart\n  Cli_PlcStop\n  Cli_CopyRamToRom\n  Cli_Compress\n  Cli_GetPlcStatus\n  Cli_GetProtection\n  Cli_SetSessionPassword\n  Cli_ClearSessionPassword\n  Cli_IsoExchangeBuffer\n  Cli_GetExecTime\n  Cli_GetLastError\n  Cli_GetPduLength\n  Cli_AsReadArea\n  Cli_AsWriteArea\n  Cli_AsDBRead\n  Cli_AsDBWrite\n  Cli_AsMBRead\n  Cli_AsMBWrite\n  Cli_AsEBRead\n  Cli_AsEBWrite\n  Cli_AsABRead\n  Cli_AsABWrite\n  Cli_AsTMRead\n  Cli_AsTMWrite\n  Cli_AsCTRead\n  Cli_AsCTWrite\n  Cli_AsListBlocksOfType\n  Cli_AsReadSZL\n  Cli_AsReadSZLList\n  Cli_AsUpload\n  Cli_AsFullUpload\n  Cli_AsDownload\n  Cli_AsCopyRamToRom\n  Cli_AsCompress\n  Cli_AsDBGet\n  Cli_AsDBFill\n  Cli_CheckAsCompletion\n  Cli_WaitAsCompletion\n  Cli_ErrorText\n  Cli_GetConnected\n  Srv_Create\n  Srv_Destroy\n  Srv_GetParam\n  Srv_SetParam\n  Srv_StartTo\n  Srv_Start\n  Srv_Stop\n  Srv_RegisterArea\n  Srv_UnregisterArea\n  Srv_LockArea\n  Srv_UnlockArea\n  Srv_GetStatus\n  Srv_SetCpuStatus\n  Srv_ClearEvents\n  Srv_PickEvent\n  Srv_GetMask\n  Srv_SetMask\n  Srv_SetEventsCallback\n  Srv_SetReadEventsCallback\n  Srv_SetRWAreaCallback\n  Srv_ErrorText\n  Srv_EventText\n  Par_Create\n  Par_Destroy\n  Par_GetParam\n  Par_SetParam\n  Par_StartTo\n  Par_Start\n  Par_Stop\n  Par_BSend\n  Par_AsBSend\n  Par_CheckAsBSendCompletion\n  Par_WaitAsBSendCompletion\n  Par_SetSendCallback\n  Par_BRecv\n  Par_CheckAsBRecvCompletion\n  Par_SetRecvCallback\n  Par_GetTimes\n  Par_GetStats\n  Par_GetLastError\n  Par_GetStatus\n  Par_ErrorText\n"
  },
  {
    "path": "deps/snap7/src/lib/snap7_libmain.cpp",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.4.1 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|=============================================================================*/\n#include \"snap7_libmain.h\"\n\n#ifndef OS_WINDOWS\nvoid libinit(void) __attribute__((constructor));\nvoid libdone(void) __attribute__((destructor));\n#endif\n\nstatic bool libresult = true;\n\nvoid libinit(void)\n{\n     // in future expansions here can be inserted some initialization code\n     libresult=true;\n}\n\nvoid libdone(void)\n{\n     // in future expansions here can be inserted some destruction code\n}\n\n#ifdef OS_WINDOWS\nBOOL APIENTRY DllMain (HINSTANCE hInst,\n                       DWORD reason,\n                       LPVOID reserved)\n{\n    switch (reason)\n    {\n      case DLL_PROCESS_ATTACH:\n        libinit();\n        break;\n      case DLL_PROCESS_DETACH:\n        libdone();\n        break;\n      case DLL_THREAD_ATTACH:\n        break;\n      case DLL_THREAD_DETACH:\n        break;\n    }\n    return libresult;\n}\n#endif\n\n//***************************************************************************\n// CLIENT\n//***************************************************************************\nS7Object S7API Cli_Create()\n{    \n    return S7Object(new TSnap7Client());\n}\n//---------------------------------------------------------------------------\nvoid S7API Cli_Destroy(S7Object &Client)\n{\n    if (Client)\n    {\n        delete PSnap7Client(Client);\n        Client=0;\n    }\n}\n//---------------------------------------------------------------------------\nint S7API Cli_SetConnectionParams(S7Object Client, const char *Address, word LocalTSAP, word RemoteTSAP)\n{\n    if (Client)\n    {\n        PSnap7Client(Client)->SetConnectionParams(Address, LocalTSAP, RemoteTSAP);\n        return 0;\n    }\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_SetConnectionType(S7Object Client, word ConnectionType)\n{\n    if (Client)\n    {\n        PSnap7Client(Client)->SetConnectionType(ConnectionType);\n        return 0;\n    }\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_ConnectTo(S7Object Client, const char *Address, int Rack, int Slot)\n{\n    if (Client)\n        return PSnap7Client(Client)->ConnectTo(Address, Rack, Slot);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_Connect(S7Object Client)\n{\n    if (Client)\n        return PSnap7Client(Client)->Connect();\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_Disconnect(S7Object Client)\n{\n    if (Client)\n        return PSnap7Client(Client)->Disconnect();\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_GetParam(S7Object Client, int ParamNumber, void *pValue)\n{\n    if (Client)\n        return PSnap7Client(Client)->GetParam(ParamNumber, pValue);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_SetParam(S7Object Client, int ParamNumber, void *pValue)\n{\n    if (Client)\n        return PSnap7Client(Client)->SetParam(ParamNumber, pValue);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_SetAsCallback(S7Object Client, pfn_CliCompletion pCompletion, void *usrPtr)\n{\n    if (Client)\n        return PSnap7Client(Client)->SetAsCallback(pCompletion, usrPtr);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_ReadArea(S7Object Client, int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->ReadArea(Area, DBNumber, Start, Amount, WordLen, pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_WriteArea(S7Object Client, int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->WriteArea(Area, DBNumber, Start, Amount, WordLen, pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_ReadMultiVars(S7Object Client, PS7DataItem Item, int ItemsCount)\n{\n    if (Client)\n        return PSnap7Client(Client)->ReadMultiVars(Item, ItemsCount);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_WriteMultiVars(S7Object Client, PS7DataItem Item, int ItemsCount)\n{\n    if (Client)\n        return PSnap7Client(Client)->WriteMultiVars(Item, ItemsCount);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_DBRead(S7Object Client, int DBNumber, int Start, int Size, void *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->DBRead(DBNumber, Start, Size, pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_DBWrite(S7Object Client, int DBNumber, int Start, int Size, void *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->DBWrite(DBNumber, Start, Size, pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_MBRead(S7Object Client, int Start, int Size, void *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->MBRead(Start, Size, pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_MBWrite(S7Object Client, int Start, int Size, void *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->MBWrite(Start, Size, pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_EBRead(S7Object Client, int Start, int Size, void *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->EBRead(Start, Size, pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_EBWrite(S7Object Client, int Start, int Size, void *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->EBWrite(Start, Size, pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_ABRead(S7Object Client, int Start, int Size, void *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->ABRead(Start, Size, pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_ABWrite(S7Object Client, int Start, int Size, void *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->ABWrite(Start, Size, pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_TMRead(S7Object Client, int Start, int Amount, void *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->TMRead(Start, Amount, pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_TMWrite(S7Object Client, int Start, int Amount, void *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->TMWrite(Start, Amount, pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_CTRead(S7Object Client, int Start, int Amount, void *pUsrData)\n{\n    if (Client)\n         return PSnap7Client(Client)->CTRead(Start, Amount, pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_CTWrite(S7Object Client, int Start, int Amount, void *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->CTWrite(Start, Amount, pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_ListBlocks(S7Object Client, TS7BlocksList *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->ListBlocks(pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_GetAgBlockInfo(S7Object Client, int BlockType, int BlockNum, TS7BlockInfo *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->GetAgBlockInfo(BlockType, BlockNum, pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_GetPgBlockInfo(S7Object Client, void *pBlock, TS7BlockInfo *pUsrData, int Size)\n{\n    if (Client)\n        return PSnap7Client(Client)->GetPgBlockInfo(pBlock, pUsrData, Size);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_ListBlocksOfType(S7Object Client, int BlockType, TS7BlocksOfType *pUsrData, int &ItemsCount)\n{\n    if (Client)\n        return PSnap7Client(Client)->ListBlocksOfType(BlockType, pUsrData, ItemsCount);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_Upload(S7Object Client, int BlockType, int BlockNum, void *pUsrData, int &Size)\n{\n    if (Client)\n        return PSnap7Client(Client)->Upload(BlockType, BlockNum, pUsrData, Size);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_FullUpload(S7Object Client, int BlockType, int BlockNum, void *pUsrData, int &Size)\n{\n    if (Client)\n        return PSnap7Client(Client)->FullUpload(BlockType, BlockNum, pUsrData, Size);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_Download(S7Object Client, int BlockNum, void *pUsrData, int Size)\n{\n    if (Client)\n        return PSnap7Client(Client)->Download(BlockNum, pUsrData, Size);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_Delete(S7Object Client, int BlockType, int BlockNum)\n{\n    if (Client)\n        return PSnap7Client(Client)->Delete(BlockType, BlockNum);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_DBGet(S7Object Client, int DBNumber, void *pUsrData, int &Size)\n{\n    if (Client)\n        return PSnap7Client(Client)->DBGet(DBNumber, pUsrData, Size);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_DBFill(S7Object Client, int DBNumber, int FillChar)\n{\n    if (Client)\n        return PSnap7Client(Client)->DBFill(DBNumber, FillChar);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_GetPlcDateTime(S7Object Client, tm &DateTime)\n{\n    if (Client)\n        return PSnap7Client(Client)->GetPlcDateTime(DateTime);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_SetPlcDateTime(S7Object Client, tm *DateTime)\n{\n    if (Client)\n        return PSnap7Client(Client)->SetPlcDateTime(DateTime);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_SetPlcSystemDateTime(S7Object Client)\n{\n    if (Client)\n        return PSnap7Client(Client)->SetPlcSystemDateTime();\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_GetOrderCode(S7Object Client, TS7OrderCode *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->GetOrderCode(pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_GetCpuInfo(S7Object Client, TS7CpuInfo *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->GetCpuInfo(pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_GetCpInfo(S7Object Client, TS7CpInfo *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->GetCpInfo(pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_ReadSZL(S7Object Client, int ID, int Index, TS7SZL *pUsrData, int &Size)\n{\n    if (Client)\n        return PSnap7Client(Client)->ReadSZL(ID, Index, pUsrData, Size);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_ReadSZLList(S7Object Client, TS7SZLList *pUsrData, int &ItemsCount)\n{\n    if (Client)\n        return PSnap7Client(Client)->ReadSZLList(pUsrData, ItemsCount);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_PlcHotStart(S7Object Client)\n{\n    if (Client)\n        return PSnap7Client(Client)->PlcHotStart();\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_PlcColdStart(S7Object Client)\n{\n    if (Client)\n        return PSnap7Client(Client)->PlcColdStart();\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_PlcStop(S7Object Client)\n{\n    if (Client)\n        return PSnap7Client(Client)->PlcStop();\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_CopyRamToRom(S7Object Client, int Timeout)\n{\n    if (Client)\n        return PSnap7Client(Client)->CopyRamToRom(Timeout);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_Compress(S7Object Client, int Timeout)\n{\n    if (Client)\n        return PSnap7Client(Client)->Compress(Timeout);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_GetPlcStatus(S7Object Client, int &Status)\n{\n    if (Client)\n        return PSnap7Client(Client)->GetPlcStatus(Status);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_GetProtection(S7Object Client, TS7Protection *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->GetProtection(pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_SetSessionPassword(S7Object Client, char *Password)\n{\n    if (Client)\n        return PSnap7Client(Client)->SetSessionPassword(Password);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_ClearSessionPassword(S7Object Client)\n{\n    if (Client)\n        return PSnap7Client(Client)->ClearSessionPassword();\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_IsoExchangeBuffer(S7Object Client, void *pUsrData, int &Size)\n{\n    if (Client)\n        return PSnap7Client(Client)->isoExchangeBuffer(pUsrData, Size);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_GetExecTime(S7Object Client, int &Time)\n{\n    if (Client)\n    {\n        Time=PSnap7Client(Client)->Time();\n        return 0;\n    }\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_GetLastError(S7Object Client, int &LastError)\n{\n    if (Client)\n    {\n        LastError=PSnap7Client(Client)->LastError;\n        return 0;\n    }\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_GetPduLength(S7Object Client, int &Requested, int &Negotiated)\n{\n    if (Client)\n    {\n        Negotiated=PSnap7Client(Client)->PDULength;\n        Requested =PSnap7Client(Client)->PDURequest;\n        return 0;\n    }\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_ErrorText(int Error, char *Text, int TextLen)\n{\n\ttry{\n\t\tErrCliText(Error, Text, TextLen);\n\t\tText[TextLen - 1] = '\\0';\n\t}\n\tcatch (...){\n\t\treturn errLibInvalidParam;\n\t}\n\treturn 0;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_GetConnected(S7Object Client, int &Connected)\n{\n    Connected=0;\n\tif (Client)\n    {\n\t\tConnected=PSnap7Client(Client)->Connected;\n\t\treturn 0;\n\t}\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_AsReadArea(S7Object Client, int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->AsReadArea(Area, DBNumber, Start, Amount, WordLen, pUsrData);\n    else\n        return errLibInvalidParam;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_AsWriteArea(S7Object Client, int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->AsWriteArea(Area, DBNumber, Start, Amount, WordLen, pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_AsDBRead(S7Object Client, int DBNumber, int Start, int Size, void *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->AsDBRead(DBNumber, Start, Size, pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_AsDBWrite(S7Object Client, int DBNumber, int Start, int Size, void *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->AsDBWrite(DBNumber, Start, Size, pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_AsMBRead(S7Object Client, int Start, int Size, void *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->AsMBRead(Start, Size, pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_AsMBWrite(S7Object Client, int Start, int Size, void *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->AsMBWrite(Start, Size, pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_AsEBRead(S7Object Client, int Start, int Size, void *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->AsEBRead(Start, Size, pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_AsEBWrite(S7Object Client, int Start, int Size, void *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->AsEBWrite(Start, Size, pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_AsABRead(S7Object Client, int Start, int Size, void *pUsrData)\n{\n\tif (Client)\n        return PSnap7Client(Client)->AsABRead(Start, Size, pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_AsABWrite(S7Object Client, int Start, int Size, void *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->AsABWrite(Start, Size, pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_AsTMRead(S7Object Client, int Start, int Amount, void *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->AsTMRead(Start, Amount, pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_AsTMWrite(S7Object Client, int Start, int Amount, void *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->AsTMWrite(Start, Amount, pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_AsCTRead(S7Object Client, int Start, int Amount, void *pUsrData)\n{\n    if (Client)\n        return PSnap7Client(Client)->AsCTRead(Start, Amount, pUsrData);\n\telse\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_AsCTWrite(S7Object Client, int Start, int Amount, void *pUsrData)\n{\n\tif (Client)\n        return PSnap7Client(Client)->AsCTWrite(Start, Amount, pUsrData);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_AsListBlocksOfType(S7Object Client, int BlockType, TS7BlocksOfType *pUsrData, int &ItemsCount)\n{\n    if (Client)\n        return PSnap7Client(Client)->AsListBlocksOfType(BlockType, pUsrData, ItemsCount);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_AsReadSZL(S7Object Client, int ID, int Index, TS7SZL *pUsrData, int &Size)\n{\n    if (Client)\n        return PSnap7Client(Client)->AsReadSZL(ID, Index, pUsrData, Size);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_AsReadSZLList(S7Object Client, TS7SZLList *pUsrData, int &ItemsCount)\n{\n    if (Client)\n        return PSnap7Client(Client)->AsReadSZLList(pUsrData, ItemsCount);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_AsUpload(S7Object Client, int BlockType, int BlockNum, void *pUsrData, int &Size)\n{\n    if (Client)\n        return PSnap7Client(Client)->AsUpload(BlockType, BlockNum, pUsrData, Size);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_AsFullUpload(S7Object Client, int BlockType, int BlockNum, void *pUsrData, int &Size)\n{\n    if (Client)\n        return PSnap7Client(Client)->AsFullUpload(BlockType, BlockNum, pUsrData, Size);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_AsDownload(S7Object Client, int BlockNum, void *pUsrData, int Size)\n{\n    if (Client)\n        return PSnap7Client(Client)->AsDownload(BlockNum, pUsrData, Size);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_AsCopyRamToRom(S7Object Client, int Timeout)\n{\n    if (Client)\n        return PSnap7Client(Client)->AsCopyRamToRom(Timeout);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_AsCompress(S7Object Client, int Timeout)\n{\n    if (Client)\n        return PSnap7Client(Client)->Compress(Timeout);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_AsDBGet(S7Object Client, int DBNumber, void *pUsrData, int &Size)\n{\n\tif (Client)\n        return PSnap7Client(Client)->AsDBGet(DBNumber, pUsrData, Size);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_AsDBFill(S7Object Client, int DBNumber, int FillChar)\n{\n    if (Client)\n        return PSnap7Client(Client)->AsDBFill(DBNumber, FillChar);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_CheckAsCompletion(S7Object Client, int &opResult)\n{\n    if (Client)\n    {\n        if (PSnap7Client(Client)->CheckAsCompletion(opResult))\n            return JobComplete;\n        else\n            return JobPending;\n    }\n    else\n\t\treturn errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Cli_WaitAsCompletion(S7Object Client, int Timeout)\n{\n    if (Client)\n        return PSnap7Client(Client)->WaitAsCompletion(Timeout);\n    else\n        return errLibInvalidObject;\n}\n//***************************************************************************\n// SERVER\n//***************************************************************************\nS7Object S7API Srv_Create()\n{\n    return S7Object(new TSnap7Server());\n}\n//---------------------------------------------------------------------------\nvoid S7API Srv_Destroy(S7Object &Server)\n{\n    if (Server)\n    {\n        delete PSnap7Server(Server);\n        Server=0;\n    }\n}\n//---------------------------------------------------------------------------\nint S7API Srv_GetParam(S7Object Server, int ParamNumber, void *pValue)\n{\n    if (Server)\n        return PSnap7Server(Server)->GetParam(ParamNumber, pValue);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Srv_SetParam(S7Object Server, int ParamNumber, void *pValue)\n{\n    if (Server)\n        return PSnap7Server(Server)->SetParam(ParamNumber, pValue);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Srv_StartTo(S7Object Server, const char *Address)\n{\n    if (Server)\n        return PSnap7Server(Server)->StartTo(Address);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Srv_Start(S7Object Server)\n{\n    if (Server)\n        return PSnap7Server(Server)->Start();\n    else\n\t\treturn errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Srv_Stop(S7Object Server)\n{\n    if (Server)\n    {\n        PSnap7Server(Server)->Stop();\n        return 0;\n    }\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Srv_RegisterArea(S7Object Server, int AreaCode, word Index, void *pUsrData, int Size)\n{\n    if (Server)\n        return PSnap7Server(Server)->RegisterArea(AreaCode, Index, pUsrData, Size);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Srv_UnregisterArea(S7Object Server, int AreaCode, word Index)\n{\n    if (Server)\n        return PSnap7Server(Server)->UnregisterArea(AreaCode, Index);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Srv_LockArea(S7Object Server, int AreaCode, word Index)\n{\n    if (Server)\n        return PSnap7Server(Server)->LockArea(AreaCode, Index);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Srv_UnlockArea(S7Object Server, int AreaCode, word Index)\n{\n    if (Server)\n        return PSnap7Server(Server)->UnlockArea(AreaCode, Index);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Srv_GetStatus(S7Object Server, int &ServerStatus, int &CpuStatus, int &ClientsCount)\n{\n    if (Server)\n    {\n        ServerStatus=PSnap7Server(Server)->Status;\n        CpuStatus=PSnap7Server(Server)->CpuStatus;\n        ClientsCount=PSnap7Server(Server)->ClientsCount;\n        return 0;\n\t}\n\telse\n\t\treturn errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Srv_SetCpuStatus(S7Object Server, int CpuStatus)\n{\n\tif (Server)\n\t{\n\t\tPSnap7Server(Server)->CpuStatus=CpuStatus;\n\t\treturn 0;\n\t}\n\telse\n\t\treturn errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Srv_ErrorText(int Error, char *Text, int TextLen)\n{\n\ttry{\n\t\tErrSrvText(Error, Text, TextLen);\n\t\tText[TextLen - 1] = '\\0';\n\t}\n\tcatch (...){\n\t\treturn errLibInvalidParam;\n\t}\n\treturn 0;\n}\n//---------------------------------------------------------------------------\nint S7API Srv_EventText(TSrvEvent &Event, char *Text, int TextLen)\n{\n\ttry{\n\t\tEvtSrvText(Event, Text, TextLen);\n\t\tText[TextLen - 1] = '\\0';\n\t}\n\tcatch (...){\n\t\treturn errLibInvalidParam;\n\t}\n\treturn 0;\n}\n//---------------------------------------------------------------------------\nint S7API Srv_PickEvent(S7Object Server, TSrvEvent *pEvent, int &EvtReady)\n{\n\tEvtReady=0;\n\tif (Server)\n\t{\n\t\tEvtReady=int(PSnap7Server(Server)->PickEvent(pEvent));\n\t\treturn 0;\n\t}\n\telse\n\t\treturn errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Srv_ClearEvents(S7Object Server)\n{\n\tif (Server)\n\t{\n\t\tPSnap7Server(Server)->EventsFlush();\n\t\treturn 0;\n\t}\n\telse\n\t\treturn errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Srv_GetMask(S7Object Server, int MaskKind, longword &Mask)\n{\n\tif (Server)\n\t{\n\t\tMask=0;\n\t\tif ((MaskKind==mkEvent) || (MaskKind==mkLog))\n\t\t{\n\t\t\tif (MaskKind==mkEvent)\n\t\t\t   Mask=PSnap7Server(Server)->EventMask;\n\t\t\telse\n\t\t\t   Mask=PSnap7Server(Server)->LogMask;\n\t\t\treturn 0;\n\t\t}\n\t\telse\n\t\t\treturn errLibInvalidParam;\n\t}\n\telse\n\t\treturn errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Srv_SetMask(S7Object Server, int MaskKind, longword Mask)\n{\n\tif (Server)\n\t{\n\t\tif ((MaskKind==mkEvent) || (MaskKind==mkLog))\n\t\t{\n\t\t\tif (MaskKind==mkEvent)\n\t\t\t   PSnap7Server(Server)->EventMask=Mask;\n\t\t\telse\n\t\t\t   PSnap7Server(Server)->LogMask=Mask;\n\t\t\treturn 0;\n\t\t}\n\t\telse\n\t\t\treturn errLibInvalidParam;\n\t}\n\telse\n\t\treturn errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Srv_SetEventsCallback(S7Object Server, pfn_SrvCallBack pCallback, void *usrPtr)\n{\n\tif (Server)\n\t\treturn PSnap7Server(Server)->SetEventsCallBack(pCallback, usrPtr);\n\telse\n\t\treturn errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Srv_SetReadEventsCallback(S7Object Server, pfn_SrvCallBack pCallback, void *usrPtr)\n{\n\tif (Server)\n\t\treturn PSnap7Server(Server)->SetReadEventsCallBack(pCallback, usrPtr);\n\telse\n\t\treturn errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Srv_SetRWAreaCallback(S7Object Server, pfn_RWAreaCallBack pCallback, void *usrPtr)\n{\n\tif (Server)\n\t\treturn PSnap7Server(Server)->SetRWAreaCallBack(pCallback, usrPtr);\n\telse\n\t\treturn errLibInvalidObject;\n}\n//***************************************************************************\n// PARTNER\n//***************************************************************************\nS7Object S7API Par_Create(int Active)\n{\n\treturn S7Object(new TSnap7Partner(Active!=0));\n}\n//---------------------------------------------------------------------------\nvoid S7API Par_Destroy(S7Object &Partner)\n{\n\tif (Partner)\n\t{\n\t\tdelete PSnap7Partner(Partner);\n        Partner=0;\n    }\n}\n//---------------------------------------------------------------------------\nint S7API Par_GetParam(S7Object Partner, int ParamNumber, void *pValue)\n{\n    if (Partner)\n        return PSnap7Partner(Partner)->GetParam(ParamNumber, pValue);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Par_SetParam(S7Object Partner, int ParamNumber, void *pValue)\n{\n    if (Partner)\n        return PSnap7Partner(Partner)->SetParam(ParamNumber, pValue);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Par_StartTo(S7Object Partner, const char *LocalAddress, const char *RemoteAddress,\n    word LocTsap, word RemTsap)\n{\n    if (Partner)\n        return PSnap7Partner(Partner)->StartTo(LocalAddress, RemoteAddress, LocTsap, RemTsap);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Par_Start(S7Object Partner)\n{\n    if (Partner)\n        return PSnap7Partner(Partner)->Start();\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Par_Stop(S7Object Partner)\n{\n    if (Partner)\n        return PSnap7Partner(Partner)->Stop();\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Par_BSend(S7Object Partner, longword R_ID, void *pUsrData, int Size)\n{\n    if (Partner)\n        return PSnap7Partner(Partner)->BSend(R_ID, pUsrData, Size);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Par_AsBSend(S7Object Partner, longword R_ID, void *pUsrData, int Size)\n{\n    if (Partner)\n        return PSnap7Partner(Partner)->AsBSend(R_ID, pUsrData, Size);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Par_CheckAsBSendCompletion(S7Object Partner, int &opResult)\n{\n\tif (Partner)\n    {\n        if (PSnap7Partner(Partner)->CheckAsBSendCompletion(opResult))\n            return JobComplete;\n        else\n            return JobPending;\n    }\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Par_WaitAsBSendCompletion(S7Object Partner, longword Timeout)\n{\n    if (Partner)\n        return PSnap7Partner(Partner)->WaitAsBSendCompletion(Timeout);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Par_SetSendCallback(S7Object Partner, pfn_ParBSendCompletion pCompletion, void *usrPtr)\n{\n    if (Partner)\n        return PSnap7Partner(Partner)->SetSendCallback(pCompletion, usrPtr);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Par_BRecv(S7Object Partner, longword &R_ID, void *pData, int &Size, longword Timeout)\n{\n    if (Partner)\n        return PSnap7Partner(Partner)->BRecv(R_ID, pData, Size, Timeout);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Par_CheckAsBRecvCompletion(S7Object Partner, int &opResult, longword &R_ID,\n\tvoid *pData, int &Size)\n{\n    if (Partner)\n    {\n        if (PSnap7Partner(Partner)->CheckAsBRecvCompletion(opResult, R_ID, pData, Size))\n            return JobComplete;\n        else\n            return JobPending;\n    }\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Par_SetRecvCallback(S7Object Partner, pfn_ParBRecvCallBack pCompletion, void *usrPtr)\n{\n    if (Partner)\n        return PSnap7Partner(Partner)->SetRecvCallback(pCompletion, usrPtr);\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Par_GetTimes(S7Object Partner, longword &SendTime, longword &RecvTime)\n{\n    if (Partner)\n    {\n        SendTime=PSnap7Partner(Partner)->SendTime;\n        RecvTime=PSnap7Partner(Partner)->RecvTime;\n        return 0;\n    }\n    else\n        return errLibInvalidObject;\n\n}\n//---------------------------------------------------------------------------\nint S7API Par_GetStats(S7Object Partner, longword &BytesSent, longword &BytesRecv,\n    longword &SendErrors, longword &RecvErrors)\n{\n    if (Partner)\n    {\n        BytesSent=PSnap7Partner(Partner)->BytesSent;\n        BytesRecv=PSnap7Partner(Partner)->BytesRecv;\n        SendErrors=PSnap7Partner(Partner)->SendErrors;\n        RecvErrors=PSnap7Partner(Partner)->RecvErrors;\n        return 0;\n    }\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Par_GetLastError(S7Object Partner, int &LastError)\n{\n    if (Partner)\n    {\n        LastError=PSnap7Partner(Partner)->LastError;\n        return 0;\n    }\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Par_GetStatus(S7Object Partner, int &Status)\n{\n    if (Partner)\n    {\n        Status=PSnap7Partner(Partner)->Status();\n        return 0;\n    }\n    else\n        return errLibInvalidObject;\n}\n//---------------------------------------------------------------------------\nint S7API Par_ErrorText(int Error, char *Text, int TextLen)\n{\n\ttry{\n\t\tErrParText(Error, Text, TextLen);\n        Text[TextLen - 1] = '\\0';\n\t}\n\tcatch (...){\n\t\treturn errLibInvalidParam;\n\t}\n\treturn 0;\n}\n\n"
  },
  {
    "path": "deps/snap7/src/lib/snap7_libmain.h",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.3.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|=============================================================================*/\n#ifndef snap7_libmain_h\n#define snap7_libmain_h\n//---------------------------------------------------------------------------\n#include \"s7_client.h\"\n#include \"s7_server.h\"\n#include \"s7_partner.h\"\n#include \"s7_text.h\"\n//---------------------------------------------------------------------------\n\nconst int mkEvent  = 0;\nconst int mkLog    = 1;\n\ntypedef uintptr_t S7Object; // multi platform/processor object reference\n\n//==============================================================================\n// CLIENT EXPORT LIST - Sync functions\n//==============================================================================\nEXPORTSPEC S7Object S7API Cli_Create();\nEXPORTSPEC void S7API Cli_Destroy(S7Object &Client);\nEXPORTSPEC int S7API Cli_Connect(S7Object Client);\nEXPORTSPEC int S7API Cli_SetConnectionParams(S7Object Client, const char *Address, word LocalTSAP, word RemoteTSAP);\nEXPORTSPEC int S7API Cli_SetConnectionType(S7Object Client, word ConnectionType);\nEXPORTSPEC int S7API Cli_ConnectTo(S7Object Client, const char *Address, int Rack, int Slot);\nEXPORTSPEC int S7API Cli_Disconnect(S7Object Client);\nEXPORTSPEC int S7API Cli_GetParam(S7Object Client, int ParamNumber, void *pValue);\nEXPORTSPEC int S7API Cli_SetParam(S7Object Client, int ParamNumber, void *pValue);\nEXPORTSPEC int S7API Cli_SetAsCallback(S7Object Client, pfn_CliCompletion pCompletion, void *usrPtr);\n// Data I/O functions\nEXPORTSPEC int S7API Cli_ReadArea(S7Object Client, int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData);\nEXPORTSPEC int S7API Cli_WriteArea(S7Object Client, int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData);\nEXPORTSPEC int S7API Cli_ReadMultiVars(S7Object Client, PS7DataItem Item, int ItemsCount);\nEXPORTSPEC int S7API Cli_WriteMultiVars(S7Object Client, PS7DataItem Item, int ItemsCount);\n// Data I/O Lean functions\nEXPORTSPEC int S7API Cli_DBRead(S7Object Client, int DBNumber, int Start, int Size, void *pUsrData);\nEXPORTSPEC int S7API Cli_DBWrite(S7Object Client, int DBNumber, int Start, int Size, void *pUsrData);\nEXPORTSPEC int S7API Cli_MBRead(S7Object Client, int Start, int Size, void *pUsrData);\nEXPORTSPEC int S7API Cli_MBWrite(S7Object Client, int Start, int Size, void *pUsrData);\nEXPORTSPEC int S7API Cli_EBRead(S7Object Client, int Start, int Size, void *pUsrData);\nEXPORTSPEC int S7API Cli_EBWrite(S7Object Client, int Start, int Size, void *pUsrData);\nEXPORTSPEC int S7API Cli_ABRead(S7Object Client, int Start, int Size, void *pUsrData);\nEXPORTSPEC int S7API Cli_ABWrite(S7Object Client, int Start, int Size, void *pUsrData);\nEXPORTSPEC int S7API Cli_TMRead(S7Object Client, int Start, int Amount, void *pUsrData);\nEXPORTSPEC int S7API Cli_TMWrite(S7Object Client, int Start, int Amount, void *pUsrData);\nEXPORTSPEC int S7API Cli_CTRead(S7Object Client, int Start, int Amount, void *pUsrData);\nEXPORTSPEC int S7API Cli_CTWrite(S7Object Client, int Start, int Amount, void *pUsrData);\n// Directory functions\nEXPORTSPEC int S7API Cli_ListBlocks(S7Object Client, TS7BlocksList *pUsrData);\nEXPORTSPEC int S7API Cli_GetAgBlockInfo(S7Object Client, int BlockType, int BlockNum, TS7BlockInfo *pUsrData);\nEXPORTSPEC int S7API Cli_GetPgBlockInfo(S7Object Client, void *pBlock, TS7BlockInfo *pUsrData, int Size);\nEXPORTSPEC int S7API Cli_ListBlocksOfType(S7Object Client, int BlockType, TS7BlocksOfType *pUsrData, int &ItemsCount);\n// Blocks functions\nEXPORTSPEC int S7API Cli_Upload(S7Object Client, int BlockType, int BlockNum, void *pUsrData, int &Size);\nEXPORTSPEC int S7API Cli_FullUpload(S7Object Client, int BlockType, int BlockNum, void *pUsrData, int &Size);\nEXPORTSPEC int S7API Cli_Download(S7Object Client, int BlockNum, void *pUsrData, int Size);\nEXPORTSPEC int S7API Cli_Delete(S7Object Client, int BlockType, int BlockNum);\nEXPORTSPEC int S7API Cli_DBGet(S7Object Client, int DBNumber, void *pUsrData, int &Size);\nEXPORTSPEC int S7API Cli_DBFill(S7Object Client, int DBNumber, int FillChar);\n// Date/Time functions\nEXPORTSPEC int S7API Cli_GetPlcDateTime(S7Object Client, tm &DateTime);\nEXPORTSPEC int S7API Cli_SetPlcDateTime(S7Object Client, tm *DateTime);\nEXPORTSPEC int S7API Cli_SetPlcSystemDateTime(S7Object Client);\n// System Info functions\nEXPORTSPEC int S7API Cli_GetOrderCode(S7Object Client, TS7OrderCode *pUsrData);\nEXPORTSPEC int S7API Cli_GetCpuInfo(S7Object Client, TS7CpuInfo *pUsrData);\nEXPORTSPEC int S7API Cli_GetCpInfo(S7Object Client, TS7CpInfo *pUsrData);\nEXPORTSPEC int S7API Cli_ReadSZL(S7Object Client, int ID, int Index, TS7SZL *pUsrData, int &Size);\nEXPORTSPEC int S7API Cli_ReadSZLList(S7Object Client, TS7SZLList *pUsrData, int &ItemsCount);\n// Control functions\nEXPORTSPEC int S7API Cli_PlcHotStart(S7Object Client);\nEXPORTSPEC int S7API Cli_PlcColdStart(S7Object Client);\nEXPORTSPEC int S7API Cli_PlcStop(S7Object Client);\nEXPORTSPEC int S7API Cli_CopyRamToRom(S7Object Client, int Timeout);\nEXPORTSPEC int S7API Cli_Compress(S7Object Client, int Timeout);\nEXPORTSPEC int S7API Cli_GetPlcStatus(S7Object Client, int &Status);\n// Security functions\nEXPORTSPEC int S7API Cli_GetProtection(S7Object Client, TS7Protection *pUsrData);\nEXPORTSPEC int S7API Cli_SetSessionPassword(S7Object Client, char *Password);\nEXPORTSPEC int S7API Cli_ClearSessionPassword(S7Object Client);\n// Low level\nEXPORTSPEC int S7API Cli_IsoExchangeBuffer(S7Object Client, void *pUsrData, int &Size);\n// Misc\nEXPORTSPEC int S7API Cli_GetExecTime(S7Object Client, int &Time);\nEXPORTSPEC int S7API Cli_GetLastError(S7Object Client, int &LastError);\nEXPORTSPEC int S7API Cli_GetPduLength(S7Object Client, int &Requested, int &Negotiated);\nEXPORTSPEC int S7API Cli_ErrorText(int Error, char *Text, int TextLen);\nEXPORTSPEC int S7API Cli_GetConnected(S7Object Client, int &Connected);\n//==============================================================================\n//  CLIENT EXPORT LIST - Async functions\n//==============================================================================\nEXPORTSPEC int S7API Cli_AsReadArea(S7Object Client, int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData);\nEXPORTSPEC int S7API Cli_AsWriteArea(S7Object Client, int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData);\nEXPORTSPEC int S7API Cli_AsDBRead(S7Object Client, int DBNumber, int Start, int Size, void *pUsrData);\nEXPORTSPEC int S7API Cli_AsDBWrite(S7Object Client, int DBNumber, int Start, int Size, void *pUsrData);\nEXPORTSPEC int S7API Cli_AsMBRead(S7Object Client, int Start, int Size, void *pUsrData);\nEXPORTSPEC int S7API Cli_AsMBWrite(S7Object Client, int Start, int Size, void *pUsrData);\nEXPORTSPEC int S7API Cli_AsEBRead(S7Object Client, int Start, int Size, void *pUsrData);\nEXPORTSPEC int S7API Cli_AsEBWrite(S7Object Client, int Start, int Size, void *pUsrData);\nEXPORTSPEC int S7API Cli_AsABRead(S7Object Client, int Start, int Size, void *pUsrData);\nEXPORTSPEC int S7API Cli_AsABWrite(S7Object Client, int Start, int Size, void *pUsrData);\nEXPORTSPEC int S7API Cli_AsTMRead(S7Object Client, int Start, int Amount, void *pUsrData);\nEXPORTSPEC int S7API Cli_AsTMWrite(S7Object Client, int Start, int Amount, void *pUsrData);\nEXPORTSPEC int S7API Cli_AsCTRead(S7Object Client, int Start, int Amount, void *pUsrData);\nEXPORTSPEC int S7API Cli_AsCTWrite(S7Object Client, int Start, int Amount, void *pUsrData);\nEXPORTSPEC int S7API Cli_AsListBlocksOfType(S7Object Client, int BlockType, TS7BlocksOfType *pUsrData, int &ItemsCount);\nEXPORTSPEC int S7API Cli_AsReadSZL(S7Object Client, int ID, int Index, TS7SZL *pUsrData, int &Size);\nEXPORTSPEC int S7API Cli_AsReadSZLList(S7Object Client, TS7SZLList *pUsrData, int &ItemsCount);\nEXPORTSPEC int S7API Cli_AsUpload(S7Object Client, int BlockType, int BlockNum, void *pUsrData, int &Size);\nEXPORTSPEC int S7API Cli_AsFullUpload(S7Object Client, int BlockType, int BlockNum, void *pUsrData, int &Size);\nEXPORTSPEC int S7API Cli_AsDownload(S7Object Client, int BlockNum, void *pUsrData, int Size);\nEXPORTSPEC int S7API Cli_AsCopyRamToRom(S7Object Client, int Timeout);\nEXPORTSPEC int S7API Cli_AsCompress(S7Object Client, int Timeout);\nEXPORTSPEC int S7API Cli_AsDBGet(S7Object Client, int DBNumber, void *pUsrData, int &Size);\nEXPORTSPEC int S7API Cli_AsDBFill(S7Object Client, int DBNumber, int FillChar);\nEXPORTSPEC int S7API Cli_CheckAsCompletion(S7Object Client, int &opResult);\nEXPORTSPEC int S7API Cli_WaitAsCompletion(S7Object Client, int Timeout);\n//==============================================================================\n//  SERVER EXPORT LIST\n//==============================================================================\nEXPORTSPEC S7Object S7API Srv_Create();\nEXPORTSPEC void S7API Srv_Destroy(S7Object &Server);\nEXPORTSPEC int S7API Srv_GetParam(S7Object Server, int ParamNumber, void *pValue);\nEXPORTSPEC int S7API Srv_SetParam(S7Object Server, int ParamNumber, void *pValue);\nEXPORTSPEC int S7API Srv_Start(S7Object Server);\nEXPORTSPEC int S7API Srv_StartTo(S7Object Server, const char *Address);\nEXPORTSPEC int S7API Srv_Stop(S7Object Server);\n// Data\nEXPORTSPEC int S7API Srv_RegisterArea(S7Object Server, int AreaCode, word Index, void *pUsrData, int Size);\nEXPORTSPEC int S7API Srv_UnregisterArea(S7Object Server, int AreaCode, word Index);\nEXPORTSPEC int S7API Srv_LockArea(S7Object Server, int AreaCode, word Index);\nEXPORTSPEC int S7API Srv_UnlockArea(S7Object Server, int AreaCode, word Index);\n// Events\nEXPORTSPEC int S7API Srv_ClearEvents(S7Object Server);\nEXPORTSPEC int S7API Srv_PickEvent(S7Object Server, TSrvEvent *pEvent, int &EvtReady);\nEXPORTSPEC int S7API Srv_GetMask(S7Object Server, int MaskKind, longword &Mask);\nEXPORTSPEC int S7API Srv_SetMask(S7Object Server, int MaskKind, longword Mask);\nEXPORTSPEC int S7API Srv_SetEventsCallback(S7Object Server, pfn_SrvCallBack pCallback, void *usrPtr);\nEXPORTSPEC int S7API Srv_SetReadEventsCallback(S7Object Server, pfn_SrvCallBack pCallback, void *usrPtr);\nEXPORTSPEC int S7API Srv_EventText(TSrvEvent &Event, char *Text, int TextLen);\nEXPORTSPEC int S7API Srv_SetRWAreaCallback(S7Object Server, pfn_RWAreaCallBack pCallback, void *usrPtr);\n// Misc\nEXPORTSPEC int S7API Srv_GetStatus(S7Object Server, int &ServerStatus, int &CpuStatus, int &ClientsCount);\nEXPORTSPEC int S7API Srv_SetCpuStatus(S7Object Server, int CpuStatus);\nEXPORTSPEC int S7API Srv_ErrorText(int Error, char *Text, int TextLen);\n//==============================================================================\n//  PARTNER EXPORT LIST\n//==============================================================================\nEXPORTSPEC S7Object S7API Par_Create(int Active);\nEXPORTSPEC void S7API Par_Destroy(S7Object &Partner);\nEXPORTSPEC int S7API Par_GetParam(S7Object Partner, int ParamNumber, void *pValue);\nEXPORTSPEC int S7API Par_SetParam(S7Object Partner, int ParamNumber, void *pValue);\nEXPORTSPEC int S7API Par_Start(S7Object Partner);\nEXPORTSPEC int S7API Par_StartTo(S7Object Partner, const char *LocalAddress, const char *RemoteAddress, \n\tword LocTsap, word RemTsap);\nEXPORTSPEC int S7API Par_Stop(S7Object Partner);\n// BSend\nEXPORTSPEC int S7API Par_BSend(S7Object Partner, longword R_ID, void *pUsrData, int Size);\nEXPORTSPEC int S7API Par_AsBSend(S7Object Partner, longword R_ID, void *pUsrData, int Size);\nEXPORTSPEC int S7API Par_CheckAsBSendCompletion(S7Object Partner, int &opResult);\nEXPORTSPEC int S7API Par_WaitAsBSendCompletion(S7Object Partner, longword Timeout);\nEXPORTSPEC int S7API Par_SetSendCallback(S7Object Partner, pfn_ParBSendCompletion pCompletion, void *usrPtr);\n// BRecv\nEXPORTSPEC int S7API Par_BRecv(S7Object Partner, longword &R_ID, void *pData, int &Size, longword Timeout);\nEXPORTSPEC int S7API Par_CheckAsBRecvCompletion(S7Object Partner, int &opResult, longword &R_ID,\n    void *pData, int &Size);\nEXPORTSPEC int S7API Par_SetRecvCallback(S7Object Partner, pfn_ParBRecvCallBack pCompletion, void *usrPtr);\n// Stat\nEXPORTSPEC int S7API Par_GetTimes(S7Object Partner, longword &SendTime, longword &RecvTime);\nEXPORTSPEC int S7API Par_GetStats(S7Object Partner, longword &BytesSent, longword &BytesRecv,\n    longword &SendErrors, longword &RecvErrors);\nEXPORTSPEC int S7API Par_GetLastError(S7Object Partner, int &LastError);\nEXPORTSPEC int S7API Par_GetStatus(S7Object Partner, int &Status);\nEXPORTSPEC int S7API Par_ErrorText(int Error, char *Text, int TextLen);\n\n\n\n#endif // snap7_libmain_h\n"
  },
  {
    "path": "deps/snap7/src/sys/snap_msgsock.cpp",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.3.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|=============================================================================*/\n\n#include \"snap_msgsock.h\"\n\n//---------------------------------------------------------------------------\n\nstatic SocketsLayer SocketsLayerInitializer;\n\n//---------------------------------------------------------------------------\n//  Base class endian aware\n//---------------------------------------------------------------------------\nTSnapBase::TSnapBase()\n{\n\tint x = 1;\n\tLittleEndian=*(char *)&x == 1;\n}\n//---------------------------------------------------------------------------\nword TSnapBase::SwapWord(word Value)\n{\n\tif (LittleEndian)\n\t\treturn  ((Value >> 8) & 0xFF) | ((Value << 8) & 0xFF00);\n\telse\n\t    return Value;\n}\n//---------------------------------------------------------------------------\nlongword TSnapBase::SwapDWord(longword Value)\n{\n\tif (LittleEndian)\n\t\treturn (Value >> 24) | ((Value << 8) & 0x00FF0000) | ((Value >> 8) & 0x0000FF00) | (Value << 24);\n\telse\n\t\treturn Value;\n}\n//---------------------------------------------------------------------------\nvoid Msg_CloseSocket(socket_t FSocket)\n{\n    #ifdef OS_WINDOWS\n    closesocket(FSocket);\n    #else\n    close(FSocket);\n    #endif\n}\n//---------------------------------------------------------------------------\nlongword Msg_GetSockAddr(socket_t FSocket)\n{\n    sockaddr_in RemoteSin;\n    #ifdef OS_WINDOWS\n    int namelen = sizeof(RemoteSin);\n    #else\n    uint32_t namelen = sizeof(RemoteSin);\n    #endif\n    namelen=sizeof(sockaddr_in);\n    if (getpeername(FSocket,(struct sockaddr*)&RemoteSin, &namelen)==0)\n        return RemoteSin.sin_addr.s_addr;\n    else\n        return 0;\n}\n//---------------------------------------------------------------------------\nTMsgSocket::TMsgSocket()\n{\n    Pinger = new TPinger();\n    // Set Defaults\n    strcpy(LocalAddress,\"0.0.0.0\");\n    LocalPort=0;\n    strcpy(RemoteAddress,\"127.0.0.1\");\n    RemotePort=0;\n    WorkInterval=100;\n    RecvTimeout=500;\n    SendTimeout=10;\n    PingTimeout=750;\n    Connected=false;\n    FSocket=INVALID_SOCKET;\n    LastTcpError=0;\n    LocalBind=0;\n}\n//---------------------------------------------------------------------------\nTMsgSocket::~TMsgSocket()\n{\n    DestroySocket();\n    delete Pinger;\n}\n//---------------------------------------------------------------------------\nvoid TMsgSocket::SetSin(sockaddr_in &sin, char *Address, u_short Port)\n{\t\n    uint32_t in_addr;\n    in_addr=inet_addr(Address);\n    memset(&sin, 0, sizeof(sin));\n    LastTcpError=0;\n\n    if (in_addr!=INADDR_NONE)\n    {\n\t\tsin.sin_addr.s_addr = in_addr;\n\t\tsin.sin_family = AF_INET;\n\t\tsin.sin_port = htons(Port);\n    }\n    else\n        LastTcpError=WSAEINVALIDADDRESS;\n}\n//---------------------------------------------------------------------------\nvoid TMsgSocket::GetSin(sockaddr_in sin, char *Address, u_short &Port)\n{\n  strcpy(Address,inet_ntoa(sin.sin_addr));\n  Port=htons(sin.sin_port);\n}\n//---------------------------------------------------------------------------\nvoid TMsgSocket::GetLocal()\n{\n    #ifdef OS_WINDOWS\n\t\tint namelen = sizeof(LocalSin);\n    #else\n        uint32_t namelen = sizeof(LocalSin);\n    #endif\n    if (getsockname(FSocket, (struct sockaddr*)&LocalSin, &namelen)==0)\n        GetSin(LocalSin, LocalAddress, LocalPort);\n}\n//---------------------------------------------------------------------------\nvoid TMsgSocket::GetRemote()\n{\n    #ifdef OS_WINDOWS\n        int namelen = sizeof(RemoteSin);\n    #else\n        uint32_t namelen = sizeof(RemoteSin);\n    #endif\n\tif (getpeername(FSocket,(struct sockaddr*)&RemoteSin, &namelen)==0)\n\t\tGetSin(RemoteSin, RemoteAddress, RemotePort);\n}\n//---------------------------------------------------------------------------\nint TMsgSocket::GetLastSocketError()\n{\n#ifdef OS_WINDOWS\n    return WSAGetLastError();\n#else    \n    return errno;\n#endif\n}\n//---------------------------------------------------------------------------\nvoid TMsgSocket::Purge()\n{\n    // small buffer to empty the socket\n    char Trash[512];\n    int Read;\n    if (LastTcpError!=WSAECONNRESET)\n    {\n        if (CanRead(0)) {\n           do\n           {\n               Read=recv(FSocket, Trash, 512, MSG_NOSIGNAL );\n           } while(Read==512);\n        }\n    }\n}\n//---------------------------------------------------------------------------\nvoid TMsgSocket::CreateSocket()\n{\n\tDestroySocket();\n\tLastTcpError=0;\n\tFSocket =socket(AF_INET, SOCK_STREAM, IPPROTO_TCP );\n\tif (FSocket!=INVALID_SOCKET)\n\t\tSetSocketOptions();\n\telse\n\t\tLastTcpError =GetLastSocketError();\n}\n//---------------------------------------------------------------------------\nvoid TMsgSocket::GotSocket()\n{\n    ClientHandle=RemoteSin.sin_addr.s_addr;\n    // could be inherited it if wee need further actions on the socket\n}\n//---------------------------------------------------------------------------\nvoid TMsgSocket::SetSocket(socket_t s)\n{\n    FSocket=s;\n    if (FSocket!=INVALID_SOCKET)\n    {\n\t\tSetSocketOptions();\n\t\tGetLocal();\n\t\tGetRemote();\n\t\tGotSocket();\n    }\n    Connected=FSocket!=INVALID_SOCKET;\n}\n//---------------------------------------------------------------------------\nvoid TMsgSocket::DestroySocket()\n{\n    if(FSocket != INVALID_SOCKET)\n    {        \n        if (shutdown(FSocket, SD_SEND)==0)\n\t\t\tPurge();\n\t#ifdef OS_WINDOWS\n\t\tclosesocket(FSocket);\n\t#else\n\t\tclose(FSocket);\n\t#endif\n\t\tFSocket=INVALID_SOCKET;\n    }\n    LastTcpError=0;\n}\n//---------------------------------------------------------------------------\nint TMsgSocket::WaitingData()\n{\n    int result = 0;\n    u_long x = 0;\n#ifdef OS_WINDOWS\n    if (ioctlsocket(FSocket, FIONREAD, &x) == 0)\n        result = x;\n#else\n    if (ioctl(FSocket, FIONREAD, &x) == 0)\n        result = x;\n#endif\n    if (result>MaxPacketSize)\n        result = MaxPacketSize;\n    return result;\n}\n//---------------------------------------------------------------------------\nint TMsgSocket::WaitForData(int Size, int Timeout)\n{\n    longword Elapsed;\n\n    // Check for connection active\n    if (CanRead(0) && (WaitingData()==0))\n        LastTcpError=WSAECONNRESET;\n    else\n        LastTcpError=0;\n\n    // Enter main loop\n    if (LastTcpError==0)\n    {\n        Elapsed =SysGetTick();\n        while((WaitingData()<Size) && (LastTcpError==0))\n        {\n            // Checks timeout\n            if (DeltaTime(Elapsed)>=(longword)(Timeout))\n                LastTcpError =WSAETIMEDOUT;\n            else\n                SysSleep(1);\n        }\n    }\n    if(LastTcpError==WSAECONNRESET)\n            Connected =false;\n\n    return LastTcpError;\n}\n//---------------------------------------------------------------------------\nvoid TMsgSocket::SetSocketOptions()\n{\n    int NoDelay = 1;\n\tint KeepAlive = 1;\n    LastTcpError=0;\n    SockCheck(setsockopt(FSocket, IPPROTO_TCP, TCP_NODELAY,(char*)&NoDelay, sizeof(NoDelay)));\n\n\tif (LastTcpError==0)\n        SockCheck(setsockopt(FSocket, SOL_SOCKET, SO_KEEPALIVE,(char*)&KeepAlive, sizeof(KeepAlive)));\n}\n//---------------------------------------------------------------------------\nint TMsgSocket::SockCheck(int SockResult)\n{\n  if (SockResult == (int)(SOCKET_ERROR))\n     LastTcpError = GetLastSocketError();\n\n  return LastTcpError;\n}\n//---------------------------------------------------------------------------\nbool TMsgSocket::CanWrite(int Timeout)\n{\n    timeval TimeV;\n    int64_t x;\n    fd_set FDset;\n\n\tif(FSocket == INVALID_SOCKET)\n\t\treturn false;\n\n    TimeV.tv_usec = (Timeout % 1000) * 1000;\n    TimeV.tv_sec = Timeout / 1000;\n\n    FD_ZERO(&FDset);\n    FD_SET(FSocket, &FDset);\n\n    x = select(FSocket + 1, NULL, &FDset, NULL, &TimeV); //<-Ignore this warning in 64bit Visual Studio\n    if (x==(int)SOCKET_ERROR) \n    {\n        LastTcpError = GetLastSocketError();\n        x=0;\n    }\n    return (x > 0);\n}\n//---------------------------------------------------------------------------\nbool TMsgSocket::CanRead(int Timeout)\n{\n    timeval TimeV;\n    int64_t x;\n    fd_set FDset;\n\n\tif(FSocket == INVALID_SOCKET)\n\t\treturn false;\n\n\tTimeV.tv_usec = (Timeout % 1000) * 1000;\n    TimeV.tv_sec = Timeout / 1000;\n\n    FD_ZERO(&FDset);\n    FD_SET(FSocket, &FDset);\n\n    x = select(FSocket + 1, &FDset, NULL, NULL, &TimeV); //<-Ignore this warning in 64bit Visual Studio\n    if (x==(int)SOCKET_ERROR)\n    {\n       LastTcpError = GetLastSocketError();\n       x=0;\n    }\n    return (x > 0);\n}\n//---------------------------------------------------------------------------\n#ifdef NON_BLOCKING_CONNECT\n//\n// Non blocking connection (UNIX) Thanks to Rolf Stalder\n//\nint TMsgSocket::SckConnect()\n{\n\tint n, flags, err;\n\tsocklen_t len;\n\tfd_set rset, wset;\n\tstruct timeval tval;\n\n \tSetSin(RemoteSin, RemoteAddress, RemotePort);\n\n\tif (LastTcpError == 0) {\n\t\tCreateSocket();\n\t\tif (LastTcpError == 0) {\n\t\t\tflags = fcntl(FSocket, F_GETFL, 0);\n\t\t\tif (flags >= 0) {\n\t\t\t\tif (fcntl(FSocket, F_SETFL, flags | O_NONBLOCK)  != -1) {\n\t\t\t\t\tn = connect(FSocket, (struct sockaddr*)&RemoteSin, sizeof(RemoteSin));\n\t\t\t\t\tif (n < 0) {\n\t\t\t\t\t\tif (errno != EINPROGRESS) {\n\t\t\t\t\t\t\tLastTcpError = GetLastSocketError();\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t// still connecting ... \n\t\t\t\t\t\t\tFD_ZERO(&rset);\n\t\t\t\t\t\t\tFD_SET(FSocket, &rset);\n\t\t\t\t\t\t\twset = rset;\n\t\t\t\t\t\t\ttval.tv_sec = PingTimeout / 1000;\n\t\t\t\t\t\t\ttval.tv_usec = (PingTimeout % 1000) * 1000;\n\n\t\t\t\t\t\t\tn = select(FSocket+1, &rset, &wset, NULL, \n\t\t\t\t\t\t\t           (PingTimeout ? &tval : NULL));\n\t\t\t\t\t\t\tif (n == 0) {\n\t\t\t\t\t\t\t\t// timeout\n\t\t\t\t\t\t\t\tLastTcpError = WSAEHOSTUNREACH;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tif (FD_ISSET(FSocket, &rset) || FD_ISSET(FSocket, &wset)) {\n\t\t\t\t\t\t\t\t\terr = 0;\n\t\t\t\t\t\t\t\t\tlen = sizeof(err);\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tif (getsockopt(\n\t\t\t\t\t\t\t\t\t      FSocket, SOL_SOCKET, SO_ERROR, &err, &len) == 0) {\n\t\t\t\t\t\t\t\t\t\tif (err) {\n\t\t\t\t\t\t\t\t\t\t\t LastTcpError = err;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\t\t\tif (fcntl(FSocket, F_SETFL, flags) != -1) {\n\t\t\t\t\t\t\t\t\t\t\t\tGetLocal();\n\t\t\t\t\t\t\t\t\t\t\t\tClientHandle = LocalSin.sin_addr.s_addr;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\t\t\t\tLastTcpError = GetLastSocketError();\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\t\tLastTcpError = GetLastSocketError();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\tLastTcpError = -1;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} // still connecting\n\t\t\t\t\t} \n\t\t\t\t\telse if (n == 0) { \n\t\t\t\t\t\t// connected immediatly\n\t\t\t\t\t\tGetLocal();\n\t\t\t\t\t\tClientHandle = LocalSin.sin_addr.s_addr;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tLastTcpError = GetLastSocketError();\n\t\t\t\t} // fcntl(F_SETFL)\n\t\t\t}\n\t\t\telse {\n\t\t\t\tLastTcpError = GetLastSocketError();\n\t\t\t} // fcntl(F_GETFL)\n\t\t} //valid socket \n\t} // LastTcpError==0\n\tConnected=LastTcpError==0;\n \treturn LastTcpError;\n}\n#else\n//\n// Regular connection (Windows)\n//\nint TMsgSocket::SckConnect()\n{\n    int Result;\n    SetSin(RemoteSin, RemoteAddress, RemotePort);\n    if (LastTcpError==0)\n    {\n        if (Ping(RemoteSin))\n        {\n            CreateSocket();\n            if (LastTcpError==0)\n            {\n                Result=connect(FSocket, (struct sockaddr*)&RemoteSin, sizeof(RemoteSin));\n                if (SockCheck(Result)==0)\n                {\n                    GetLocal();\n                    // Client handle is self_address (here the connection is ACTIVE)\n                    ClientHandle=LocalSin.sin_addr.s_addr;\n                }\n            }\n        }\n        else\n            LastTcpError=WSAEHOSTUNREACH;\n    }\n    Connected=LastTcpError==0;\n    return LastTcpError;\n}\n#endif\n//---------------------------------------------------------------------------\nvoid TMsgSocket::SckDisconnect()\n{\n    DestroySocket();\n    Connected=false;\n}\n//---------------------------------------------------------------------------\nvoid TMsgSocket::ForceClose()\n{\n    if(FSocket != INVALID_SOCKET)\n    {\n        try {\n            #ifdef OS_WINDOWS\n            closesocket(FSocket);\n            #else\n            close(FSocket);\n            #endif\n        } catch (...) {\n        }\n        FSocket=INVALID_SOCKET;\n    }\n    LastTcpError=0;\n}\n//---------------------------------------------------------------------------\nint TMsgSocket::SckBind()\n{\n    int Res;\n    int Opt=1;\n    SetSin(LocalSin, LocalAddress, LocalPort);\n    if (LastTcpError==0)\n    {\n        CreateSocket();\n        if (LastTcpError==0)\n        {\t\t\n            setsockopt(FSocket ,SOL_SOCKET, SO_REUSEADDR, (const char *)&Opt, sizeof(int));\n            Res =bind(FSocket, (struct sockaddr*)&LocalSin, sizeof(sockaddr_in));\n            SockCheck(Res);\n            if (Res==0) \n            {\n                LocalBind=LocalSin.sin_addr.s_addr;\n            }\n        }\n    }\n    else\n        LastTcpError=WSAEINVALIDADDRESS;\n\n    return LastTcpError;\n}\n//---------------------------------------------------------------------------\nint TMsgSocket::SckListen()\n{\n    LastTcpError=0;\n    SockCheck(listen(FSocket ,SOMAXCONN));\n    return LastTcpError;\n}\n//---------------------------------------------------------------------------\nbool TMsgSocket::Ping(char *Host)\n{\n    return Pinger->Ping(Host, PingTimeout);\n}\n//---------------------------------------------------------------------------\nbool TMsgSocket::Ping(sockaddr_in Addr)\n{\n\tif (PingTimeout == 0)\n\t\treturn true;\n\telse\n        return Pinger->Ping(Addr.sin_addr.s_addr, PingTimeout);\n}\n//---------------------------------------------------------------------------\nsocket_t TMsgSocket::SckAccept()\n{\n    socket_t result;\n    LastTcpError=0;\n    result = accept(FSocket, NULL, NULL);\n    if(result==INVALID_SOCKET)\n        LastTcpError =GetLastSocketError();\n    return result;\n}\n//---------------------------------------------------------------------------\nint TMsgSocket::SendPacket(void *Data, int Size)\n{\n    int Result;\n    \n    LastTcpError=0;\n    if (SendTimeout>0)\n    {\n        if (!CanWrite(SendTimeout))\n        {\n            LastTcpError = WSAETIMEDOUT;\n            return LastTcpError;\n        }\n    }\n    if (send(FSocket, (char*)Data, Size, MSG_NOSIGNAL)==Size)\n        return 0;\n    else\n        Result =SOCKET_ERROR;\n\n    SockCheck(Result);\n    return Result;\n}\n//---------------------------------------------------------------------------\nbool TMsgSocket::PacketReady(int Size)\n{\n\treturn (WaitingData()>=Size);\n}\n//---------------------------------------------------------------------------\nint TMsgSocket::Receive(void *Data, int BufSize, int &SizeRecvd)\n{\n    LastTcpError=0;\n    if (CanRead(RecvTimeout))\n    {\n        SizeRecvd=recv(FSocket ,(char*)Data ,BufSize ,MSG_NOSIGNAL );\n\n        if (SizeRecvd>0) // something read (default case)\n           LastTcpError=0;\n        else\n            if (SizeRecvd==0)\n                LastTcpError = WSAECONNRESET;  // Connection reset by Peer\n            else\n                LastTcpError=GetLastSocketError(); // we need to know what happened\n    }\n    else\n        LastTcpError = WSAETIMEDOUT;\n\n    if (LastTcpError==WSAECONNRESET)\n        Connected = false;\n\n    return LastTcpError;\n}\n//---------------------------------------------------------------------------\nint TMsgSocket::RecvPacket(void *Data, int Size)\n{\n    int BytesRead;\n    WaitForData(Size, RecvTimeout);\n    if (LastTcpError==0)\n    {\n        BytesRead=recv(FSocket, (char*)Data, Size, MSG_NOSIGNAL);\n        if (BytesRead==0)\n            LastTcpError = WSAECONNRESET;  // Connection reset by Peer\n        else\n            if (BytesRead<0)\n                LastTcpError = GetLastSocketError();\n    }\n    else // After the timeout the bytes waiting were less then we expected\n        if (LastTcpError==WSAETIMEDOUT)\n            Purge();\n\n    if (LastTcpError==WSAECONNRESET)\n        Connected =false;\n\n    return LastTcpError;\n}\n//---------------------------------------------------------------------------\nint TMsgSocket::PeekPacket(void *Data, int Size)\n{\n    int BytesRead;\n    WaitForData(Size, RecvTimeout);\n    if (LastTcpError==0)\n    {\n        BytesRead=recv(FSocket, (char*)Data, Size, MSG_PEEK | MSG_NOSIGNAL );\n        if (BytesRead==0)\n            LastTcpError = WSAECONNRESET;  // Connection reset by Peer\n        else\n            if (BytesRead<0)\n                LastTcpError = GetLastSocketError();\n    }\n    else // After the timeout the bytes waiting were less then we expected\n        if (LastTcpError==WSAETIMEDOUT)\n            Purge();\n\n    if (LastTcpError==WSAECONNRESET)\n        Connected =false;\n\n    return LastTcpError;\n}\n//---------------------------------------------------------------------------\nbool TMsgSocket::Execute()\n{\n    return true;\n}\n//==============================================================================\n// PING\n//==============================================================================\n\nstatic int PingKind;\n\n#ifdef OS_WINDOWS\n// iphlpapi, is loaded dinamically because if this fails we can still try\n// to use raw sockets\n\nstatic char const *iphlpapi = \"\\\\iphlpapi.dll\";\n#pragma pack(1)\n\n//typedef byte TTxBuffer[40];\ntypedef byte TTxBuffer[32];\n#pragma pack()\n\ntypedef HANDLE (__stdcall *pfn_IcmpCreateFile)();\ntypedef bool (__stdcall *pfn_IcmpCloseHandle)(HANDLE PingHandle);\n\ntypedef int (__stdcall *pfn_IcmpSendEcho2)(\n    HANDLE PingHandle,\n    void *Event,\n    void *AcpRoutine,\n    void *AcpContext,\n    unsigned long DestinationAddress,\n    void *RequestData,\n    int RequestSize,\n    void *not_used,  //should be *IP_OPTION_INFORMATION but we don't use it\n    void *ReplyBuffer,\n    int ReplySize,\n    int Timeout\n);\n\nstatic pfn_IcmpCreateFile IcmpCreateFile;\nstatic pfn_IcmpCloseHandle IcmpCloseHandle;\nstatic pfn_IcmpSendEcho2 IcmpSendEcho2;\nstatic HINSTANCE IcmpDllHandle = 0;\nstatic bool IcmpAvail = false;\n\nbool IcmpInit()\n{\n\tchar iphlppath[MAX_PATH+12];\n\n\tint PathLen = GetSystemDirectoryA(iphlppath, MAX_PATH);\n\tif (PathLen != 0)\n\t{\n\t\tstrcat(iphlppath, iphlpapi);\n\t\tIcmpDllHandle = LoadLibraryA(iphlppath);\n\t}\n\telse\n\t\tIcmpDllHandle = 0;\n\n    if (IcmpDllHandle != 0)\n    {\n        IcmpCreateFile=(pfn_IcmpCreateFile)GetProcAddress(IcmpDllHandle,\"IcmpCreateFile\");\n        IcmpCloseHandle=(pfn_IcmpCloseHandle)GetProcAddress(IcmpDllHandle,\"IcmpCloseHandle\");\n        IcmpSendEcho2=(pfn_IcmpSendEcho2)GetProcAddress(IcmpDllHandle,\"IcmpSendEcho2\");\n        return (IcmpCreateFile!=NULL) && (IcmpCloseHandle!=NULL) && (IcmpSendEcho2!=NULL);\n    }\n    else\n        return false;\n}\n\nvoid IcmpDone()\n{\n    if (IcmpDllHandle!=0)\n       FreeLibrary(IcmpDllHandle);\n    IcmpAvail=false;\n}\n#endif\n\n//---------------------------------------------------------------------------\n//  RAW Socket Pinger\n//---------------------------------------------------------------------------\nTRawSocketPinger::TRawSocketPinger()\n{\n    FSocket =socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);\n    FId  =word(size_t(this));\n    FSeq =0;\n}\n//---------------------------------------------------------------------------\nTRawSocketPinger::~TRawSocketPinger()\n{\n    if (FSocket!=INVALID_SOCKET)\n    {\n      #ifdef OS_WINDOWS\n          closesocket(FSocket);\n      #else\n          close(FSocket);\n      #endif\n      FSocket=INVALID_SOCKET;\n    };\n}\n//---------------------------------------------------------------------------\nvoid TRawSocketPinger::InitPacket()\n{\n    memset(&IcmpBuffer,0,ICmpBufferSize);\n    FSeq++;\n    \n\tSendPacket=PIcmpPacket(pbyte(&IcmpBuffer)+sizeof(TIPHeader));\n    SendPacket->Header.ic_type=ICMP_ECHORQ;\n    SendPacket->Header.ic_code=0;\n    SendPacket->Header.ic_cksum=0;\n    SendPacket->Header.ic_id=FId;\n    SendPacket->Header.ic_seq=FSeq;\n \n    memset(&SendPacket->Data,0,sizeof(SendPacket->Data));\n    SendPacket->Header.ic_cksum=PacketChecksum();\n}\n//---------------------------------------------------------------------------\nword TRawSocketPinger::PacketChecksum()\n{\n    word *P = (word*)(SendPacket);\n    longword Sum = 0;\n    int c;\n    for (c = 0; c < int(sizeof(TIcmpPacket) / 2); c++) {\n        Sum+=*P;\n        P++;\n    }\n    Sum=(Sum >> 16) + (Sum & 0xFFFF);\n    Sum=Sum+(Sum >> 16);\n    return word(~Sum);\n}\n//---------------------------------------------------------------------------\nbool TRawSocketPinger::CanRead(int Timeout)\n{\n    timeval TimeV;\n    int64_t x;\n    fd_set FDset;\n\n    TimeV.tv_usec = (Timeout % 1000) * 1000;\n    TimeV.tv_sec = Timeout / 1000;\n\n    FD_ZERO(&FDset);\n    FD_SET(FSocket, &FDset);\n\n    x = select(FSocket + 1, &FDset, NULL, NULL, &TimeV); //<-Ignore this warning in 64bit Visual Studio\n    if (x==(int)(SOCKET_ERROR))\n       x=0;\n    return (x > 0);\n}\n//---------------------------------------------------------------------------\nbool TRawSocketPinger::Ping(longword ip_addr, int Timeout)\n{\n    sockaddr_in LSockAddr;\n    sockaddr_in RSockAddr;\n    PIcmpReply Reply;\n\n    if (FSocket==INVALID_SOCKET)\n      return true;\n\n    // Init packet\n    InitPacket();\n    Reply=PIcmpReply(&IcmpBuffer);\n    // Init Remote and Local Addresses struct\n    RSockAddr.sin_family=AF_INET;\n    RSockAddr.sin_port=0;\n    RSockAddr.sin_addr.s_addr=ip_addr;\n\n    LSockAddr.sin_family=AF_INET;\n    LSockAddr.sin_port=0;\n    LSockAddr.sin_addr.s_addr=inet_addr(\"0.0.0.0\");\n\n    // Bind to local\n    if (bind(FSocket, (struct sockaddr*)&LSockAddr, sizeof(sockaddr_in))!=0)\n        return false;\n    // Connect to remote (not a really TCP connection, only to setup the socket)\n    if (connect(FSocket, (struct sockaddr*)&RSockAddr, sizeof(sockaddr_in))!=0)\n        return false;\n    // Send ICMP packet\n    if (send(FSocket, (char*)SendPacket, sizeof(TIcmpPacket), MSG_NOSIGNAL)!=int(sizeof(TIcmpPacket)))\n        return false;\n    // Wait for a reply\n    if (!CanRead(Timeout))\n        return false;// time expired\n    // Get the answer\n    if (recv(FSocket, (char*)&IcmpBuffer, ICmpBufferSize, MSG_NOSIGNAL)<int(sizeof(TIcmpReply)))\n        return false;\n    // Check the answer\n    return (Reply->IPH.ip_src==RSockAddr.sin_addr.s_addr) &&  // the peer is what we are looking for\n           (Reply->ICmpReply.Header.ic_type==ICMP_ECHORP);    // type = reply\n}\n//---------------------------------------------------------------------------\n//  Pinger\n//---------------------------------------------------------------------------\nTPinger::TPinger()\n{\n}\n//---------------------------------------------------------------------------\nTPinger::~TPinger()\n{\n}\n//---------------------------------------------------------------------------\nbool TPinger::RawPing(longword ip_addr, int Timeout)\n{\n    PRawSocketPinger RawPinger = new TRawSocketPinger();\n    bool Result;\n    Result=RawPinger->Ping(ip_addr, Timeout);\n    delete RawPinger;\n    return Result;\n}\n//---------------------------------------------------------------------------\n#ifdef OS_WINDOWS\nbool TPinger::WinPing(longword ip_addr, int Timeout)\n{\n    HANDLE PingHandle;\n    TTxBuffer TxBuffer;\n    TIcmpBuffer IcmpBuffer;\n    bool Result;\n\n    PingHandle = IcmpCreateFile();\n    if (PingHandle != INVALID_HANDLE_VALUE)\n    {\n        memset(&TxBuffer,'\\55',sizeof(TTxBuffer));\n        Result=(IcmpSendEcho2(PingHandle, NULL, NULL, NULL, ip_addr,\n            &TxBuffer, sizeof(TxBuffer), NULL, &IcmpBuffer, ICmpBufferSize, Timeout))>0;\n        IcmpCloseHandle(PingHandle);\n        return Result;\n    }\n    else\n        return false;\n}\n#endif\n//---------------------------------------------------------------------------\nbool TPinger::Ping(char *Host, int Timeout)\n{\n    longword Addr;\n    Addr=inet_addr(Host);\n    return Ping(Addr, Timeout);\n}\n//---------------------------------------------------------------------------\nbool TPinger::Ping(longword ip_addr, int Timeout)\n{\n#ifdef OS_WINDOWS\n    if (PingKind==pkWinHelper)\n        return WinPing(ip_addr, Timeout);\n    else\n#endif\n    if (PingKind==pkRawSocket)\n        return RawPing(ip_addr, Timeout);\n    else\n        return true; // we still need to continue\n}\n//---------------------------------------------------------------------------\n// Checks if raw sockets are allowed\n//---------------------------------------------------------------------------\nbool RawSocketsCheck()\n{\n    socket_t RawSocket;\n    bool Result;\n    RawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);\n\n    Result=RawSocket != INVALID_SOCKET;\n    if (Result)\n    #ifdef OS_WINDOWS\n        closesocket(RawSocket);\n    #else\n        close(RawSocket);\n    #endif\n\n    return Result;\n}\n//---------------------------------------------------------------------------\n// Sockets init\n// - Winsock Startup (Windows)\n// - ICMP Helper Load (Windows)\n// - Check for raw socket (Unix or Windows if ICMP load failed)\n//---------------------------------------------------------------------------\nSocketsLayer::SocketsLayer()\n{\n#ifdef OS_WINDOWS\n    timeBeginPeriod(1); // it's not strictly related to socket but here is a nice place\n    WSAStartup(0x202,&wsaData);\n    if (IcmpInit())\n       PingKind=pkWinHelper;\n    else\n#endif\n    if (RawSocketsCheck())\n        PingKind=pkRawSocket;\n    else\n        PingKind=pkCannotPing;\n}\n\nSocketsLayer::~SocketsLayer()\n{\n#ifdef OS_WINDOWS\n    IcmpDone();\n    WSACleanup();\n    timeEndPeriod(1);\n#endif\n}\n\n\n"
  },
  {
    "path": "deps/snap7/src/sys/snap_msgsock.h",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.3.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|=============================================================================*/\n#ifndef snap_msgsock_h\n#define snap_msgsock_h\n//---------------------------------------------------------------------------\n#include \"snap_platform.h\"\n#include \"snap_sysutils.h\"\n//----------------------------------------------------------------------------\n#if defined(OS_WINDOWS) || defined (OS_SOLARIS) || defined(OS_OSX)\n# define MSG_NOSIGNAL    0\n#endif\n//----------------------------------------------------------------------------\n// Non blocking connection to avoid root priviledges under UNIX \n// i.e. raw socket pinger is not more used.\n// Thanks to Rolf Stalder that made it ;)\n//----------------------------------------------------------------------------\n#ifdef PLATFORM_UNIX\n    #define NON_BLOCKING_CONNECT\n#endif\n#ifdef NON_BLOCKING_CONNECT\n    #include <fcntl.h>\n#endif\n//----------------------------------------------------------------------------\n/*\n  In Windows sizeof socket varies depending of the platform :\n    win32 -> sizeof(SOCKET) = 4\n    win64 -> sizeof(SOCKET) = 8\n\n  Even though sizeof(SOCKET) is 8, should be safe to cast it to int, because\n  the value constitutes an index in per-process table of limited size\n  and not a real pointer.\n\n  Other Os define the socket as int regardless of the processor.\n\n  We want to sleep peacefully, so it's better to define a portable socket.\n*/\n\n#ifdef OS_WINDOWS\ntypedef SOCKET socket_t;\n#else\ntypedef int socket_t;\n#endif\n\n//----------------------------------------------------------------------------\n#define  SD_RECEIVE      0x00\n#define  SD_SEND         0x01\n#define  SD_BOTH         0x02\n#define  MaxPacketSize   65536\n\n//----------------------------------------------------------------------------\n// For other platform we need to re-define next constants\n#if defined(PLATFORM_UNIX) || defined(OS_OSX)\n\n#define INVALID_SOCKET (socket_t)(~0)\n#define SOCKET_ERROR             (-1)\n\n#define WSAEINTR             EINTR\n#define WSAEBADF             EBADF\n#define WSAEACCES            EACCES\n#define WSAEFAULT            EFAULT\n#define WSAEINVAL            EINVAL\n#define WSAEMFILE            EMFILE\n#define WSAEWOULDBLOCK       EWOULDBLOCK\n#define WSAEINPROGRESS       EINPROGRESS\n#define WSAEALREADY          EALREADY\n#define WSAENOTSOCK          ENOTSOCK\n#define WSAEDESTADDRREQ      EDESTADDRREQ\n#define WSAEMSGSIZE          EMSGSIZE\n#define WSAEPROTOTYPE        EPROTOTYPE\n#define WSAENOPROTOOPT       ENOPROTOOPT\n#define WSAEPROTONOSUPPORT   EPROTONOSUPPORT\n#define WSAESOCKTNOSUPPORT   ESOCKTNOSUPPORT\n#define WSAEOPNOTSUPP        EOPNOTSUPP\n#define WSAEPFNOSUPPORT      EPFNOSUPPORT\n#define WSAEAFNOSUPPORT      EAFNOSUPPORT\n#define WSAEADDRINUSE        EADDRINUSE\n#define WSAEADDRNOTAVAIL     EADDRNOTAVAIL\n#define WSAENETDOWN          ENETDOWN\n#define WSAENETUNREACH       ENETUNREACH\n#define WSAENETRESET         ENETRESET\n#define WSAECONNABORTED      ECONNABORTED\n#define WSAECONNRESET        ECONNRESET\n#define WSAENOBUFS           ENOBUFS\n#define WSAEISCONN           EISCONN\n#define WSAENOTCONN          ENOTCONN\n#define WSAESHUTDOWN         ESHUTDOWN\n#define WSAETOOMANYREFS      ETOOMANYREFS\n#define WSAETIMEDOUT         ETIMEDOUT\n#define WSAECONNREFUSED      ECONNREFUSED\n#define WSAELOOP             ELOOP\n#define WSAENAMETOOLONG      ENAMETOOLONG\n#define WSAEHOSTDOWN         EHOSTDOWN\n#define WSAEHOSTUNREACH      EHOSTUNREACH\n#define WSAENOTEMPTY         ENOTEMPTY\n#define WSAEUSERS            EUSERS\n#define WSAEDQUOT            EDQUOT\n#define WSAESTALE            ESTALE\n#define WSAEREMOTE           EREMOTE\n#endif\n\n#define WSAEINVALIDADDRESS   12001\n\n#define ICmpBufferSize 4096\ntypedef byte TIcmpBuffer[ICmpBufferSize];\n\n// Ping result\n#define PR_CANNOT_PERFORM -1  // cannot ping :\n                              //   unix    : no root rights or SUID flag set to\n                              //             open raw sockets\n                              //   windows : neither helper DLL found nor raw\n                              //             sockets can be opened (no administrator rights)\n                              //  In this case the execution continues whitout\n                              //  the benefit of the smart-connect.\n\n#define PR_SUCCESS         0  // Host found\n#define PR_ERROR           1  // Ping Error, Ping was performed but ...\n                              //   - host didn't replied (not found)\n                              //   - routing error\n                              //   - TTL expired\n                              //   - ... all other icmp error that we don't need\n                              //      to know.\n\n// Ping Kind\n#define pkCannotPing  1  // see PR_CANNOT_PERFORM comments\n#define pkWinHelper   2  // use iphlpapi.dll (only windows)\n#define pkRawSocket   3  // use raw sockets (unix/windows)\n\nconst byte ICMP_ECHORP  = 0;  // ECHO Reply\nconst byte ICMP_ECHORQ  = 8;  // ECHO Request\n//---------------------------------------------------------------------------\n// RAW SOCKET PING STRUCTS\n//---------------------------------------------------------------------------\n#pragma pack(1)\ntypedef struct{\n    byte ip_hl_v;\n    byte ip_tos;\n    word ip_len;\n    word ip_id ;\n    word ip_off;\n    byte ip_ttl;\n    byte ip_p;\n    word ip_sum;\n    longword ip_src;\n    longword ip_dst;\n}TIPHeader;\n\ntypedef struct{\n    byte ic_type;  // Type of message\n    byte ic_code;  // Code\n    word ic_cksum; // 16 bit checksum\n    word ic_id;    // ID (ic1 : ipv4)\n    word ic_seq;   // Sequence\n}TIcmpHeader;\n\ntypedef struct{\n    TIcmpHeader Header;\n    byte Data[32]; // use the well known default\n}TIcmpPacket, *PIcmpPacket;\n\ntypedef struct{\n    TIPHeader IPH;\n    TIcmpPacket ICmpReply;\n}TIcmpReply, *PIcmpReply;\n#pragma pack()\n\n//---------------------------------------------------------------------------\nclass TRawSocketPinger\n{\nprivate:\n    socket_t FSocket;\n    PIcmpPacket SendPacket;\n    TIcmpBuffer IcmpBuffer;\n    word FId, FSeq;\n    void InitPacket();\n    word PacketChecksum();\n    bool CanRead(int Timeout);\npublic:\n    bool Ping(longword ip_addr, int Timeout);\n    TRawSocketPinger();\n    ~TRawSocketPinger();\n};\ntypedef TRawSocketPinger *PRawSocketPinger;\n//---------------------------------------------------------------------------\nclass TPinger\n{\nprivate:\n    PRawSocketPinger RawPinger;\n    bool RawAvail;\n#ifdef OS_WINDOWS\n\tbool WinPing(longword ip_addr, int Timeout);\n#endif\n\tbool RawPing(longword ip_addr, int Timeout);\npublic:\n    TPinger();\n    ~TPinger();\n\tbool Ping(char *Host, int Timeout);\n\tbool Ping(longword ip_addr, int Timeout);\n};\ntypedef TPinger *PPinger;\n//---------------------------------------------------------------------------\nclass TSnapBase // base class endian-aware\n{\nprivate:\n\t\tbool LittleEndian;\nprotected:\n\t\tlongword SwapDWord(longword Value);\n\t\tword SwapWord(word Value);\npublic:\n\t\tTSnapBase();\n};\n//---------------------------------------------------------------------------\nclass TMsgSocket : public TSnapBase\n{\nprivate:\n        PPinger Pinger;\n        int GetLastSocketError();\n        int SockCheck(int SockResult);\n        void DestroySocket();\n        void SetSocketOptions();\n        bool CanWrite(int Timeout);\n        void GetLocal();\n        void GetRemote();\n        void SetSin(sockaddr_in &sin, char *Address, u_short Port);\n        void GetSin(sockaddr_in sin, char *Address, u_short &Port);\nprotected:\n        socket_t FSocket;\n        sockaddr_in LocalSin;\n        sockaddr_in RemoteSin;\n        //--------------------------------------------------------------------------\n        // low level socket\n        void CreateSocket();\n        // Called when a socket is assigned externally\n        void GotSocket();\n        // Returns how many bytes are ready to be read in the winsock buffer\n        int WaitingData();\n        // Waits until there at least \"size\" bytes ready to be read or until receive timeout occurs\n        int WaitForData(int Size, int Timeout);\n        // Clear socket input buffer\n        void Purge();\npublic:\n        longword ClientHandle;\n        longword LocalBind;\n        // Coordinates Address:Port\n        char LocalAddress[16];\n        char RemoteAddress[16];\n        word LocalPort;\n        word RemotePort;\n        // \"speed\" of the socket listener (used server-side)\n        int WorkInterval;\n        // Timeouts : 3 different values for fine tuning.\n        // Send timeout should be small since with work with small packets and TCP_NO_DELAY\n        //   option, so we don't expect \"time to wait\".\n        // Recv timeout depends of equipment's processing time : we send a packet, the equipment\n        //   processes the message, finally it sends the answer. In any case Recv timeout > Send Timeout.\n        // PingTimeout is the maximum time interval during which we expect that the PLC answers.\n        //   By default is 750 ms, increase it if there are many switch/repeaters.\n        int PingTimeout;\n        int RecvTimeout;\n        int SendTimeout;\n        //int ConnTimeout;\n        // Output : Last operation error\n        int LastTcpError;\n        // Output : Connected to the remote Host/Peer/Client\n        bool Connected;\n        //--------------------------------------------------------------------------\n        TMsgSocket();\n        virtual ~TMsgSocket();\n        // Returns true if \"something\" can be read during the Timeout interval..\n        bool CanRead(int Timeout);\n        // Connects to a peer (using RemoteAddress and RemotePort)\n        int SckConnect(); // (client-side)\n        // Disconnects from a peer (gracefully)\n        void SckDisconnect();\n        // Disconnects RAW\n        void ForceClose();\n        // Binds to a local adapter (using LocalAddress and LocalPort) (server-side)\n        int SckBind();\n        // Listens for an incoming connection (server-side)\n        int SckListen();\n        // Set an external socket reference (tipically from a listener)\n        void SetSocket(socket_t s);\n        // Accepts an incoming connection returning a socket descriptor (server-side)\n        socket_t SckAccept();\n        // Pings the peer before connecting\n        bool Ping(char *Host);\n        bool Ping(sockaddr_in Addr);\n        // Sends a packet\n        int SendPacket(void *Data,  int Size);\n        // Returns true if a Packet at least of \"Size\" bytes is ready to be read\n        bool PacketReady(int Size);\n        // Receives everything\n        int Receive(void *Data, int BufSize, int & SizeRecvd);\n        // Receives a packet of size specified.\n        int RecvPacket(void *Data, int Size);\n        // Peeks a packet of size specified without extract it from the socket queue\n        int PeekPacket(void *Data, int Size);\n        virtual bool Execute();\n};\n\ntypedef TMsgSocket *PMsgSocket;\n//---------------------------------------------------------------------------\nvoid Msg_CloseSocket(socket_t FSocket);\nlongword Msg_GetSockAddr(socket_t FSocket);\n//---------------------------------------------------------------------------\nclass SocketsLayer\n{\nprivate:\n#ifdef OS_WINDOWS\n    WSADATA wsaData;\n#endif\npublic:\n    SocketsLayer();\n    ~SocketsLayer();\n};\n\n#endif // snap_msgsock_h\n"
  },
  {
    "path": "deps/snap7/src/sys/snap_platform.h",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.4.1 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|=============================================================================*/\n#ifndef snap_platform_h\n#define snap_platform_h\n//---------------------------------------------------------------------------\n#if defined (_WIN32)|| defined(_WIN64)|| defined(__WIN32__) || defined(__WINDOWS__)\n# define OS_WINDOWS\n#endif\n\n// Visual Studio needs this to use the correct time_t size\n#if defined (_WIN32) && !defined(_WIN64) && !defined(_EMBEDDING_VS2013UP)\n  # define _USE_32BIT_TIME_T \n#endif\n\n// Linux, BSD and Solaris define \"unix\", OSX doesn't, even though it derives from BSD\n#if defined(unix) || defined(__unix__) || defined(__unix)\n# define PLATFORM_UNIX\n#endif\n\n#if BSD>=0\n# define OS_BSD\n#endif\n\n#if __APPLE__\n# define OS_OSX\n#endif\n\n#if defined(__SVR4) || defined(__svr4__)\n# define OS_SOLARIS\n// Thanks to Rolf Stalder now it's possible to use pthreads also for Solaris\n// In any case the Solaris native threads model is still present and can be\n// used uncommenting the #define line below.\n# undef OS_SOLARIS_NATIVE_THREADS\n// # define OS_SOLARIS_NATIVE_THREADS\n#endif\n\n#if defined(PLATFORM_UNIX)\n# include <unistd.h>\n# include <sys/param.h>\n# if defined(_POSIX_VERSION)\n#   define POSIX\n# endif\n#endif\n\n#ifdef OS_OSX\n# include <unistd.h>\n#endif\n\n#if (!defined (OS_WINDOWS)) && (!defined(PLATFORM_UNIX)) && (!defined(OS_BSD)) && (!defined(OS_OSX))\n# error platform still unsupported (please add it yourself and report ;-)\n#endif\n\n// Visual C++ not C99 compliant (VS2008--)\n#ifdef _MSC_VER\n# if _MSC_VER >= 1600\n#  include <stdint.h>  // VS2010++ have it \n# else\n   typedef signed __int8     int8_t;\n   typedef signed __int16    int16_t;\n   typedef signed __int32    int32_t;\n   typedef signed __int64    int64_t;\n   typedef unsigned __int8   uint8_t;\n   typedef unsigned __int16  uint16_t;\n   typedef unsigned __int32  uint32_t;\n   typedef unsigned __int64  uint64_t;\n   #ifdef _WIN64\n     typedef unsigned __int64  uintptr_t;\n   #else\n     typedef unsigned __int32  uintptr_t;\n   #endif\n# endif\n#else\n# include <stdint.h>\n#endif\n\n#include <time.h>\n#include <cstring>\n#include <stdlib.h>\n\n#ifdef OS_WINDOWS\n# define WIN32_LEAN_AND_MEAN\n# include <windows.h>\n# include <winsock2.h>\n# include <mmsystem.h>\n#endif\n\n#ifdef OS_SOLARIS\n# include <sys/filio.h>\n# include <cstdlib>\n# include <string.h>\n#endif\n\n#if defined(PLATFORM_UNIX) || defined(OS_OSX)\n# include <errno.h>\n# include <sys/time.h>\n# include <sys/socket.h>\n# include <arpa/inet.h>\n# include <netinet/tcp.h>\n# include <netinet/in.h>\n# include <sys/ioctl.h>\n#endif\n\n#ifdef OS_WINDOWS\n# define EXPORTSPEC extern \"C\" __declspec ( dllexport )\n# define S7API __stdcall\n#else\n# define EXPORTSPEC extern \"C\"\n# define S7API\n#endif\n\n// Exact length types regardless of platform/processor\n// We absolute need of them, all structs have an exact size that\n// must be the same across the processor used 32/64 bit\n\n// *Use them* if you change/expand the code and avoid long, u_long and so on...\n\ntypedef uint8_t    byte;\ntypedef uint16_t   word;\ntypedef uint32_t   longword;\ntypedef byte       *pbyte;\ntypedef word       *pword;\ntypedef uintptr_t  snap_obj; // multi platform/processor object reference\n\n#ifndef OS_WINDOWS\n# define INFINITE  0XFFFFFFFF\n#endif\n\n\n#endif // snap_platform_h\n"
  },
  {
    "path": "deps/snap7/src/sys/snap_sysutils.cpp",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.3.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|=============================================================================*/\n\n#include \"snap_sysutils.h\"\n\n#ifdef OS_OSX\nint clock_gettime(int clk_id, struct timespec* t) \n{\n    struct timeval now;\n    int rv = gettimeofday(&now, NULL);\n    if (rv) return rv;\n    t->tv_sec  = now.tv_sec;\n    t->tv_nsec = now.tv_usec * 1000;\n    return 0;\n}\n#endif\n\n//---------------------------------------------------------------------------\nlongword SysGetTick()\n{\n#ifdef OS_WINDOWS\n    return timeGetTime();\n#else\n    struct timespec ts;\n    clock_gettime(CLOCK_MONOTONIC, &ts);\n    return (longword) (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000);\n#endif\n}\n//---------------------------------------------------------------------------\nvoid SysSleep(longword Delay_ms)\n{\n#ifdef OS_WINDOWS\n\tSleep(Delay_ms);\n#else\n    struct timespec ts;\n    ts.tv_sec = (time_t)(Delay_ms / 1000);\n    ts.tv_nsec =(long)((Delay_ms - ts.tv_sec) * 1000000);\n    nanosleep(&ts, (struct timespec *)0);\n#endif\n}\n//---------------------------------------------------------------------------\nlongword DeltaTime(longword &Elapsed)\n{\n    longword TheTime;\n    TheTime=SysGetTick();\n    // Checks for rollover\n    if (TheTime<Elapsed)\n        Elapsed=0;\n    return TheTime-Elapsed;\n}\n"
  },
  {
    "path": "deps/snap7/src/sys/snap_sysutils.h",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.3.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|=============================================================================*/\n#ifndef snap_sysutils_h\n#define snap_sysutils_h\n//---------------------------------------------------------------------------\n#include \"snap_platform.h\"\n//---------------------------------------------------------------------------\n#ifdef OS_OSX\n# define CLOCK_MONOTONIC 0\n#endif\n\nlongword SysGetTick();\nvoid SysSleep(longword Delay_ms);\nlongword DeltaTime(longword &Elapsed);\n\n#endif // snap_sysutils_h\n"
  },
  {
    "path": "deps/snap7/src/sys/snap_tcpsrvr.cpp",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.3.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|=============================================================================*/\n\n#include \"snap_tcpsrvr.h\"\n//---------------------------------------------------------------------------\n// EVENTS QUEUE\n//---------------------------------------------------------------------------\n\nTMsgEventQueue::TMsgEventQueue(const int Capacity, const int BlockSize) \n{\n    FCapacity = Capacity;\n    Max = FCapacity - 1;\n    FBlockSize = BlockSize;\n    Buffer = new byte[FCapacity * FBlockSize];\n    Flush();\n}\n//---------------------------------------------------------------------------\nTMsgEventQueue::~TMsgEventQueue() \n{\n    delete[] Buffer;\n}\n//---------------------------------------------------------------------------\nvoid TMsgEventQueue::Flush() \n{\n    IndexIn = 0;\n    IndexOut = 0;\n}\n//---------------------------------------------------------------------------\nvoid TMsgEventQueue::Insert(void *lpdata) \n{\n    pbyte PBlock;\n    if (!Full())\n    {\n        // Calc offset\n        if (IndexIn < Max) IndexIn++;\n        else IndexIn = 0;\n        PBlock = Buffer + uintptr_t(IndexIn * FBlockSize);\n        memcpy(PBlock, lpdata, FBlockSize);\n    };\n}\n//---------------------------------------------------------------------------\nbool TMsgEventQueue::Extract(void *lpdata) \n{\n    int IdxOut;\n    pbyte PBlock;\n\n    if (!Empty())\n    {\n        // stores IndexOut\n        IdxOut = IndexOut;\n        if (IdxOut < Max) IdxOut++;\n        else IdxOut = 0;\n        PBlock = Buffer + uintptr_t(IdxOut * FBlockSize);\n        // moves data\n        memcpy(lpdata, PBlock, FBlockSize);\n        // Updates IndexOut\n        IndexOut = IdxOut;\n        return true;\n    }\n    else\n        return false;\n}\n//---------------------------------------------------------------------------\nbool TMsgEventQueue::Empty() \n{\n    return (IndexIn == IndexOut);\n}\n//---------------------------------------------------------------------------\nbool TMsgEventQueue::Full() \n{\n    int IdxOut = IndexOut; // To avoid troubles if IndexOut changes during next line\n    return ( (IdxOut == IndexIn + 1) || ((IndexIn == Max) && (IdxOut == 0)));\n}\n//---------------------------------------------------------------------------\n// WORKER THREAD\n//---------------------------------------------------------------------------\nTMsgWorkerThread::TMsgWorkerThread(TMsgSocket *Socket, TCustomMsgServer *Server) \n{\n    FreeOnTerminate = true;\n    WorkerSocket = Socket;\n    FServer = Server;\n}\n//---------------------------------------------------------------------------\nvoid TMsgWorkerThread::Execute() \n{\n    bool Exception = false;\n    bool SelfClose = false;\n    // Working loop\n    while (!Terminated && !SelfClose && !Exception && !FServer->Destroying)\n    {\n        try\n        {\n            if (!WorkerSocket->Execute()) // False -> End of Activities\n                SelfClose = true;\n        } catch (...)\n        {\n            Exception = true;\n        }\n    };\n    if (!FServer->Destroying)\n    {\n        // Exception detected during Worker activity\n        if (Exception)\n        {\n            WorkerSocket->ForceClose();\n            FServer->DoEvent(WorkerSocket->ClientHandle, evcClientException, 0, 0, 0, 0, 0);\n        }\n        else\n            if (SelfClose)\n        {\n            FServer->DoEvent(WorkerSocket->ClientHandle, evcClientDisconnected, 0, 0, 0, 0, 0);\n        }\n        else\n            FServer->DoEvent(WorkerSocket->ClientHandle, evcClientTerminated, 0, 0, 0, 0, 0);\n    }\n    delete WorkerSocket;\n    // Delete reference from list\n    FServer->Delete(Index);\n}\n//---------------------------------------------------------------------------\n// LISTENER THREAD\n//---------------------------------------------------------------------------\n\nTMsgListenerThread::TMsgListenerThread(TMsgSocket *Listener, TCustomMsgServer *Server) \n{\n    FServer = Server;\n    FListener = Listener;\n    FreeOnTerminate = false;\n}\n//---------------------------------------------------------------------------\n\nvoid TMsgListenerThread::Execute() \n{\n    socket_t Sock;\n    bool Valid;\n\n    while (!Terminated)\n    {\n        if (FListener->CanRead(FListener->WorkInterval))\n        {\n            Sock = FListener->SckAccept(); // in any case we must accept\n            Valid = Sock != INVALID_SOCKET;\n            // check if we are not destroying\n            if ((!Terminated) && (!FServer->Destroying))\n            {\n                if (Valid)\n                    FServer->Incoming(Sock);\n            }\n            else\n                if (Valid)\n                    Msg_CloseSocket(Sock);\n        };\n    }\n}\n//---------------------------------------------------------------------------\n// TCP SERVER\n//---------------------------------------------------------------------------\nTCustomMsgServer::TCustomMsgServer() \n{\n    strcpy(FLocalAddress, \"0.0.0.0\");\n    CSList = new TSnapCriticalSection();\n    CSEvent = new TSnapCriticalSection();\n    FEventQueue = new TMsgEventQueue(MaxEvents, sizeof (TSrvEvent));\n    memset(Workers, 0, sizeof (Workers));\n    for (int i = 0; i < MaxWorkers; i++)\n        Workers[i] = NULL;\n    Status = SrvStopped;\n    EventMask = 0xFFFFFFFF;\n    LogMask = 0xFFFFFFFF;\n    Destroying = false;\n    FLastError = 0;\n    ClientsCount = 0;\n    LocalBind = 0;\n    MaxClients = MaxWorkers;\n    OnEvent = NULL;\n}\n//---------------------------------------------------------------------------\nTCustomMsgServer::~TCustomMsgServer() \n{\n    Destroying = true;\n    Stop();\n    OnEvent = NULL;\n    delete CSList;\n    delete CSEvent;\n    delete FEventQueue;\n}\n//---------------------------------------------------------------------------\nvoid TCustomMsgServer::LockList() \n{\n    CSList->Enter();\n}\n//---------------------------------------------------------------------------\nvoid TCustomMsgServer::UnlockList() \n{\n    CSList->Leave();\n}\n//---------------------------------------------------------------------------\nint TCustomMsgServer::FirstFree() \n{\n    int i;\n    for (i = 0; i < MaxWorkers; i++)\n    {\n        if (Workers[i] == 0)\n            return i;\n    }\n    return -1;\n}\n//---------------------------------------------------------------------------\n\nint TCustomMsgServer::StartListener() \n{\n    int Result;\n    // Creates the listener\n    SockListener = new TMsgSocket();\n    strncpy(SockListener->LocalAddress, FLocalAddress, 16);\n    SockListener->LocalPort = LocalPort;\n    // Binds\n    Result = SockListener->SckBind();\n    if (Result == 0)\n    {\n        LocalBind = SockListener->LocalBind;\n        // Listen\n        Result = SockListener->SckListen();\n        if (Result == 0)\n        {\n            // Creates the Listener thread\n            ServerThread = new TMsgListenerThread(SockListener, this);\n            ServerThread->Start();\n        }\n        else\n            delete SockListener;\n    }\n    else\n        delete SockListener;\n\n    return Result;\n}\n//---------------------------------------------------------------------------\nvoid TCustomMsgServer::TerminateAll() \n{\n    int c;\n    longword Elapsed;\n    bool Timeout;\n\n    if (ClientsCount > 0)\n    {\n        for (c = 0; c < MaxWorkers; c++)\n        {\n            if (Workers[c] != 0)\n                PMsgWorkerThread(Workers[c])->Terminate();\n        }\n        // Wait for closing\n        Elapsed = SysGetTick();\n        Timeout = false;\n        while (!Timeout && (ClientsCount > 0))\n        {\n            Timeout = DeltaTime(Elapsed) > WkTimeout;\n            if (!Timeout)\n                SysSleep(100);\n        };\n        if (ClientsCount > 0)\n            KillAll(); // one o more threads are hanged\n        ClientsCount = 0;\n    }\n}\n//---------------------------------------------------------------------------\nvoid TCustomMsgServer::KillAll() \n{\n    int c, cnt = 0;\n    LockList();\n    for (c = 0; c < MaxWorkers; c++)\n    {\n        if (Workers[c] != 0)\n            try\n            {\n                PMsgWorkerThread(Workers[c])->Kill();\n                PMsgWorkerThread(Workers[c])->WorkerSocket->ForceClose();\n                delete PMsgWorkerThread(Workers[c]);\n                Workers[c] = 0;\n                cnt++;\n            } catch (...)\n            {\n            };\n    }\n    UnlockList();\n    DoEvent(0, evcClientsDropped, 0, cnt, 0, 0, 0);\n}\n//---------------------------------------------------------------------------\nbool TCustomMsgServer::CanAccept(socket_t Socket) \n{\n    return ((MaxClients == 0) || (ClientsCount < MaxClients));\n}\n//---------------------------------------------------------------------------\nPWorkerSocket TCustomMsgServer::CreateWorkerSocket(socket_t Sock) \n{\n    PWorkerSocket Result;\n    // Creates a funny default class : a tcp echo worker\n    Result = new TEcoTcpWorker();\n    Result->SetSocket(Sock);\n    return Result;\n}\n//---------------------------------------------------------------------------\nvoid TCustomMsgServer::DoEvent(int Sender, longword Code, word RetCode, word Param1, word Param2, word Param3, word Param4) \n{\n    TSrvEvent SrvEvent;\n    bool GoLog = (Code & LogMask) != 0;\n    bool GoEvent = (Code & EventMask) != 0;\n\n    if (!Destroying && (GoLog || GoEvent))\n    {\n        CSEvent->Enter();\n\n        time(&SrvEvent.EvtTime);\n        SrvEvent.EvtSender = Sender;\n        SrvEvent.EvtCode = Code;\n        SrvEvent.EvtRetCode = RetCode;\n        SrvEvent.EvtParam1 = Param1;\n        SrvEvent.EvtParam2 = Param2;\n        SrvEvent.EvtParam3 = Param3;\n        SrvEvent.EvtParam4 = Param4;\n\n        if (GoEvent && (OnEvent != NULL))\n            try\n            { // callback is outside here, we have to shield it\n                OnEvent(FUsrPtr, &SrvEvent, sizeof (TSrvEvent));\n            } catch (...)\n            {\n            };\n\n        if (GoLog)\n            FEventQueue->Insert(&SrvEvent);\n\n        CSEvent->Leave();\n    };\n}\n//---------------------------------------------------------------------------\nvoid TCustomMsgServer::Delete(int Index) \n{\n    LockList();\n    Workers[Index] = 0;\n    ClientsCount--;\n    UnlockList();\n}\n//---------------------------------------------------------------------------\nvoid TCustomMsgServer::Incoming(socket_t Sock) \n{\n    int idx;\n    PWorkerSocket WorkerSocket;\n    longword ClientHandle = Msg_GetSockAddr(Sock);\n\n    if (CanAccept(Sock))\n    {\n        LockList();\n        // First position available in the thread buffer\n        idx = FirstFree();\n        if (idx >= 0)\n        {\n            // Creates the Worker and assigns it the connected socket\n            WorkerSocket = CreateWorkerSocket(Sock);\n            // Creates the Worker thread\n            Workers[idx] = new TMsgWorkerThread(WorkerSocket, this);\n            PMsgWorkerThread(Workers[idx])->Index = idx;\n            // Update the number\n            ClientsCount++;\n            // And Starts the worker\n            PMsgWorkerThread(Workers[idx])->Start();\n            DoEvent(WorkerSocket->ClientHandle, evcClientAdded, 0, 0, 0, 0, 0);\n        }\n        else\n        {\n            DoEvent(ClientHandle, evcClientNoRoom, 0, 0, 0, 0, 0);\n            Msg_CloseSocket(Sock);\n        }\n        UnlockList();\n    }\n    else\n    {\n        Msg_CloseSocket(Sock);\n        DoEvent(ClientHandle, evcClientRejected, 0, 0, 0, 0, 0);\n    };\n}\n//---------------------------------------------------------------------------\nint TCustomMsgServer::Start() \n{\n    int Result = 0;\n    if (Status != SrvRunning)\n    {\n        Result = StartListener();\n        if (Result != 0)\n        {\n            DoEvent(0, evcListenerCannotStart, Result, 0, 0, 0, 0);\n            Status = SrvError;\n        }\n        else\n        {\n            DoEvent(0, evcServerStarted, SockListener->ClientHandle, LocalPort, 0, 0, 0);\n            Status = SrvRunning;\n        };\n    };\n    FLastError = Result;\n    return Result;\n}\n//---------------------------------------------------------------------------\nint TCustomMsgServer::StartTo(const char *Address, word Port) \n{\n    strncpy(FLocalAddress, Address, 16);\n    LocalPort = Port;\n    return Start();\n}\n//---------------------------------------------------------------------------\nvoid TCustomMsgServer::Stop() \n{\n    if (Status == SrvRunning)\n    {\n        // Kills the listener thread\n        ServerThread->Terminate();\n        if (ServerThread->WaitFor(ThTimeout) != WAIT_OBJECT_0)\n            ServerThread->Kill();\n        delete ServerThread;\n        // Kills the listener\n        delete SockListener;\n\n        // Terminate all client threads\n        TerminateAll();\n\n        Status = SrvStopped;\n        LocalBind = 0;\n        DoEvent(0, evcServerStopped, 0, 0, 0, 0, 0);\n    };\n    FLastError = 0;\n}\n//---------------------------------------------------------------------------\nint TCustomMsgServer::SetEventsCallBack(pfn_SrvCallBack PCallBack, void *UsrPtr) \n{\n    OnEvent = PCallBack;\n    FUsrPtr = UsrPtr;\n    return 0;\n}\n//---------------------------------------------------------------------------\nbool TCustomMsgServer::PickEvent(void *pEvent) \n{\n    try\n    {\n        return FEventQueue->Extract(pEvent);\n    } catch (...)\n    {\n        return false;\n    };\n}\n//---------------------------------------------------------------------------\nbool TCustomMsgServer::EventEmpty() \n{\n    return FEventQueue->Empty();\n}\n//---------------------------------------------------------------------------\nvoid TCustomMsgServer::EventsFlush() \n{\n    CSEvent->Enter();\n    FEventQueue->Flush();\n    CSEvent->Leave();\n}\n//---------------------------------------------------------------------------\n\n\n"
  },
  {
    "path": "deps/snap7/src/sys/snap_tcpsrvr.h",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.3.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|=============================================================================*/\n#ifndef snap_tcpsrvr_h\n#define snap_tcpsrvr_h\n//---------------------------------------------------------------------------\n#include \"snap_msgsock.h\"\n#include \"snap_threads.h\"\n//---------------------------------------------------------------------------\n\n#define MaxWorkers 1024\n#define MaxEvents  1500\n\nconst int SrvStopped = 0;\nconst int SrvRunning = 1;\nconst int SrvError   = 2;\n\nconst longword evcServerStarted       = 0x00000001;\nconst longword evcServerStopped       = 0x00000002;\nconst longword evcListenerCannotStart = 0x00000004;\nconst longword evcClientAdded         = 0x00000008;\nconst longword evcClientRejected      = 0x00000010;\nconst longword evcClientNoRoom        = 0x00000020;\nconst longword evcClientException     = 0x00000040;\nconst longword evcClientDisconnected  = 0x00000080;\nconst longword evcClientTerminated    = 0x00000100;\nconst longword evcClientsDropped      = 0x00000200;\nconst longword evcReserved_00000400   = 0x00000400;\nconst longword evcReserved_00000800   = 0x00000800;\nconst longword evcReserved_00001000   = 0x00001000;\nconst longword evcReserved_00002000   = 0x00002000;\nconst longword evcReserved_00004000   = 0x00004000;\nconst longword evcReserved_00008000   = 0x00008000;\n\n// Server Interface errors\nconst longword errSrvBase             = 0x0000FFFF;\nconst longword errSrvMask             = 0xFFFF0000;\nconst longword errSrvCannotStart      = 0x00100000;\n\nconst longword ThTimeout   = 2000; // Thread timeout\nconst longword WkTimeout   = 3000; // Workers termination timeout\n\n#pragma pack(1)\n\ntypedef struct{\n    time_t EvtTime;    // Timestamp\n    int EvtSender;     // Sender\n    longword EvtCode;  // Event code\n    word EvtRetCode;   // Event result\n    word EvtParam1;    // Param 1 (if available)\n    word EvtParam2;    // Param 2 (if available)\n    word EvtParam3;    // Param 3 (if available)\n    word EvtParam4;    // Param 4 (if available)\n}TSrvEvent, *PSrvEvent;\n\nextern \"C\" \n{\ntypedef void (S7API *pfn_SrvCallBack)(void * usrPtr, PSrvEvent PEvent, int Size);\n}\n#pragma pack()\n\n//---------------------------------------------------------------------------\n// EVENTS QUEUE\n//---------------------------------------------------------------------------\nclass TMsgEventQueue\n{\nprivate:\n        int   IndexIn;   // <-- insert index\n        int   IndexOut;  // --> extract index\n        int   Max;       // Buffer upper bound [0..Max]\n        int   FCapacity; // Queue capacity\n        pbyte Buffer;\n        int   FBlockSize;\npublic:\n        TMsgEventQueue(const int Capacity, const int BlockSize);\n        ~TMsgEventQueue();\n        void Flush();\n        void Insert(void *lpdata);\n        bool Extract(void *lpdata);\n        bool Empty();\n        bool Full();\n};\ntypedef TMsgEventQueue *PMsgEventQueue;\n\n//---------------------------------------------------------------------------\n// WORKER THREAD\n//---------------------------------------------------------------------------\nclass TCustomMsgServer; // forward declaration\n\n// It's created when connection is accepted, it will interface with the client.\nclass TMsgWorkerThread : public TSnapThread\n{\nprivate:\n        TCustomMsgServer *FServer;\nprotected:\n        TMsgSocket *WorkerSocket;\npublic:\n        int Index;\n        friend class TCustomMsgServer;\n        TMsgWorkerThread(TMsgSocket *Socket, TCustomMsgServer *Server);\n        void Execute();\n};\ntypedef TMsgWorkerThread *PMsgWorkerThread;\n\n//---------------------------------------------------------------------------\n// LISTENER THREAD\n//---------------------------------------------------------------------------\n// It listens for incoming connection.\nclass TMsgListenerThread : public TSnapThread\n{\nprivate:\n        TMsgSocket *FListener;\n        TCustomMsgServer *FServer;\npublic:\n        TMsgListenerThread(TMsgSocket *Listener, TCustomMsgServer *Server);\n        void Execute();\n};\ntypedef TMsgListenerThread *PMsgListenerThread;\n\n//---------------------------------------------------------------------------\n// TCP SERVER\n//---------------------------------------------------------------------------\ntypedef TMsgSocket *PWorkerSocket;\n\nclass TCustomMsgServer\n{\nprivate:\n        int FLastError;\n        char FLocalAddress[16];\n        // Socket listener\n        PMsgSocket SockListener;\n        // Server listener\n        PMsgListenerThread ServerThread;\n        // Critical section to lock Workers list activities\n        PSnapCriticalSection CSList;\n        // Event queue\n        PMsgEventQueue FEventQueue;\n        // Callback related\n        pfn_SrvCallBack OnEvent;\n        void *FUsrPtr;\n        // private methods\n        int StartListener();\n        void LockList();\n        void UnlockList();\n        int FirstFree();\nprotected:\n        bool Destroying;\n        // Critical section to lock Event activities\n        PSnapCriticalSection CSEvent;\n\t    // Workers list\n        void *Workers[MaxWorkers];\n        // Terminates all worker threads\n        virtual void TerminateAll();\n        // Kills all worker threads that are unresponsive\n        void KillAll();\n        // if (true the connection is accepted, otherwise the connection\n        // is closed gracefully\n        virtual bool CanAccept(socket_t Socket);\n        // Returns the class of the worker socket, override it for real servers\n        virtual PWorkerSocket CreateWorkerSocket(socket_t Sock);\n        // Handles the event\n        virtual void DoEvent(int Sender, longword Code, word RetCode, word Param1,\n          word Param2, word Param3, word Param4);\n        // Delete the worker from the list (It's invoked by Worker Thread)\n        void Delete(int Index);\n        // Incoming connection (It's invoked by ServerThread, the listener)\n        virtual void Incoming(socket_t Sock);\npublic:\n        friend class TMsgWorkerThread;\n        friend class TMsgListenerThread;\n        word LocalPort;\n        longword LocalBind;\n        longword LogMask;\n        longword EventMask;\n        int Status;\n        int ClientsCount;\n        int MaxClients;\n        TCustomMsgServer();\n        virtual ~TCustomMsgServer();\n        // Starts the server\n        int Start();\n        int StartTo(const char *Address, word Port);\n        // Stops the server\n        void Stop();\n        // Sets Event callback\n        int SetEventsCallBack(pfn_SrvCallBack PCallBack, void *UsrPtr);\n        // Pick an event from the circular queue\n        bool PickEvent(void *pEvent);\n        // Returns true if (the Event queue is empty\n        bool EventEmpty();\n        // Flushes Event queue\n        void EventsFlush();\n};\n\n//---------------------------------------------------------------------------\n// TCP WORKER\n//---------------------------------------------------------------------------\n// Default worker class, a simply tcp echo to test the connection and\n// data I/O to use the server outside the project\nclass TEcoTcpWorker : public TMsgSocket\n{\npublic:\n\tbool Execute()\n\t{\n            byte Buffer[4096];\n            int Size;\n\n            if (CanRead(WorkInterval)) // Small time to avoid time wait during the close\n            {\n                Receive(&Buffer,sizeof(Buffer),Size);\n                if ((LastTcpError==0) && (Size>0))\n                {\n                    SendPacket(&Buffer,Size);\n                    return LastTcpError==0;\n                }\n                else\n                    return false;\n            }\n        else\n            return true;\n\t};\n};\n\n//---------------------------------------------------------------------------\n#endif // snap_tcpsrvr_h\n"
  },
  {
    "path": "deps/snap7/src/sys/snap_threads.cpp",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.3.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|=============================================================================*/\n\n#include \"snap_threads.h\"\n//---------------------------------------------------------------------------\n#ifdef OS_WINDOWS\nDWORD WINAPI ThreadProc(LPVOID param)\n#else\n\nvoid* ThreadProc(void* param)\n#endif\n{\n    PSnapThread Thread;\n    // Unix but not Solaris\n#if (defined(POSIX) || defined(OS_OSX)) && (!defined(OS_SOLARIS_NATIVE_THREADS))\n    int last_type, last_state;\n    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &last_type);\n    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &last_state);\n#endif\n    Thread = PSnapThread(param);\n\n    if (!Thread->Terminated)\n        try\n        {\n            Thread->Execute();\n        } catch (...)\n        {\n        };\n    Thread->Closed = true;\n    if (Thread->FreeOnTerminate)\n    {\n        delete Thread;\n    };\n#ifdef OS_WINDOWS\n    ExitThread(0);\n#endif\n#if defined(POSIX) && (!defined(OS_SOLARIS_NATIVE_THREADS))\n    pthread_exit((void*)0);\n#endif\n#if defined(OS_OSX)\n    pthread_exit((void*)0);\n#endif\n#ifdef OS_SOLARIS_NATIVE_THREADS\n    thr_exit((void*)0);\n#endif\n    return 0; // never reach, only to avoid compiler warning\n}\n//---------------------------------------------------------------------------\nTSnapThread::TSnapThread() \n{\n    Started = false;\n\tClosed=false;\n    Terminated = false;\n    FreeOnTerminate = false;\n}\n//---------------------------------------------------------------------------\nTSnapThread::~TSnapThread() \n{\n    if (Started && !Closed)\n    {\n        Terminate();\n        Join();\n    };\n#ifdef OS_WINDOWS\n\tif (Started)\n\t\tCloseHandle(th);\n#endif\n}\n//---------------------------------------------------------------------------\nvoid TSnapThread::ThreadCreate() \n{\n#ifdef OS_WINDOWS\n    th = CreateThread(0, 0, ThreadProc, this, 0, 0);\n#endif\n#if defined(POSIX) && (!defined(OS_SOLARIS_NATIVE_THREADS))\n    pthread_attr_t a;\n    pthread_attr_init(&a);\n    pthread_attr_setdetachstate(&a, PTHREAD_CREATE_DETACHED);\n    pthread_create(&th, &a, &ThreadProc, this);\n#endif  \n#if defined(OS_OSX)\n    pthread_create(&th, 0, &ThreadProc, this);\n#endif\n#ifdef OS_SOLARIS_NATIVE_THREADS\n    thr_create(0, // default stack base\n               0, // default stack size\n               &ThreadProc, // Thread routine\n               this, //  argument\n               0,\n               &th);\n#endif\n}\n//---------------------------------------------------------------------------\nvoid TSnapThread::Start() \n{\n    if (!Started)\n    {\n        ThreadCreate();\n        Started = true;\n    }\n}\n//---------------------------------------------------------------------------\nvoid TSnapThread::Terminate() \n{\n    Terminated = true;\n}\n//---------------------------------------------------------------------------\nvoid TSnapThread::Kill() \n{\n    if (Started && !Closed)\n    {\n        ThreadKill();\n        Closed = true;\n    }\n}\n//---------------------------------------------------------------------------\nvoid TSnapThread::Join() \n{\n    if (Started && !Closed)\n    {\n        ThreadJoin();\n        Closed = true;\n    }\n}\n//---------------------------------------------------------------------------\nlongword TSnapThread::WaitFor(uint64_t Timeout) \n{\n    if (Started)\n    {\n        if (!Closed)\n            return ThreadWait(Timeout);\n        else\n            return WAIT_OBJECT_0;\n    }\n    else\n        return WAIT_OBJECT_0;\n}\n//---------------------------------------------------------------------------\n\n"
  },
  {
    "path": "deps/snap7/src/sys/snap_threads.h",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.3.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|=============================================================================*/\n#ifndef snap_threads_h\n#define snap_threads_h\n//---------------------------------------------------------------------------\n#include \"snap_platform.h\"\n\n#ifdef OS_WINDOWS\n# include \"win_threads.h\"\n#endif\n#if defined(POSIX) && (!defined(OS_SOLARIS_NATIVE_THREADS))\n# include \"unix_threads.h\"\n#endif\n#ifdef OS_SOLARIS_NATIVE_THREADS\n# include \"sol_threads.h\"\n#endif\n#if defined(OS_OSX)\n# include \"unix_threads.h\"\n#endif\n\n//---------------------------------------------------------------------------\n#endif // snap_threads_h\n"
  },
  {
    "path": "deps/snap7/src/sys/sol_threads.h",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.3.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|==============================================================================|\n|                                                                              |\n| Solaris 11 Threads support                                                   |\n|                                                                              |\n|=============================================================================*/\n#ifndef sol_threads_h\n#define sol_threads_h\n//---------------------------------------------------------------------------\n#include \"snap_platform.h\"\n#include \"snap_sysutils.h\"\n#include <thread.h>\n#include <synch.h>\n//---------------------------------------------------------------------------\n\nclass TSnapCriticalSection {\nprivate:\n    mutex_t mx;\n    int result;\npublic:\n\n    TSnapCriticalSection() {\n        mutex_init(&mx, USYNC_THREAD, 0);\n    };\n\n    ~TSnapCriticalSection() {\n        mutex_destroy(&mx);\n    };\n\n    void Enter() {\n        mutex_lock(&mx);\n    };\n\n    void Leave() {\n        mutex_unlock(&mx);\n    };\n\n    bool TryEnter() {\n        return mutex_trylock(&mx) == 0;\n    };\n};\ntypedef TSnapCriticalSection *PSnapCriticalSection;\n\n//---------------------------------------------------------------------------\nconst longword WAIT_OBJECT_0 = 0x00000000L;\nconst longword WAIT_ABANDONED = 0x00000080L;\nconst longword WAIT_TIMEOUT = 0x00000102L;\nconst longword WAIT_FAILED = 0xFFFFFFFFL;\n\nclass TSnapEvent {\nprivate:\n    cond_t CVariable;\n    mutex_t Mutex;\n    bool AutoReset;\n    bool State;\npublic:\n\n    TSnapEvent(bool ManualReset) \n    {\n        AutoReset = !ManualReset;\n        cond_init(&CVariable, USYNC_THREAD, 0) == 0;\n        mutex_init(&Mutex, USYNC_THREAD, 0);\n        State = false;\n    }\n\n    ~TSnapEvent() \n    {\n        cond_destroy(&CVariable);\n        mutex_destroy(&Mutex);\n    };\n\n    void Set() \n    {\n        mutex_lock(&Mutex);\n        State = true;\n        if (AutoReset)\n            cond_signal(&CVariable);\n        else\n            cond_broadcast(&CVariable);\n        mutex_unlock(&Mutex);\n    };\n\n    void Reset() \n    {\n        mutex_lock(&Mutex);\n        State = false;\n        mutex_unlock(&Mutex);\n    }\n\n    longword WaitForever() \n    {\n        mutex_lock(&Mutex);\n        while (!State) // <-- to avoid spurious wakeups\n            cond_wait(&CVariable, &Mutex);\n        if (AutoReset)\n            State = false;\n        mutex_unlock(&Mutex);\n        return WAIT_OBJECT_0;\n    };\n\n    longword WaitFor(int64_t Timeout) \n    {\n        longword Result = WAIT_OBJECT_0;\n        if (Timeout == 0)\n            Timeout = 1; // 0 is not allowed \n\n        if (Timeout > 0) {\n            mutex_lock(&Mutex);\n            if (!State) {\n                timespec ts;\n                timeval tv;\n                gettimeofday(&tv, NULL);\n                uint64_t nsecs = ((uint64_t) tv.tv_sec) * 1000000000 +\n                        Timeout * 1000000 +\n                        ((uint64_t) tv.tv_usec) * 1000;\n                ts.tv_sec = nsecs / 1000000000;\n                ts.tv_nsec = (nsecs - ((uint64_t) ts.tv_sec) * 1000000000);\n                do \n                {\n                    Result = cond_timedwait(&CVariable, &Mutex, &ts);\n                    if (Result == ETIMEDOUT)\n                        Result = WAIT_TIMEOUT;\n                } \n                while (Result == 0 && !State);\n            } \n            else\n                if (AutoReset) // take the ownership\n                    State = false;\n            mutex_unlock(&Mutex);\n            return Result;\n        } \n        else // Timeout<0\n            return WaitForever();\n    };\n};\ntypedef TSnapEvent *PSnapEvent;\n//---------------------------------------------------------------------------\n\nclass TSnapThread {\nprivate:\n    thread_t th;\n    bool FCreateSuspended;\n    void ThreadCreate();\n\n    void ThreadJoin() \n    {\n        thr_join(th, 0, 0);\n    };\n\n    void ThreadKill() \n    {\n        thr_kill(th, 0);\n    };\n\n    longword ThreadWait(uint64_t Timeout) \n    {\n        longword Elapsed = SysGetTick();\n        while (!Closed && !(DeltaTime(Elapsed) > Timeout))\n            SysSleep(100);\n        if (Closed)\n            return WAIT_OBJECT_0;\n        else\n            return WAIT_TIMEOUT;\n    };\nprotected:\n    bool Started;\npublic:\n    bool Terminated;\n    bool Closed;\n    bool FreeOnTerminate;\n    TSnapThread();\n    virtual ~TSnapThread();\n\n    virtual void Execute() {\n    };\n    void Start();\n    void Terminate();\n    void Kill();\n    void Join();\n    longword WaitFor(uint64_t Timeout);\n};\ntypedef TSnapThread *PSnapThread;\n\n//---------------------------------------------------------------------------\n#endif // sol_threads_h\n"
  },
  {
    "path": "deps/snap7/src/sys/unix_threads.h",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.3.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|==============================================================================|\n|                                                                              |\n| Posix Threads support (Linux, FreeBSD)                                       |\n|                                                                              |\n|=============================================================================*/\n#ifndef unix_threads_h\n#define unix_threads_h\n//---------------------------------------------------------------------------\n#include \"snap_platform.h\"\n#include \"snap_sysutils.h\"\n#include <semaphore.h>\n#include <pthread.h>\n//---------------------------------------------------------------------------\n\nclass TSnapCriticalSection \n{\nprivate:\n    pthread_mutex_t mx;\n//    int result;\npublic:\n\n    TSnapCriticalSection() \n    {\n        /*\n\t\t   \n        This would be the best code, but very often it causes a segmentation fault in many\n        unix systems (the problem seems to be pthread_mutexattr_destroy()).\n        So, to avoid problems in future kernel/libc release, we use the \"safe\" default.\n\t\t   \n        pthread_mutexattr_t mxAttr;\n        pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_RECURSIVE);\n        pthread_mutex_init(&mx, &mxAttr);\n        pthread_mutexattr_destroy(&mxAttr);\n\n         */\n        pthread_mutex_init(&mx, 0);\n    };\n\n    ~TSnapCriticalSection() \n    {\n        pthread_mutex_destroy(&mx);\n    };\n\n    void Enter() \n    {\n        pthread_mutex_lock(&mx);\n    };\n\n    void Leave() \n    {\n        pthread_mutex_unlock(&mx);\n    };\n\n    bool TryEnter() \n    {\n        return pthread_mutex_trylock(&mx) == 0;\n    };\n};\ntypedef TSnapCriticalSection *PSnapCriticalSection;\n\n//---------------------------------------------------------------------------\nconst longword WAIT_OBJECT_0 = 0x00000000L;\nconst longword WAIT_ABANDONED = 0x00000080L;\nconst longword WAIT_TIMEOUT = 0x00000102L;\nconst longword WAIT_FAILED = 0xFFFFFFFFL;\n\nclass TSnapEvent \n{\nprivate:\n    pthread_cond_t CVariable;\n    pthread_mutex_t Mutex;\n    bool AutoReset;\n    bool State;\npublic:\n\n    TSnapEvent(bool ManualReset) \n    {\n        AutoReset = !ManualReset;\n        if (pthread_cond_init(&CVariable, 0) == 0)\n        \tpthread_mutex_init(&Mutex, 0);\n        State = false;\n    }\n\n    ~TSnapEvent() \n    {\n        pthread_cond_destroy(&CVariable);\n        pthread_mutex_destroy(&Mutex);\n    };\n\n    void Set() \n    {\n        pthread_mutex_lock(&Mutex);\n        State = true;\n        if (AutoReset)\n            pthread_cond_signal(&CVariable);\n        else\n            pthread_cond_broadcast(&CVariable);\n        pthread_mutex_unlock(&Mutex);\n    };\n\n    void Reset() \n    {\n        pthread_mutex_lock(&Mutex);\n        State = false;\n        pthread_mutex_unlock(&Mutex);\n    }\n\n    longword WaitForever() \n    {\n        pthread_mutex_lock(&Mutex);\n        while (!State) // <-- to avoid spurious wakeups\n            pthread_cond_wait(&CVariable, &Mutex);\n        if (AutoReset)\n            State = false;\n        pthread_mutex_unlock(&Mutex);\n        return WAIT_OBJECT_0;\n    };\n\n    longword WaitFor(int64_t Timeout) \n    {\n        longword Result = WAIT_OBJECT_0;\n        if (Timeout == 0)\n            Timeout = 1; // 0 is not allowed\n\n        if (Timeout > 0) \n        {\n            pthread_mutex_lock(&Mutex);\n            if (!State)\n            {\n                timespec ts;\n                timeval tv;\n                gettimeofday(&tv, NULL);\n                uint64_t nsecs = ((uint64_t) tv.tv_sec) * 1000000000 +\n                        Timeout * 1000000 +\n                        ((uint64_t) tv.tv_usec) * 1000;\n                ts.tv_sec = nsecs / 1000000000;\n                ts.tv_nsec = (nsecs - ((uint64_t) ts.tv_sec) * 1000000000);\n                do {\n                    Result = pthread_cond_timedwait(&CVariable, &Mutex, &ts);\n                    if (Result == ETIMEDOUT)\n                        Result = WAIT_TIMEOUT;\n                } while (Result == 0 && !State);\n            } \n            else\n                if (AutoReset) // take the ownership\n                    State = false;\n            pthread_mutex_unlock(&Mutex);\n            return Result;\n        }\n        else // Timeout<0\n            return WaitForever();\n    };\n};\ntypedef TSnapEvent *PSnapEvent;\n//---------------------------------------------------------------------------\nclass TSnapThread \n{\nprivate:\n    pthread_t th;\n    bool FCreateSuspended;\n    void ThreadCreate();\n\n    void ThreadJoin() \n    {\n        pthread_join(th, 0);\n    };\n\n    void ThreadKill() \n    {\n        pthread_cancel(th);\n    };\n\n    longword ThreadWait(uint64_t Timeout) \n    {\n        longword Elapsed = SysGetTick();\n        while (!Closed && !(DeltaTime(Elapsed) > Timeout))\n            SysSleep(100);\n        if (Closed)\n            return WAIT_OBJECT_0;\n        else\n            return WAIT_TIMEOUT;\n    };\nprotected:\n    bool Started;\npublic:\n    bool Terminated;\n    bool Closed;\n    bool FreeOnTerminate;\n    TSnapThread();\n    virtual ~TSnapThread();\n\n    virtual void Execute() \n    {\n    };\n    void Start();\n    void Terminate();\n    void Kill();\n    void Join();\n    longword WaitFor(uint64_t Timeout);\n};\ntypedef TSnapThread *PSnapThread;\n\n//---------------------------------------------------------------------------\n#endif // unix_threads_h\n"
  },
  {
    "path": "deps/snap7/src/sys/win_threads.h",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.3.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2015 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|==============================================================================|\n|                                                                              |\n| Windows Threads support (Windows, ReactOS)                                   |\n|                                                                              |\n|=============================================================================*/\n#ifndef win_threads_h\n#define win_threads_h\n//---------------------------------------------------------------------------\n#include \"snap_platform.h\"\n#include \"snap_sysutils.h\"\n//---------------------------------------------------------------------------\n\nclass TSnapCriticalSection \n{\nprivate:\n    CRITICAL_SECTION cs;\npublic:\n\n    TSnapCriticalSection() \n    {\n        InitializeCriticalSection(&cs);\n    };\n\n    ~TSnapCriticalSection() \n    {\n        DeleteCriticalSection(&cs);\n    };\n\n    void Enter() \n    {\n        EnterCriticalSection(&cs);\n    };\n\n    void Leave() \n    {\n        LeaveCriticalSection(&cs);\n    };\n\n    bool TryEnter() \n    {\n        return (TryEnterCriticalSection(&cs) != 0);\n    };\n};\ntypedef TSnapCriticalSection *PSnapCriticalSection;\n//---------------------------------------------------------------------------\n\nclass TSnapEvent \n{\nprivate:\n    HANDLE Event;\npublic:\n\n    TSnapEvent(bool ManualReset) \n    {\n        Event = CreateEvent(0, ManualReset, false, 0);\n    };\n\n    ~TSnapEvent() \n    {\n        if (Event != 0)\n            CloseHandle(Event);\n    };\n\n    void Set() \n    {\n        if (Event != 0)\n            SetEvent(Event);\n    };\n\n    void Reset() \n    {\n        if (Event != 0)\n            ResetEvent(Event);\n    };\n\n    longword WaitForever() \n    {\n        if (Event != 0)\n            return WaitForSingleObject(Event, INFINITE);\n        else\n            return WAIT_FAILED;\n    };\n\n    longword WaitFor(int64_t Timeout) {\n        if (Event != 0)\n            return WaitForSingleObject(Event, DWORD(Timeout));\n        else\n            return WAIT_FAILED;\n    };\n};\ntypedef TSnapEvent *PSnapEvent;\n//---------------------------------------------------------------------------\n\nclass TSnapThread {\nprivate:\n    HANDLE th;\n    bool FCreateSuspended;\n    void ThreadCreate();\n\n    void ThreadJoin() \n    {\n        WaitForSingleObject(th, INFINITE);\n    };\n\n    void ThreadKill() \n    {\n        TerminateThread(th, 0);\n    };\n\n    longword ThreadWait(uint64_t Timeout) \n    {\n        return WaitForSingleObject(th, DWORD(Timeout));\n    };\nprotected:\n    bool Started;\npublic:\n    bool Terminated;\n    bool Closed;\n    bool FreeOnTerminate;\n    TSnapThread();\n    virtual ~TSnapThread();\n\n    virtual void Execute() \n    {\n    };\n    void Start();\n    void Terminate();\n    void Kill();\n    void Join();\n    longword WaitFor(uint64_t Timeout);\n};\ntypedef TSnapThread *PSnapThread;\n\n//---------------------------------------------------------------------------\n#endif // win_threads_h\n"
  },
  {
    "path": "doc/client.md",
    "content": " ## S7Client\n - [Control functions](#control-functions)\n   - [Connect()](#connect)\n   - [ConnectTo()](#connect-to)\n   - [SetConnectionParams()](#set-connection-params)\n   - [SetConnectionType()](#set-connection-type)\n   - [Disconnect()](#disconnect)\n   - [GetParam()](#get-param)\n   - [SetParam()](#set-param)\n - [Data I/O functions](#data-functions)\n   - [ReadArea()](#read-area)\n   - [WriteArea()](#write-area)\n   - [DBRead()](#dbread)\n   - [DBWrite()](#dbwrite)\n   - [ABRead()](#abread)\n   - [ABWrite()](#abwrite)\n   - [EBRead()](#ebread)\n   - [EBWrite()](#ebwrite)\n   - [MBRead()](#mbread)\n   - [MBWrite()](#mbwrite)\n   - [TMRead()](#tmread)\n   - [TMWrite()](#tmwrite)\n   - [CTRead()](#ctread)\n   - [CTWrite()](#ctwrite)\n   - [ReadMultiVars()](#read-multi-vars)\n   - [WriteMultiVars()](#write-multi-vars)\n - [Directory function](#directory-functions)\n   - [ListBlocks()](#list-blocks)\n   - [ListBlocksOfType()](#list-blocks-of-type)\n   - [GetAgBlockInfo()](#get-ag-blockinfo)\n   - [GetPgBlockInfo()](#get-pg-blockinfo)\n - [Block oriented functions](#block-functions)\n   - [FullUpload()](#full-upload)\n   - [Upload()](#upload)\n   - [Download()](#download)\n   - [Delete()](#delete)\n   - [DBGet()](#dbget)\n   - [DBFill()](#dbfill)\n - [Date/Time functions](#datetime-functions)\n   - [GetPlcDateTime()](#get-plc-datetime)\n   - [SetPlcDateTime()](#set-plc-datetime)\n   - [SetPlcSystemDateTime()](#set-plc-system-datetime)\n - [System info functions](#systeminfo-functions)\n   - [ReadSZL()](#read-szl)\n   - [ReadSZLList()](#read-szl-list)\n   - [GetOrderCode()](#get-order-code)\n   - [GetCpuInfo()](#get-cpu-info)\n   - [GetCpInfo()](#get-cp-info)\n - [PLC control functions](#control-functions)\n   - [PlcHotStart()](#plc-hot-start)\n   - [PlcColdStart()](#plc-cold-start)\n   - [PlcStop()](#plc-stop)\n   - [CopyRamToRom()](#copy-ram-to-rom)\n   - [Compress()](#compress)\n - [Security functions](#security-functions)\n   - [SetSessionPassword()](#set-session-password)\n   - [ClearSessionPassword()](#clear-session-password)\n   - [GetProtection()](#get-protection)\n - [Properties](#properties)\n   - [ExecTime()](#exec-time)\n   - [LastError()](#last-error)\n   - [PDURequested()](#pdu-requested)\n   - [PDULength()](#pdu-length)\n   - [PlcStatus()](#plc-status)\n   - [Connected()](#connected)\n   - [ErrorText()](#error-text)\n\n### <a name=\"control-functions\"></a>API - Control functions\n\n----------\n\n#### <a name=\"connect\"></a>S7Client.Connect([callback])\nConnects the client to the PLC with the parameters specified in the previous call of `ConnectTo()` or `SetConnectionParams()`.\n\n - The optional `callback` parameter will be executed after connection attempt\n\nIf `callback` is **not** set the function is **blocking** and  returns `true` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` argument is given to the callback.\n\n#### <a name=\"connect-to\"></a>S7Client.ConnectTo(ip, rack, slot[, callback])\nConnects the client to the hardware at `ip`, `rack`, `slot` coordinates.\n\n- `ip` PLC/Equipment IPV4 Address ex. “192.168.1.12”\n- `rack` PLC Rack number\n- `slot` PLC Slot number\n- The optional `callback` parameter will be executed after connection attempt\n\nIf `callback` is **not** set the function is **blocking** and returns `true` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` argument is given to the callback.\n\n#### <a name=\"set-connection-params\"></a>S7Client.SetConnectionParams(ip, localTSAP, remoteTSAP)\nSets internally `ip`, `localTSAP`, `remoteTSAP` coordinates.\n\n- `ip` PLC/Equipment IPv4 address ex. “192.168.1.12”\n- `localTSAP` Local TSAP (PC TSAP)\n- `remoteTSAP`  Remote TSAP (PLC TSAP)\n\nReturns `true` on success or `false` on error.\n\n#### <a name=\"set-connection-type\"></a>S7Client.SetConnectionType(type)\nSets the connection resource type, i.e the way in which the Clients connects to a PLC.\n\n- `type`\n\n| ConnectionType            | Value      | Description |\n|:--------------------------|:----------:|:------------|\n| `S7Client.CONNTYPE_PG`    | 0x01       | PG\n| `S7Client.CONNTYPE_OP`    | 0x02       | OP\n| `S7Client.CONNTYPE_BASIC` | 0x03..0x10 | S7 Basic\n\n#### <a name=\"disconnect\"></a>S7Client.Disconnect()\nDisconnects “gracefully” the Client from the PLC.\n\nReturns `true` on success or `false` on error.\n\n#### <a name=\"get-param\"></a>S7Client.GetParam(paramNumber)\nReads an internal Client object parameter.\n\n - `paramNumber` One from the parameter list below\n\n| Name                   | Value | Description |\n|:-----------------------|:-----:|:------------|\n| `S7Client.RemotePort`  | 2     | Socket remote Port\n| `S7Client.PingTimeout` | 3     | Client Ping timeout\n| `S7Client.SendTimeout` | 4     | Socket Send timeout\n| `S7Client.RecvTimeout` | 5     | Socket Recv timeout\n| `S7Client.SrcRef`      | 7     | ISOTcp Source reference\n| `S7Client.DstRef`      | 8     | ISOTcp Destination reference\n| `S7Client.SrcTSap`     | 9     | ISOTcp Source TSAP\n| `S7Client.PDURequest`  | 10    | Initial PDU length request\n\nReturns the `parameter value` on success or `false` on error.\n\n#### <a name=\"set-param\"></a>S7Client.SetParam(paramNumber, value)\nSets an internal Client object parameter.\n\n - `paramNumber` One from the parameter list above\n - `value` New parameter value\n\nReturns `true` on success or `false` on error.\n\n### <a name=\"data-functions\"></a>API - Data I/O functions\n\n----------\n\n#### <a name=\"read-area\"></a>S7Client.ReadArea(area, dbNumber, start, amount, wordLen[, callback])\nThis is the main function to read data from a PLC. With it you can read DB, Inputs, Outputs, Merkers, Timers and Counters.\n\n - `area` Area identifier (see table [below](#table-area))\n - `dbNumber` DB number if area = S7AreaDB, otherwise ignored\n - `start` Offset to start\n - `amount` Amount of **words** to read\n - `wordLen` Word size (see table [below](#table-wordlen))\n - The optional `callback` parameter will be executed after read\n\nIf `callback` is **not** set the function is **blocking** and returns a `buffer` object on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` and `result` argument is given to the callback.\n\n#### <a name=\"write-area\"></a>S7Client.WriteArea(area, dbNumber, start, amount, wordLen, buffer[, callback])\nThis is the main function to write data into a PLC.\n\n - `area` Area identifier (see table [below](#table-area))\n - `dbNumber` DB number if area = S7AreaDB, otherwise ignored\n - `start` Offset to start\n - `amount` Amount of **words** to write\n - `wordLen` Word size (see table [below](#table-wordlen))\n - `buffer` User buffer\n - The optional `callback` parameter will be executed after write\n\nIf `callback` is **not** set the function is **blocking** and returns `true` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` argument is given to the callback.\n\n<a name=\"table-area\"></a>\n\n| Area                   | Value | Description |\n|:-----------------------|:-----:|:------------|\n| `S7Client.S7AreaPE`    | 0x81  | Process inputs\n| `S7Client.S7AreaPA`    | 0x82  | Process outputs\n| `S7Client.S7AreaMK`    | 0x83  | Merkers\n| `S7Client.S7AreaDB`    | 0x84  | DB\n| `S7Client.S7AreaCT`    | 0x1C  | Counters\n| `S7Client.S7AreaTM`    | 0x1D  | Timers\n\n<a name=\"table-wordlen\"></a>\n\n| WordLen                | Value | Description |\n|:-----------------------|:-----:|:------------|\n| `S7Client.S7WLBit`     | 0x01  | Bit (inside a word)\n| `S7Client.S7WLByte`    | 0x02  | Byte (8 bit)\n| `S7Client.S7WLWord`    | 0x04  | Word (16 bit)\n| `S7Client.S7WLDWord`   | 0x06  | Double Word (32 bit)\n| `S7Client.S7WLReal`    | 0x08  | Real (32 bit float)\n| `S7Client.S7WLCounter` | 0x1C  | Counter (16 bit)\n| `S7Client.S7WLTimer`   | 0x1D  | Timer (16 bit)\n\n#### <a name=\"dbread\"></a>S7Client.DBRead(dbNumber, start, size[, callback])\nThis is a lean function of `ReadArea()` to read PLC DB.\nIt simply internally calls `ReadArea()` with `area = S7Client.S7AreaDB` and `wordLen = s7client.S7WLByte`.\n\n - `dbNumber` DB number\n - `start` Offset to start\n - `size` Size to read (bytes)\n - The optional `callback` parameter will be executed after read\n\nIf `callback` is **not** set the function is **blocking** and returns a `buffer` object on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` and `result` argument is given to the callback.\n\n#### <a name=\"dbwrite\"></a>S7Client.DBWrite(dbNumber, start, size, buffer[, callback])\nThis is a lean function of `WriteArea()` to write PLC DB.\nIt simply internally calls `WriteArea()` with `area = S7Client.S7AreaDB` and `wordLen = s7client.S7WLByte`.\n\n - `dbNumber` DB number\n - `start` Offset to start\n - `size` Size to write (bytes)\n - `buffer` User buffer\n - The optional `callback` parameter will be executed after write\n\nIf `callback` is **not** set the function is **blocking** and returns `true` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` argument is given to the callback.\n\n#### <a name=\"abread\"></a>S7Client.ABRead(start, size[, callback])\nThis is a lean function of `ReadArea()` to read PLC process outputs.\nIt simply internally calls `ReadArea()` with `area = S7Client.S7AreaPA` and `wordLen = s7client.S7WLByte`.\n\n - `start` Offset to start\n - `size` Size to read (bytes)\n - The optional `callback` parameter will be executed after read\n\nIf `callback` is **not** set the function is **blocking** and returns a `buffer` object on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` and `result` argument is given to the callback.\n\n#### <a name=\"abwrite\"></a>S7Client.ABWrite(start, size, buffer[, callback])\nThis is a lean function of `WriteArea()` to write PLC process outputs.\nIt simply internally calls `WriteArea()` with `area = S7Client.S7AreaPA` and `wordLen = s7client.S7WLByte`.\n\n - `start` Offset to start\n - `size` Size to write (bytes)\n - `buffer` User buffer\n - The optional `callback` parameter will be executed after write\n\nIf `callback` is **not** set the function is **blocking** and returns `true` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` argument is given to the callback.\n\n#### <a name=\"ebread\"></a>S7Client.EBRead(start, size[, callback])\nThis is a lean function of `ReadArea()` to read PLC process inputs.\nIt simply internally calls `ReadArea()` with `area = S7Client.S7AreaPE` and `wordLen = s7client.S7WLByte`.\n\n - `start` Offset to start\n - `size` Size to read (bytes)\n - The optional `callback` parameter will be executed after read\n\nIf `callback` is **not** set the function is **blocking** and returns a `buffer` object on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` and `result` argument is given to the callback.\n\n#### <a name=\"ebwrite\"></a>S7Client.EBWrite(start, size, buffer[, callback])\nThis is a lean function of `WriteArea()` to write PLC process inputs.\nIt simply internally calls `WriteArea()` with `area = S7Client.S7AreaPE` and `wordLen = s7client.S7WLByte`.\n\n - `start` Offset to start\n - `size` Size to write (bytes)\n - `buffer` User buffer\n - The optional `callback` parameter will be executed after write\n\nIf `callback` is **not** set the function is **blocking** and returns `true` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` argument is given to the callback.\n\n#### <a name=\"mbread\"></a>S7Client.MBRead(start, size[, callback])\nThis is a lean function of `ReadArea()` to read PLC Merkers.\nIt simply internally calls `ReadArea()` with `area = S7Client.S7AreaMK` and `wordLen = s7client.S7WLByte`.\n\n - `start` Offset to start\n - `size` Size to read (bytes)\n - The optional `callback` parameter will be executed after read\n\nIf `callback` is **not** set the function is **blocking** and returns a `buffer` object on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` and `result` argument is given to the callback.\n\n#### <a name=\"mbwrite\"></a>S7Client.MBWrite(start, size, buffer[, callback])\nThis is a lean function of `WriteArea()` to write PLC Merkers.\nIt simply internally calls `WriteArea()` with `area = S7Client.S7AreaMK` and `wordLen = s7client.S7WLByte`.\n\n - `start` Offset to start\n - `size` Size to write (bytes)\n - `buffer` User buffer\n - The optional `callback` parameter will be executed after write\n\nIf `callback` is **not** set the function is **blocking** and returns `true` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` argument is given to the callback.\n\n#### <a name=\"tmread\"></a>S7Client.TMRead(start, amount[, callback])\nThis is a lean function of `ReadArea()` to read PLC Timers.\nIt simply internally calls `ReadArea()` with `area = S7Client.S7AreaTM` and `wordLen = S7Client.S7WLTimer`.\n\n - `start` Offset to start\n - `amount` Number of timers\n - The optional `callback` parameter will be executed after read\n\nIf `callback` is **not** set the function is **blocking** and returns a `buffer` object on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` and `result` argument is given to the callback.\n\n#### <a name=\"tmwrite\"></a>S7Client.TMWrite(start, amount, buffer[, callback])\nThis is a lean function of `WriteArea()` to write PLC Timers.\nIt simply internally calls `WriteArea()` with `area = S7Client.S7AreaTM` and `wordLen = S7Client.S7WLTimer`.\n\n - `start` Offset to start\n - `amount` Number of timers\n - `buffer` User buffer\n - The optional `callback` parameter will be executed after write\n\nIf `callback` is **not** set the function is **blocking** and returns `true` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` argument is given to the callback.\n\n#### <a name=\"ctread\"></a>S7Client.CTRead(start, amount[, callback])\nThis is a lean function of `ReadArea()` to read PLC Counters.\nIt simply internally calls `ReadArea()` with `area = S7Client.S7AreaCT` and `wordLen = S7Client.S7WLCounter`.\n\n - `start` Offset to start\n - `amount` Number of counters\n - The optional `callback` parameter will be executed after read\n\nIf `callback` is **not** set the function is **blocking** and returns a `buffer` object on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` and `result` argument is given to the callback.\n\n#### <a name=\"ctwrite\"></a>S7Client.CTWrite(start, amount, buffer[, callback])\nThis is a lean function of `WriteArea()` to write PLC Counters.\nIt simply internally calls `WriteArea()` with `area = S7Client.S7AreaCT` and `wordLen = S7Client.S7WLCounter`.\n\n - `start` Offset to start\n - `amount` Number of counters\n - `buffer` User buffer\n - The optional `callback` parameter will be executed after write\n\nIf `callback` is **not** set the function is **blocking** and returns `true` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` argument is given to the callback.\n\n#### <a name=\"read-multi-vars\"></a>S7Client.ReadMultiVars(multiVars[, callback])\nThis is function allows to read different kind of variables from a PLC in a single call. With it you can read DB, Inputs, Outputs, Merkers, Timers and Counters.\n\n - `multiVars` Array of objects with read information (see structure below)\n - The optional `callback` parameter will be executed after read\n\nIf `callback` is **not** set the function is **blocking** and returns an `array` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` and `result` argument is given to the callback.\n\nExample:\n```javascript\n// multiVars array structure\n[\n  {\n    \"Area\": S7Client.S7AreaDB,\n    \"WordLen\": S7Client.S7WLByte,\n    \"DBNumber\": 1,\n    \"Start\": 0,\n    \"Amount\": 1\n  },\n  {\n    \"Area\": S7Client.S7AreaCT,\n    \"WordLen\": S7Client.S7WLCounter,\n    \"Start\": 0,\n    \"Amount\": 8\n  },\n  {\n    \"Area\": S7Client.S7AreaPA,\n    \"WordLen\": S7Client.S7WLByte,\n    \"Start\": 0,\n    \"Amount\": 16\n  },\n  ...\n]\n// result array\n[\n  {\n    \"Result\": 0, // Error code\n    \"Data\": ...  // Buffer object or null if Result <> 0\n  },\n  ...\n]\n```\n\nSince could happen that some variables are read, some other not because maybe they don't exist in PLC. It is important to check the single item result.\n\nDue the different kind of variables involved , there is no split feature available for this function, so the maximum data size must not exceed the PDU size.\nThe advantage of this function becomes big when you have many small non-contiguous variables to be read.\n\n#### <a name=\"write-multi-vars\"></a>S7Client.WriteMultiVars(multiVars[, callback])\nThis is function allows to write different kind of variables into a PLC in a single call. With it you can write DB, Inputs, Outputs, Merkers, Timers and Counters.\n\n - `multiVars` Array of objects with write information (see structure below)\n - The optional `callback` parameter will be executed after write\n\nIf `callback` is **not** set the function is **blocking** and returns an `array` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` and `result` argument is given to the callback.\n\nExample:\n```javascript\n// multiVars array structure\n[\n  {\n    \"Area\": S7Client.S7AreaDB,\n    \"WordLen\": S7Client.S7WLByte,\n    \"DBNumber\": 1,\n    \"Start\": 0,\n    \"Amount\": 1,\n    \"Data\": buffer1 // Buffer variable\n  },\n  {\n    \"Area\": S7Client.S7AreaCT,\n    \"WordLen\": S7Client.S7WLCounter,\n    \"Start\": 0,\n    \"Amount\": 8,\n    \"Data\": buffer2 // Buffer variable\n  },\n  {\n    \"Area\": S7Client.S7AreaPA,\n    \"WordLen\": S7Client.S7WLByte,\n    \"Start\": 0,\n    \"Amount\": 16,\n    \"Data\": buffer3 // Buffer variable\n  },\n  ...\n]\n// result array\n[\n  {\n    \"Result\": 0 // Error code\n  },\n  ...\n]\n```\n\n### <a name=\"directory-functions\"></a>API - Directory functions\n\n----------\n\n#### <a name=\"list-blocks\"></a>S7Client.ListBlocks([callback])\nThis function returns an object of the AG blocks amount divided by type.\n\n- The optional `callback` parameter will be executed after completion\n\nIf `callback` is **not** set the function is **blocking** and returns an `object` (see below) on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` and `result` argument is given to the callback.\n\nExample:\n```javascript\n{\n  \"OBCount\": 0,\n  \"FBCount\": 0,\n  \"FCCount\": 0,\n  \"SFBCount\": 0,\n  \"SFCCount\": 0,\n  \"DBCount\": 0,\n  \"SDBCount\": 0\n}\n```\n\n#### <a name=\"list-blocks-of-type\"></a>S7Client.ListBlocksOfType(blockType[, callback])\nThis function returns an array of the AG list of a specified block type.\n\n - `blockType` Type of block (see table below)\n - The optional `callback` parameter will be executed after completion\n\nIf `callback` is **not** set the function is **blocking** and returns an `array` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` and `result` argument is given to the callback.\n\nEach item of the result array will contain a block number.\n\n<a name=\"table-blocktype\"></a>\n\n| BlockType              | Value | Description |\n|:-----------------------|:-----:|:------------|\n| `S7Client.Block_OB`    | 0x38  | OB\n| `S7Client.Block_DB`    | 0x41  | DB\n| `S7Client.Block_SDB`   | 0x42  | SDB\n| `S7Client.Block_FC`    | 0x43  | FC\n| `S7Client.Block_SFC`   | 0x44  | SFC\n| `S7Client.Block_FB`    | 0x45  | FB\n| `S7Client.Block_SFB`   | 0x46  | SFB\n\n#### <a name=\"get-ag-blockinfo\"></a>S7Client.GetAgBlockInfo(blockType, blockNum[, callback])\nReturns an object with detailed information about a given AG block.\nThis function is very useful if you need to read or write data in a DB which you do not know the size in advance (see MC7Size field)\n\n - `blockType` Type of block (see table [above](#table-blocktype))\n - `blockNum` Number of block\n - The optional `callback` parameter will be executed after completion\n\nIf `callback` is **not** set the function is **blocking** and returns an `object` (see below) on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` and `result` argument is given to the callback.\n\nExample:\n<a name=\"example-blockinfo\"></a>\n```javascript\n{\n  \"BlkType\": ,   // Block Type (see SubBlkType table)\n  \"BlkNumber\": , // Block number\n  \"BlkLang\": ,   // Block Language (see LangType Table)\n  \"BlkFlags\": ,  // Block flags (bitmapped)\n  \"MC7Size\": ,   // The real size in bytes\n  \"LoadSize\": ,  // Load memory size\n  \"LocalData\": , // Local data\n  \"SBBLength\": , // SBB Length\n  \"CheckSum\": ,  // Checksum\n  \"Version\": ,   // Version (BCD 00<HI><LO>)\n  \"CodeDate\": ,  // Code date\n  \"IntfDate\": ,  // Interface date\n  \"Author\": ,    // Author\n  \"Family\": ,    // Family\n  \"Header\":      // Header\n}\n```\n\n| SubBlockType           | Value | Description |\n|:-----------------------|:-----:|:------------|\n| `S7Client.SubBlk_OB`   | 0x08  | OB\n| `S7Client.SubBlk_DB`   | 0x0A  | DB\n| `S7Client.SubBlk_SDB`  | 0x0B  | SDB\n| `S7Client.SubBlk_FC`   | 0x0C  | FC\n| `S7Client.SubBlk_SFC`  | 0x0D  | SFC\n| `S7Client.SubBlk_FB`   | 0x0E  | FB\n| `S7Client.SubBlk_SFB`  | 0x0F  | SFB\n\n| LangType                  | Value | Description |\n|:--------------------------|:-----:|:------------|\n| `S7Client.BlockLangAWL`   | 0x01  | AWL\n| `S7Client.BlockLangKOP`   | 0x02  | KOP\n| `S7Client.BlockLangFUP`   | 0x03  | FUP\n| `S7Client.BlockLangSCL`   | 0x04  | SCL\n| `S7Client.BlockLangDB`    | 0x05  | DB\n| `S7Client.BlockLangGRAPH` | 0x06  | GRAPH\n\n#### <a name=\"get-pg-blockinfo\"></a>S7Client.GetPgBlockInfo(buffer)\nReturns detailed information about a block present in a user buffer. This function is usually used in conjunction with `FullUpload()`.\nAn uploaded block saved to disk, could be loaded in a user buffer and checked with this function.\n\n - `buffer` User buffer\n\nReturns an `object` (see [example](#example-blockinfo) above) on success or `false`on error.\n\n### <a name=\"block-functions\"></a>API - Block oriented functions\n\n----------\n\n#### <a name=\"full-upload\"></a>S7Client.FullUpload(blockType, blockNum, size[, callback])\nUploads a block from AG. The whole block (including header and footer) is copied into the user buffer.\n\n - `blockType` Type of block (see table [above](#table-blocktype))\n - `blockNum` Number of block\n - `size` Buffer size (if smaller than the data\nuploaded, only `size` bytes are copied and `errCliPartialDataRead` is returned)\n - The optional `callback` parameter will be executed after completion\n\nIf `callback` is **not** set the function is **blocking** and returns a `Buffer` object on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` and `result` argument is given to the callback.\n\n#### <a name=\"upload\"></a>S7Client.Upload(blockType, blockNum[, callback])\nUploads a block body from AG. Only the block body (but header and footer) is copied into the user buffer.\n\n - `blockType` Type of block (see table [above](#table-blocktype))\n - `blockNum` Number of block\n - The optional `callback` parameter will be executed after completion\n\nIf `callback` is **not** set the function is **blocking** and returns a `Buffer` object on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` and `result` argument is given to the callback.\n\n#### <a name=\"download\"></a>S7Client.Download(blockNum, buffer[, callback])\nDownloads a block into AG. A whole block (including header and footer) must be available into the user buffer.\n\n - `blockNum` Number of block\n - `buffer` User buffer\n - The optional `callback` parameter will be executed after completion\n\nIf `callback` is **not** set the function is **blocking** and returns `true` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` argument is given to the callback.\n\nIf the parameter `blockNum` is `-1`, the block number is not changed else the block is downloaded with the provided number (just like a “Download As…”).\n\n#### <a name=\"delete\"></a>S7Client.Delete(blockType, blockNum[, callback])\nDeletes a block into AG.\n\n    !!! There is no undo function available !!!\n\n - `blockType` Type of block (see table [above](#table-blocktype))\n - `blockNum` Number of block\n - The optional `callback` parameter will be executed after completion\n\nIf `callback` is **not** set the function is **blocking** and returns `true` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` argument is given to the callback.\n\n#### <a name=\"dbget\"></a>S7Client.DBGet(dbNumber[, callback])\nUploads a DB from AG. This function is equivalent to `Upload()` with `BlockType = Block_DB` but it uses a different approach so it’s not subject to the security level set.\n\nOnly data is uploaded.\n\n - `dbNumber` DB number\n - The optional `callback` parameter will be executed after completion\n\nIf `callback` is **not** set the function is **blocking** and returns a `Buffer` object on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` and `result` argument is given to the callback.\n\nThis function first gathers the DB size via `GetAgBlockInfo()` then calls `DBRead()`.\n\n#### <a name=\"dbfill\"></a>S7Client.DBFill(dbNumber, fillChar[, callback])\nFills a DB in AG with a given byte without the need of specifying its size.\n\n - `dbNumber` DB number\n - `fillChar` char or char code\n - The optional `callback` parameter will be executed after completion\n\nIf `callback` is **not** set the function is **blocking** and returns `true` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` argument is given to the callback.\n\n### <a name=\"datetime-functions\"></a>API - Date/Time functions\n\n----------\n\n#### <a name=\"get-plc-datetime\"></a>S7Client.GetPlcDateTime([callback])\nReads PLC date and time.\n\n- The optional `callback` parameter will be executed after completion\n\nIf `callback` is **not** set the function is **blocking** and returns a javascript `Date()` object on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` and `result` argument is given to the callback.\n\n#### <a name=\"set-plc-datetime\"></a>S7Client.SetPlcDateTime(dateTime[, callback])\nSets the PLC date and time.\n\n - `dateTime`\n - The optional `callback` parameter will be executed after completion\n\nThe `dateTime` argument can be a javascript `Date()` object or an object with the structure below.\n```javascript\n{\n  \"year\": 2015,  // year\n  \"month\": 4,    // months since January     0-11\n  \"day\": 3,      // day of the month         1-31\n  \"hours\": 19,   // hours since midnight     0-23\n  \"minutes\": 37, // minutes after the hour   0-59\n  \"seconds\": 0   // seconds after the minute 0-59\n}\n```\n\nIf `callback` is **not** set the function is **blocking** and returns a `true` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` argument is given to the callback.\n\n#### <a name=\"set-plc-system-datetime\"></a>S7Client.SetPlcSystemDateTime([callback])\nSets the PLC date and time in accord to the PC system Date/Time.\n\n - The optional `callback` parameter will be executed after completion\n\nIf `callback` is **not** set the function is **blocking** and returns `true` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` argument is given to the callback.\n\n### <a name=\"systeminfo-functions\"></a>API - System info functions\n\n----------\n\n#### <a name=\"read-szl\"></a>S7Client.ReadSZL(id, index[, callback])\nReads a partial list of given `id`and `index`.\n\n - The optional `callback` parameter will be executed after completion\n\nIf `callback` is **not** set the function is **blocking** and returns a `buffer` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` and `result` argument is given to the callback.\n\n#### <a name=\"read-szl-list\"></a>S7Client.ReadSZLList([callback])\nReads the directory of the partial lists.\n\n - The optional `callback` parameter will be executed after completion\n\nIf `callback` is **not** set the function is **blocking** and returns an `array` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` and `result` argument is given to the callback.\n\n#### <a name=\"get-order-code\"></a>S7Client.GetOrderCode([callback])\nGets CPU order code and version info.\n\n - The optional `callback` parameter will be executed after completion\n\nIf `callback` is **not** set the function is **blocking** and returns an `object` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` and `result` argument is given to the callback.\n\nExample:\n```javascript\n{\n  \"Code\": , // Order Code\n  \"V1\": ,   // Version V1.V2.V3\n  \"V2\": ,\n  \"V3\":\n}\n```\n\n#### <a name=\"get-cpu-info\"></a>S7Client.GetCpuInfo([callback])\nGets CPU module name, serial number and other info.\n\n - The optional `callback` parameter will be executed after completion\n\nIf `callback` is **not** set the function is **blocking** and returns an `object` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` and `result` argument is given to the callback.\n\nExample:\n```javascript\n{\n  \"ModuleTypeName\": ,\n  \"SerialNumber\": ,\n  \"ASName\": ,\n  \"Copyright\": ,\n  \"ModuleName\":\n}\n```\n\n#### <a name=\"get-cp-info\"></a>S7Client.GetCpInfo([callback])\nGets CP (communication processor) info.\n\n - The optional `callback` parameter will be executed after completion\n\nIf `callback` is **not** set the function is **blocking** and returns an `object` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` and `result` argument is given to the callback.\n\nExample:\n```javascript\n{\n  \"MaxPduLength\": ,\n  \"MaxConnections\": ,\n  \"MaxMpiRate\": ,\n  \"MaxBusRate\":\n}\n```\n\n### <a name=\"control-functions\"></a>API - PLC control functions\n\n----------\n\n#### <a name=\"plc-hot-start\"></a>S7Client.PlcHotStart([callback])\nPuts the CPU in RUN mode performing an HOT START.\n\n - The optional `callback` parameter will be executed after completion\n\nIf `callback` is **not** set the function is **blocking** and returns `true` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` argument is given to the callback.\n\n#### <a name=\"plc-cold-start\"></a>S7Client.PlcColdStart([callback])\nPuts the CPU in RUN mode performing a COLD START.\n\n - The optional `callback` parameter will be executed after completion\n\nIf `callback` is **not** set the function is **blocking** and returns `true` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` argument is given to the callback.\n\n#### <a name=\"plc-stop\"></a>S7Client.PlcStop([callback])\nPuts the CPU in STOP mode.\n\n - The optional `callback` parameter will be executed after completion\n\nIf `callback` is **not** set the function is **blocking** and returns `true` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` argument is given to the callback.\n\n#### <a name=\"copy-ram-to-rom\"></a>S7Client.CopyRamToRom(timeout[, callback])\nPerforms the Copy Ram to Rom action.\n\n - `timeout` Maximum time expected to complete the operation (ms)\n - The optional `callback` parameter will be executed after completion or on timeout\n\nIf `callback` is **not** set the function is **blocking** and returns `true` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` argument is given to the callback.\n\nNot all CPUs support this operation.\nThe CPU must be in STOP mode.\n\n#### <a name=\"compress\"></a>S7Client.Compress(timeout[, callback])\nPerforms the Memory compress action.\n\n - `timeout` Maximum time expected to complete the operation (ms)\n - The optional `callback` parameter will be executed after completion or on timeout\n\nIf `callback` is **not** set the function is **blocking** and returns `true` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` argument is given to the callback.\n\n### <a name=\"security-functions\"></a>API - Security functions\n\n----------\n\n#### <a name=\"set-session-password\"></a>S7Client.SetSessionPassword(password[, callback])\nSend the password to the PLC to meet its security level.\n\n - `password` Password\n - The optional `callback` parameter will be executed after completion\n\nIf `callback` is **not** set the function is **blocking** and returns `true` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` argument is given to the callback.\n\nA `password` accepted by a PLC is an 8 chars string, a longer password will be trimmed, and a shorter one will be \"right space padded\".\n\n#### <a name=\"clear-session-password\"></a>S7Client.ClearSessionPassword([callback])\nClears the password set for the current session (logout).\n\n - The optional `callback` parameter will be executed after completion\n\nIf `callback` is **not** set the function is **blocking** and returns `true` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` argument is given to the callback.\n\n#### <a name=\"get-protection\"></a>S7Client.GetProtection([callback])\nGets the CPU protection level info.\n\n - The optional `callback` parameter will be executed after completion\n\nIf `callback` is **not** set the function is **blocking** and returns the protection object on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` and `result` argument is given to the callback.\n\nExample:\n```javascript\n{\n  \"sch_schal\": 1,\n  \"sch_par\": 0,\n  \"sch_rel\": 0,\n  \"bart_sch\": 1,\n  \"anl_sch\": 0\n}\n```\n\n| S7Protection | Values  | Description |\n|:-------------|:--------|:------------|\n| `sch_schal`  | 1,2,3   | Protection level set with the mode selector\n| `sch_par`    | 0,1,2,3 | Password level, 0 : no password\n| `sch_rel`    | 0,1,2,3 | Valid protection level of the CPU\n| `bart_sch`   | 1,2,3,4 | Mode selector setting (1:RUN, 2:RUN-P, 3:STOP, :MRES, 0:undefined or cannot be determined)\n| `anl_sch`    | 0,1,2   | Startup switch setting (1:CRST, 2:WRST, 0:undefined, does not exist of cannot be determined)\n\n### <a name=\"properties\"></a>API - Properties\n\n----------\n\n#### <a name=\"exec-time\"></a>S7Client.ExecTime()\nReturns the last job execution time in milliseconds or `false`on error.\n\n#### <a name=\"last-error\"></a>S7Client.LastError()\nReturns the last job result.\n\n#### <a name=\"pdu-requested\"></a>S7Client.PDURequested()\nReturns the PDU length requested by the client or `false` on error. The requested PDU length can be modified with [SetParam()](#set-param).\n\n#### <a name=\"pdu-length\"></a>S7Client.PDULength()\nReturns the PDU length negotiated between the client and the PLC during the connection or `false` on error.\n\nIt’s useful to know the PDU negotiated when we need to call `ReadMultivar()` or `WriteMultiVar()`. All other data transfer functions handle this information by themselves and split the telegrams automatically if needed.\n\n#### <a name=\"plc-status\"></a>S7Client.PlcStatus([callback])\nReturns the CPU status (running/stopped).\n\n - The optional `callback` parameter will be executed after completion\n\nIf `callback` is **not** set the function is **blocking** and returns the CPU status on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` and `result` argument is given to the callback.\n\n| Status                        | Value | Description |\n|:------------------------------|:-----:|:------------|\n| `S7Client.S7CpuStatusUnknown` | 0x00  | The CPU status is unknown\n| `S7Client.S7CpuStatusRun`     | 0x08  | The CPU is running\n| `S7Client.S7CpuStatusStop`    | 0x04  | The CPU is stopped\n\n#### <a name=\"connected\"></a>S7Client.Connected()\nReturns the connection status.\n\n#### <a name=\"error-text\"></a>S7Client.ErrorText(errNum)\nReturns a textual explanation of a given error number.\n\n - `errNum` Error number\n"
  },
  {
    "path": "doc/server.md",
    "content": "## S7Server\n- [Administrative functions](#administrative-functions)\n  - [Start()](#start)\n  - [StartTo()](#start-to)\n  - [Stop()](#stop)\n  - [GetParam()](#get-param)\n  - [SetParam()](#set-param)\n  - [SetResourceless()](#set-resourceless)\n- [Memory functions](#memory-functions)\n  - [RegisterArea()](#register-area)\n  - [UnregisterArea()](#unregister-area)\n  - [GetArea()](#get-area)\n  - [SetArea()](#set-area)\n  - [LockArea()](#lock-area)\n  - [UnlockArea()](#unlock-area)\n- [Event functions](#event-functions)\n  - [Event 'event'](#event-event)\n  - [Event 'readWrite'](#event-read-write)\n  - [GetEventMask()](#get-event-mask)\n  - [SetEventMask()](#set-event-mask)\n- [Miscellaneous functions](#miscellaneous-functions)\n  - [LastError()](#last-error)\n  - [EventText()](#event-text)\n  - [ErrorText()](#error-text)\n  - [ServerStatus()](#server-status)\n  - [ClientsCount()](#clients-count)\n  - [GetCpuStatus()](#get-cpu-status)\n  - [SetCpuStatus()](#set-cpu-status)\n\n### <a name=\"administrative-functions\"></a>API - Administrative functions\n\n----------\n\n#### <a name=\"start\"></a>S7Server.Start([callback])\nStarts 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.\n\n- The optional `callback` parameter will be executed after completion\n\nIf `callback` is **not** set the function is **blocking** and returns `true` on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` argument is given to the callback.\n\n#### <a name=\"start-to\"></a>S7Server.StartTo(ip[, callback])\nStarts the server and binds it to the specified IP address and the IsoTCP port.\n\n- `ip` PLC/Equipment IPV4 Address ex. “192.168.1.12”\n- The optional `callback` parameter will be executed after completion\n\nIf `callback` is **not** set the function is **blocking** and returns the CPU status on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` argument is given to the callback.\n\n#### <a name=\"stop\"></a>S7Server.Stop([callback])\nStops the server, disconnects gracefully all clients, destroys al S7 workers and unbinds the listener socket from its address.\n\n- The optional `callback` parameter will be executed after completion\n\nIf `callback` is **not** set the function is **blocking** and returns the CPU status on success or `false` on error.<br />\nIf `callback` is set the function is **non-blocking** and an `error` argument is given to the callback.\n\n#### <a name=\"get-param\"></a>S7Server.GetParam(paramNumber)\nReturns an internal server parameter.\n\n - `paramNumber` One from the parameter list [below](#table-area)\n\n<a name=\"table-parameter\"></a>\n\n| Name                    | Value | Description |\n|:------------------------|:-----:|:------------|\n| `S7Server.LocalPort`    | 1     | Socket local port\n| `S7Server.WorkInterval` | 6     | Socket worker interval\n| `S7Server.PDURequest`   | 10    | Initial PDU length request\n| `S7Server.MaxClients`   | 11    | Max clients allowed\n\nReturns the `parameter value` on success or `false` on error.\n\n#### <a name=\"set-param\"></a>S7Server.SetParam(paramNumber, value)\nSets an internal server parameter.\n\n - `paramNumber` One from the parameter list [above](#table-area)\n - `value` New parameter value\n\nReturns `true` on success or `false` on error.\n\n#### <a name=\"set-resourceless\"></a>S7Server.SetResourceless(value)\nSets the server to resourceless mode.\n\n - `value` new value\n\nReturns `true` on success or `false` on error.\n\n### <a name=\"memory-functions\"></a>API - Memory functions\n\n----------\n\n#### <a name=\"register-area\"></a>S7Server.RegisterArea(areaCode[, index], buffer)\nRegisters a memory area in the server. That memory block will be visible by the clients.\n\n - `areaCode` Area identifier (see table [below](#table-area))\n - `index` DB number if `areaCode` equals `srvAreaDB`, otherwise ignored\n - `buffer` User buffer\n\nReturns `true` on success or `false` on error.\n\n#### <a name=\"unregister-area\"></a>S7Server.UnregisterArea(areaCode[, index])\nUnregisters a memory area in the server.\n\n - `areaCode` Area identifier (see table [below](#table-area))\n - `index` DB number if `areaCode` equals `srvAreaDB`, otherwise ignored\n\nReturns `true` on success or `false` on error.\n\n#### <a name=\"get-area\"></a>S7Server.GetArea(areaCode[, index])\nGets the content of a previously registered memory area block.\n\n - `areaCode` Area identifier (see table [below](#table-area))\n - `index` DB number if `areaCode` equals `srvAreaDB`, otherwise ignored\n\nReturns a `buffer` object.\n\n#### <a name=\"set-area\"></a>S7Server.SetArea(areaCode[, index], buffer)\nSets the content of a previously registered memory area block.\n\n - `areaCode` Area identifier (see table [below](#table-area))\n - `index` DB number if `areaCode` equals `srvAreaDB`, otherwise ignored\n - `buffer` Buffer object\n\n#### <a name=\"lock-area\"></a>S7Server.LockArea(areaCode[, index])\nLocks the memory area so that a server worker thread is blocked on access attempt until the lock is released with [UnlockArea()](#unlock-area).\n\n - `areaCode` Area identifier (see table [below](#table-area))\n - `index` DB number if `areaCode` equals `srvAreaDB`, otherwise ignored\n\n#### <a name=\"unlock-area\"></a>S7Server.UnlockArea(areaCode[, index])\nUnlocks a previously locked memory area.\n\n\n - `areaCode` Area identifier (see table [below](#table-area))\n - `index` DB number if `areaCode` equals `srvAreaDB`, otherwise ignored\n\n<a name=\"table-area\"></a>\n\n| Area                   | Value | Description |\n|:-----------------------|:-----:|:------------|\n| `S7Server.srvAreaPE`   |   0   | Process inputs\n| `S7Server.srvAreaPA`   |   1   | Process outputs\n| `S7Server.srvAreaMK`   |   2   | Merkers\n| `S7Server.srvAreaCT`   |   3   | Counters\n| `S7Server.srvAreaTM`   |   4   | Timers\n| `S7Server.srvAreaDB`   |   5   | DB\n\n### <a name=\"event-functions\"></a>API - Event functions\n\n----------\n\n#### <a name=\"event-event\"></a>S7Server event: 'event'\nEmitted on server events.\n\n - `event` Event object\n\n<a name=\"event-object\"></a> Event object:\n\n```javascript\n{\n  EvtTime;    // <Date>   Date\n  EvtSender;  // <String> Sender\n  EvtCode;    // <Number> Event code\n  EvtRetCode; // <Number> Event result\n  EvtParam1;  // <Number> Param 1 (if available)\n  EvtParam2;  // <Number> Param 2 (if available)\n  EvtParam3;  // <Number> Param 3 (if available)\n  EvtParam4;  // <Number> Param 4 (if available)\n}\n```\nExample:\n\n```javascript\nvar s7server = new snap7.S7Server();\n\ns7server.on(\"event\", function(event) {\n    console.log(s7server.EventText(event));\n});\n\ns7server.StartTo('127.0.0.1');\n```\n\n#### <a name=\"event-read-write\"></a>S7Server event: 'readWrite'\nEmitted on every read/write event. Only available in resourceless mode.\n\n - `sender` IPv4 address of the sender\n - `operation` Operation type\n - `tagObj` Tag object\n - `buffer` Buffer object\n - `callback` Callback function\n\nThe server worker thread is **blocked** until `callback` is called. Therefore **calling is crucial**, to prevent a deadlock in the worker thread.<br />\nOn 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.\n\n<a name=\"table-operation-type\"></a>\n\n| Operation type            | Value | Description          |\n|:--------------------------|:-----:|:---------------------|\n| `S7Server.operationRead`  | 0x00  | Read operation\n| `S7Server.operationWrite` | 0x01  | Write operation\n\n<a name=\"tag-object\"></a> Tag object:\n\n```javascript\n{\n  Area;     // <Number> Area code (DB, MK,…)\n  DBNumber; // <Number> DB number (if any or 0)\n  Start;    // <Number> Offset start\n  Size;     // <Number> Number of elements\n  WordLen;  // <Number> Tag WordLength\n}\n```\n\nExample:\n\n```javascript\nvar s7server = new snap7.S7Server();\n\ns7server.SetResourceless(true);\n\ns7server.on(\"readWrite\", function(sender, operation, tagObj, buffer, callback) {\n  console.log((operation === s7server.operationRead ? 'Read' : 'Write') + ' event from ' + sender);\n  console.log('Area     : ' + tagObj.Area);\n  console.log('DBNumber : ' + tagObj.DBNumber);\n  console.log('Start    : ' + tagObj.Start);\n  console.log('Size     : ' + tagObj.Size);\n  console.log('WordLen  : ' + tagObj.WordLen);\n\n  if (operation === s7server.operationRead) {\n    buffer.fill(255);\n    return callback(buffer);\n  } else {\n    console.log('Buffer   : ' + buffer);\n    return callback();\n  }\n});\n\ns7server.StartTo('127.0.0.1');\n```\n\n#### <a name=\"get-event-mask\"></a>S7Server.GetEventMask()\nReturns the server event filter mask.\n\n\n#### <a name=\"set-event-mask\"></a>S7Server.SetEventMask(mask)\nSets the server event filter mask.\n\n - `mask` Bit mask (see table [below](#table-mask))\n\n<a name=\"table-mask\"></a>\n\n| Event code                          | Value          |\n|:------------------------------------|:--------------:|\n| `S7Server.evcAll`                   |   0xFFFFFFFF\n| `S7Server.evcNone`                  |   0x00000000\n| `S7Server.evcServerStarted`         |   0x00000001\n| `S7Server.evcServerStopped`         |   0x00000002\n| `S7Server.evcListenerCannotStart`   |   0x00000004\n| `S7Server.evcClientAdded`           |   0x00000008\n| `S7Server.evcClientRejected`        |   0x00000010\n| `S7Server.evcClientNoRoom`          |   0x00000020\n| `S7Server.evcClientException`       |   0x00000040\n| `S7Server.evcClientDisconnected`    |   0x00000080\n| `S7Server.evcClientTerminated`      |   0x00000100\n| `S7Server.evcClientsDropped`        |   0x00000200\n| `S7Server.evcPDUincoming`           |   0x00010000\n| `S7Server.evcDataRead`              |   0x00020000\n| `S7Server.evcDataWrite`             |   0x00040000\n| `S7Server.evcNegotiatePDU`          |   0x00080000\n| `S7Server.evcReadSZL`               |   0x00100000\n| `S7Server.evcClock`                 |   0x00200000\n| `S7Server.evcUpload`                |   0x00400000\n| `S7Server.evcDownload`              |   0x00800000\n| `S7Server.evcDirectory`             |   0x01000000\n| `S7Server.evcSecurity`              |   0x02000000\n| `S7Server.evcControl`               |   0x04000000\n\n\n### <a name=\"miscellaneous-functions\"></a>API - Miscellaneous functions\n\n----------\n\n#### <a name=\"last-error\"></a>S7Server.LastError()\nReturns the last job result.\n\n#### <a name=\"event-text\"></a>S7Server.EventText(eventObj)\nReturns a textual explanation of a given event.\n\n - `eventObj` Event object (example [here](#event-object))\n\n#### <a name=\"error-text\"></a>S7Server.ErrorText(errNum)\nReturns a textual explanation of a given error number.\n\n - `errNum` Error number\n\n#### <a name=\"server-status\"></a>S7Server.ServerStatus()\nReturns the server status. (see table [below](#table-server-status))\n\n<a name=\"table-server-status\"></a>\n\n| Status                | Value | Description          |\n|:----------------------|:-----:|:---------------------|\n| `S7Server.SrvStopped` | 0x00  | The Server is stopped\n| `S7Server.SrvRunning` | 0x01  | The Server is Running\n| `S7Server.SrvError`   | 0x02  | Server Error\n\n#### <a name=\"clients-count\"></a>S7Server.ClientsCount()\nReturns the number of clients connected to the server.\n\n#### <a name=\"get-cpu-status\"></a>S7Server.GetCpuStatus()\nReturns the Virtual CPU status. (see table [below](#table-cpu-status))\n\n#### <a name=\"set-cpu-status\"></a>S7Server.SetCpuStatus(cpuStatus)\nSets the Virtual CPU status.\n\n - `cpuStatus` Status value (see table [below](#table-cpu-status))\n\n<a name=\"table-cpu-status\"></a>\n\n| Status                        | Value | Description              |\n|:------------------------------|:-----:|:-------------------------|\n| `S7Server.S7CpuStatusUnknown` | 0x00  | The CPU status is unknown\n| `S7Server.S7CpuStatusRun`     | 0x08  | The CPU is running\n| `S7Server.S7CpuStatusStop`    | 0x04  | The CPU is stopped\n"
  },
  {
    "path": "lib/node-snap7.js",
    "content": "/*\n * Copyright (c) 2019, Mathias Küsel\n * MIT License <https://github.com/mathiask88/node-snap7/blob/master/LICENSE>\n */\n\nvar events = require('events');\n\nmodule.exports = snap7 = require('bindings')('node_snap7.node');\n\nsnap7.S7Client.prototype.DBRead = function (dbNumber, start, size, cb) {\n    return this.ReadArea(this.S7AreaDB, dbNumber, start, size, this.S7WLByte, cb);\n}\n\nsnap7.S7Client.prototype.DBWrite = function (dbNumber, start, size, buf, cb) {\n    return this.WriteArea(this.S7AreaDB, dbNumber, start, size, this.S7WLByte, buf, cb);\n}\n\nsnap7.S7Client.prototype.MBRead = function (start, size, cb) {\n    return this.ReadArea(this.S7AreaMK, 0, start, size, this.S7WLByte, cb);\n}\n\nsnap7.S7Client.prototype.MBWrite = function (start, size, buf, cb) {\n    return this.WriteArea(this.S7AreaMK, 0, start, size, this.S7WLByte, buf, cb);\n}\n\nsnap7.S7Client.prototype.EBRead = function (start, size, cb) {\n    return this.ReadArea(this.S7AreaPE, 0, start, size, this.S7WLByte, cb);\n}\n\nsnap7.S7Client.prototype.EBWrite = function (start, size, buf, cb) {\n    return this.WriteArea(this.S7AreaPE, 0, start, size, this.S7WLByte, buf, cb);\n}\n\nsnap7.S7Client.prototype.ABRead = function (start, size, cb) {\n    return this.ReadArea(this.S7AreaPA, 0, start, size, this.S7WLByte, cb);\n}\n\nsnap7.S7Client.prototype.ABWrite = function (start, size, buf, cb) {\n    return this.WriteArea(this.S7AreaPA, 0, start, size, this.S7WLByte, buf, cb);\n}\n\nsnap7.S7Client.prototype.TMRead = function (start, size, cb) {\n    return this.ReadArea(this.S7AreaTM, 0, start, size, this.S7WLTimer, cb);\n}\n\nsnap7.S7Client.prototype.TMWrite = function (start, size, buf, cb) {\n    return this.WriteArea(this.S7AreaTM, 0, start, size, this.S7WLTimer, buf, cb);\n}\n\nsnap7.S7Client.prototype.CTRead = function (start, size, cb) {\n    return this.ReadArea(this.S7AreaCT, 0, start, size, this.S7WLCounter, cb);\n}\n\nsnap7.S7Client.prototype.CTWrite = function (start, size, buf, cb) {\n    return this.WriteArea(this.S7AreaCT, 0, start, size, this.S7WLCounter, buf, cb);\n}\n\nsnap7.S7Server.super_ = events.EventEmitter;\nObject.setPrototypeOf(snap7.S7Server.prototype, events.EventEmitter.prototype);\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"node-snap7\",\n  \"main\": \"./lib/node-snap7.js\",\n  \"version\": \"1.0.9\",\n  \"description\": \"Native node.js addon/wrapper for snap7\",\n  \"homepage\": \"https://github.com/mathiask88/node-snap7\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git://github.com/mathiask88/node-snap7.git\"\n  },\n  \"keywords\": [\n    \"snap7\",\n    \"sps\",\n    \"S7\",\n    \"PLC\"\n  ],\n  \"author\": {\n    \"name\": \"Mathias Küsel\"\n  },\n  \"engines\": {\n    \"node\": \"16 || 18 || 20 || 22 || 24\"\n  },\n  \"license\": \"MIT\",\n  \"readmeFilename\": \"README.md\",\n  \"dependencies\": {\n    \"nan\": \"^2.23.0\",\n    \"bindings\": \"^1.5.0\",\n    \"prebuild-install\": \"^7.1.2\"\n  },\n  \"devDependencies\": {\n    \"prebuild\": \"^13.0.1\",\n    \"prebuild-ci\": \"^4.0.0\"\n  },\n  \"scripts\": {\n    \"install\": \"prebuild-install || node-gyp rebuild\",\n    \"test\": \"prebuild-ci\"\n  }\n}\n"
  },
  {
    "path": "src/node_snap7.cpp",
    "content": "/*\n * Copyright (c) 2019, Mathias Küsel\n * MIT License <https://github.com/mathiask88/node-snap7/blob/master/LICENSE>\n */\n\n#include <node_snap7_client.h>\n#include <node_snap7_server.h>\n\nnamespace node_snap7 {\n\nNAN_MODULE_INIT(InitAll) {\n  S7Client::Init(target);\n  S7Server::Init(target);\n}\n\nNODE_MODULE(node_snap7, InitAll)\n\n}  // namespace node_snap7\n"
  },
  {
    "path": "src/node_snap7_client.cpp",
    "content": "/*\n * Copyright (c) 2019, Mathias Küsel\n * MIT License <https://github.com/mathiask88/node-snap7/blob/master/LICENSE>\n */\n\n#include <node_snap7_client.h>\n#include <node_buffer.h>\n#include <sstream>\n\nnamespace node_snap7 {\n\nNan::Persistent<v8::FunctionTemplate> S7Client::constructor;\n\nNAN_MODULE_INIT(S7Client::Init) {\n  Nan::HandleScope scope;\n\n  v8::Local<v8::FunctionTemplate> tpl;\n  tpl = Nan::New<v8::FunctionTemplate>(S7Client::New);\n\n  v8::Local<v8::String> name = Nan::New<v8::String>(\"S7Client\")\n    .ToLocalChecked();\n\n  tpl->SetClassName(name);\n  tpl->InstanceTemplate()->SetInternalFieldCount(1);\n\n  // Setup the prototype\n  // Control functions\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"Connect\"\n    , S7Client::Connect);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"ConnectTo\"\n    , S7Client::ConnectTo);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"SetConnectionParams\"\n    , S7Client::SetConnectionParams);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"SetConnectionType\"\n    , S7Client::SetConnectionType);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"Disconnect\"\n    , S7Client::Disconnect);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"GetParam\"\n    , S7Client::GetParam);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"SetParam\"\n    , S7Client::SetParam);\n\n  // Data I/O Main functions\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"ReadArea\"\n    , S7Client::ReadArea);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"WriteArea\"\n    , S7Client::WriteArea);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"ReadMultiVars\"\n    , S7Client::ReadMultiVars);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"WriteMultiVars\"\n    , S7Client::WriteMultiVars);\n\n  // Directory functions\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"ListBlocks\"\n    , S7Client::ListBlocks);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"GetAgBlockInfo\"\n    , S7Client::GetAgBlockInfo);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"GetPgBlockInfo\"\n    , S7Client::GetPgBlockInfo);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"ListBlocksOfType\"\n    , S7Client::ListBlocksOfType);\n\n  // Blocks functions\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"Upload\"\n    , S7Client::Upload);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"FullUpload\"\n    , S7Client::FullUpload);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"Download\"\n    , S7Client::Download);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"Delete\"\n    , S7Client::Delete);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"DBGet\"\n    , S7Client::DBGet);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"DBFill\"\n    , S7Client::DBFill);\n\n  // Date/Time functions\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"GetPlcDateTime\"\n    , S7Client::GetPlcDateTime);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"SetPlcDateTime\"\n    , S7Client::SetPlcDateTime);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"SetPlcSystemDateTime\"\n    , S7Client::SetPlcSystemDateTime);\n\n  // System Info functions\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"GetOrderCode\"\n    , S7Client::GetOrderCode);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"GetCpuInfo\"\n    , S7Client::GetCpuInfo);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"GetCpInfo\"\n    , S7Client::GetCpInfo);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"ReadSZL\"\n    , S7Client::ReadSZL);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"ReadSZLList\"\n    , S7Client::ReadSZLList);\n\n  // Control functions\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"PlcHotStart\"\n    , S7Client::PlcHotStart);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"PlcColdStart\"\n    , S7Client::PlcColdStart);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"PlcStop\"\n    , S7Client::PlcStop);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"CopyRamToRom\"\n    , S7Client::CopyRamToRom);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"Compress\"\n    , S7Client::Compress);\n\n  // Security functions\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"GetProtection\"\n    , S7Client::GetProtection);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"SetSessionPassword\"\n    , S7Client::SetSessionPassword);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"ClearSessionPassword\"\n    , S7Client::ClearSessionPassword);\n\n  // Properties\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"ExecTime\"\n    , S7Client::ExecTime);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"LastError\"\n    , S7Client::LastError);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"PDURequested\"\n    , S7Client::PDURequested);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"PDULength\"\n    , S7Client::PDULength);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"PlcStatus\"\n    , S7Client::PlcStatus);\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"Connected\"\n    , S7Client::Connected);\n\n  // Error to text function\n  Nan::SetPrototypeMethod(\n      tpl\n    , \"ErrorText\"\n    , S7Client::ErrorText);\n\n  // Error codes\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errNegotiatingPDU\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errNegotiatingPDU)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliInvalidParams\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliInvalidParams)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliJobPending\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliJobPending)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliTooManyItems\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliTooManyItems)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliInvalidWordLen\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliInvalidWordLen)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliPartialDataWritten\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliPartialDataWritten)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliSizeOverPDU\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliSizeOverPDU)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliInvalidPlcAnswer\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliInvalidPlcAnswer)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliAddressOutOfRange\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliAddressOutOfRange)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliInvalidTransportSize\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliInvalidTransportSize)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliWriteDataSizeMismatch\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliWriteDataSizeMismatch)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliItemNotAvailable\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliItemNotAvailable)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliInvalidValue\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliInvalidValue)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliCannotStartPLC\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliCannotStartPLC)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliAlreadyRun\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliAlreadyRun)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliCannotStopPLC\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliCannotStopPLC)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliCannotCopyRamToRom\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliCannotCopyRamToRom)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliCannotCompress\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliCannotCompress)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliAlreadyStop\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliAlreadyStop)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliFunNotAvailable\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliFunNotAvailable)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliUploadSequenceFailed\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliUploadSequenceFailed)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliInvalidDataSizeRecvd\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliInvalidDataSizeRecvd)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliInvalidBlockType\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliInvalidBlockType)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliInvalidBlockNumber\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliInvalidBlockNumber)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliInvalidBlockSize\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliInvalidBlockSize)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliDownloadSequenceFailed\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliDownloadSequenceFailed)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliInsertRefused\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliInsertRefused)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliDeleteRefused\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliDeleteRefused)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliNeedPassword\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliNeedPassword)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliInvalidPassword\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliInvalidPassword)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliNoPasswordToSetOrClear\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliNoPasswordToSetOrClear)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliJobTimeout\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliJobTimeout)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliPartialDataRead\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliPartialDataRead)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliBufferTooSmall\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliBufferTooSmall)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliFunctionRefused\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliFunctionRefused)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliDestroying\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliDestroying)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliInvalidParamNumber\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliInvalidParamNumber)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"errCliCannotChangeParam\").ToLocalChecked()\n    , Nan::New<v8::Integer>(errCliCannotChangeParam)\n    , v8::ReadOnly);\n\n  // Client Connection Type\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"CONNTYPE_PG\").ToLocalChecked()\n    , Nan::New<v8::Integer>(CONNTYPE_PG)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"CONNTYPE_OP\").ToLocalChecked()\n    , Nan::New<v8::Integer>(CONNTYPE_OP)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"CONNTYPE_BASIC\").ToLocalChecked()\n    , Nan::New<v8::Integer>(CONNTYPE_BASIC)\n    , v8::ReadOnly);\n\n  // CPU Status codes\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"S7CpuStatusUnknown\").ToLocalChecked()\n    , Nan::New<v8::Integer>(S7CpuStatusUnknown)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"S7CpuStatusRun\").ToLocalChecked()\n    , Nan::New<v8::Integer>(S7CpuStatusRun)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"S7CpuStatusStop\").ToLocalChecked()\n    , Nan::New<v8::Integer>(S7CpuStatusStop)\n    , v8::ReadOnly);\n\n  // Area ID\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"S7AreaPE\").ToLocalChecked()\n    , Nan::New<v8::Integer>(S7AreaPE)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"S7AreaPA\").ToLocalChecked()\n    , Nan::New<v8::Integer>(S7AreaPA)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"S7AreaMK\").ToLocalChecked()\n    , Nan::New<v8::Integer>(S7AreaMK)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"S7AreaDB\").ToLocalChecked()\n    , Nan::New<v8::Integer>(S7AreaDB)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"S7AreaCT\").ToLocalChecked()\n    , Nan::New<v8::Integer>(S7AreaCT)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"S7AreaTM\").ToLocalChecked()\n    , Nan::New<v8::Integer>(S7AreaTM)\n    , v8::ReadOnly);\n\n  // Word Length\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"S7WLBit\").ToLocalChecked()\n    , Nan::New<v8::Integer>(S7WLBit)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"S7WLByte\").ToLocalChecked()\n    , Nan::New<v8::Integer>(S7WLByte)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"S7WLWord\").ToLocalChecked()\n    , Nan::New<v8::Integer>(S7WLWord)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"S7WLDWord\").ToLocalChecked()\n    , Nan::New<v8::Integer>(S7WLDWord)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"S7WLReal\").ToLocalChecked()\n    , Nan::New<v8::Integer>(S7WLReal)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"S7WLCounter\").ToLocalChecked()\n    , Nan::New<v8::Integer>(S7WLCounter)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"S7WLTimer\").ToLocalChecked()\n    , Nan::New<v8::Integer>(S7WLTimer)\n    , v8::ReadOnly);\n\n  // Block type\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"Block_OB\").ToLocalChecked()\n    , Nan::New<v8::Integer>(Block_OB)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"Block_DB\").ToLocalChecked()\n    , Nan::New<v8::Integer>(Block_DB)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"Block_SDB\").ToLocalChecked()\n    , Nan::New<v8::Integer>(Block_SDB)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"Block_FC\").ToLocalChecked()\n    , Nan::New<v8::Integer>(Block_FC)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"Block_SFC\").ToLocalChecked()\n    , Nan::New<v8::Integer>(Block_SFC)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"Block_FB\").ToLocalChecked()\n    , Nan::New<v8::Integer>(Block_FB)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"Block_SFB\").ToLocalChecked()\n    , Nan::New<v8::Integer>(Block_SFB)\n    , v8::ReadOnly);\n\n  // Sub Block Type\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"SubBlk_OB\").ToLocalChecked()\n    , Nan::New<v8::Integer>(SubBlk_OB)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"SubBlk_SDB\").ToLocalChecked()\n    , Nan::New<v8::Integer>(SubBlk_SDB)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"SubBlk_FC\").ToLocalChecked()\n    , Nan::New<v8::Integer>(SubBlk_FC)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"SubBlk_SFC\").ToLocalChecked()\n    , Nan::New<v8::Integer>(SubBlk_SFC)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"SubBlk_FB\").ToLocalChecked()\n    , Nan::New<v8::Integer>(SubBlk_FB)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"SubBlk_SFB\").ToLocalChecked()\n    , Nan::New<v8::Integer>(SubBlk_SFB)\n    , v8::ReadOnly);\n\n  // Block languages\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"BlockLangAWL\").ToLocalChecked()\n    , Nan::New<v8::Integer>(BlockLangAWL)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"BlockLangKOP\").ToLocalChecked()\n    , Nan::New<v8::Integer>(BlockLangKOP)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"BlockLangFUP\").ToLocalChecked()\n    , Nan::New<v8::Integer>(BlockLangFUP)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"BlockLangSCL\").ToLocalChecked()\n    , Nan::New<v8::Integer>(BlockLangSCL)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"BlockLangDB\").ToLocalChecked()\n    , Nan::New<v8::Integer>(BlockLangDB)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"BlockLangGRAPH\").ToLocalChecked()\n    , Nan::New<v8::Integer>(BlockLangGRAPH)\n    , v8::ReadOnly);\n\n  // Parameter\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"LocalPort\").ToLocalChecked()\n    , Nan::New<v8::Integer>(p_u16_LocalPort)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"RemotePort\").ToLocalChecked()\n    , Nan::New<v8::Integer>(p_u16_RemotePort)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"PingTimeout\").ToLocalChecked()\n    , Nan::New<v8::Integer>(p_i32_PingTimeout)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"SendTimeout\").ToLocalChecked()\n    , Nan::New<v8::Integer>(p_i32_SendTimeout)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"RecvTimeout\").ToLocalChecked()\n    , Nan::New<v8::Integer>(p_i32_RecvTimeout)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"WorkInterval\").ToLocalChecked()\n    , Nan::New<v8::Integer>(p_i32_WorkInterval)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"SrcRef\").ToLocalChecked()\n    , Nan::New<v8::Integer>(p_u16_SrcRef)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"DstRef\").ToLocalChecked()\n    , Nan::New<v8::Integer>(p_u16_DstRef)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"SrcTSap\").ToLocalChecked()\n    , Nan::New<v8::Integer>(p_u16_SrcTSap)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"PDURequest\").ToLocalChecked()\n    , Nan::New<v8::Integer>(p_i32_PDURequest)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"MaxClients\").ToLocalChecked()\n    , Nan::New<v8::Integer>(p_i32_MaxClients)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"BSendTimeout\").ToLocalChecked()\n    , Nan::New<v8::Integer>(p_i32_BSendTimeout)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"BRecvTimeout\").ToLocalChecked()\n    , Nan::New<v8::Integer>(p_i32_BRecvTimeout)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"RecoveryTime\").ToLocalChecked()\n    , Nan::New<v8::Integer>(p_u32_RecoveryTime)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n      tpl\n    , Nan::New<v8::String>(\"KeepAliveTime\").ToLocalChecked()\n    , Nan::New<v8::Integer>(p_u32_KeepAliveTime)\n    , v8::ReadOnly);\n\n  constructor.Reset(tpl);\n  Nan::Set(target, name, Nan::GetFunction(tpl).ToLocalChecked());\n}\n\nNAN_METHOD(S7Client::New) {\n  if (info.IsConstructCall()) {\n    S7Client *s7client = new S7Client();\n\n    s7client->Wrap(info.This());\n  info.GetReturnValue().Set(info.This());\n  } else {\n    v8::Local<v8::FunctionTemplate> constructorHandle;\n    constructorHandle = Nan::New<v8::FunctionTemplate>(constructor);\n  info.GetReturnValue().Set(\n    Nan::NewInstance(Nan::GetFunction(constructorHandle).ToLocalChecked()).ToLocalChecked());\n  }\n}\n\nS7Client::S7Client() {\n  snap7Client = new TS7Client();\n  uv_mutex_init(&mutex);\n}\n\nS7Client::~S7Client() {\n  snap7Client->Disconnect();\n  delete snap7Client;\n  constructor.Reset();\n  uv_mutex_destroy(&mutex);\n}\n\nint S7Client::GetByteCountFromWordLen(int WordLen) {\n  switch (WordLen) {\n  case S7WLBit:\n  case S7WLByte:\n      return 1;\n  case S7WLWord:\n  case S7WLCounter:\n  case S7WLTimer:\n      return 2;\n  case S7WLReal:\n  case S7WLDWord:\n      return 4;\n  default:\n      return 0;\n  }\n}\n\nvoid S7Client::FreeCallback(char *data, void *hint) {\n  delete[] data;\n}\n\nvoid S7Client::FreeCallbackSZL(char *data, void *hint) {\n  delete reinterpret_cast<PS7SZL>(data);\n}\n\n// Control functions\nNAN_METHOD(S7Client::Connect) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (!info[0]->IsFunction()) {\n    int ret = s7client->snap7Client->Connect();\n    info.GetReturnValue().Set(Nan::New<v8::Boolean>(ret == 0));\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[0].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, CONNECT));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nNAN_METHOD(S7Client::ConnectTo) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (info.Length() < 3) {\n    return Nan::ThrowTypeError(\"Wrong number of arguments\");\n  }\n\n  if (!info[0]->IsString() || !info[1]->IsInt32() || !info[2]->IsInt32()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  Nan::Utf8String *remAddress = new Nan::Utf8String(info[0]);\n  if (!info[3]->IsFunction()) {\n    int ret = s7client->snap7Client->ConnectTo(\n        **remAddress\n      , Nan::To<int32_t>(info[1]).FromJust()\n      , Nan::To<int32_t>(info[2]).FromJust());\n    delete remAddress;\n    info.GetReturnValue().Set(Nan::New<v8::Boolean>(ret == 0));\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[3].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, CONNECTTO\n      , remAddress, Nan::To<int32_t>(info[1]).FromJust(), Nan::To<int32_t>(info[2]).FromJust()));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nNAN_METHOD(S7Client::SetConnectionParams) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (!info[0]->IsString() || !info[1]->IsUint32() ||\n      !info[2]->IsUint32()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  Nan::Utf8String remAddress(info[0]);\n  word LocalTSAP = Nan::To<uint32_t>(info[1]).FromJust();\n  word RemoteTSAP = Nan::To<uint32_t>(info[2]).FromJust();\n\n  int ret = s7client->snap7Client->SetConnectionParams(\n      *remAddress\n    , LocalTSAP\n    , RemoteTSAP);\n  info.GetReturnValue().Set(Nan::New<v8::Boolean>(ret == 0));\n}\n\nNAN_METHOD(S7Client::SetConnectionType) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (!info[0]->IsUint32()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  word type = Nan::To<uint32_t>(info[0]).FromJust();\n\n  int  ret = s7client->snap7Client->SetConnectionType(type);\n  info.GetReturnValue().Set(Nan::New<v8::Boolean>(ret == 0));\n}\n\nNAN_METHOD(S7Client::Disconnect) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  int ret = s7client->snap7Client->Disconnect();\n  info.GetReturnValue().Set(Nan::New<v8::Boolean>(ret == 0));\n}\n\nNAN_METHOD(S7Client::GetParam) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (!info[0]->IsInt32()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  int pData;\n  int returnValue = s7client->snap7Client->GetParam(Nan::To<int32_t>(info[0]).FromJust()\n    , &pData);\n\n  if (returnValue == 0) {\n    info.GetReturnValue().Set(Nan::New<v8::Integer>(pData));\n  } else {\n    info.GetReturnValue().Set(Nan::New<v8::Integer>(returnValue));\n  }\n}\n\nNAN_METHOD(S7Client::SetParam) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (!(info[0]->IsInt32() || info[1]->IsInt32())) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  int pData = Nan::To<int32_t>(info[1]).FromJust();\n  int ret = s7client->snap7Client->SetParam(Nan::To<int32_t>(info[0]).FromJust(), &pData);\n  info.GetReturnValue().Set(Nan::New<v8::Boolean>(ret == 0));\n}\n\n// Data I/O Main functions\nvoid IOWorker::Execute() {\n  uv_mutex_lock(&s7client->mutex);\n\n  switch (caller) {\n  case CONNECTTO:\n      returnValue = s7client->snap7Client->ConnectTo(\n          **static_cast<Nan::Utf8String*>(pData), int1, int2);\n      break;\n\n  case CONNECT:\n      returnValue = s7client->snap7Client->Connect();\n      break;\n\n  case READAREA:\n      returnValue = s7client->snap7Client->ReadArea(int1, int2, int3, int4\n        , int5, pData);\n      break;\n\n  case WRITEAREA:\n      returnValue = s7client->snap7Client->WriteArea(int1, int2, int3, int4\n        , int5, pData);\n      break;\n\n  case READMULTI:\n      returnValue = s7client->snap7Client->ReadMultiVars(\n          static_cast<PS7DataItem>(pData), int1);\n      break;\n\n  case WRITEMULTI:\n      returnValue = s7client->snap7Client->WriteMultiVars(\n          static_cast<PS7DataItem>(pData), int1);\n      break;\n\n  case PLCSTATUS:\n      returnValue = s7client->snap7Client->PlcStatus();\n      if ((returnValue == S7CpuStatusUnknown) ||\n          (returnValue == S7CpuStatusStop) ||\n          (returnValue == S7CpuStatusRun)) {\n        int1 = returnValue;\n        returnValue = 0;\n      }\n      break;\n\n  case CLEARSESSIONPW:\n      returnValue = s7client->snap7Client->ClearSessionPassword();\n      break;\n\n  case SETSESSIONPW:\n      returnValue = s7client->snap7Client->SetSessionPassword(\n          **static_cast<Nan::Utf8String*>(pData));\n      break;\n\n  case GETPROTECTION:\n      returnValue = s7client->snap7Client->GetProtection(\n          static_cast<PS7Protection>(pData));\n      break;\n\n  case PLCSTOP:\n      returnValue = s7client->snap7Client->PlcStop();\n      break;\n\n  case PLCCOLDSTART:\n      returnValue = s7client->snap7Client->PlcColdStart();\n      break;\n\n  case PLCHOTSTART:\n      returnValue = s7client->snap7Client->PlcHotStart();\n      break;\n\n  case GETCPINFO:\n      returnValue = s7client->snap7Client->GetCpInfo(\n          static_cast<PS7CpInfo>(pData));\n      break;\n\n  case GETCPUINFO:\n      returnValue = s7client->snap7Client->GetCpuInfo(\n          static_cast<PS7CpuInfo>(pData));\n      break;\n\n  case GETORDERCODE:\n      returnValue = s7client->snap7Client->GetOrderCode(\n          static_cast<PS7OrderCode>(pData));\n      break;\n\n  case SETPLCSYSTEMDATETIME:\n      returnValue = s7client->snap7Client->SetPlcSystemDateTime();\n      break;\n\n  case GETPLCDATETIME:\n      returnValue = s7client->snap7Client->GetPlcDateTime(\n          static_cast<tm*>(pData));\n      break;\n\n  case SETPLCDATETIME:\n      returnValue = s7client->snap7Client->SetPlcDateTime(\n          static_cast<tm*>(pData));\n      break;\n\n  case COMPRESS:\n      returnValue = s7client->snap7Client->Compress(int1);\n      break;\n\n  case COPYRAMTOROM:\n      returnValue = s7client->snap7Client->CopyRamToRom(int1);\n      break;\n\n  case DBFILL:\n      returnValue = s7client->snap7Client->DBFill(int1, int2);\n      break;\n\n  case DBGET:\n      returnValue = s7client->snap7Client->DBGet(int1, pData, &int2);\n      break;\n\n  case DELETEBLOCK:\n      returnValue = s7client->snap7Client->Delete(int1, int2);\n      break;\n\n  case DOWNLOAD:\n      returnValue = s7client->snap7Client->Download(int1, pData, int2);\n      break;\n\n  case FULLUPLOAD:\n      returnValue = s7client->snap7Client->FullUpload(int1, int2, pData, &int3);\n      break;\n\n  case UPLOAD:\n      returnValue = s7client->snap7Client->Upload(int1, int2, pData, &int3);\n      break;\n\n  case LISTBLOCKSOFTYPE:\n      returnValue = s7client->snap7Client->ListBlocksOfType(int1\n        , static_cast<PS7BlocksOfType>(pData), &int2);\n      break;\n\n  case GETAGBLOCKINFO:\n      returnValue = s7client->snap7Client->GetAgBlockInfo(int1, int2\n        , static_cast<PS7BlockInfo>(pData));\n      break;\n\n  case LISTBLOCKS:\n      returnValue = s7client->snap7Client->ListBlocks(\n          static_cast<PS7BlocksList>(pData));\n      break;\n\n  case READSZLLIST:\n      returnValue = s7client->snap7Client->ReadSZLList(\n          static_cast<PS7SZLList>(pData), &int1);\n      break;\n\n  case READSZL:\n      returnValue = s7client->snap7Client->ReadSZL(int1, int2\n        , static_cast<PS7SZL>(pData), &int3);\n      break;\n  }\n\n  uv_mutex_unlock(&s7client->mutex);\n}\n\nvoid IOWorker::HandleOKCallback() {\n  Nan::HandleScope scope;\n\n  v8::Local<v8::Value> argv1[1];\n  v8::Local<v8::Value> argv2[2];\n\n  if (returnValue == 0) {\n    argv2[0] = argv1[0] = Nan::Null();\n  } else {\n    argv2[0] = argv1[0] = Nan::New<v8::Integer>(returnValue);\n  }\n\n  switch (caller) {\n  case CONNECTTO:\n  case SETSESSIONPW:\n      delete static_cast<Nan::Utf8String*>(pData);\n      callback->Call(1, argv1, async_resource);\n      break;\n\n  case CONNECT:\n  case WRITEAREA:\n  case CLEARSESSIONPW:\n  case PLCSTOP:\n  case PLCCOLDSTART:\n  case PLCHOTSTART:\n  case SETPLCSYSTEMDATETIME:\n  case COPYRAMTOROM:\n  case COMPRESS:\n  case DBFILL:\n  case DELETEBLOCK:\n  case DOWNLOAD:\n      callback->Call(1, argv1, async_resource);\n      break;\n\n  case READAREA:\n    if (returnValue == 0) {\n      argv2[1] = Nan::NewBuffer(\n          static_cast<char*>(pData)\n        , int4 * s7client->GetByteCountFromWordLen(int5)\n        , S7Client::FreeCallback,\n        NULL).ToLocalChecked();\n    } else {\n      argv2[1] = Nan::Null();\n      delete[] static_cast<char*>(pData);\n    }\n    callback->Call(2, argv2, async_resource);\n    break;\n\n  case READMULTI:\n      if (returnValue == 0) {\n        argv2[1] = s7client->S7DataItemToArray(static_cast<PS7DataItem>(pData)\n          , int1, true);\n      } else {\n        for (int i = 0; i < int1; i++) {\n          delete[] static_cast<char*>(static_cast<PS7DataItem>(pData)[i].pdata);\n        }\n        delete[] static_cast<PS7DataItem>(pData);\n        argv2[1] = Nan::Null();\n      }\n      callback->Call(2, argv2, async_resource);\n      break;\n\n  case WRITEMULTI:\n      if (returnValue == 0) {\n        argv2[1] = s7client->S7DataItemToArray(static_cast<PS7DataItem>(pData)\n          , int1, false);\n      } else {\n        delete[] static_cast<PS7DataItem>(pData);\n        argv2[1] = Nan::Null();\n      }\n      callback->Call(2, argv2, async_resource);\n      break;\n\n  case GETPROTECTION:\n      if (returnValue == 0) {\n        argv2[1] = s7client->S7ProtectionToObject(\n          static_cast<PS7Protection>(pData));\n      } else {\n        argv2[1] = Nan::Null();\n      }\n      delete static_cast<PS7Protection>(pData);\n      callback->Call(2, argv2, async_resource);\n      break;\n\n  case GETCPINFO:\n      if (returnValue == 0) {\n        argv2[1] = s7client->S7CpInfoToObject(\n          static_cast<PS7CpInfo>(pData));\n      } else {\n        argv2[1] = Nan::Null();\n      }\n      delete static_cast<PS7CpInfo>(pData);\n      callback->Call(2, argv2, async_resource);\n      break;\n\n  case GETCPUINFO:\n      if (returnValue == 0) {\n        argv2[1] = s7client->S7CpuInfoToObject(\n          static_cast<PS7CpuInfo>(pData));\n      } else {\n        argv2[1] = Nan::Null();\n      }\n      delete static_cast<PS7CpuInfo>(pData);\n      callback->Call(2, argv2, async_resource);\n      break;\n\n  case GETORDERCODE:\n      if (returnValue == 0) {\n        argv2[1] = s7client->S7OrderCodeToObject(\n          static_cast<PS7OrderCode>(pData));\n      } else {\n        argv2[1] = Nan::Null();\n      }\n      delete static_cast<PS7OrderCode>(pData);\n      callback->Call(2, argv2, async_resource);\n      break;\n\n  case GETPLCDATETIME:\n      if (returnValue == 0) {\n        double timestamp = static_cast<double>(mktime(static_cast<tm*>(pData)));\n        argv2[1] = Nan::New<v8::Date>(timestamp * 1000).ToLocalChecked();\n      } else {\n        argv2[1] = Nan::Null();\n      }\n      delete static_cast<tm*>(pData);\n      callback->Call(2, argv2, async_resource);\n      break;\n\n  case SETPLCDATETIME:\n      delete static_cast<tm*>(pData);\n      callback->Call(1, argv1, async_resource);\n      break;\n\n  case PLCSTATUS:\n      if (returnValue == 0) {\n        argv2[1] = Nan::New<v8::Integer>(int1);\n      } else {\n        argv2[1] = Nan::Null();\n      }\n      callback->Call(2, argv2, async_resource);\n      break;\n\n  case DBGET:\n      if (returnValue == 0) {\n        argv2[1] = Nan::NewBuffer(\n            static_cast<char*>(pData)\n          , int2\n          , S7Client::FreeCallback\n          , NULL).ToLocalChecked();\n      } else {\n        argv2[1] = Nan::Null();\n        delete[] static_cast<char*>(pData);\n      }\n      callback->Call(2, argv2, async_resource);\n      break;\n\n  case FULLUPLOAD:\n  case UPLOAD:\n      if (returnValue == 0) {\n        argv2[1] = Nan::NewBuffer(\n            static_cast<char*>(pData)\n          , int3\n          , S7Client::FreeCallback\n          , NULL).ToLocalChecked();\n      } else {\n        argv2[1] = Nan::Null();\n        delete[] static_cast<char*>(pData);\n      }\n      callback->Call(2, argv2, async_resource);\n      break;\n\n  case LISTBLOCKSOFTYPE:\n      if (returnValue == 0) {\n        argv2[1] = s7client->S7BlocksOfTypeToArray(\n            static_cast<PS7BlocksOfType>(pData), int2);\n      } else {\n        argv2[1] = Nan::Null();\n      }\n      delete[] static_cast<PS7BlocksOfType>(pData);\n      callback->Call(2, argv2, async_resource);\n      break;\n\n  case GETAGBLOCKINFO:\n      if (returnValue == 0) {\n        v8::Local<v8::Object> block_info = s7client->S7BlockInfoToObject(\n            static_cast<PS7BlockInfo>(pData));\n        argv2[1] = block_info;\n      } else {\n        argv2[1] = Nan::Null();\n      }\n      delete static_cast<PS7BlockInfo>(pData);\n      callback->Call(2, argv2, async_resource);\n      break;\n\n  case LISTBLOCKS:\n      if (returnValue == 0) {\n        v8::Local<v8::Object> blocks_list = s7client->S7BlocksListToObject(\n            static_cast<PS7BlocksList>(pData));\n        argv2[1] = blocks_list;\n      } else {\n        argv2[1] = Nan::Null();\n      }\n      delete static_cast<PS7BlocksList>(pData);\n      callback->Call(2, argv2, async_resource);\n      break;\n\n  case READSZLLIST:\n      if (returnValue == 0) {\n        v8::Local<v8::Array> szl_list = s7client->S7SZLListToArray(\n            static_cast<PS7SZLList>(pData), int1);\n        argv2[1] = szl_list;\n      } else {\n        argv2[1] = Nan::Null();\n      }\n      delete static_cast<PS7SZLList>(pData);\n      callback->Call(2, argv2, async_resource);\n      break;\n\n  case READSZL:\n      if (returnValue == 0) {\n        argv2[1] = Nan::NewBuffer(\n            reinterpret_cast<char*>(static_cast<PS7SZL>(pData))\n          , int3\n          , S7Client::FreeCallbackSZL\n          , NULL).ToLocalChecked();\n      } else {\n        argv2[1] = Nan::Null();\n        delete static_cast<PS7SZL>(pData);\n      }\n      callback->Call(2, argv2, async_resource);\n      break;\n  }\n}\n\nNAN_METHOD(S7Client::ReadArea) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (info.Length() < 5)\n    return Nan::ThrowTypeError(\"Wrong number of Arguments\");\n\n  if (!info[0]->IsInt32() || !info[1]->IsInt32() ||\n      !info[2]->IsInt32() || !info[3]->IsInt32() ||\n      !info[4]->IsInt32())\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n\n  int amount = Nan::To<int32_t>(info[3]).FromJust();\n  int byteCount = s7client->GetByteCountFromWordLen(Nan::To<int32_t>(info[4]).FromJust());\n  int size = amount * byteCount;\n  char *bufferData = new char[size];\n\n  if (!info[5]->IsFunction()) {\n    int returnValue = s7client->snap7Client->ReadArea(\n\t\tNan::To<int32_t>(info[0]).FromJust(), Nan::To<int32_t>(info[1]).FromJust()\n      , Nan::To<int32_t>(info[2]).FromJust(), Nan::To<int32_t>(info[3]).FromJust()\n      , Nan::To<int32_t>(info[4]).FromJust(), bufferData);\n\n    if (returnValue == 0) {\n      v8::Local<v8::Object> ret = Nan::NewBuffer(\n          bufferData\n        , size\n        , S7Client::FreeCallback\n        , NULL).ToLocalChecked();\n      info.GetReturnValue().Set(ret);\n    } else {\n      delete[] bufferData;\n      info.GetReturnValue().Set(Nan::False());\n    }\n\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[5].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, READAREA\n      , bufferData, Nan::To<int32_t>(info[0]).FromJust(), Nan::To<int32_t>(info[1]).FromJust()\n      , Nan::To<int32_t>(info[2]).FromJust(), Nan::To<int32_t>(info[3]).FromJust(), Nan::To<int32_t>(info[4]).FromJust()));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nNAN_METHOD(S7Client::WriteArea) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (info.Length() < 6)\n    return Nan::ThrowTypeError(\"Wrong number of Arguments\");\n\n  if (!info[0]->IsInt32() || !info[1]->IsInt32() ||\n      !info[2]->IsInt32() || !info[3]->IsInt32() ||\n      !info[4]->IsInt32() || !node::Buffer::HasInstance(info[5]))\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n\n  if (!info[6]->IsFunction()) {\n    info.GetReturnValue().Set(Nan::New<v8::Boolean>(\n      s7client->snap7Client->WriteArea(Nan::To<int32_t>(info[0]).FromJust()\n        , Nan::To<int32_t>(info[1]).FromJust(), Nan::To<int32_t>(info[2]).FromJust()\n        , Nan::To<int32_t>(info[3]).FromJust(), Nan::To<int32_t>(info[4]).FromJust()\n        , node::Buffer::Data(info[5].As<v8::Object>())) == 0));\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[6].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, WRITEAREA\n      , node::Buffer::Data(info[5].As<v8::Object>()), Nan::To<int32_t>(info[0]).FromJust()\n      , Nan::To<int32_t>(info[1]).FromJust(), Nan::To<int32_t>(info[2]).FromJust(), Nan::To<int32_t>(info[3]).FromJust()\n      , Nan::To<int32_t>(info[4]).FromJust()));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nNAN_METHOD(S7Client::ReadMultiVars) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (info.Length() < 1) {\n    return Nan::ThrowTypeError(\"Wrong number of arguments\");\n  }\n\n  if (!info[0]->IsArray()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  v8::Local<v8::Array> data_arr = v8::Local<v8::Array>::Cast(info[0]);\n  int len = data_arr->Length();\n  if (len == 0) {\n    return Nan::ThrowTypeError(\"Array needs at least 1 item\");\n  } else if (len > MaxVars) {\n    std::stringstream err;\n    err << \"Array exceeds max variables (\" << MaxVars\n        << \") that can be transferred with ReadMultiVars()\";\n    return Nan::ThrowTypeError(err.str().c_str());\n  }\n\n  for (int i = 0; i < len; i++) {\n    if (!Nan::Get(data_arr, i).ToLocalChecked()->IsObject()) {\n      return Nan::ThrowTypeError(\"Wrong argument structure\");\n    } else {\n      v8::Local<v8::Object> data_obj = Nan::To<v8::Object>(Nan::Get(data_arr, i).ToLocalChecked()).ToLocalChecked();\n      if (!Nan::Has(data_obj, Nan::New<v8::String>(\"Area\").ToLocalChecked()).FromJust() ||\n          !Nan::Has(data_obj, Nan::New<v8::String>(\"WordLen\").ToLocalChecked()).FromJust() ||\n          !Nan::Has(data_obj, Nan::New<v8::String>(\"Start\").ToLocalChecked()).FromJust() ||\n          !Nan::Has(data_obj, Nan::New<v8::String>(\"Amount\").ToLocalChecked()).FromJust()) {\n        return Nan::ThrowTypeError(\"Wrong argument structure\");\n      } else if (!Nan::Get(data_obj, Nan::New<v8::String>(\"Area\").ToLocalChecked()).ToLocalChecked()->IsInt32() ||\n                 !Nan::Get(data_obj, Nan::New<v8::String>(\"WordLen\").ToLocalChecked()).ToLocalChecked()->IsInt32() ||\n                 !Nan::Get(data_obj, Nan::New<v8::String>(\"Start\").ToLocalChecked()).ToLocalChecked()->IsInt32() ||\n                 !Nan::Get(data_obj, Nan::New<v8::String>(\"Amount\").ToLocalChecked()).ToLocalChecked()->IsInt32()) {\n        return Nan::ThrowTypeError(\"Wrong argument structure\");\n      } else if (Nan::To<int32_t>(Nan::Get(data_obj, Nan::New<v8::String>(\"Area\").ToLocalChecked()).ToLocalChecked()).FromJust() == S7AreaDB) {\n        if (!Nan::Has(data_obj, Nan::New<v8::String>(\"DBNumber\").ToLocalChecked()).FromJust()) {\n          return Nan::ThrowTypeError(\"Wrong argument structure\");\n        }\n      } else {\n        Nan::Set(data_obj, Nan::New<v8::String>(\"DBNumber\").ToLocalChecked(), Nan::New<v8::Integer>(0));\n      }\n    }\n  }\n\n  PS7DataItem Items = new TS7DataItem[len];\n  v8::Local<v8::Object> data_obj;\n  int byteCount, size;\n\n  for (int i = 0; i < len; i++) {\n    data_obj = Nan::To<v8::Object>(Nan::Get(data_arr, i).ToLocalChecked()).ToLocalChecked();\n\n    Items[i].Area = Nan::To<int32_t>(Nan::Get(data_obj,\n      Nan::New<v8::String>(\"Area\").ToLocalChecked()).ToLocalChecked()).FromJust();\n    Items[i].WordLen = Nan::To<int32_t>(Nan::Get(data_obj,\n      Nan::New<v8::String>(\"WordLen\").ToLocalChecked()).ToLocalChecked()).FromJust();\n    Items[i].DBNumber = Nan::To<int32_t>(Nan::Get(data_obj,\n      Nan::New<v8::String>(\"DBNumber\").ToLocalChecked()).ToLocalChecked()).FromJust();\n    Items[i].Start = Nan::To<int32_t>(Nan::Get(data_obj,\n      Nan::New<v8::String>(\"Start\").ToLocalChecked()).ToLocalChecked()).FromJust();\n    Items[i].Amount = Nan::To<int32_t>(Nan::Get(data_obj,\n      Nan::New<v8::String>(\"Amount\").ToLocalChecked()).ToLocalChecked()).FromJust();\n\n    byteCount = s7client->GetByteCountFromWordLen(Items[i].WordLen);\n    size = Items[i].Amount * byteCount;\n    Items[i].pdata = new char[size];\n  }\n\n  if (!info[1]->IsFunction()) {\n    int returnValue = s7client->snap7Client->ReadMultiVars(Items, len);\n\n    if (returnValue == 0) {\n      info.GetReturnValue().Set(s7client->S7DataItemToArray(Items, len, true));\n    } else {\n      for (int i = 0; i < len; i++) {\n        delete[] static_cast<char*>(Items[i].pdata);\n      }\n      delete[] Items;\n      info.GetReturnValue().Set(Nan::False());\n    }\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[1].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, READMULTI\n      , Items, len));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nv8::Local<v8::Array> S7Client::S7DataItemToArray(\n    PS7DataItem Items\n  , int len\n  , bool readMulti\n) {\n  Nan::EscapableHandleScope scope;\n\n  v8::Local<v8::Array> res_arr = Nan::New<v8::Array>(len);\n  v8::Local<v8::Object> res_obj;\n  int byteCount, size;\n\n  for (int i = 0; i < len; i++) {\n    res_obj = Nan::New<v8::Object>();\n    Nan::Set(res_obj, Nan::New<v8::String>(\"Result\").ToLocalChecked()\n      , Nan::New<v8::Integer>(Items[i].Result));\n\n    if (readMulti == true) {\n      if (Items[i].Result == 0) {\n        byteCount = S7Client::GetByteCountFromWordLen(Items[i].WordLen);\n        size = byteCount * Items[i].Amount;\n        Nan::Set(\n            res_obj\n          , Nan::New<v8::String>(\"Data\").ToLocalChecked()\n          , Nan::NewBuffer(\n              static_cast<char*>(Items[i].pdata)\n            , size\n            , S7Client::FreeCallback\n            , NULL).ToLocalChecked());\n      } else {\n        delete[] static_cast<char*>(Items[i].pdata);\n        Nan::Set(res_obj, Nan::New<v8::String>(\"Data\").ToLocalChecked(), Nan::Null());\n      }\n    }\n    Nan::Set(res_arr, i, res_obj);\n  }\n  delete[] Items;\n\n  return scope.Escape(res_arr);\n}\n\nNAN_METHOD(S7Client::WriteMultiVars) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (info.Length() < 1) {\n    return Nan::ThrowTypeError(\"Wrong number of arguments\");\n  }\n\n  if (!info[0]->IsArray()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  v8::Local<v8::Array> data_arr = v8::Local<v8::Array>::Cast(info[0]);\n  int len = data_arr->Length();\n  if (len == 0) {\n    return Nan::ThrowTypeError(\"Array needs at least 1 item\");\n  } else if (len > MaxVars) {\n    std::stringstream err;\n    err << \"Array exceeds max variables (\" << MaxVars\n        << \") that can be transferred with WriteMultiVars()\";\n    return Nan::ThrowTypeError(err.str().c_str());\n  }\n\n  for (int i = 0; i < len; i++) {\n    if (!Nan::Get(data_arr, i).ToLocalChecked()->IsObject()) {\n      return Nan::ThrowTypeError(\"Wrong argument structure\");\n    } else {\n      v8::Local<v8::Object> data_obj = Nan::To<v8::Object>(Nan::Get(data_arr, i).ToLocalChecked()).ToLocalChecked();\n      if (!Nan::Has(data_obj, Nan::New<v8::String>(\"Area\").ToLocalChecked()).FromJust() ||\n          !Nan::Has(data_obj, Nan::New<v8::String>(\"WordLen\").ToLocalChecked()).FromJust() ||\n          !Nan::Has(data_obj, Nan::New<v8::String>(\"Start\").ToLocalChecked()).FromJust() ||\n          !Nan::Has(data_obj, Nan::New<v8::String>(\"Amount\").ToLocalChecked()).FromJust() ||\n          !Nan::Has(data_obj, Nan::New<v8::String>(\"Data\").ToLocalChecked()).FromJust()) {\n        return Nan::ThrowTypeError(\"Wrong argument structure\");\n      } else if (!Nan::Get(data_obj, Nan::New<v8::String>(\"Area\").ToLocalChecked()).ToLocalChecked()->IsInt32() ||\n                 !Nan::Get(data_obj, Nan::New<v8::String>(\"WordLen\").ToLocalChecked()).ToLocalChecked()->IsInt32() ||\n                 !Nan::Get(data_obj, Nan::New<v8::String>(\"Start\").ToLocalChecked()).ToLocalChecked()->IsInt32() ||\n                 !Nan::Get(data_obj, Nan::New<v8::String>(\"Amount\").ToLocalChecked()).ToLocalChecked()->IsInt32() ||\n                 !node::Buffer::HasInstance(Nan::Get(data_obj, Nan::New<v8::String>(\"Data\").ToLocalChecked()).ToLocalChecked())) {\n        return Nan::ThrowTypeError(\"Wrong argument structure\");\n      } else if (Nan::To<int32_t>(Nan::Get(data_obj, Nan::New<v8::String>(\"Area\").ToLocalChecked()).ToLocalChecked()).FromJust() == S7AreaDB) {\n        if (!Nan::Has(data_obj, Nan::New<v8::String>(\"DBNumber\").ToLocalChecked()).FromJust()) {\n          return Nan::ThrowTypeError(\"Wrong argument structure\");\n        }\n      } else {\n        Nan::Set(data_obj, Nan::New<v8::String>(\"DBNumber\").ToLocalChecked(), Nan::New<v8::Integer>(0));\n      }\n    }\n  }\n\n  PS7DataItem Items = new TS7DataItem[len];\n  v8::Local<v8::Object> data_obj;\n  for (int i = 0; i < len; i++) {\n    data_obj = Nan::To<v8::Object>(Nan::Get(data_arr, i).ToLocalChecked()).ToLocalChecked();\n\n    Items[i].Area = Nan::To<int32_t>(Nan::Get(data_obj,\n      Nan::New<v8::String>(\"Area\").ToLocalChecked()).ToLocalChecked()).FromJust();\n    Items[i].WordLen = Nan::To<int32_t>(Nan::Get(data_obj,\n      Nan::New<v8::String>(\"WordLen\").ToLocalChecked()).ToLocalChecked()).FromJust();\n    Items[i].DBNumber = Nan::To<int32_t>(Nan::Get(data_obj,\n      Nan::New<v8::String>(\"DBNumber\").ToLocalChecked()).ToLocalChecked()).FromJust();\n    Items[i].Start = Nan::To<int32_t>(Nan::Get(data_obj,\n      Nan::New<v8::String>(\"Start\").ToLocalChecked()).ToLocalChecked()).FromJust();\n    Items[i].Amount = Nan::To<int32_t>(Nan::Get(data_obj,\n      Nan::New<v8::String>(\"Amount\").ToLocalChecked()).ToLocalChecked()).FromJust();\n    Items[i].pdata = node::Buffer::Data(Nan::Get(data_obj,\n      Nan::New<v8::String>(\"Data\").ToLocalChecked()).ToLocalChecked().As<v8::Object>());\n  }\n\n  if (!info[1]->IsFunction()) {\n    int returnValue = s7client->snap7Client->WriteMultiVars(Items, len);\n\n    if (returnValue == 0) {\n      info.GetReturnValue().Set(s7client->S7DataItemToArray(Items, len, false));\n    } else {\n      delete[] Items;\n      info.GetReturnValue().Set(Nan::False());\n    }\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[1].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, WRITEMULTI\n      , Items, len));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\n// Directory functions\nNAN_METHOD(S7Client::ListBlocks) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  PS7BlocksList BlocksList = new TS7BlocksList;\n  if (!info[0]->IsFunction()) {\n    int returnValue = s7client->snap7Client->ListBlocks(BlocksList);\n\n    v8::Local<v8::Object> blocks_list = s7client->S7BlocksListToObject(\n        BlocksList);\n\n    if (returnValue == 0) {\n      delete BlocksList;\n      info.GetReturnValue().Set(blocks_list);\n    } else {\n      delete BlocksList;\n      info.GetReturnValue().Set(Nan::False());\n    }\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[0].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, LISTBLOCKS\n      , BlocksList));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nv8::Local<v8::Object> S7Client::S7BlocksListToObject(\n    PS7BlocksList BlocksList\n) {\n  Nan::EscapableHandleScope scope;\n\n  v8::Local<v8::Object> blocks_list = Nan::New<v8::Object>();\n  Nan::Set(blocks_list, Nan::New<v8::String>(\"OBCount\").ToLocalChecked()\n    , Nan::New<v8::Number>(BlocksList->OBCount));\n  Nan::Set(blocks_list, Nan::New<v8::String>(\"FBCount\").ToLocalChecked()\n    , Nan::New<v8::Number>(BlocksList->FBCount));\n  Nan::Set(blocks_list, Nan::New<v8::String>(\"FCCount\").ToLocalChecked()\n    , Nan::New<v8::Number>(BlocksList->FCCount));\n  Nan::Set(blocks_list, Nan::New<v8::String>(\"SFBCount\").ToLocalChecked()\n    , Nan::New<v8::Number>(BlocksList->SFBCount));\n  Nan::Set(blocks_list, Nan::New<v8::String>(\"SFCCount\").ToLocalChecked()\n    , Nan::New<v8::Number>(BlocksList->SFCCount));\n  Nan::Set(blocks_list, Nan::New<v8::String>(\"DBCount\").ToLocalChecked()\n    , Nan::New<v8::Number>(BlocksList->DBCount));\n  Nan::Set(blocks_list, Nan::New<v8::String>(\"SDBCount\").ToLocalChecked()\n    , Nan::New<v8::Number>(BlocksList->SDBCount));\n\n  return scope.Escape(blocks_list);\n}\n\n\nNAN_METHOD(S7Client::GetAgBlockInfo) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (!info[0]->IsInt32() || !info[1]->IsInt32()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  PS7BlockInfo BlockInfo = new TS7BlockInfo;\n  if (!info[2]->IsFunction()) {\n    int returnValue = s7client->snap7Client->GetAgBlockInfo(\n\t\tNan::To<int32_t>(info[0]).FromJust(), Nan::To<int32_t>(info[1]).FromJust(), BlockInfo);\n\n    if (returnValue == 0) {\n      v8::Local<v8::Object> block_info = s7client->S7BlockInfoToObject(\n          BlockInfo);\n\n      delete BlockInfo;\n      info.GetReturnValue().Set(block_info);\n    } else {\n      delete BlockInfo;\n      info.GetReturnValue().Set(Nan::False());\n    }\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[2].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, GETAGBLOCKINFO\n      , BlockInfo, Nan::To<int32_t>(info[0]).FromJust(), Nan::To<int32_t>(info[1]).FromJust()));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nNAN_METHOD(S7Client::GetPgBlockInfo) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (!node::Buffer::HasInstance(info[0])) {\n    return Nan::ThrowTypeError(\"Argument should be a Buffer\");\n  }\n\n  PS7BlockInfo BlockInfo = new TS7BlockInfo;\n\n  int returnValue = s7client->snap7Client->GetPgBlockInfo(\n    node::Buffer::Data(info[0].As<v8::Object>()), BlockInfo\n    , static_cast<int>(node::Buffer::Length(info[0].As<v8::Object>())));\n\n  if (returnValue == 0) {\n    v8::Local<v8::Object> block_info = s7client->S7BlockInfoToObject(BlockInfo);\n    delete BlockInfo;\n    info.GetReturnValue().Set(block_info);\n  } else {\n    delete BlockInfo;\n    info.GetReturnValue().Set(Nan::False());\n  }\n}\n\nv8::Local<v8::Object> S7Client::S7BlockInfoToObject(PS7BlockInfo BlockInfo) {\n  Nan::EscapableHandleScope scope;\n\n  v8::Local<v8::Object> block_info = Nan::New<v8::Object>();\n  Nan::Set(block_info, Nan::New<v8::String>(\"BlkType\").ToLocalChecked()\n    , Nan::New<v8::Number>(BlockInfo->BlkType));\n  Nan::Set(block_info, Nan::New<v8::String>(\"BlkNumber\").ToLocalChecked()\n    , Nan::New<v8::Number>(BlockInfo->BlkNumber));\n  Nan::Set(block_info, Nan::New<v8::String>(\"BlkLang\").ToLocalChecked()\n    , Nan::New<v8::Number>(BlockInfo->BlkLang));\n  Nan::Set(block_info, Nan::New<v8::String>(\"BlkFlags\").ToLocalChecked()\n    , Nan::New<v8::Number>(BlockInfo->BlkFlags));\n  Nan::Set(block_info, Nan::New<v8::String>(\"MC7Size\").ToLocalChecked()\n    , Nan::New<v8::Number>(BlockInfo->MC7Size));\n  Nan::Set(block_info, Nan::New<v8::String>(\"LoadSize\").ToLocalChecked()\n    , Nan::New<v8::Number>(BlockInfo->LoadSize));\n  Nan::Set(block_info, Nan::New<v8::String>(\"LocalData\").ToLocalChecked()\n    , Nan::New<v8::Number>(BlockInfo->LocalData));\n  Nan::Set(block_info, Nan::New<v8::String>(\"SBBLength\").ToLocalChecked()\n    , Nan::New<v8::Number>(BlockInfo->SBBLength));\n  Nan::Set(block_info, Nan::New<v8::String>(\"CheckSum\").ToLocalChecked()\n    , Nan::New<v8::Number>(BlockInfo->CheckSum));\n  Nan::Set(block_info, Nan::New<v8::String>(\"Version\").ToLocalChecked()\n    , Nan::New<v8::Number>(BlockInfo->Version));\n  Nan::Set(block_info, Nan::New<v8::String>(\"CodeDate\").ToLocalChecked()\n    , Nan::New<v8::String>(BlockInfo->CodeDate).ToLocalChecked());\n  Nan::Set(block_info, Nan::New<v8::String>(\"IntfDate\").ToLocalChecked()\n    , Nan::New<v8::String>(BlockInfo->IntfDate).ToLocalChecked());\n  Nan::Set(block_info, Nan::New<v8::String>(\"Author\").ToLocalChecked()\n    , Nan::New<v8::String>(BlockInfo->Author).ToLocalChecked());\n  Nan::Set(block_info, Nan::New<v8::String>(\"Family\").ToLocalChecked()\n    , Nan::New<v8::String>(BlockInfo->Family).ToLocalChecked());\n  Nan::Set(block_info, Nan::New<v8::String>(\"Header\").ToLocalChecked()\n    , Nan::New<v8::String>(BlockInfo->Header).ToLocalChecked());\n\n  return scope.Escape(block_info);\n}\n\nNAN_METHOD(S7Client::ListBlocksOfType) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (!info[0]->IsInt32()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  int BlockNum = sizeof(TS7BlocksOfType) / sizeof(PS7BlocksOfType);\n  PS7BlocksOfType BlockList = new TS7BlocksOfType[BlockNum];\n  if (!info[1]->IsFunction()) {\n    int returnValue = s7client->snap7Client->ListBlocksOfType(\n\t\tNan::To<int32_t>(info[0]).FromJust(), BlockList, &BlockNum);\n\n    if (returnValue == 0) {\n      v8::Local<v8::Array> block_list = s7client->S7BlocksOfTypeToArray(\n          BlockList, BlockNum);\n      delete[] BlockList;\n      info.GetReturnValue().Set(block_list);\n    } else {\n      delete[] BlockList;\n      info.GetReturnValue().Set(Nan::False());\n    }\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[1].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, LISTBLOCKSOFTYPE\n      , BlockList, Nan::To<int32_t>(info[0]).FromJust(), BlockNum));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nv8::Local<v8::Array> S7Client::S7BlocksOfTypeToArray(\n    PS7BlocksOfType BlocksList\n  , int count\n) {\n  Nan::EscapableHandleScope scope;\n\n  v8::Local<v8::Array> block_list = Nan::New<v8::Array>(count);\n  for (int i = 0; i < count; i++) {\n    Nan::Set(block_list, i, Nan::New<v8::Integer>((*BlocksList)[i]));\n  }\n\n  return scope.Escape(block_list);\n}\n\n// Blocks functions\nNAN_METHOD(S7Client::Upload) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (!info[0]->IsInt32() || !info[1]->IsInt32() || !info[2]->IsInt32()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  char *bufferData = new char[Nan::To<int32_t>(info[2]).FromJust()];\n  int size = Nan::To<int32_t>(info[2]).FromJust();\n  if (!info[3]->IsFunction()) {\n    int returnValue = s7client->snap7Client->Upload(\n\t\tNan::To<int32_t>(info[0]).FromJust(), Nan::To<int32_t>(info[1]).FromJust(), bufferData, &size);\n\n    if (returnValue == 0) {\n      v8::Local<v8::Object> ret_buf;\n      ret_buf = Nan::NewBuffer(\n          bufferData\n        , size\n        , S7Client::FreeCallback\n        , NULL).ToLocalChecked();\n      info.GetReturnValue().Set(ret_buf);\n    } else {\n      delete[] bufferData;\n      info.GetReturnValue().Set(Nan::False());\n    }\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[3].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, UPLOAD\n      , bufferData, Nan::To<int32_t>(info[0]).FromJust(), Nan::To<int32_t>(info[1]).FromJust(), size));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nNAN_METHOD(S7Client::FullUpload) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (!info[0]->IsInt32() || !info[1]->IsInt32() || !info[2]->IsInt32()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  int size = Nan::To<int32_t>(info[2]).FromJust();\n  char *bufferData = new char[size];\n  if (!info[3]->IsFunction()) {\n    int returnValue = s7client->snap7Client->FullUpload(\n\t\tNan::To<int32_t>(info[0]).FromJust(), Nan::To<int32_t>(info[1]).FromJust(), bufferData, &size);\n\n    if (returnValue == 0) {\n      v8::Local<v8::Object> ret_buf;\n      ret_buf = Nan::NewBuffer(\n          bufferData\n        , size\n        , S7Client::FreeCallback\n        , NULL).ToLocalChecked();\n      info.GetReturnValue().Set(ret_buf);\n    } else {\n      delete[] bufferData;\n      info.GetReturnValue().Set(Nan::False());\n    }\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[3].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, FULLUPLOAD\n      , bufferData, Nan::To<int32_t>(info[0]).FromJust(), Nan::To<int32_t>(info[1]).FromJust(), size));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nNAN_METHOD(S7Client::Download) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (!info[0]->IsInt32() || !node::Buffer::HasInstance(info[1])) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  if (!info[2]->IsFunction()) {\n    info.GetReturnValue().Set(Nan::New<v8::Boolean>(s7client->snap7Client->Download(\n\t\tNan::To<int32_t>(info[0]).FromJust(), node::Buffer::Data(info[1].As<v8::Object>())\n      , static_cast<int>(node::Buffer::Length(info[1].As<v8::Object>()))) == 0));\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[2].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, DOWNLOAD\n      , node::Buffer::Data(info[1].As<v8::Object>()), Nan::To<int32_t>(info[0]).FromJust()\n      , static_cast<int>(node::Buffer::Length(info[1].As<v8::Object>()))));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nNAN_METHOD(S7Client::Delete) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (!info[0]->IsInt32() || !info[1]->IsInt32()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  if (!info[2]->IsFunction()) {\n    info.GetReturnValue().Set(Nan::New<v8::Boolean>(s7client->snap7Client->Delete(\n\t\tNan::To<int32_t>(info[0]).FromJust(), Nan::To<int32_t>(info[1]).FromJust()) == 0));\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[2].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, DELETEBLOCK\n      , Nan::To<int32_t>(info[0]).FromJust(), Nan::To<int32_t>(info[1]).FromJust()));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nNAN_METHOD(S7Client::DBGet) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (!info[0]->IsInt32()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  int size = 65536;\n  char *bufferData = new char[size];\n  if (!info[1]->IsFunction()) {\n    int returnValue = s7client->snap7Client->DBGet(\n\t\tNan::To<int32_t>(info[0]).FromJust(), bufferData, &size);\n\n    if (returnValue == 0) {\n      v8::Local<v8::Object> ret_buf;\n      ret_buf = Nan::NewBuffer(\n          bufferData\n        , size\n        , S7Client::FreeCallback\n        , NULL).ToLocalChecked();\n      info.GetReturnValue().Set(ret_buf);\n    } else {\n      delete[] bufferData;\n      info.GetReturnValue().Set(Nan::False());\n    }\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[1].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, DBGET\n      , bufferData, Nan::To<int32_t>(info[0]).FromJust(), size));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nNAN_METHOD(S7Client::DBFill) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (!info[0]->IsInt32() || !(info[1]->IsInt32() || info[1]->IsString())) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  int fill;\n  if (info[1]->IsInt32()) {\n    fill = Nan::To<int32_t>(info[1]).FromJust();\n  } else {\n    Nan::Utf8String fillstr(info[1]);\n    fill = static_cast<int>(**fillstr);\n  }\n\n  if (!info[2]->IsFunction()) {\n    info.GetReturnValue().Set(Nan::New<v8::Boolean>(s7client->snap7Client->DBFill(\n\t\tNan::To<int32_t>(info[0]).FromJust(), fill) == 0));\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[2].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, DBFILL\n      , Nan::To<int32_t>(info[0]).FromJust(), fill));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\n// Date/Time functions\nNAN_METHOD(S7Client::GetPlcDateTime) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  tm *DateTime = new tm;\n  if (!info[0]->IsFunction()) {\n    int returnValue = s7client->snap7Client->GetPlcDateTime(DateTime);\n    double timestamp = static_cast<double>(mktime(DateTime));\n    delete DateTime;\n\n    if (returnValue == 0)\n      info.GetReturnValue().Set(Nan::New<v8::Date>(timestamp * 1000).ToLocalChecked());\n    else\n      info.GetReturnValue().Set(Nan::False());\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[0].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, GETPLCDATETIME\n      , DateTime));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nNAN_METHOD(S7Client::SetPlcDateTime) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (!(info[0]->IsObject() || info[0]->IsDate())) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  tm *DateTime = new tm;\n  if (info[0]->IsDate()) {\n    v8::Local<v8::Date> date = v8::Local<v8::Date>::Cast(Nan::To<v8::Object>(info[0]).ToLocalChecked());\n    time_t timestamp = static_cast<time_t>(Nan::To<double>(date).FromJust() / 1000);\n    *DateTime = *localtime(&timestamp);\n  } else {\n    v8::Local<v8::Object> date_time = Nan::To<v8::Object>(info[0]).ToLocalChecked();\n    DateTime->tm_year = Nan::To<int32_t>(Nan::Get(date_time,\n      Nan::New<v8::String>(\"year\").ToLocalChecked()).ToLocalChecked()).FromJust() - 1900;\n    DateTime->tm_mon = Nan::To<int32_t>(Nan::Get(date_time,\n      Nan::New<v8::String>(\"month\").ToLocalChecked()).ToLocalChecked()).FromJust();\n    DateTime->tm_mday = Nan::To<int32_t>(Nan::Get(date_time,\n      Nan::New<v8::String>(\"day\").ToLocalChecked()).ToLocalChecked()).FromJust();\n    DateTime->tm_hour = Nan::To<int32_t>(Nan::Get(date_time,\n      Nan::New<v8::String>(\"hours\").ToLocalChecked()).ToLocalChecked()).FromJust();\n    DateTime->tm_min = Nan::To<int32_t>(Nan::Get(date_time,\n      Nan::New<v8::String>(\"minutes\").ToLocalChecked()).ToLocalChecked()).FromJust();\n    DateTime->tm_sec = Nan::To<int32_t>(Nan::Get(date_time,\n      Nan::New<v8::String>(\"seconds\").ToLocalChecked()).ToLocalChecked()).FromJust();\n  }\n\n  if (!info[1]->IsFunction()) {\n    v8::Local<v8::Boolean> ret = Nan::New<v8::Boolean>(\n      s7client->snap7Client->SetPlcDateTime(DateTime) == 0);\n    delete DateTime;\n    info.GetReturnValue().Set(ret);\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[1].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, SETPLCDATETIME\n      , DateTime));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nNAN_METHOD(S7Client::SetPlcSystemDateTime) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (!info[0]->IsFunction()) {\n    info.GetReturnValue().Set(Nan::New<v8::Boolean>(\n      s7client->snap7Client->SetPlcSystemDateTime() == 0));\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[0].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, SETPLCSYSTEMDATETIME));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\n// System Info functions\nNAN_METHOD(S7Client::GetOrderCode) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  PS7OrderCode OrderCode = new TS7OrderCode;\n  if (!info[0]->IsFunction()) {\n    int returnValue = s7client->snap7Client->GetOrderCode(OrderCode);\n\n    if (returnValue == 0) {\n      v8::Local<v8::Object> order_code = s7client->S7OrderCodeToObject(OrderCode);\n      delete OrderCode;\n      info.GetReturnValue().Set(order_code);\n    } else {\n      delete OrderCode;\n      info.GetReturnValue().Set(Nan::False());\n    }\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[0].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, GETORDERCODE\n      , OrderCode));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nv8::Local<v8::Object> S7Client::S7OrderCodeToObject(PS7OrderCode OrderCode) {\n  Nan::EscapableHandleScope scope;\n\n  v8::Local<v8::Object> order_code = Nan::New<v8::Object>();\n  Nan::Set(order_code, Nan::New<v8::String>(\"Code\").ToLocalChecked()\n    , Nan::New<v8::String>(OrderCode->Code).ToLocalChecked());\n  Nan::Set(order_code, Nan::New<v8::String>(\"V1\").ToLocalChecked()\n    , Nan::New<v8::Number>(OrderCode->V1));\n  Nan::Set(order_code, Nan::New<v8::String>(\"V2\").ToLocalChecked()\n    , Nan::New<v8::Number>(OrderCode->V2));\n  Nan::Set(order_code, Nan::New<v8::String>(\"V3\").ToLocalChecked()\n    , Nan::New<v8::Number>(OrderCode->V3));\n\n  return scope.Escape(order_code);\n}\n\n\nNAN_METHOD(S7Client::GetCpuInfo) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  PS7CpuInfo CpuInfo = new TS7CpuInfo;\n  if (!info[0]->IsFunction()) {\n    int returnValue = s7client->snap7Client->GetCpuInfo(CpuInfo);\n\n    if (returnValue == 0) {\n      v8::Local<v8::Object> cpu_info = s7client->S7CpuInfoToObject(CpuInfo);\n      delete CpuInfo;\n      info.GetReturnValue().Set(cpu_info);\n    } else {\n      delete CpuInfo;\n      info.GetReturnValue().Set(Nan::False());\n    }\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[0].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, GETCPUINFO, CpuInfo));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nv8::Local<v8::Object> S7Client::S7CpuInfoToObject(PS7CpuInfo CpuInfo) {\n  Nan::EscapableHandleScope scope;\n\n  v8::Local<v8::Object> cpu_info = Nan::New<v8::Object>();\n  Nan::Set(cpu_info, Nan::New<v8::String>(\"ModuleTypeName\").ToLocalChecked()\n    , Nan::New<v8::String>(CpuInfo->ModuleTypeName).ToLocalChecked());\n  Nan::Set(cpu_info, Nan::New<v8::String>(\"SerialNumber\").ToLocalChecked()\n    , Nan::New<v8::String>(CpuInfo->SerialNumber).ToLocalChecked());\n  Nan::Set(cpu_info, Nan::New<v8::String>(\"ASName\").ToLocalChecked()\n    , Nan::New<v8::String>(CpuInfo->ASName).ToLocalChecked());\n  Nan::Set(cpu_info, Nan::New<v8::String>(\"Copyright\").ToLocalChecked()\n    , Nan::New<v8::String>(CpuInfo->Copyright).ToLocalChecked());\n  Nan::Set(cpu_info, Nan::New<v8::String>(\"ModuleName\").ToLocalChecked()\n    , Nan::New<v8::String>(CpuInfo->ModuleName).ToLocalChecked());\n\n  return scope.Escape(cpu_info);\n}\n\n\nNAN_METHOD(S7Client::GetCpInfo) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  PS7CpInfo CpInfo = new TS7CpInfo;\n  if (!info[0]->IsFunction()) {\n    int returnValue = s7client->snap7Client->GetCpInfo(CpInfo);\n\n    if (returnValue == 0) {\n      v8::Local<v8::Object> cp_info = s7client->S7CpInfoToObject(CpInfo);\n      delete CpInfo;\n      info.GetReturnValue().Set(cp_info);\n    } else {\n      delete CpInfo;\n      info.GetReturnValue().Set(Nan::False());\n    }\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[0].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, GETCPINFO, CpInfo));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nv8::Local<v8::Object> S7Client::S7CpInfoToObject(PS7CpInfo CpInfo) {\n  Nan::EscapableHandleScope scope;\n\n  v8::Local<v8::Object> cp_info = Nan::New<v8::Object>();\n  Nan::Set(cp_info, Nan::New<v8::String>(\"MaxPduLength\").ToLocalChecked()\n    , Nan::New<v8::Number>(CpInfo->MaxPduLengt));\n  Nan::Set(cp_info, Nan::New<v8::String>(\"MaxConnections\").ToLocalChecked()\n    , Nan::New<v8::Number>(CpInfo->MaxConnections));\n  Nan::Set(cp_info, Nan::New<v8::String>(\"MaxMpiRate\").ToLocalChecked()\n    , Nan::New<v8::Number>(CpInfo->MaxMpiRate));\n  Nan::Set(cp_info, Nan::New<v8::String>(\"MaxBusRate\").ToLocalChecked()\n    , Nan::New<v8::Number>(CpInfo->MaxBusRate));\n\n  return scope.Escape(cp_info);\n}\n\nNAN_METHOD(S7Client::ReadSZL) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (!(info[0]->IsInt32() || info[1]->IsInt32())) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  PS7SZL SZL = new TS7SZL;\n  int size = sizeof(TS7SZL);\n  if (!info[2]->IsFunction()) {\n    int returnValue = s7client->snap7Client->ReadSZL(Nan::To<int32_t>(info[0]).FromJust()\n      , Nan::To<int32_t>(info[1]).FromJust(), SZL, &size);\n\n    if (returnValue == 0) {\n      v8::Local<v8::Object> ret_buf;\n      ret_buf = Nan::NewBuffer(\n          reinterpret_cast<char*>(SZL)\n        , size\n        , S7Client::FreeCallbackSZL\n        , NULL).ToLocalChecked();\n\n      info.GetReturnValue().Set(ret_buf);\n    } else {\n      delete SZL;\n      info.GetReturnValue().Set(Nan::False());\n    }\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[2].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, READSZL, SZL\n      , Nan::To<int32_t>(info[0]).FromJust(), Nan::To<int32_t>(info[1]).FromJust(), size));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nNAN_METHOD(S7Client::ReadSZLList) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  PS7SZLList SZLList = new TS7SZLList;\n  int size = sizeof(TS7SZLList);\n  if (!info[0]->IsFunction()) {\n    int returnValue = s7client->snap7Client->ReadSZLList(SZLList, &size);\n\n    if (returnValue == 0) {\n      v8::Local<v8::Array> szl_list = s7client->S7SZLListToArray(SZLList, size);\n\n      delete SZLList;\n      info.GetReturnValue().Set(szl_list);\n    } else {\n      delete SZLList;\n      info.GetReturnValue().Set(Nan::False());\n    }\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[0].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, READSZLLIST, SZLList\n      , size));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nv8::Local<v8::Array> S7Client::S7SZLListToArray(PS7SZLList SZLList, int count) {\n  Nan::EscapableHandleScope scope;\n\n  v8::Local<v8::Array> szl_list = Nan::New<v8::Array>(count);\n  for (int i = 0; i < count; i++) {\n    Nan::Set(szl_list, i, Nan::New<v8::Integer>((*SZLList).List[i]));\n  }\n\n  return scope.Escape(szl_list);\n}\n\n// Control functions\nNAN_METHOD(S7Client::PlcHotStart) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (!info[0]->IsFunction()) {\n    info.GetReturnValue().Set(Nan::New<v8::Boolean>(\n      s7client->snap7Client->PlcHotStart() == 0));\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[0].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, PLCHOTSTART));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nNAN_METHOD(S7Client::PlcColdStart) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (!info[0]->IsFunction()) {\n    info.GetReturnValue().Set(Nan::New<v8::Boolean>(\n      s7client->snap7Client->PlcColdStart() == 0));\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[0].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, PLCCOLDSTART));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nNAN_METHOD(S7Client::PlcStop) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (!info[0]->IsFunction()) {\n    info.GetReturnValue().Set(Nan::New<v8::Boolean>(\n      s7client->snap7Client->PlcStop() == 0));\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[0].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, PLCSTOP));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nNAN_METHOD(S7Client::CopyRamToRom) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (!info[0]->IsInt32()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  if (!info[1]->IsFunction()) {\n    info.GetReturnValue().Set(Nan::New<v8::Boolean>(\n      s7client->snap7Client->CopyRamToRom(Nan::To<int32_t>(info[0]).FromJust()) == 0));\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[1].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, COPYRAMTOROM\n      , Nan::To<int32_t>(info[0]).FromJust()));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nNAN_METHOD(S7Client::Compress) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (!info[0]->IsInt32()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  if (!info[1]->IsFunction()) {\n    info.GetReturnValue().Set(Nan::New<v8::Boolean>(\n      s7client->snap7Client->Compress(Nan::To<int32_t>(info[0]).FromJust()) == 0));\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[1].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, COMPRESS\n      , Nan::To<int32_t>(info[0]).FromJust()));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\n// Security functions\nNAN_METHOD(S7Client::GetProtection) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  PS7Protection S7Protection = new TS7Protection;\n  if (!info[0]->IsFunction()) {\n    int returnValue = s7client->snap7Client->GetProtection(S7Protection);\n\n    if (returnValue == 0) {\n      v8::Local<v8::Object> protection = s7client->S7ProtectionToObject(\n        S7Protection);\n      delete S7Protection;\n      info.GetReturnValue().Set(protection);\n    } else {\n      delete S7Protection;\n      info.GetReturnValue().Set(Nan::False());\n    }\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[0].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, GETPROTECTION\n      , S7Protection));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nv8::Local<v8::Object> S7Client::S7ProtectionToObject(\n    PS7Protection S7Protection\n) {\n  Nan::EscapableHandleScope scope;\n\n  v8::Local<v8::Object> protection = Nan::New<v8::Object>();\n  Nan::Set(protection, Nan::New<v8::String>(\"sch_schal\").ToLocalChecked()\n    , Nan::New<v8::Number>(S7Protection->sch_schal));\n  Nan::Set(protection, Nan::New<v8::String>(\"sch_par\").ToLocalChecked()\n    , Nan::New<v8::Number>(S7Protection->sch_par));\n  Nan::Set(protection, Nan::New<v8::String>(\"sch_rel\").ToLocalChecked()\n    , Nan::New<v8::Number>(S7Protection->sch_rel));\n  Nan::Set(protection, Nan::New<v8::String>(\"bart_sch\").ToLocalChecked()\n    , Nan::New<v8::Number>(S7Protection->bart_sch));\n  Nan::Set(protection, Nan::New<v8::String>(\"anl_sch\").ToLocalChecked()\n    , Nan::New<v8::Number>(S7Protection->anl_sch));\n\n  return scope.Escape(protection);\n}\n\nNAN_METHOD(S7Client::SetSessionPassword) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (!info[0]->IsString()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  Nan::Utf8String *password = new Nan::Utf8String(info[0]);\n  if (!info[1]->IsFunction()) {\n    v8::Local<v8::Boolean> ret = Nan::New<v8::Boolean>(\n      s7client->snap7Client->SetSessionPassword(**password) == 0);\n    delete password;\n    info.GetReturnValue().Set(ret);\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[1].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, SETSESSIONPW\n      , password));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nNAN_METHOD(S7Client::ClearSessionPassword) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (!info[0]->IsFunction()) {\n    info.GetReturnValue().Set(Nan::New<v8::Boolean>(\n      s7client->snap7Client->ClearSessionPassword() == 0));\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[0].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, CLEARSESSIONPW));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\n// Properties\nNAN_METHOD(S7Client::ExecTime) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  int returnValue = s7client->snap7Client->ExecTime();\n  if (returnValue == errLibInvalidObject) {\n    info.GetReturnValue().Set(Nan::False());\n  } else {\n    info.GetReturnValue().Set(Nan::New<v8::Integer>(returnValue));\n  }\n}\n\nNAN_METHOD(S7Client::LastError) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  info.GetReturnValue().Set(Nan::New<v8::Integer>(\n    s7client->snap7Client->LastError()));\n}\n\nNAN_METHOD(S7Client::PDURequested) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  int returnValue = s7client->snap7Client->PDURequested();\n  if (returnValue == 0) {\n    info.GetReturnValue().Set(Nan::False());\n  } else {\n    info.GetReturnValue().Set(Nan::New<v8::Integer>(returnValue));\n  }\n}\n\nNAN_METHOD(S7Client::PDULength) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  int returnValue = s7client->snap7Client->PDULength();\n  if (returnValue == 0) {\n    info.GetReturnValue().Set(Nan::False());\n  } else {\n    info.GetReturnValue().Set(Nan::New<v8::Integer>(returnValue));\n  }\n}\n\nNAN_METHOD(S7Client::PlcStatus) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  if (!info[0]->IsFunction()) {\n    int returnValue = s7client->snap7Client->PlcStatus();\n    if ((returnValue == S7CpuStatusUnknown) ||\n        (returnValue == S7CpuStatusStop) ||\n        (returnValue == S7CpuStatusRun)) {\n      info.GetReturnValue().Set(Nan::New<v8::Integer>(returnValue));\n    } else {\n      info.GetReturnValue().Set(Nan::False());\n    }\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[0].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorker(callback, s7client, PLCSTATUS));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nNAN_METHOD(S7Client::Connected) {\n  S7Client *s7client = ObjectWrap::Unwrap<S7Client>(info.Holder());\n\n  info.GetReturnValue().Set(Nan::New<v8::Boolean>(\n    s7client->snap7Client->Connected()));\n}\n\nNAN_METHOD(S7Client::ErrorText) {\n  if (!info[0]->IsInt32()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  info.GetReturnValue().Set(Nan::New<v8::String>(\n    CliErrorText(Nan::To<int32_t>(info[0]).FromJust()).c_str()).ToLocalChecked());\n}\n\n}  // namespace node_snap7\n"
  },
  {
    "path": "src/node_snap7_client.h",
    "content": "/*\n * Copyright (c) 2019, Mathias Küsel\n * MIT License <https://github.com/mathiask88/node-snap7/blob/master/LICENSE>\n */\n\n#ifndef SRC_NODE_SNAP7_CLIENT_H_\n#define SRC_NODE_SNAP7_CLIENT_H_\n\n#include <snap7.h>\n#include <node.h>\n#include <nan.h>\n\nnamespace node_snap7 {\n\nenum DataIOFunction { READAREA = 1, WRITEAREA, READMULTI, WRITEMULTI\n  , PLCSTATUS, GETPROTECTION, CLEARSESSIONPW, SETSESSIONPW, PLCSTOP\n  , PLCCOLDSTART, PLCHOTSTART, GETCPINFO, GETCPUINFO, GETORDERCODE\n  , SETPLCSYSTEMDATETIME, GETPLCDATETIME, COMPRESS, COPYRAMTOROM\n  , SETPLCDATETIME, DBFILL, DBGET, DELETEBLOCK, DOWNLOAD, FULLUPLOAD\n  , UPLOAD, LISTBLOCKSOFTYPE, GETAGBLOCKINFO, LISTBLOCKS, CONNECT\n  , CONNECTTO, READSZLLIST, READSZL\n};\n\nclass S7Client : public Nan::ObjectWrap {\n public:\n  S7Client();\n  static NAN_MODULE_INIT(Init);\n  static NAN_METHOD(New);\n  // Control functions\n  static NAN_METHOD(Connect);\n  static NAN_METHOD(ConnectTo);\n  static NAN_METHOD(SetConnectionParams);\n  static NAN_METHOD(SetConnectionType);\n  static NAN_METHOD(Disconnect);\n  static NAN_METHOD(GetParam);\n  static NAN_METHOD(SetParam);\n  // Data I/O Main functions\n  static NAN_METHOD(ReadArea);\n  static NAN_METHOD(WriteArea);\n  static NAN_METHOD(ReadMultiVars);\n  static NAN_METHOD(WriteMultiVars);\n  // Directory functions\n  static NAN_METHOD(ListBlocks);\n  static NAN_METHOD(GetAgBlockInfo);\n  static NAN_METHOD(GetPgBlockInfo);\n  static NAN_METHOD(ListBlocksOfType);\n  // Blocks functions\n  static NAN_METHOD(Upload);\n  static NAN_METHOD(FullUpload);\n  static NAN_METHOD(Download);\n  static NAN_METHOD(Delete);\n  static NAN_METHOD(DBGet);\n  static NAN_METHOD(DBFill);\n  // Date/Time functions\n  static NAN_METHOD(GetPlcDateTime);\n  static NAN_METHOD(SetPlcDateTime);\n  static NAN_METHOD(SetPlcSystemDateTime);\n  // System Info functions\n  static NAN_METHOD(GetOrderCode);\n  static NAN_METHOD(GetCpuInfo);\n  static NAN_METHOD(GetCpInfo);\n  static NAN_METHOD(ReadSZL);\n  static NAN_METHOD(ReadSZLList);\n  // Control functions\n  static NAN_METHOD(PlcHotStart);\n  static NAN_METHOD(PlcColdStart);\n  static NAN_METHOD(PlcStop);\n  static NAN_METHOD(CopyRamToRom);\n  static NAN_METHOD(Compress);\n  // Security functions\n  static NAN_METHOD(GetProtection);\n  static NAN_METHOD(SetSessionPassword);\n  static NAN_METHOD(ClearSessionPassword);\n  // Properties\n  static NAN_METHOD(ExecTime);\n  static NAN_METHOD(LastError);\n  static NAN_METHOD(PDURequested);\n  static NAN_METHOD(PDULength);\n  static NAN_METHOD(PlcStatus);\n  static NAN_METHOD(Connected);\n\n  static NAN_METHOD(ErrorText);\n  // Internal Helper functions\n  static int GetByteCountFromWordLen(int WordLen);\n  v8::Local<v8::Array> S7DataItemToArray(PS7DataItem Items, int len\n    , bool readMulti);\n  v8::Local<v8::Object> S7ProtectionToObject(PS7Protection S7Protection);\n  v8::Local<v8::Object> S7CpInfoToObject(PS7CpInfo CpInfo);\n  v8::Local<v8::Object> S7CpuInfoToObject(PS7CpuInfo CpuInfo);\n  v8::Local<v8::Object> S7OrderCodeToObject(PS7OrderCode OrderCode);\n  v8::Local<v8::Object> S7BlockInfoToObject(PS7BlockInfo BlockInfo);\n  v8::Local<v8::Object> S7BlocksListToObject(PS7BlocksList BlocksList);\n  v8::Local<v8::Array> S7BlocksOfTypeToArray(PS7BlocksOfType BlocksList\n    , int count);\n  v8::Local<v8::Array> S7SZLListToArray(PS7SZLList SZLList, int count);\n\n  static void FreeCallback(char *data, void* hint);\n  static void FreeCallbackSZL(char *data, void* hint);\n\n\n  uv_mutex_t mutex;\n  TS7Client *snap7Client;\n\n private:\n  ~S7Client();\n  static Nan::Persistent<v8::FunctionTemplate> constructor;\n};\n\nclass IOWorker : public Nan::AsyncWorker {\n public:\n  // No args\n  IOWorker(Nan::Callback *callback, S7Client *s7client, DataIOFunction caller)\n      : Nan::AsyncWorker(callback), s7client(s7client), caller(caller) {}\n  // 1 args\n  IOWorker(Nan::Callback *callback, S7Client *s7client, DataIOFunction caller\n    , void *arg1)\n    : Nan::AsyncWorker(callback), s7client(s7client), caller(caller)\n    , pData(arg1) {}\n  IOWorker(Nan::Callback *callback, S7Client *s7client, DataIOFunction caller\n    , int arg1)\n    : Nan::AsyncWorker(callback), s7client(s7client), caller(caller)\n    , int1(arg1) {}\n  // 2 args\n  IOWorker(Nan::Callback *callback, S7Client *s7client, DataIOFunction caller\n    , void *arg1, int arg2)\n    : Nan::AsyncWorker(callback), s7client(s7client), caller(caller)\n    , pData(arg1), int1(arg2) {}\n  IOWorker(Nan::Callback *callback, S7Client *s7client, DataIOFunction caller\n    , int arg1, int arg2)\n    : Nan::AsyncWorker(callback), s7client(s7client), caller(caller)\n    , int1(arg1), int2(arg2) {}\n  // 3 args\n  IOWorker(Nan::Callback *callback, S7Client *s7client, DataIOFunction caller\n    , void *arg1, int arg2, int arg3)\n    : Nan::AsyncWorker(callback), s7client(s7client), caller(caller)\n    , pData(arg1), int1(arg2), int2(arg3) {}\n  // 4 args\n  IOWorker(Nan::Callback *callback, S7Client *s7client, DataIOFunction caller\n    , void *arg1, int arg2, int arg3, int arg4)\n    : Nan::AsyncWorker(callback), s7client(s7client), caller(caller)\n    , pData(arg1), int1(arg2), int2(arg3), int3(arg4) {}\n  // 6 args\n  IOWorker(Nan::Callback *callback, S7Client *s7client, DataIOFunction caller\n    , void *arg1, int arg2, int arg3, int arg4, int arg5, int arg6)\n    : Nan::AsyncWorker(callback), s7client(s7client), caller(caller)\n    , pData(arg1), int1(arg2), int2(arg3), int3(arg4), int4(arg5), int5(arg6) {}\n\n  ~IOWorker() {}\n\n private:\n  void Execute();\n  void HandleOKCallback();\n\n  S7Client *s7client;\n  DataIOFunction caller;\n  void *pData;\n  int int1, int2, int3, int4, int5, returnValue;\n};\n\n}  // namespace node_snap7\n\n#endif  // SRC_NODE_SNAP7_CLIENT_H_\n"
  },
  {
    "path": "src/node_snap7_server.cpp",
    "content": "/*\n * Copyright (c) 2019, Mathias Küsel\n * MIT License <https://github.com/mathiask88/node-snap7/blob/master/LICENSE>\n */\n\n#include <node_snap7_server.h>\n\nnamespace node_snap7 {\n\nstatic uv_async_t event_async_g;\nstatic uv_async_t rw_async_g;\nstatic uv_mutex_t mutex_rw;\nstatic uv_mutex_t mutex_event;\nstatic uv_sem_t sem_rw;\nstatic std::deque<TSrvEvent> event_list_g;\n\nstatic struct rw_event_baton_t {\n  int Sender;\n  int Operation;\n  TS7Tag Tag;\n  void *pUsrData;\n} rw_event_baton_g;\n\nvoid S7API EventCallBack(void *usrPtr, PSrvEvent PEvent, int Size) {\n  uv_mutex_lock(&mutex_event);\n  event_list_g.push_back(*PEvent);\n  uv_mutex_unlock(&mutex_event);\n\n  uv_async_send(&event_async_g);\n}\n\nint S7API RWAreaCallBack(void *usrPtr, int Sender, int Operation, PS7Tag PTag\n  , void *pUsrData\n) {\n  uv_mutex_lock(&mutex_rw);\n  rw_event_baton_g.Sender = Sender;\n  rw_event_baton_g.Operation = Operation;\n  rw_event_baton_g.Tag = *PTag;\n  rw_event_baton_g.pUsrData = pUsrData;\n\n  uv_async_send(&rw_async_g);\n\n  uv_sem_wait(&sem_rw);\n  uv_mutex_unlock(&mutex_rw);\n\n  return 0;\n}\n\nNan::Persistent<v8::FunctionTemplate> S7Server::constructor;\n\nNAN_MODULE_INIT(S7Server::Init) {\n  Nan::HandleScope scope;\n\n  v8::Local<v8::FunctionTemplate> tpl;\n  tpl = Nan::New<v8::FunctionTemplate>(S7Server::New);\n\n  v8::Local<v8::String> name = Nan::New<v8::String>(\"S7Server\")\n    .ToLocalChecked();\n\n  tpl->SetClassName(name);\n  tpl->InstanceTemplate()->SetInternalFieldCount(1);\n\n  // Setup the prototype\n  Nan::SetPrototypeMethod(\n    tpl\n    , \"Start\"\n    , S7Server::Start);\n  Nan::SetPrototypeMethod(\n    tpl\n    , \"StartTo\"\n    , S7Server::StartTo);\n  Nan::SetPrototypeMethod(\n    tpl\n    , \"Stop\"\n    , S7Server::Stop);\n  Nan::SetPrototypeMethod(\n    tpl\n    , \"SetParam\"\n    , S7Server::SetParam);\n  Nan::SetPrototypeMethod(\n    tpl\n    , \"GetParam\"\n    , S7Server::GetParam);\n  Nan::SetPrototypeMethod(\n    tpl\n    , \"SetResourceless\"\n    , S7Server::SetResourceless);\n  Nan::SetPrototypeMethod(\n    tpl\n    , \"RegisterArea\"\n    , S7Server::RegisterArea);\n  Nan::SetPrototypeMethod(\n    tpl\n    , \"UnregisterArea\"\n    , S7Server::UnregisterArea);\n  Nan::SetPrototypeMethod(\n    tpl\n    , \"LockArea\"\n    , S7Server::LockArea);\n  Nan::SetPrototypeMethod(\n    tpl\n    , \"UnlockArea\"\n    , S7Server::UnlockArea);\n  Nan::SetPrototypeMethod(\n    tpl\n    , \"SetArea\"\n    , S7Server::SetArea);\n  Nan::SetPrototypeMethod(\n    tpl\n    , \"GetArea\"\n    , S7Server::GetArea);\n  Nan::SetPrototypeMethod(\n    tpl\n    , \"SetEventMask\"\n    , S7Server::SetEventsMask);\n  Nan::SetPrototypeMethod(\n    tpl\n    , \"GetEventsMask\"\n    , S7Server::GetEventsMask);\n  Nan::SetPrototypeMethod(\n    tpl\n    , \"ErrorText\"\n    , S7Server::ErrorText);\n  Nan::SetPrototypeMethod(\n    tpl\n    , \"LastError\"\n    , S7Server::LastError);\n  Nan::SetPrototypeMethod(\n    tpl\n    , \"EventText\"\n    , S7Server::EventText);\n  Nan::SetPrototypeMethod(\n    tpl\n    , \"ServerStatus\"\n    , S7Server::ServerStatus);\n  Nan::SetPrototypeMethod(\n    tpl\n    , \"ClientsCount\"\n    , S7Server::ClientsCount);\n  Nan::SetPrototypeMethod(\n    tpl\n    , \"GetCpuStatus\"\n    , S7Server::GetCpuStatus);\n  Nan::SetPrototypeMethod(\n    tpl\n    , \"SetCpuStatus\"\n    , S7Server::SetCpuStatus);\n\n  // Error codes\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"errSrvCannotStart\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(errSrvCannotStart)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"errSrvDBNullPointer\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(errSrvDBNullPointer)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"errSrvAreaAlreadyExists\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(errSrvAreaAlreadyExists)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"errSrvUnknownArea\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(errSrvUnknownArea)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"errSrvInvalidParams\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(errSrvInvalidParams)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"errSrvTooManyDB\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(errSrvTooManyDB)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"errSrvInvalidParamNumber\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(errSrvInvalidParamNumber)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"errSrvCannotChangeParam\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(errSrvCannotChangeParam)\n    , v8::ReadOnly);\n\n  // Server area IDs\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"srvAreaPE\").ToLocalChecked()\n    , Nan::New<v8::Integer>(srvAreaPE)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"srvAreaPA\").ToLocalChecked()\n    , Nan::New<v8::Integer>(srvAreaPA)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"srvAreaMK\").ToLocalChecked()\n    , Nan::New<v8::Integer>(srvAreaMK)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"srvAreaCT\").ToLocalChecked()\n    , Nan::New<v8::Integer>(srvAreaCT)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"srvAreaTM\").ToLocalChecked()\n    , Nan::New<v8::Integer>(srvAreaTM)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"srvAreaDB\").ToLocalChecked()\n    , Nan::New<v8::Integer>(srvAreaDB)\n    , v8::ReadOnly);\n\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"operationWrite\").ToLocalChecked()\n    , Nan::New<v8::Integer>(OperationWrite)\n    , v8::ReadOnly);\n\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"operationRead\").ToLocalChecked()\n    , Nan::New<v8::Integer>(OperationRead)\n    , v8::ReadOnly);\n\n  // TCP server event codes\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evcServerStarted\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(evcServerStarted)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evcServerStopped\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(evcServerStopped)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evcListenerCannotStart\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(evcListenerCannotStart)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evcClientAdded\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(evcClientAdded)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evcClientRejected\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(evcClientRejected)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evcClientNoRoom\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(evcClientNoRoom)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evcClientException\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(evcClientException)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evcClientDisconnected\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(evcClientDisconnected)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evcClientTerminated\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(evcClientTerminated)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evcClientsDropped\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(evcClientsDropped)\n    , v8::ReadOnly);\n\n  // S7 server event codes\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evcPDUincoming\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(evcPDUincoming)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evcDataRead\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(evcDataRead)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evcDataWrite\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(evcDataWrite)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evcNegotiatePDU\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(evcNegotiatePDU)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evcReadSZL\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(evcReadSZL)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evcClock\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(evcClock)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evcUpload\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(evcUpload)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evcDownload\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(evcDownload)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evcDirectory\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(evcDirectory)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evcSecurity\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(evcSecurity)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evcControl\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(evcControl)\n    , v8::ReadOnly);\n\n  // Masks to enable/disable all events\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evcAll\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(evcAll)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evcNone\").ToLocalChecked()\n    , Nan::New<v8::Uint32>(evcNone)\n    , v8::ReadOnly);\n\n  // Event subcodes\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evsUnknown\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evsUnknown)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evsStartUpload\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evsStartUpload)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evsStartDownload\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evsStartDownload)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evsGetBlockList\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evsGetBlockList)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evsStartListBoT\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evsStartListBoT)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evsListBoT\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evsListBoT)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evsGetBlockInfo\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evsGetBlockInfo)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evsGetClock\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evsGetClock)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evsSetClock\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evsSetClock)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evsSetPassword\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evsSetPassword)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evsClrPassword\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evsClrPassword)\n    , v8::ReadOnly);\n\n  // Event params : functions group\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"grProgrammer\").ToLocalChecked()\n    , Nan::New<v8::Integer>(grProgrammer)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"grCyclicData\").ToLocalChecked()\n    , Nan::New<v8::Integer>(grCyclicData)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"grBlocksInfo\").ToLocalChecked()\n    , Nan::New<v8::Integer>(grBlocksInfo)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"grSZL\").ToLocalChecked()\n    , Nan::New<v8::Integer>(grSZL)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"grPassword\").ToLocalChecked()\n    , Nan::New<v8::Integer>(grPassword)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"grBSend\").ToLocalChecked()\n    , Nan::New<v8::Integer>(grBSend)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"grClock\").ToLocalChecked()\n    , Nan::New<v8::Integer>(grClock)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"grSecurity\").ToLocalChecked()\n    , Nan::New<v8::Integer>(grSecurity)\n    , v8::ReadOnly);\n\n  // Event params : control codes\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"CodeControlUnknown\").ToLocalChecked()\n    , Nan::New<v8::Integer>(CodeControlUnknown)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"CodeControlColdStart\").ToLocalChecked()\n    , Nan::New<v8::Integer>(CodeControlColdStart)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"CodeControlWarmStart\").ToLocalChecked()\n    , Nan::New<v8::Integer>(CodeControlWarmStart)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"CodeControlStop\").ToLocalChecked()\n    , Nan::New<v8::Integer>(CodeControlStop)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"CodeControlCompress\").ToLocalChecked()\n    , Nan::New<v8::Integer>(CodeControlCompress)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"CodeControlCpyRamRom\").ToLocalChecked()\n    , Nan::New<v8::Integer>(CodeControlCpyRamRom)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"CodeControlInsDel\").ToLocalChecked()\n    , Nan::New<v8::Integer>(CodeControlInsDel)\n    , v8::ReadOnly);\n\n  // Event results\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evrNoError\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evrNoError)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evrFragmentRejected\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evrFragmentRejected)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evrMalformedPDU\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evrMalformedPDU)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evrSparseBytes\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evrSparseBytes)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evrCannotHandlePDU\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evrCannotHandlePDU)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evrNotImplemented\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evrNotImplemented)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evrErrException\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evrErrException)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evrErrAreaNotFound\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evrErrAreaNotFound)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evrErrOutOfRange\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evrErrOutOfRange)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evrErrOverPDU\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evrErrOverPDU)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evrErrTransportSize\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evrErrTransportSize)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evrInvalidGroupUData\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evrInvalidGroupUData)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evrInvalidSZL\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evrInvalidSZL)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evrDataSizeMismatch\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evrDataSizeMismatch)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evrCannotUpload\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evrCannotUpload)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evrCannotDownload\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evrCannotDownload)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evrUploadInvalidID\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evrUploadInvalidID)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"evrResNotFound\").ToLocalChecked()\n    , Nan::New<v8::Integer>(evrResNotFound)\n    , v8::ReadOnly);\n\n  // Server parameter\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"LocalPort\").ToLocalChecked()\n    , Nan::New<v8::Integer>(p_u16_LocalPort)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"WorkInterval\").ToLocalChecked()\n    , Nan::New<v8::Integer>(p_i32_WorkInterval)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"PDURequest\").ToLocalChecked()\n    , Nan::New<v8::Integer>(p_i32_PDURequest)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"MaxClients\").ToLocalChecked()\n    , Nan::New<v8::Integer>(p_i32_MaxClients)\n    , v8::ReadOnly);\n\n  // CPU status codes\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"S7CpuStatusUnknown\").ToLocalChecked()\n    , Nan::New<v8::Integer>(S7CpuStatusUnknown)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"S7CpuStatusRun\").ToLocalChecked()\n    , Nan::New<v8::Integer>(S7CpuStatusRun)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"S7CpuStatusStop\").ToLocalChecked()\n    , Nan::New<v8::Integer>(S7CpuStatusStop)\n    , v8::ReadOnly);\n\n  // Server status codes\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"SrvStopped\").ToLocalChecked()\n    , Nan::New<v8::Integer>(0)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"SrvRunning\").ToLocalChecked()\n    , Nan::New<v8::Integer>(1)\n    , v8::ReadOnly);\n  Nan::SetPrototypeTemplate(\n    tpl\n    , Nan::New<v8::String>(\"SrvError\").ToLocalChecked()\n    , Nan::New<v8::Integer>(2)\n    , v8::ReadOnly);\n\n  constructor.Reset(tpl);\n  Nan::Set(target, name, Nan::GetFunction(tpl).ToLocalChecked());\n}\n\nNAN_METHOD(S7Server::New) {\n  if (info.IsConstructCall()) {\n    S7Server *s7Server = new S7Server(info.This());\n\n    s7Server->Wrap(info.This());\n  info.GetReturnValue().Set(info.This());\n  } else {\n    v8::Local<v8::FunctionTemplate> constructorHandle;\n    constructorHandle = Nan::New<v8::FunctionTemplate>(constructor);\n    info.GetReturnValue().Set(\n      Nan::NewInstance(Nan::GetFunction(constructorHandle).ToLocalChecked()).ToLocalChecked());\n  }\n}\n\nS7Server::S7Server(v8::Local<v8::Object> resource)\n  : async_resource(\"S7Server:emit\", resource) {\n  lastError = 0;\n  snap7Server = new TS7Server();\n\n  event_async_g.data = rw_async_g.data = this;\n\n  uv_async_init(uv_default_loop(), &event_async_g, S7Server::HandleEvent);\n  uv_async_init(uv_default_loop(), &rw_async_g, S7Server::HandleReadWriteEvent);\n\n  uv_unref(reinterpret_cast<uv_handle_t *>(&event_async_g));\n  uv_unref(reinterpret_cast<uv_handle_t *>(&rw_async_g));\n  uv_mutex_init(&mutex);\n  uv_mutex_init(&mutex_rw);\n  uv_mutex_init(&mutex_event);\n  uv_sem_init(&sem_rw, 0);\n\n  snap7Server->SetEventsCallback(&EventCallBack, NULL);\n}\n\nS7Server::~S7Server() {\n  snap7Server->Stop();\n  delete snap7Server;\n\n  constructor.Reset();\n\n  uv_close(reinterpret_cast<uv_handle_t *>(&event_async_g), 0);\n  uv_close(reinterpret_cast<uv_handle_t *>(&rw_async_g), 0);\n  uv_sem_destroy(&sem_rw);\n  uv_mutex_destroy(&mutex_event);\n  uv_mutex_destroy(&mutex_rw);\n  uv_mutex_destroy(&mutex);\n}\n\nint S7Server::GetByteCountFromWordLen(int WordLen) {\n  switch (WordLen) {\n  case S7WLBit:\n  case S7WLByte:\n    return 1;\n  case S7WLWord:\n  case S7WLCounter:\n  case S7WLTimer:\n    return 2;\n  case S7WLReal:\n  case S7WLDWord:\n    return 4;\n  default:\n    return 0;\n  }\n}\n\nNAN_METHOD(S7Server::RWBufferCallback) {\n  Nan::HandleScope scope;\n\n  if (rw_event_baton_g.Operation == OperationRead) {\n    if (!node::Buffer::HasInstance(info[0])) {\n      return Nan::ThrowTypeError(\"Wrong argument\");\n    }\n\n    int byteCount, size;\n    byteCount = S7Server::GetByteCountFromWordLen(rw_event_baton_g.Tag.WordLen);\n    size = byteCount * rw_event_baton_g.Tag.Size;\n\n    if (node::Buffer::Length(info[0].As<v8::Object>()) < size) {\n      return Nan::ThrowTypeError(\"Buffer length too small\");\n    }\n\n    memcpy(\n        rw_event_baton_g.pUsrData\n      , node::Buffer::Data(info[0].As<v8::Object>())\n      , size);\n  }\n\n  uv_sem_post(&sem_rw);\n}\n\n#if NODE_VERSION_AT_LEAST(0, 11, 13)\nvoid S7Server::HandleEvent(uv_async_t* handle) {\n#else\nvoid S7Server::HandleEvent(uv_async_t* handle, int status) {\n#endif\n  Nan::HandleScope scope;\n\n  S7Server *s7server = static_cast<S7Server*>(handle->data);\n\n  uv_mutex_lock(&mutex_event);\n  while (!event_list_g.empty()) {\n    PSrvEvent Event = &event_list_g.front();\n    in_addr sin;\n    sin.s_addr = Event->EvtSender;\n    double time = static_cast<double>(Event->EvtTime * 1000);\n\n    v8::Local<v8::Object> event_obj = Nan::New<v8::Object>();\n    Nan::Set(event_obj, Nan::New<v8::String>(\"EvtTime\").ToLocalChecked()\n      , Nan::New<v8::Date>(time).ToLocalChecked());\n    Nan::Set(event_obj, Nan::New<v8::String>(\"EvtSender\").ToLocalChecked()\n      , Nan::New<v8::String>(inet_ntoa(sin)).ToLocalChecked());\n    Nan::Set(event_obj, Nan::New<v8::String>(\"EvtCode\").ToLocalChecked()\n      , Nan::New<v8::Uint32>(Event->EvtCode));\n    Nan::Set(event_obj, Nan::New<v8::String>(\"EvtRetCode\").ToLocalChecked()\n      , Nan::New<v8::Integer>(Event->EvtRetCode));\n    Nan::Set(event_obj, Nan::New<v8::String>(\"EvtParam1\").ToLocalChecked()\n      , Nan::New<v8::Integer>(Event->EvtParam1));\n    Nan::Set(event_obj, Nan::New<v8::String>(\"EvtParam2\").ToLocalChecked()\n      , Nan::New<v8::Integer>(Event->EvtParam2));\n    Nan::Set(event_obj, Nan::New<v8::String>(\"EvtParam3\").ToLocalChecked()\n      , Nan::New<v8::Integer>(Event->EvtParam3));\n    Nan::Set(event_obj, Nan::New<v8::String>(\"EvtParam4\").ToLocalChecked()\n      , Nan::New<v8::Integer>(Event->EvtParam4));\n\n    v8::Local<v8::Value> argv[2] = {\n      Nan::New(\"event\").ToLocalChecked(),\n      event_obj\n    };\n\n    s7server->async_resource.runInAsyncScope(s7server->handle(), \"emit\", 2, argv);\n    event_list_g.pop_front();\n  }\n  uv_mutex_unlock(&mutex_event);\n}\n\n#if NODE_VERSION_AT_LEAST(0, 11, 13)\nvoid S7Server::HandleReadWriteEvent(uv_async_t* handle) {\n#else\nvoid S7Server::HandleReadWriteEvent(uv_async_t* handle, int status) {\n#endif\n  Nan::HandleScope scope;\n\n  S7Server *s7server = static_cast<S7Server*>(handle->data);\n  in_addr sin;\n  sin.s_addr = rw_event_baton_g.Sender;\n\n  v8::Local<v8::Object> rw_tag_obj = Nan::New<v8::Object>();\n  Nan::Set(rw_tag_obj, Nan::New<v8::String>(\"Area\").ToLocalChecked()\n    , Nan::New<v8::Integer>(rw_event_baton_g.Tag.Area));\n  Nan::Set(rw_tag_obj, Nan::New<v8::String>(\"DBNumber\").ToLocalChecked()\n    , Nan::New<v8::Integer>(rw_event_baton_g.Tag.DBNumber));\n  Nan::Set(rw_tag_obj, Nan::New<v8::String>(\"Start\").ToLocalChecked()\n    , Nan::New<v8::Integer>(rw_event_baton_g.Tag.Start));\n  Nan::Set(rw_tag_obj, Nan::New<v8::String>(\"Size\").ToLocalChecked()\n    , Nan::New<v8::Integer>(rw_event_baton_g.Tag.Size));\n  Nan::Set(rw_tag_obj, Nan::New<v8::String>(\"WordLen\").ToLocalChecked()\n    , Nan::New<v8::Integer>(rw_event_baton_g.Tag.WordLen));\n\n  int byteCount, size;\n  byteCount = S7Server::GetByteCountFromWordLen(rw_event_baton_g.Tag.WordLen);\n  size = byteCount * rw_event_baton_g.Tag.Size;\n\n  v8::Local<v8::Object> buffer;\n\n  if (rw_event_baton_g.Operation == OperationWrite) {\n    buffer = Nan::CopyBuffer(\n      static_cast<char*>(rw_event_baton_g.pUsrData),\n      size).ToLocalChecked();\n  } else {\n    buffer = Nan::NewBuffer(size).ToLocalChecked();\n    memset(node::Buffer::Data(buffer), 0, size);\n  }\n\n  v8::Local<v8::Value> argv[6] = {\n    Nan::New(\"readWrite\").ToLocalChecked(),\n    Nan::New<v8::String>(inet_ntoa(sin)).ToLocalChecked(),\n    Nan::New<v8::Integer>(rw_event_baton_g.Operation),\n    rw_tag_obj,\n    buffer,\n    Nan::New<v8::Function>(S7Server::RWBufferCallback)\n  };\n\n  s7server->async_resource.runInAsyncScope(s7server->handle(), \"emit\", 6, argv);\n}\n\nvoid IOWorkerServer::Execute() {\n  uv_mutex_lock(&s7server->mutex);\n\n  switch (caller) {\n  case STARTTO:\n    ret = s7server->snap7Server->StartTo(\n      **static_cast<Nan::Utf8String*>(pData));\n\n    if (ret == 0) {\n      uv_ref(reinterpret_cast<uv_handle_t *>(&event_async_g));\n    }\n    break;\n\n  case START:\n    ret = s7server->snap7Server->Start();\n\n    if (ret == 0) {\n      uv_ref(reinterpret_cast<uv_handle_t *>(&event_async_g));\n    }\n    break;\n\n  case STOP:\n    ret = s7server->snap7Server->Stop();\n\n    if (ret == 0) {\n      uv_unref(reinterpret_cast<uv_handle_t *>(&event_async_g));\n    }\n    break;\n  }\n\n  uv_mutex_unlock(&s7server->mutex);\n}\n\nvoid IOWorkerServer::HandleOKCallback() {\n  Nan::HandleScope scope;\n\n  v8::Local<v8::Value> argv1[1];\n  v8::Local<v8::Value> argv2[2];\n\n  if (ret == 0) {\n    argv2[0] = argv1[0] = Nan::Null();\n  } else {\n    argv2[0] = argv1[0] = Nan::New<v8::Integer>(ret);\n  }\n\n  switch (caller) {\n  case STARTTO:\n    delete static_cast<Nan::Utf8String*>(pData);\n    callback->Call(1, argv1, async_resource);\n    break;\n\n  case START:\n  case STOP:\n    callback->Call(1, argv1, async_resource);\n    break;\n  }\n}\n\nNAN_METHOD(S7Server::Start) {\n  S7Server *s7server = ObjectWrap::Unwrap<S7Server>(info.Holder());\n\n  if (!info[0]->IsFunction()) {\n    int ret = s7server->snap7Server->Start();\n\n    if (ret == 0) {\n      uv_ref(reinterpret_cast<uv_handle_t *>(&event_async_g));\n    }\n\n    s7server->lastError = ret;\n\n    info.GetReturnValue().Set(Nan::New<v8::Boolean>(ret == 0));\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[0].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorkerServer(callback, s7server, START));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nNAN_METHOD(S7Server::StartTo) {\n  S7Server *s7server = ObjectWrap::Unwrap<S7Server>(info.Holder());\n\n  if (info.Length() < 1) {\n    return Nan::ThrowTypeError(\"Wrong number of arguments\");\n  }\n\n  if (!info[0]->IsString()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  Nan::Utf8String *address = new Nan::Utf8String(info[0]);\n  if (!info[1]->IsFunction()) {\n    int ret = s7server->snap7Server->StartTo(**address);\n    delete address;\n\n    if (ret == 0) {\n      uv_ref(reinterpret_cast<uv_handle_t *>(&event_async_g));\n    }\n\n    s7server->lastError = ret;\n\n    info.GetReturnValue().Set(Nan::New<v8::Boolean>(ret == 0));\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[1].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorkerServer(callback, s7server, STARTTO\n      , address));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nNAN_METHOD(S7Server::Stop) {\n  S7Server *s7server = ObjectWrap::Unwrap<S7Server>(info.Holder());\n\n  if (!info[0]->IsFunction()) {\n    int ret = s7server->snap7Server->Stop();\n\n    if (ret == 0) {\n      uv_unref(reinterpret_cast<uv_handle_t *>(&event_async_g));\n    }\n\n    s7server->lastError = ret;\n\n    info.GetReturnValue().Set(Nan::New<v8::Boolean>(ret == 0));\n  } else {\n    Nan::Callback *callback = new Nan::Callback(info[0].As<v8::Function>());\n    Nan::AsyncQueueWorker(new IOWorkerServer(callback, s7server, STOP));\n    info.GetReturnValue().SetUndefined();\n  }\n}\n\nNAN_METHOD(S7Server::SetResourceless) {\n  S7Server *s7server = ObjectWrap::Unwrap<S7Server>(info.Holder());\n\n  if (!info[0]->IsBoolean()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  bool resourceless = Nan::To<bool>(info[0]).FromJust();\n\n  int ret;\n  if (resourceless) {\n    ret = s7server->snap7Server->SetRWAreaCallback(&RWAreaCallBack, NULL);\n  } else {\n    ret = s7server->snap7Server->SetRWAreaCallback(NULL, NULL);\n  }\n  s7server->lastError = ret;\n\n  info.GetReturnValue().Set(Nan::New<v8::Boolean>(ret == 0));\n}\n\nNAN_METHOD(S7Server::GetParam) {\n  S7Server *s7server = ObjectWrap::Unwrap<S7Server>(info.Holder());\n\n  if (!info[0]->IsInt32()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  int pData;\n  int ret = s7server->snap7Server->GetParam(Nan::To<int32_t>(info[0]).FromJust()\n    , &pData);\n  s7server->lastError = ret;\n\n  info.GetReturnValue().Set(Nan::New<v8::Boolean>(ret == 0));\n}\n\nNAN_METHOD(S7Server::SetParam) {\n  S7Server *s7server = ObjectWrap::Unwrap<S7Server>(info.Holder());\n\n  if (!(info[0]->IsInt32() || info[1]->IsInt32())) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  int pData = Nan::To<int32_t>(info[1]).FromJust();\n  int ret = s7server->snap7Server->SetParam(Nan::To<int32_t>(info[0]).FromJust(), &pData);\n  s7server->lastError = ret;\n\n  info.GetReturnValue().Set(Nan::New<v8::Boolean>(ret == 0));\n}\n\nNAN_METHOD(S7Server::GetEventsMask) {\n  S7Server *s7server = ObjectWrap::Unwrap<S7Server>(info.Holder());\n\n  int ret = s7server->snap7Server->GetEventsMask();\n\n  info.GetReturnValue().Set(Nan::New<v8::Uint32>(ret));\n}\n\nNAN_METHOD(S7Server::SetEventsMask) {\n  S7Server *s7server = ObjectWrap::Unwrap<S7Server>(info.Holder());\n\n  if (!info[0]->IsUint32()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  s7server->snap7Server->SetEventsMask(Nan::To<uint32_t>(info[0]).FromJust());\n  info.GetReturnValue().SetUndefined();\n}\n\nNAN_METHOD(S7Server::RegisterArea) {\n  S7Server *s7server = ObjectWrap::Unwrap<S7Server>(info.Holder());\n\n  if (!info[0]->IsInt32()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  int index;\n  char *pBuffer;\n  size_t len;\n  int area = Nan::To<int32_t>(info[0]).FromJust();\n\n  if (area == srvAreaDB) {\n    if (!info[1]->IsInt32() || !node::Buffer::HasInstance(info[2])) {\n      return Nan::ThrowTypeError(\"Wrong arguments\");\n    }\n\n    index = Nan::To<int32_t>(info[1]).FromJust();\n    len = node::Buffer::Length(info[2].As<v8::Object>());\n    pBuffer = node::Buffer::Data(info[2].As<v8::Object>());\n  } else if (!node::Buffer::HasInstance(info[1])) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  } else {\n    index = 0;\n    len = node::Buffer::Length(info[1].As<v8::Object>());\n    pBuffer = node::Buffer::Data(info[1].As<v8::Object>());\n  }\n\n  if (len > 0xFFFF) {\n    return Nan::ThrowRangeError(\"Max area buffer size is 65535\");\n  }\n\n  word size = static_cast<word>(len);\n  char *data = new char[size];\n  memcpy(data, pBuffer, size);\n\n  int ret = s7server->snap7Server->RegisterArea(area, index, data, size);\n  s7server->lastError = ret;\n\n  if (ret == 0) {\n    s7server->area2buffer[area][index].pBuffer = data;\n    s7server->area2buffer[area][index].size = size;\n  } else {\n    delete[] data;\n  }\n\n  info.GetReturnValue().Set(Nan::New<v8::Boolean>(ret == 0));\n}\n\nNAN_METHOD(S7Server::UnregisterArea) {\n  S7Server *s7server = ObjectWrap::Unwrap<S7Server>(info.Holder());\n\n  if (!info[0]->IsInt32()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  int index = 0;\n  int area = Nan::To<int32_t>(info[0]).FromJust();\n\n  if (area == srvAreaDB) {\n    if (!info[1]->IsInt32()) {\n      return Nan::ThrowTypeError(\"Wrong arguments\");\n    }\n\n    index = Nan::To<int32_t>(info[1]).FromJust();\n  }\n\n  int ret = s7server->snap7Server->UnregisterArea(area, index);\n  s7server->lastError = ret;\n\n  if (ret == 0) {\n    delete[] s7server->area2buffer[area][index].pBuffer;\n    s7server->area2buffer[area].erase(index);\n  }\n\n  info.GetReturnValue().Set(Nan::New<v8::Boolean>(ret == 0));\n}\n\nNAN_METHOD(S7Server::SetArea) {\n  S7Server *s7server = ObjectWrap::Unwrap<S7Server>(info.Holder());\n\n  if (!info[0]->IsInt32()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  int area = Nan::To<int32_t>(info[0]).FromJust();\n  if (!s7server->area2buffer.count(area)) {\n    return Nan::ThrowError(\"Unknown area\");\n  }\n\n  int index;\n  char *pBuffer;\n  size_t len;\n\n  if (area == srvAreaDB) {\n    if (!info[1]->IsInt32() || !node::Buffer::HasInstance(info[2])) {\n      return Nan::ThrowTypeError(\"Wrong arguments\");\n    }\n\n    index = Nan::To<int32_t>(info[1]).FromJust();\n    if (!s7server->area2buffer[area].count(index)) {\n      return Nan::ThrowError(\"DB index not found\");\n    }\n\n    len = node::Buffer::Length(info[2].As<v8::Object>());\n    pBuffer = node::Buffer::Data(info[2].As<v8::Object>());\n  } else {\n    index = 0;\n    if (node::Buffer::HasInstance(info[1])) {\n      len = node::Buffer::Length(info[1].As<v8::Object>());\n      pBuffer = node::Buffer::Data(info[1].As<v8::Object>());\n    } else if (node::Buffer::HasInstance(info[2])) {\n      len = node::Buffer::Length(info[2].As<v8::Object>());\n      pBuffer = node::Buffer::Data(info[2].As<v8::Object>());\n    } else {\n      return Nan::ThrowTypeError(\"Wrong arguments\");\n    }\n  }\n\n  if (len != s7server->area2buffer[area][index].size) {\n    return Nan::ThrowError(\"Wrong buffer length\");\n  }\n\n  s7server->snap7Server->LockArea(area, index);\n\n  memcpy(\n    s7server->area2buffer[area][index].pBuffer\n    , pBuffer, s7server->area2buffer[area][index].size);\n\n  s7server->snap7Server->UnlockArea(area, index);\n\n  info.GetReturnValue().SetUndefined();\n}\n\nNAN_METHOD(S7Server::GetArea) {\n  S7Server *s7server = ObjectWrap::Unwrap<S7Server>(info.Holder());\n\n  if (!info[0]->IsInt32()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  int index = 0;\n  int area = Nan::To<int32_t>(info[0]).FromJust();\n\n  if (!s7server->area2buffer.count(area)) {\n    return Nan::ThrowError(\"Unknown area\");\n  }\n\n  if (area == srvAreaDB) {\n    if (!info[1]->IsInt32()) {\n      return Nan::ThrowTypeError(\"Wrong arguments\");\n    }\n\n    index = Nan::To<int32_t>(info[1]).FromJust();\n    if (!s7server->area2buffer[area].count(index)) {\n      return Nan::ThrowError(\"DB index not found\");\n    }\n  }\n\n  s7server->snap7Server->LockArea(area, index);\n\n  v8::Local<v8::Object> buffer = Nan::CopyBuffer(\n      s7server->area2buffer[area][index].pBuffer\n    , s7server->area2buffer[area][index].size).ToLocalChecked();\n\n  s7server->snap7Server->UnlockArea(area, index);\n\n  info.GetReturnValue().Set(buffer);\n}\n\nNAN_METHOD(S7Server::LockArea) {\n  S7Server *s7server = ObjectWrap::Unwrap<S7Server>(info.Holder());\n\n  if (!info[0]->IsInt32()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  int index = 0;\n  int area = Nan::To<int32_t>(info[0]).FromJust();\n\n  if (area == srvAreaDB) {\n    if (!info[1]->IsInt32()) {\n      return Nan::ThrowTypeError(\"Wrong arguments\");\n    }\n\n    index = Nan::To<int32_t>(info[1]).FromJust();\n  }\n\n  int ret = s7server->snap7Server->LockArea(area, index);\n  s7server->lastError = ret;\n\n  info.GetReturnValue().Set(Nan::New<v8::Boolean>(ret == 0));\n}\n\nNAN_METHOD(S7Server::UnlockArea) {\n  S7Server *s7server = ObjectWrap::Unwrap<S7Server>(info.Holder());\n\n  if (!info[0]->IsInt32()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  int index = 0;\n  int area = Nan::To<int32_t>(info[0]).FromJust();\n\n  if (area == srvAreaDB) {\n    if (!info[1]->IsInt32()) {\n      return Nan::ThrowTypeError(\"Wrong arguments\");\n    }\n\n    index = Nan::To<int32_t>(info[1]).FromJust();\n  }\n\n  int ret = s7server->snap7Server->UnlockArea(area, index);\n  s7server->lastError = ret;\n\n  info.GetReturnValue().Set(Nan::New<v8::Boolean>(ret == 0));\n}\n\nNAN_METHOD(S7Server::ServerStatus) {\n  S7Server *s7server = ObjectWrap::Unwrap<S7Server>(info.Holder());\n\n  int ret = s7server->snap7Server->ServerStatus();\n  if ((ret == 0) || (ret == 1) || (ret == 2)) {\n    s7server->lastError = 0;\n    info.GetReturnValue().Set(Nan::New<v8::Integer>(ret));\n  } else {\n    s7server->lastError = ret;\n    info.GetReturnValue().Set(Nan::False());\n  }\n}\n\nNAN_METHOD(S7Server::ClientsCount) {\n  S7Server *s7server = ObjectWrap::Unwrap<S7Server>(info.Holder());\n\n  int ret = s7server->snap7Server->ClientsCount();\n  info.GetReturnValue().Set(Nan::New<v8::Integer>(ret));\n}\n\nNAN_METHOD(S7Server::GetCpuStatus) {\n  S7Server *s7server = ObjectWrap::Unwrap<S7Server>(info.Holder());\n\n  int ret = s7server->snap7Server->GetCpuStatus();\n  if ((ret == S7CpuStatusUnknown) ||\n    (ret == S7CpuStatusStop) ||\n    (ret == S7CpuStatusRun)) {\n    s7server->lastError = 0;\n    info.GetReturnValue().Set(Nan::New<v8::Integer>(ret));\n  } else {\n    s7server->lastError = ret;\n    info.GetReturnValue().Set(Nan::False());\n  }\n}\n\nNAN_METHOD(S7Server::SetCpuStatus) {\n  S7Server *s7server = ObjectWrap::Unwrap<S7Server>(info.Holder());\n\n  if (!info[0]->IsInt32()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  int ret = s7server->snap7Server->SetCpuStatus(Nan::To<int32_t>(info[0]).FromJust());\n  s7server->lastError = ret;\n\n  info.GetReturnValue().Set(Nan::New<v8::Boolean>(ret == 0));\n}\n\nNAN_METHOD(S7Server::ErrorText) {\n  if (!info[0]->IsInt32()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  info.GetReturnValue().Set(Nan::New<v8::String>(\n    SrvErrorText(Nan::To<int32_t>(info[0]).FromJust()).c_str()).ToLocalChecked());\n}\n\nNAN_METHOD(S7Server::EventText) {\n  TSrvEvent SrvEvent;\n\n  if (!info[0]->IsObject()) {\n    return Nan::ThrowTypeError(\"Wrong arguments\");\n  }\n\n  v8::Local<v8::Object> event_obj = v8::Local<v8::Object>::Cast(info[0]);\n  if (!Nan::Has(event_obj, Nan::New<v8::String>(\"EvtTime\").ToLocalChecked()).FromJust() ||\n    !Nan::Has(event_obj, Nan::New<v8::String>(\"EvtSender\").ToLocalChecked()).FromJust() ||\n    !Nan::Has(event_obj, Nan::New<v8::String>(\"EvtCode\").ToLocalChecked()).FromJust() ||\n    !Nan::Has(event_obj, Nan::New<v8::String>(\"EvtRetCode\").ToLocalChecked()).FromJust() ||\n    !Nan::Has(event_obj, Nan::New<v8::String>(\"EvtParam1\").ToLocalChecked()).FromJust() ||\n    !Nan::Has(event_obj, Nan::New<v8::String>(\"EvtParam2\").ToLocalChecked()).FromJust() ||\n    !Nan::Has(event_obj, Nan::New<v8::String>(\"EvtParam3\").ToLocalChecked()).FromJust() ||\n    !Nan::Has(event_obj, Nan::New<v8::String>(\"EvtParam4\").ToLocalChecked()).FromJust()) {\n    return Nan::ThrowTypeError(\"Wrong argument structure\");\n  }\n\n  if (!Nan::Get(event_obj, Nan::New<v8::String>(\"EvtTime\").ToLocalChecked()).ToLocalChecked()->IsDate() ||\n    !Nan::Get(event_obj, Nan::New<v8::String>(\"EvtSender\").ToLocalChecked()).ToLocalChecked()->IsString() ||\n    !Nan::Get(event_obj, Nan::New<v8::String>(\"EvtCode\").ToLocalChecked()).ToLocalChecked()->IsUint32() ||\n    !Nan::Get(event_obj, Nan::New<v8::String>(\"EvtRetCode\").ToLocalChecked()).ToLocalChecked()->IsInt32() ||\n    !Nan::Get(event_obj, Nan::New<v8::String>(\"EvtParam1\").ToLocalChecked()).ToLocalChecked()->IsInt32() ||\n    !Nan::Get(event_obj, Nan::New<v8::String>(\"EvtParam2\").ToLocalChecked()).ToLocalChecked()->IsInt32() ||\n    !Nan::Get(event_obj, Nan::New<v8::String>(\"EvtParam3\").ToLocalChecked()).ToLocalChecked()->IsInt32() ||\n    !Nan::Get(event_obj, Nan::New<v8::String>(\"EvtParam4\").ToLocalChecked()).ToLocalChecked()->IsInt32()) {\n    return Nan::ThrowTypeError(\"Wrong argument types\");\n  }\n\n  Nan::Utf8String *remAddress = new Nan::Utf8String(\n    Nan::Get(\n        event_obj\n      , Nan::New<v8::String>(\"EvtSender\").ToLocalChecked()).ToLocalChecked());\n\n  SrvEvent.EvtTime = static_cast<time_t>(Nan::To<double>(v8::Local<v8::Date>::Cast(Nan::Get(event_obj, Nan::New<v8::String>(\"EvtTime\").ToLocalChecked()).ToLocalChecked())).FromJust() / 1000);\n  SrvEvent.EvtSender = inet_addr(**remAddress);\n  SrvEvent.EvtCode = Nan::To<uint32_t>(Nan::Get(event_obj, Nan::New<v8::String>(\"EvtCode\").ToLocalChecked()).ToLocalChecked()).FromJust();\n  SrvEvent.EvtRetCode = Nan::To<int32_t>(Nan::Get(event_obj, Nan::New<v8::String>(\"EvtRetCode\").ToLocalChecked()).ToLocalChecked()).FromJust();\n  SrvEvent.EvtParam1 = Nan::To<int32_t>(Nan::Get(event_obj, Nan::New<v8::String>(\"EvtParam1\").ToLocalChecked()).ToLocalChecked()).FromJust();\n  SrvEvent.EvtParam2 = Nan::To<int32_t>(Nan::Get(event_obj, Nan::New<v8::String>(\"EvtParam2\").ToLocalChecked()).ToLocalChecked()).FromJust();\n  SrvEvent.EvtParam3 = Nan::To<int32_t>(Nan::Get(event_obj, Nan::New<v8::String>(\"EvtParam3\").ToLocalChecked()).ToLocalChecked()).FromJust();\n  SrvEvent.EvtParam4 = Nan::To<int32_t>(Nan::Get(event_obj, Nan::New<v8::String>(\"EvtParam4\").ToLocalChecked()).ToLocalChecked()).FromJust();\n\n  delete remAddress;\n\n  info.GetReturnValue().Set(Nan::New<v8::String>(\n    SrvEventText(&SrvEvent).c_str()).ToLocalChecked());\n}\n\nNAN_METHOD(S7Server::LastError) {\n  S7Server *s7server = ObjectWrap::Unwrap<S7Server>(info.Holder());\n\n  info.GetReturnValue().Set(Nan::New<v8::Integer>(s7server->lastError));\n}\n\n}  // namespace node_snap7\n"
  },
  {
    "path": "src/node_snap7_server.h",
    "content": "/*\n * Copyright (c) 2019, Mathias Küsel\n * MIT License <https://github.com/mathiask88/node-snap7/blob/master/LICENSE>\n */\n\n#ifndef SRC_NODE_SNAP7_SERVER_H_\n#define SRC_NODE_SNAP7_SERVER_H_\n\n#include <snap7.h>\n#include <node.h>\n#include <node_buffer.h>\n#include <nan.h>\n#include <map>\n#include <deque>\n\nnamespace node_snap7 {\n\nenum ServerIOFunction {\n  START = 1, STARTTO, STOP\n};\n\ntypedef struct {\n  char* pBuffer;\n  word size;\n}TBufferInfo;\n\nclass S7Server : public Nan::ObjectWrap {\n public:\n  explicit S7Server(v8::Local<v8::Object> resource);\n  static NAN_MODULE_INIT(Init);\n  static NAN_METHOD(New);\n\n  static NAN_METHOD(Start);\n  static NAN_METHOD(StartTo);\n  static NAN_METHOD(Stop);\n  static NAN_METHOD(SetResourceless);\n  static NAN_METHOD(GetParam);\n  static NAN_METHOD(SetParam);\n  static NAN_METHOD(GetEventsMask);\n  static NAN_METHOD(SetEventsMask);\n  static NAN_METHOD(RegisterArea);\n  static NAN_METHOD(UnregisterArea);\n  static NAN_METHOD(SetArea);\n  static NAN_METHOD(GetArea);\n  static NAN_METHOD(LockArea);\n  static NAN_METHOD(UnlockArea);\n  static NAN_METHOD(ServerStatus);\n  static NAN_METHOD(ClientsCount);\n  static NAN_METHOD(GetCpuStatus);\n  static NAN_METHOD(SetCpuStatus);\n\n  static NAN_METHOD(ErrorText);\n  static NAN_METHOD(EventText);\n  static NAN_METHOD(LastError);\n\n  static int GetByteCountFromWordLen(int WordLen);\n\n#if NODE_VERSION_AT_LEAST(0, 11, 13)\n  static void HandleEvent(uv_async_t* handle);\n#else\n  static void HandleEvent(uv_async_t* handle, int status);\n#endif\n\n#if NODE_VERSION_AT_LEAST(0, 11, 13)\n  static void HandleReadWriteEvent(uv_async_t* handle);\n#else\n  static void HandleReadWriteEvent(uv_async_t* handle, int status);\n#endif\n\n  static NAN_METHOD(RWBufferCallback);\n\n  uv_mutex_t mutex;\n  TS7Server *snap7Server;\n  std::map<int, std::map<int, TBufferInfo> > area2buffer;\n  int lastError;\n  Nan::AsyncResource async_resource;\n\n private:\n  ~S7Server();\n  static Nan::Persistent<v8::FunctionTemplate> constructor;\n};\n\nclass IOWorkerServer : public Nan::AsyncWorker {\n public:\n  // No args\n  IOWorkerServer(Nan::Callback *callback, S7Server *s7server, ServerIOFunction caller)\n    : Nan::AsyncWorker(callback), s7server(s7server), caller(caller) {}\n  // 1 args\n  IOWorkerServer(Nan::Callback *callback, S7Server *s7server, ServerIOFunction caller\n    , void *arg1)\n    : Nan::AsyncWorker(callback), s7server(s7server), caller(caller)\n    , pData(arg1) {}\n\n  ~IOWorkerServer() {}\n\n private:\n  void Execute();\n  void HandleOKCallback();\n\n  S7Server *s7server;\n  ServerIOFunction caller;\n  void *pData;\n  int ret;\n};\n\n}  // namespace node_snap7\n\n#endif  // SRC_NODE_SNAP7_SERVER_H_\n"
  },
  {
    "path": "src/snap7.cpp",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.4.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2014 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|==============================================================================|\n|                                                                              |\n|  C++ Snap 7 classes Implementation                                           |\n|                                                                              |\n|=============================================================================*/\n\n#include \"snap7.h\"\n\n//==============================================================================\n// CLIENT\n//==============================================================================\nTS7Client::TS7Client()\n{\n    Client=Cli_Create();\n}\n//---------------------------------------------------------------------------\nTS7Client::~TS7Client()\n{\n    Cli_Destroy(&Client);\n}\n//---------------------------------------------------------------------------\nint TS7Client::Connect()\n{\n    return Cli_Connect(Client);\n}\n//---------------------------------------------------------------------------\nint TS7Client::ConnectTo(const char *RemAddress, int Rack, int Slot)\n{\n    return Cli_ConnectTo(Client, RemAddress, Rack, Slot);\n}\n//---------------------------------------------------------------------------\nint TS7Client::SetConnectionParams(const char *RemAddress, word LocalTSAP, word RemoteTSAP)\n{\n    return Cli_SetConnectionParams(Client, RemAddress, LocalTSAP, RemoteTSAP);\n}\n//---------------------------------------------------------------------------\nint TS7Client::SetConnectionType(word ConnectionType)\n{\n    return Cli_SetConnectionType(Client, ConnectionType);\n}\n//---------------------------------------------------------------------------\nint TS7Client::Disconnect()\n{\n    return Cli_Disconnect(Client);\n}\n//---------------------------------------------------------------------------\nint TS7Client::GetParam(int ParamNumber, void *pValue)\n{\n    return Cli_GetParam(Client, ParamNumber, pValue);\n}\n//---------------------------------------------------------------------------\nint TS7Client::SetParam(int ParamNumber, void *pValue)\n{\n    return Cli_SetParam(Client, ParamNumber, pValue);\n}\n//---------------------------------------------------------------------------\nint TS7Client::ReadArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData)\n{\n    return Cli_ReadArea(Client, Area, DBNumber, Start, Amount, WordLen, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::WriteArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData)\n{\n    return Cli_WriteArea(Client, Area, DBNumber, Start, Amount, WordLen, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::ReadMultiVars(PS7DataItem Item, int ItemsCount)\n{\n    return Cli_ReadMultiVars(Client, Item, ItemsCount);\n}\n//---------------------------------------------------------------------------\nint TS7Client::WriteMultiVars(PS7DataItem Item, int ItemsCount)\n{\n    return Cli_WriteMultiVars(Client, Item, ItemsCount);\n}\n//---------------------------------------------------------------------------\nint TS7Client::DBRead(int DBNumber, int Start, int Size, void *pUsrData)\n{\n    return Cli_DBRead(Client, DBNumber, Start, Size, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::DBWrite(int DBNumber, int Start, int Size, void *pUsrData)\n{\n    return Cli_DBWrite(Client, DBNumber, Start, Size, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::MBRead(int Start, int Size, void *pUsrData)\n{\n    return Cli_MBRead(Client, Start, Size, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::MBWrite(int Start, int Size, void *pUsrData)\n{\n    return Cli_MBWrite(Client, Start, Size, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::EBRead(int Start, int Size, void *pUsrData)\n{\n    return Cli_EBRead(Client, Start, Size, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::EBWrite(int Start, int Size, void *pUsrData)\n{\n    return Cli_EBWrite(Client, Start, Size, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::ABRead(int Start, int Size, void *pUsrData)\n{\n    return Cli_ABRead(Client, Start, Size, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::ABWrite(int Start, int Size, void *pUsrData)\n{\n    return Cli_ABWrite(Client, Start, Size, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::TMRead(int Start, int Amount, void *pUsrData)\n{\n    return Cli_TMRead(Client, Start, Amount, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::TMWrite(int Start, int Amount, void *pUsrData)\n{\n    return Cli_TMWrite(Client, Start, Amount, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::CTRead(int Start, int Amount, void *pUsrData)\n{\n    return Cli_CTRead(Client, Start, Amount, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::CTWrite(int Start, int Amount, void *pUsrData)\n{\n    return Cli_CTWrite(Client, Start, Amount, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::ListBlocks(PS7BlocksList pUsrData)\n{\n    return Cli_ListBlocks(Client, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::GetAgBlockInfo(int BlockType, int BlockNum, PS7BlockInfo pUsrData)\n{\n    return Cli_GetAgBlockInfo(Client, BlockType, BlockNum, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::GetPgBlockInfo(void *pBlock, PS7BlockInfo pUsrData, int Size)\n{\n    return Cli_GetPgBlockInfo(Client, pBlock, pUsrData, Size);\n}\n//---------------------------------------------------------------------------\nint TS7Client::ListBlocksOfType(int BlockType, TS7BlocksOfType *pUsrData, int *ItemsCount)\n{\n    return Cli_ListBlocksOfType(Client, BlockType, pUsrData, ItemsCount);\n}\n//---------------------------------------------------------------------------\nint TS7Client::Upload(int BlockType, int BlockNum, void *pUsrData, int *Size)\n{\n    return Cli_Upload(Client, BlockType, BlockNum, pUsrData, Size);\n}\n//---------------------------------------------------------------------------\nint TS7Client::FullUpload(int BlockType, int BlockNum, void *pUsrData, int *Size)\n{\n    return Cli_FullUpload(Client, BlockType, BlockNum, pUsrData, Size);\n}\n//---------------------------------------------------------------------------\nint TS7Client::Download(int BlockNum, void *pUsrData, int Size)\n{\n    return Cli_Download(Client, BlockNum, pUsrData, Size);\n}\n//---------------------------------------------------------------------------\nint TS7Client::Delete(int BlockType, int BlockNum)\n{\n    return Cli_Delete(Client, BlockType, BlockNum);\n}\n//---------------------------------------------------------------------------\nint TS7Client::DBGet(int DBNumber, void *pUsrData, int *Size)\n{\n    return Cli_DBGet(Client, DBNumber, pUsrData, Size);\n}\n//---------------------------------------------------------------------------\nint TS7Client::DBFill(int DBNumber, int FillChar)\n{\n    return Cli_DBFill(Client, DBNumber, FillChar);\n}\n//---------------------------------------------------------------------------\nint TS7Client::GetPlcDateTime(tm *DateTime)\n{\n    return Cli_GetPlcDateTime(Client, DateTime);\n}\n//---------------------------------------------------------------------------\nint TS7Client::SetPlcDateTime(tm *DateTime)\n{\n    return Cli_SetPlcDateTime(Client, DateTime);\n}\n//---------------------------------------------------------------------------\nint TS7Client::SetPlcSystemDateTime()\n{\n    return Cli_SetPlcSystemDateTime(Client);\n}\n//---------------------------------------------------------------------------\nint TS7Client::GetOrderCode(PS7OrderCode pUsrData)\n{\n    return Cli_GetOrderCode(Client, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::GetCpuInfo(PS7CpuInfo pUsrData)\n{\n    return Cli_GetCpuInfo(Client, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::GetCpInfo(PS7CpInfo pUsrData)\n{\n    return Cli_GetCpInfo(Client, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::ReadSZL(int ID, int Index, PS7SZL pUsrData, int *Size)\n{\n    return Cli_ReadSZL(Client, ID, Index, pUsrData, Size);\n}\n//---------------------------------------------------------------------------\nint TS7Client::ReadSZLList(PS7SZLList pUsrData, int *ItemsCount)\n{\n    return Cli_ReadSZLList(Client, pUsrData, ItemsCount);\n}\n//---------------------------------------------------------------------------\nint TS7Client::PlcHotStart()\n{\n    return Cli_PlcHotStart(Client);\n}\n//---------------------------------------------------------------------------\nint TS7Client::PlcColdStart()\n{\n    return Cli_PlcColdStart(Client);\n}\n//---------------------------------------------------------------------------\nint TS7Client::PlcStop()\n{\n    return Cli_PlcStop(Client);\n}\n//---------------------------------------------------------------------------\nint TS7Client::CopyRamToRom(int Timeout)\n{\n    return Cli_CopyRamToRom(Client, Timeout);\n}\n//---------------------------------------------------------------------------\nint TS7Client::Compress(int Timeout)\n{\n    return Cli_Compress(Client, Timeout);\n}\n//---------------------------------------------------------------------------\nint TS7Client::GetProtection(PS7Protection pUsrData)\n{\n    return Cli_GetProtection(Client, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::SetSessionPassword(char *Password)\n{\n    return Cli_SetSessionPassword(Client, Password);\n}\n//---------------------------------------------------------------------------\nint TS7Client::ClearSessionPassword()\n{\n    return Cli_ClearSessionPassword(Client);\n}\n//---------------------------------------------------------------------------\nint TS7Client::ExecTime()\n{\n    int Time;\n    int Result = Cli_GetExecTime(Client, &Time);\n    if (Result==0)\n        return Time;\n    else\n        return Result;\n}\n//---------------------------------------------------------------------------\nint TS7Client::LastError()\n{\n    int LastError;\n    int Result =Cli_GetLastError(Client, &LastError);\n    if (Result==0)\n       return LastError;\n    else\n       return Result;\n}\n//---------------------------------------------------------------------------\nint TS7Client::PDULength()\n{\n    int Requested, Negotiated;\n    if (Cli_GetPduLength(Client, &Requested, &Negotiated)==0)\n        return Negotiated;\n    else\n        return 0;\n}\n//---------------------------------------------------------------------------\nint TS7Client::PDURequested()\n{\n    int Requested, Negotiated;\n    if (Cli_GetPduLength(Client, &Requested, &Negotiated)==0)\n        return Requested;\n    else\n        return 0;\n}\n//---------------------------------------------------------------------------\nint TS7Client::PlcStatus()\n{\n    int Status;\n    int Result = Cli_GetPlcStatus(Client, &Status);\n    if (Result==0)\n        return Status;\n    else\n        return Result;\n}\n//---------------------------------------------------------------------------\nbool TS7Client::Connected()\n{\n\tint ClientStatus;\n\tif (Cli_GetConnected(Client ,&ClientStatus)==0)\n\t\treturn ClientStatus!=0;\n\telse\n\t\treturn false;\n}\n//---------------------------------------------------------------------------\nint TS7Client::SetAsCallback(pfn_CliCompletion pCompletion, void *usrPtr)\n{\n    return Cli_SetAsCallback(Client, pCompletion, usrPtr);\n}\n//---------------------------------------------------------------------------\nbool TS7Client::CheckAsCompletion(int *opResult)\n{\n\treturn Cli_CheckAsCompletion(Client ,opResult)==JobComplete;\n}\n//---------------------------------------------------------------------------\nint TS7Client::WaitAsCompletion(longword Timeout)\n{\n    return Cli_WaitAsCompletion(Client, Timeout);\n}\n//---------------------------------------------------------------------------\nint TS7Client::AsReadArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData)\n{\n    return Cli_AsReadArea(Client, Area, DBNumber, Start, Amount, WordLen, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::AsWriteArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData)\n{\n    return Cli_AsWriteArea(Client, Area, DBNumber, Start, Amount, WordLen, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::AsListBlocksOfType(int BlockType,  PS7BlocksOfType pUsrData, int *ItemsCount)\n{\n    return Cli_AsListBlocksOfType(Client, BlockType,  pUsrData, ItemsCount);\n}\n//---------------------------------------------------------------------------\nint TS7Client::AsReadSZL(int ID, int Index,  PS7SZL pUsrData, int *Size)\n{\n    return Cli_AsReadSZL(Client, ID, Index, pUsrData, Size);\n}\n//---------------------------------------------------------------------------\nint TS7Client::AsReadSZLList(PS7SZLList pUsrData, int *ItemsCount)\n{\n    return Cli_AsReadSZLList(Client, pUsrData, ItemsCount);\n}\n//---------------------------------------------------------------------------\nint TS7Client::AsUpload(int BlockType, int BlockNum, void *pUsrData, int *Size)\n{\n    return Cli_AsUpload(Client, BlockType, BlockNum, pUsrData, Size);\n}\n//---------------------------------------------------------------------------\nint TS7Client::AsFullUpload(int BlockType, int BlockNum, void *pUsrData, int *Size)\n{\n    return Cli_AsFullUpload(Client, BlockType, BlockNum, pUsrData, Size);\n}\n//---------------------------------------------------------------------------\nint TS7Client::AsDownload(int BlockNum, void *pUsrData, int Size)\n{\n    return Cli_AsDownload(Client, BlockNum, pUsrData, Size);\n}\n//---------------------------------------------------------------------------\nint TS7Client::AsCopyRamToRom(int Timeout)\n{\n    return Cli_AsCopyRamToRom(Client, Timeout);\n}\n//---------------------------------------------------------------------------\nint TS7Client::AsCompress(int Timeout)\n{\n    return Cli_AsCompress(Client, Timeout);\n}\n//---------------------------------------------------------------------------\nint TS7Client::AsDBRead(int DBNumber, int Start, int Size, void *pUsrData)\n{\n    return Cli_AsDBRead(Client, DBNumber, Start, Size, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::AsDBWrite(int DBNumber, int Start, int Size, void *pUsrData)\n{\n    return Cli_AsDBWrite(Client, DBNumber, Start, Size, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::AsMBRead(int Start, int Size, void *pUsrData)\n{\n    return Cli_AsMBRead(Client, Start, Size, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::AsMBWrite(int Start, int Size, void *pUsrData)\n{\n    return Cli_AsMBWrite(Client, Start, Size, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::AsEBRead(int Start, int Size, void *pUsrData)\n{\n    return Cli_AsEBRead(Client, Start, Size, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::AsEBWrite(int Start, int Size, void *pUsrData)\n{\n    return Cli_AsEBWrite(Client, Start, Size, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::AsABRead(int Start, int Size, void *pUsrData)\n{\n    return Cli_AsABRead(Client, Start, Size, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::AsABWrite(int Start, int Size, void *pUsrData)\n{\n    return Cli_AsABWrite(Client, Start, Size, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::AsTMRead(int Start, int Amount, void *pUsrData)\n{\n    return Cli_AsTMRead(Client, Start, Amount, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::AsTMWrite(int Start, int Amount, void *pUsrData)\n{\n    return Cli_AsTMWrite(Client, Start, Amount, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::AsCTRead(int Start, int Amount, void *pUsrData)\n{\n    return Cli_AsCTRead(Client, Start, Amount, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::AsCTWrite(int Start, int Amount, void *pUsrData)\n{\n    return Cli_AsCTWrite(Client, Start, Amount, pUsrData);\n}\n//---------------------------------------------------------------------------\nint TS7Client::AsDBGet(int DBNumber, void *pUsrData, int *Size)\n{\n    return Cli_AsDBGet(Client, DBNumber, pUsrData, Size);\n}\n//---------------------------------------------------------------------------\nint TS7Client::AsDBFill(int DBNumber, int FillChar)\n{\n    return Cli_AsDBFill(Client, DBNumber, FillChar);\n}\n//==============================================================================\n// SERVER\n//==============================================================================\nTS7Server::TS7Server()\n{\n    Server=Srv_Create();\n}\n//---------------------------------------------------------------------------\nTS7Server::~TS7Server()\n{\n    Srv_Destroy(&Server);\n}\n//---------------------------------------------------------------------------\nint TS7Server::Start()\n{\n    return Srv_Start(Server);\n}\n//---------------------------------------------------------------------------\nint TS7Server::StartTo(const char *Address)\n{\n    return Srv_StartTo(Server, Address);\n}\n//---------------------------------------------------------------------------\nint TS7Server::Stop()\n{\n    return Srv_Stop(Server);\n}\n//---------------------------------------------------------------------------\nint TS7Server::GetParam(int ParamNumber, void *pValue)\n{\n    return Srv_GetParam(Server, ParamNumber, pValue);\n}\n//---------------------------------------------------------------------------\nint TS7Server::SetParam(int ParamNumber, void *pValue)\n{\n    return Srv_SetParam(Server, ParamNumber, pValue);\n}\n//---------------------------------------------------------------------------\nint TS7Server::SetEventsCallback(pfn_SrvCallBack PCallBack, void *UsrPtr)\n{\n    return Srv_SetEventsCallback(Server, PCallBack, UsrPtr);\n}\n//---------------------------------------------------------------------------\nint TS7Server::SetReadEventsCallback(pfn_SrvCallBack PCallBack, void *UsrPtr)\n{\n\treturn Srv_SetReadEventsCallback(Server, PCallBack, UsrPtr);\n}\n//---------------------------------------------------------------------------\nint TS7Server::SetRWAreaCallback(pfn_RWAreaCallBack PCallBack, void *UsrPtr)\n{\n\treturn Srv_SetRWAreaCallback(Server, PCallBack, UsrPtr);\n}\n//---------------------------------------------------------------------------\nbool TS7Server::PickEvent(TSrvEvent *pEvent)\n{\n    int EvtReady;\n    if (Srv_PickEvent(Server, pEvent, &EvtReady)==0)\n       return EvtReady!=0;\n    else\n       return false;\n}\n//---------------------------------------------------------------------------\nvoid TS7Server::ClearEvents()\n{\n    Srv_ClearEvents(Server);\n}\n//---------------------------------------------------------------------------\nlongword TS7Server::GetEventsMask()\n{\n    longword Mask;\n    int Result = Srv_GetMask(Server, mkEvent, &Mask);\n    if (Result==0)\n        return Mask;\n    else\n        return 0;\n}\n//---------------------------------------------------------------------------\nlongword TS7Server::GetLogMask()\n{\n    longword Mask;\n    int Result = Srv_GetMask(Server, mkLog, &Mask);\n    if (Result==0)\n        return Mask;\n    else\n        return 0;\n}\n//---------------------------------------------------------------------------\nvoid TS7Server::SetEventsMask(longword Mask)\n{\n    Srv_SetMask(Server, mkEvent, Mask);\n}\n//---------------------------------------------------------------------------\nvoid TS7Server::SetLogMask(longword Mask)\n{\n    Srv_SetMask(Server, mkLog, Mask);\n}\n//---------------------------------------------------------------------------\nint TS7Server::RegisterArea(int AreaCode, word Index, void *pUsrData, word Size)\n{\n    return Srv_RegisterArea(Server, AreaCode, Index, pUsrData, Size);\n}\n//---------------------------------------------------------------------------\nint TS7Server::UnregisterArea(int AreaCode, word Index)\n{\n    return Srv_UnregisterArea(Server, AreaCode, Index);\n}\n//---------------------------------------------------------------------------\nint TS7Server::LockArea(int AreaCode, word Index)\n{\n    return Srv_LockArea(Server, AreaCode, Index);\n}\n//---------------------------------------------------------------------------\nint TS7Server::UnlockArea(int AreaCode, word Index)\n{\n    return Srv_UnlockArea(Server, AreaCode, Index);\n}\n//---------------------------------------------------------------------------\nint TS7Server::ServerStatus()\n{\n    int ServerStatus, CpuStatus, ClientsCount;\n    int Result =Srv_GetStatus(Server, &ServerStatus, &CpuStatus, &ClientsCount);\n    if (Result==0)\n        return ServerStatus;\n    else\n        return Result;\n}\n//---------------------------------------------------------------------------\nint TS7Server::GetCpuStatus()\n{\n    int ServerStatus, CpuStatus, ClientsCount;\n    int Result =Srv_GetStatus(Server, &ServerStatus, &CpuStatus, &ClientsCount);\n    if (Result==0)\n            return CpuStatus;\n    else\n            return Result;\n}\n//---------------------------------------------------------------------------\nint TS7Server::ClientsCount()\n{\n    int ServerStatus, CpuStatus, ClientsCount;\n    int Result =Srv_GetStatus(Server, &ServerStatus, &CpuStatus, &ClientsCount);\n    if (Result==0)\n        return ClientsCount;\n    else\n        return Result;\n}\n//---------------------------------------------------------------------------\nint TS7Server::SetCpuStatus(int Status)\n{\n    return Srv_SetCpuStatus(Server, Status);\n}\n//==============================================================================\n// PARTNER\n//==============================================================================\nTS7Partner::TS7Partner(bool Active)\n{\n    Partner=Par_Create(int(Active));\n}\n//---------------------------------------------------------------------------\nTS7Partner::~TS7Partner()\n{\n    Par_Destroy(&Partner);\n}\n//---------------------------------------------------------------------------\nint TS7Partner::GetParam(int ParamNumber, void *pValue)\n{\n    return Par_GetParam(Partner, ParamNumber, pValue);\n}\n//---------------------------------------------------------------------------\nint TS7Partner::SetParam(int ParamNumber, void *pValue)\n{\n    return Par_SetParam(Partner, ParamNumber, pValue);\n}\n//---------------------------------------------------------------------------\nint TS7Partner::Start()\n{\n    return Par_Start(Partner);\n}\n//---------------------------------------------------------------------------\nint TS7Partner::StartTo(const char *LocalAddress, const char *RemoteAddress, int LocalTSAP, int RemoteTSAP)\n{\n    return Par_StartTo(Partner, LocalAddress, RemoteAddress, LocalTSAP, RemoteTSAP);\n}\n//---------------------------------------------------------------------------\nint TS7Partner::Stop()\n{\n    return Par_Stop(Partner);\n}\n//---------------------------------------------------------------------------\nint TS7Partner::BSend(longword R_ID, void *pUsrData, int Size)\n{\n    return Par_BSend(Partner, R_ID, pUsrData, Size);\n}\n//---------------------------------------------------------------------------\nint TS7Partner::AsBSend(longword R_ID, void *pUsrData, int Size)\n{\n    return Par_AsBSend(Partner, R_ID, pUsrData, Size);\n}\n//---------------------------------------------------------------------------\nbool TS7Partner::CheckAsBSendCompletion(int *opResult)\n{\n    return Par_CheckAsBSendCompletion(Partner ,opResult)==JobComplete;\n}\n//---------------------------------------------------------------------------\nint TS7Partner::WaitAsBSendCompletion(longword Timeout)\n{\n    return Par_WaitAsBSendCompletion(Partner, Timeout);\n}\n//---------------------------------------------------------------------------\nint TS7Partner::SetSendCallback(pfn_ParSendCompletion pCompletion, void *usrPtr)\n{\n    return Par_SetSendCallback(Partner, pCompletion, usrPtr);\n}\n//---------------------------------------------------------------------------\nint TS7Partner::BRecv(longword *R_ID, void *pUsrData, int *Size, longword Timeout)\n{\n    return Par_BRecv(Partner, R_ID, pUsrData, Size, Timeout);\n}\n//---------------------------------------------------------------------------\nbool TS7Partner::CheckAsBRecvCompletion(int *opResult, longword *R_ID, void *pUsrData, int *Size)\n{\n    return Par_CheckAsBRecvCompletion(Partner, opResult, R_ID, pUsrData, Size) == JobComplete;\n}\n//---------------------------------------------------------------------------\nint TS7Partner::SetRecvCallback(pfn_ParRecvCallBack pCallback, void *usrPtr)\n{\n    return Par_SetRecvCallback(Partner, pCallback, usrPtr);\n}\n//---------------------------------------------------------------------------\nint TS7Partner::Status()\n{\n    int ParStatus;\n    int Result = Par_GetStatus(Partner, &ParStatus);\n    if (Result==0)\n        return ParStatus;\n    else\n        return Result;\n}\n//---------------------------------------------------------------------------\nint TS7Partner::LastError()\n{\n    int Error;\n    int Result = Par_GetLastError(Partner, &Error);\n    if (Result==0)\n        return Error;\n    else\n        return Result;\n}\n//---------------------------------------------------------------------------\nint TS7Partner::GetTimes(longword *SendTime, longword *RecvTime)\n{\n    return Par_GetTimes(Partner, SendTime, RecvTime);\n}\n//---------------------------------------------------------------------------\nint TS7Partner::GetStats(longword *BytesSent, longword *BytesRecv, longword *ErrSend, longword *ErrRecv)\n{\n    return Par_GetStats(Partner, BytesSent, BytesRecv, ErrSend, ErrRecv);\n}\n//---------------------------------------------------------------------------\nbool TS7Partner::Linked()\n{\n    return Status()==par_linked;\n}\n//==============================================================================\n// Text routines\n//==============================================================================\nTextString CliErrorText(int Error)\n{\n    char text[TextLen];\n    Cli_ErrorText(Error, text, TextLen);\n    return TextString(text);\n}\n//---------------------------------------------------------------------------\nTextString SrvErrorText(int Error)\n{\n    char text[TextLen];\n    Srv_ErrorText(Error, text, TextLen);\n    return TextString(text);\n}\n//---------------------------------------------------------------------------\nTextString ParErrorText(int Error)\n{\n    char text[TextLen];\n    Par_ErrorText(Error, text, TextLen);\n    return TextString(text);\n}\n//---------------------------------------------------------------------------\nTextString SrvEventText(TSrvEvent *Event)\n{\n    char text[TextLen];\n    Srv_EventText(Event, text, TextLen);\n    return TextString(text);\n}\n\n"
  },
  {
    "path": "src/snap7.h",
    "content": "/*=============================================================================|\n|  PROJECT SNAP7                                                         1.4.0 |\n|==============================================================================|\n|  Copyright (C) 2013, 2014 Davide Nardella                                    |\n|  All rights reserved.                                                        |\n|==============================================================================|\n|  SNAP7 is free software: you can redistribute it and/or modify               |\n|  it under the terms of the Lesser GNU General Public License as published by |\n|  the Free Software Foundation, either version 3 of the License, or           |\n|  (at your option) any later version.                                         |\n|                                                                              |\n|  It means that you can distribute your commercial software linked with       |\n|  SNAP7 without the requirement to distribute the source code of your         |\n|  application and without the requirement that your application be itself     |\n|  distributed under LGPL.                                                     |\n|                                                                              |\n|  SNAP7 is distributed in the hope that it will be useful,                    |\n|  but WITHOUT ANY WARRANTY; without even the implied warranty of              |\n|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |\n|  Lesser GNU General Public License for more details.                         |\n|                                                                              |\n|  You should have received a copy of the GNU General Public License and a     |\n|  copy of Lesser GNU General Public License along with Snap7.                 |\n|  If not, see  http://www.gnu.org/licenses/                                   |\n|==============================================================================|\n|                                                                              |\n|  C/C++ Snap 7 classes/Imports definitions                                    |\n|                                                                              |\n|=============================================================================*/\n#ifndef snap7_h\n#define snap7_h\n//---------------------------------------------------------------------------\n// Platform detection\n//---------------------------------------------------------------------------\n#if defined (_WIN32)||defined(_WIN64)||defined(__WIN32__)||defined(__WINDOWS__)\n# define OS_WINDOWS\n#endif\n\n// Visual Studio needs this to use the correct time_t size\n#if defined (_WIN32) && !defined(_WIN64)\n# define _USE_32BIT_TIME_T \n#endif\n\n#if defined(unix) || defined(__unix__) || defined(__unix)\n# define PLATFORM_UNIX\n#endif\n\n#if defined(__SVR4) || defined(__svr4__)\n# define OS_SOLARIS\n#endif\n\n#if BSD>=0\n# define OS_BSD\n#endif\n\n#if defined(__APPLE__)\n# define OS_OSX\n#endif\n\n#if defined(PLATFORM_UNIX) || defined(OS_OSX)\n# include <unistd.h>\n# if defined(_POSIX_VERSION)\n#   define POSIX\n# endif\n#endif\n\n//---------------------------------------------------------------------------\n// C++ Library\n//---------------------------------------------------------------------------\n#ifdef __cplusplus\n#include <string>\n#include <time.h>\n\n// Visual C++ not C99 compliant (VS2008--)\n#ifdef _MSC_VER\n# if _MSC_VER >= 1600\n#  include <stdint.h>  // VS2010++ have it \n# else\n   typedef signed __int8     int8_t;\n   typedef signed __int16    int16_t;\n   typedef signed __int32    int32_t;\n   typedef signed __int64    int64_t;\n   typedef unsigned __int8   uint8_t;\n   typedef unsigned __int16  uint16_t;\n   typedef unsigned __int32  uint32_t;\n   typedef unsigned __int64  uint64_t;\n   #ifdef _WIN64\n     typedef unsigned __int64  uintptr_t;\n   #else\n     typedef unsigned __int32  uintptr_t;\n   #endif\n# endif\n#else\n# include <stdint.h>\n#endif\n\nextern \"C\" {\n#endif\n//---------------------------------------------------------------------------\n// C exact length types\n//---------------------------------------------------------------------------\n#ifndef __cplusplus\n\n#ifdef OS_BSD\n#  include <stdint.h>\n#  include <time.h>\n#endif\n\n#ifdef OS_OSX\n#  include <stdint.h>  \n#  include <time.h>\n#endif\n\n#ifdef OS_SOLARIS\n#  include <stdint.h>  \n#  include <time.h>\n#endif\n\n#if defined(_UINTPTR_T_DEFINED)\n#  include <stdint.h>\n#  include <time.h>\n#endif\n\n#if !defined(_UINTPTR_T_DEFINED) && !defined(OS_SOLARIS) && !defined(OS_BSD) && !defined(OS_OSX)\n  typedef unsigned char   uint8_t;  //  8 bit unsigned integer\n  typedef unsigned short  uint16_t; // 16 bit unsigned integer\n  typedef unsigned int    uint32_t; // 32 bit unsigned integer\n  typedef unsigned long   uintptr_t;// 64 bit unsigned integer\n#endif\n\n#endif\n\n#ifdef OS_WINDOWS\n# define S7API __stdcall\n#else\n# define S7API\n#endif\n\n#pragma pack(1)\n//******************************************************************************\n//                                   COMMON\n//******************************************************************************\n// Exact length types regardless of platform/processor\ntypedef uint8_t    byte;\ntypedef uint16_t   word;\ntypedef uint32_t   longword;\ntypedef byte       *pbyte;\ntypedef word       *pword;\ntypedef uintptr_t  S7Object; // multi platform/processor object reference\n                             // DON'T CONFUSE IT WITH AN OLE OBJECT, IT'S SIMPLY\n                             // AN INTEGER VALUE (32 OR 64 BIT) USED AS HANDLE.\n\n#ifndef __cplusplus\ntypedef struct\n{\n  int   tm_sec;\n  int   tm_min;\n  int   tm_hour;\n  int   tm_mday;\n  int   tm_mon;\n  int   tm_year;\n  int   tm_wday;\n  int   tm_yday;\n  int   tm_isdst;\n}tm;\n\ntypedef int bool;\n#define false 0;\n#define true  1;\n#endif\n\nconst int errLibInvalidParam  = -1;\nconst int errLibInvalidObject = -2;\n\n// CPU status\n#define S7CpuStatusUnknown  0x00\n#define S7CpuStatusRun      0x08\n#define S7CpuStatusStop     0x04\n\n// ISO Errors\nconst longword errIsoConnect            = 0x00010000; // Connection error\nconst longword errIsoDisconnect         = 0x00020000; // Disconnect error\nconst longword errIsoInvalidPDU         = 0x00030000; // Bad format\nconst longword errIsoInvalidDataSize    = 0x00040000; // Bad Datasize passed to send/recv buffer is invalid\nconst longword errIsoNullPointer    \t= 0x00050000; // Null passed as pointer\nconst longword errIsoShortPacket    \t= 0x00060000; // A short packet received\nconst longword errIsoTooManyFragments   = 0x00070000; // Too many packets without EoT flag\nconst longword errIsoPduOverflow    \t= 0x00080000; // The sum of fragments data exceded maximum packet size\nconst longword errIsoSendPacket         = 0x00090000; // An error occurred during send\nconst longword errIsoRecvPacket         = 0x000A0000; // An error occurred during recv\nconst longword errIsoInvalidParams    \t= 0x000B0000; // Invalid TSAP params\nconst longword errIsoResvd_1            = 0x000C0000; // Unassigned\nconst longword errIsoResvd_2            = 0x000D0000; // Unassigned\nconst longword errIsoResvd_3            = 0x000E0000; // Unassigned\nconst longword errIsoResvd_4            = 0x000F0000; // Unassigned\n\n// Tag Struct\ntypedef struct{\n\tint Area;\n\tint DBNumber;\n\tint Start;\n\tint Size;\n\tint WordLen;\n}TS7Tag, *PS7Tag;\n\n//------------------------------------------------------------------------------\n//                                  PARAMS LIST            \n//------------------------------------------------------------------------------\nconst int p_u16_LocalPort  \t    = 1;\nconst int p_u16_RemotePort \t    = 2;\nconst int p_i32_PingTimeout\t    = 3;\nconst int p_i32_SendTimeout     = 4;\nconst int p_i32_RecvTimeout     = 5;\nconst int p_i32_WorkInterval    = 6;\nconst int p_u16_SrcRef          = 7;\nconst int p_u16_DstRef          = 8;\nconst int p_u16_SrcTSap         = 9;\nconst int p_i32_PDURequest      = 10;\nconst int p_i32_MaxClients      = 11;\nconst int p_i32_BSendTimeout    = 12;\nconst int p_i32_BRecvTimeout    = 13;\nconst int p_u32_RecoveryTime    = 14;\nconst int p_u32_KeepAliveTime   = 15;\n\n// Client/Partner Job status \nconst int JobComplete           = 0;\nconst int JobPending            = 1;\n\n//******************************************************************************\n//                                   CLIENT\n//******************************************************************************\n\n// Error codes\nconst longword errNegotiatingPDU            = 0x00100000;\nconst longword errCliInvalidParams          = 0x00200000;\nconst longword errCliJobPending             = 0x00300000;\nconst longword errCliTooManyItems           = 0x00400000;\nconst longword errCliInvalidWordLen         = 0x00500000;\nconst longword errCliPartialDataWritten     = 0x00600000;\nconst longword errCliSizeOverPDU            = 0x00700000;\nconst longword errCliInvalidPlcAnswer       = 0x00800000;\nconst longword errCliAddressOutOfRange      = 0x00900000;\nconst longword errCliInvalidTransportSize   = 0x00A00000;\nconst longword errCliWriteDataSizeMismatch  = 0x00B00000;\nconst longword errCliItemNotAvailable       = 0x00C00000;\nconst longword errCliInvalidValue           = 0x00D00000;\nconst longword errCliCannotStartPLC         = 0x00E00000;\nconst longword errCliAlreadyRun             = 0x00F00000;\nconst longword errCliCannotStopPLC          = 0x01000000;\nconst longword errCliCannotCopyRamToRom     = 0x01100000;\nconst longword errCliCannotCompress         = 0x01200000;\nconst longword errCliAlreadyStop            = 0x01300000;\nconst longword errCliFunNotAvailable        = 0x01400000;\nconst longword errCliUploadSequenceFailed   = 0x01500000;\nconst longword errCliInvalidDataSizeRecvd   = 0x01600000;\nconst longword errCliInvalidBlockType       = 0x01700000;\nconst longword errCliInvalidBlockNumber     = 0x01800000;\nconst longword errCliInvalidBlockSize       = 0x01900000;\nconst longword errCliDownloadSequenceFailed = 0x01A00000;\nconst longword errCliInsertRefused          = 0x01B00000;\nconst longword errCliDeleteRefused          = 0x01C00000;\nconst longword errCliNeedPassword           = 0x01D00000;\nconst longword errCliInvalidPassword        = 0x01E00000;\nconst longword errCliNoPasswordToSetOrClear = 0x01F00000;\nconst longword errCliJobTimeout             = 0x02000000;\nconst longword errCliPartialDataRead        = 0x02100000;\nconst longword errCliBufferTooSmall         = 0x02200000;\nconst longword errCliFunctionRefused        = 0x02300000;\nconst longword errCliDestroying             = 0x02400000;\nconst longword errCliInvalidParamNumber     = 0x02500000;\nconst longword errCliCannotChangeParam      = 0x02600000;\n\nconst int MaxVars     = 20; // Max vars that can be transferred with MultiRead/MultiWrite\n\n// Client Connection Type\nconst word CONNTYPE_PG                      = 0x0001;  // Connect to the PLC as a PG\nconst word CONNTYPE_OP                      = 0x0002;  // Connect to the PLC as an OP\nconst word CONNTYPE_BASIC                   = 0x0003;  // Basic connection\n\n// Area ID\nconst byte S7AreaPE   =\t0x81;\nconst byte S7AreaPA   =\t0x82;\nconst byte S7AreaMK   =\t0x83;\nconst byte S7AreaDB   =\t0x84;\nconst byte S7AreaCT   =\t0x1C;\nconst byte S7AreaTM   =\t0x1D;\n\n// Word Length\nconst int S7WLBit     = 0x01;\nconst int S7WLByte    = 0x02;\nconst int S7WLWord    = 0x04;\nconst int S7WLDWord   = 0x06;\nconst int S7WLReal    = 0x08;\nconst int S7WLCounter = 0x1C;\nconst int S7WLTimer   = 0x1D;\n\n// Block type\nconst byte Block_OB   = 0x38;\nconst byte Block_DB   = 0x41;\nconst byte Block_SDB  = 0x42;\nconst byte Block_FC   = 0x43;\nconst byte Block_SFC  = 0x44;\nconst byte Block_FB   = 0x45;\nconst byte Block_SFB  = 0x46;\n\n// Sub Block Type\nconst byte SubBlk_OB  = 0x08;\nconst byte SubBlk_DB  = 0x0A;\nconst byte SubBlk_SDB = 0x0B;\nconst byte SubBlk_FC  = 0x0C;\nconst byte SubBlk_SFC = 0x0D;\nconst byte SubBlk_FB  = 0x0E;\nconst byte SubBlk_SFB = 0x0F;\n\n// Block languages\nconst byte BlockLangAWL       = 0x01;\nconst byte BlockLangKOP       = 0x02;\nconst byte BlockLangFUP       = 0x03;\nconst byte BlockLangSCL       = 0x04;\nconst byte BlockLangDB        = 0x05;\nconst byte BlockLangGRAPH     = 0x06;\n\n// Read/Write Multivars\ntypedef struct{\n   int   Area;\n   int   WordLen;\n   int   Result;\n   int   DBNumber;\n   int   Start;\n   int   Amount;\n   void  *pdata;\n} TS7DataItem, *PS7DataItem;\n\n//typedef int TS7ResultItems[MaxVars];\n//typedef TS7ResultItems *PS7ResultItems;\n\n// List Blocks\ntypedef struct {\n   int OBCount;\n   int FBCount;\n   int FCCount;\n   int SFBCount;\n   int SFCCount;\n   int DBCount;\n   int SDBCount;\n} TS7BlocksList, *PS7BlocksList;\n\n// Blocks info\ntypedef struct {\n   int BlkType;    // Block Type (OB, DB) \n   int BlkNumber;  // Block number\n   int BlkLang;    // Block Language\n   int BlkFlags;   // Block flags\n   int MC7Size;    // The real size in bytes\n   int LoadSize;   // Load memory size\n   int LocalData;  // Local data\n   int SBBLength;  // SBB Length\n   int CheckSum;   // Checksum\n   int Version;    // Block version\n   // Chars info\n   char CodeDate[11]; // Code date\n   char IntfDate[11]; // Interface date \n   char Author[9];    // Author\n   char Family[9];    // Family\n   char Header[9];    // Header\n} TS7BlockInfo, *PS7BlockInfo ;\n\ntypedef word TS7BlocksOfType[0x2000];\ntypedef TS7BlocksOfType *PS7BlocksOfType;\n\n// Order code\ntypedef struct {\n   char Code[21];\n   byte V1;\n   byte V2;\n   byte V3;\n} TS7OrderCode, *PS7OrderCode;\n\n// CPU Info\ntypedef struct {\n   char ModuleTypeName[33];\n   char SerialNumber[25];\n   char ASName[25];\n   char Copyright[27];\n   char ModuleName[25];\n} TS7CpuInfo, *PS7CpuInfo;\n\n// CP Info\ntypedef struct {\n   int MaxPduLengt;\n   int MaxConnections;\n   int MaxMpiRate;\n   int MaxBusRate;\n} TS7CpInfo, *PS7CpInfo;\n\n// See §33.1 of \"System Software for S7-300/400 System and Standard Functions\"\n// and see SFC51 description too\ntypedef struct {\n   word LENTHDR;\n   word N_DR;\n} SZL_HEADER, *PSZL_HEADER;\n\ntypedef struct {\n   SZL_HEADER Header;\n   byte Data[0x4000-4];\n} TS7SZL, *PS7SZL;\n\n// SZL List of available SZL IDs : same as SZL but List items are big-endian adjusted\ntypedef struct {\n   SZL_HEADER Header;\n   word List[0x2000-2];\n} TS7SZLList, *PS7SZLList;\n\n// See §33.19 of \"System Software for S7-300/400 System and Standard Functions\"\ntypedef struct {\n   word  sch_schal;\n   word  sch_par;\n   word  sch_rel;\n   word  bart_sch;\n   word  anl_sch;\n} TS7Protection, *PS7Protection;\n\n// Client completion callback\ntypedef void (S7API *pfn_CliCompletion) (void *usrPtr, int opCode, int opResult);\n//------------------------------------------------------------------------------\n//  Import prototypes\n//------------------------------------------------------------------------------\nS7Object S7API Cli_Create();\nvoid S7API Cli_Destroy(S7Object *Client);\nint S7API Cli_ConnectTo(S7Object Client, const char *Address, int Rack, int Slot);\nint S7API Cli_SetConnectionParams(S7Object Client, const char *Address, word LocalTSAP, word RemoteTSAP);\nint S7API Cli_SetConnectionType(S7Object Client, word ConnectionType);\nint S7API Cli_Connect(S7Object Client);\nint S7API Cli_Disconnect(S7Object Client);\nint S7API Cli_GetParam(S7Object Client, int ParamNumber, void *pValue);\nint S7API Cli_SetParam(S7Object Client, int ParamNumber, void *pValue);\nint S7API Cli_SetAsCallback(S7Object Client, pfn_CliCompletion pCompletion, void *usrPtr);\n// Data I/O main functions\nint S7API Cli_ReadArea(S7Object Client, int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData);\nint S7API Cli_WriteArea(S7Object Client, int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData);\nint S7API Cli_ReadMultiVars(S7Object Client, PS7DataItem Item, int ItemsCount);\nint S7API Cli_WriteMultiVars(S7Object Client, PS7DataItem Item, int ItemsCount);\n// Data I/O Lean functions\nint S7API Cli_DBRead(S7Object Client, int DBNumber, int Start, int Size, void *pUsrData);\nint S7API Cli_DBWrite(S7Object Client, int DBNumber, int Start, int Size, void *pUsrData);\nint S7API Cli_MBRead(S7Object Client, int Start, int Size, void *pUsrData);\nint S7API Cli_MBWrite(S7Object Client, int Start, int Size, void *pUsrData);\nint S7API Cli_EBRead(S7Object Client, int Start, int Size, void *pUsrData);\nint S7API Cli_EBWrite(S7Object Client, int Start, int Size, void *pUsrData);\nint S7API Cli_ABRead(S7Object Client, int Start, int Size, void *pUsrData);\nint S7API Cli_ABWrite(S7Object Client, int Start, int Size, void *pUsrData);\nint S7API Cli_TMRead(S7Object Client, int Start, int Amount, void *pUsrData);\nint S7API Cli_TMWrite(S7Object Client, int Start, int Amount, void *pUsrData);\nint S7API Cli_CTRead(S7Object Client, int Start, int Amount, void *pUsrData);\nint S7API Cli_CTWrite(S7Object Client, int Start, int Amount, void *pUsrData);\n// Directory functions\nint S7API Cli_ListBlocks(S7Object Client, TS7BlocksList *pUsrData);\nint S7API Cli_GetAgBlockInfo(S7Object Client, int BlockType, int BlockNum, TS7BlockInfo *pUsrData);\nint S7API Cli_GetPgBlockInfo(S7Object Client, void *pBlock, TS7BlockInfo *pUsrData, int Size);\nint S7API Cli_ListBlocksOfType(S7Object Client, int BlockType, TS7BlocksOfType *pUsrData, int *ItemsCount);\n// Blocks functions\nint S7API Cli_Upload(S7Object Client, int BlockType, int BlockNum, void *pUsrData, int *Size);\nint S7API Cli_FullUpload(S7Object Client, int BlockType, int BlockNum, void *pUsrData, int *Size);\nint S7API Cli_Download(S7Object Client, int BlockNum, void *pUsrData, int Size);\nint S7API Cli_Delete(S7Object Client, int BlockType, int BlockNum);\nint S7API Cli_DBGet(S7Object Client, int DBNumber, void *pUsrData, int *Size);\nint S7API Cli_DBFill(S7Object Client, int DBNumber, int FillChar);\n// Date/Time functions\nint S7API Cli_GetPlcDateTime(S7Object Client, tm *DateTime);\nint S7API Cli_SetPlcDateTime(S7Object Client, tm *DateTime);\nint S7API Cli_SetPlcSystemDateTime(S7Object Client);\n// System Info functions\nint S7API Cli_GetOrderCode(S7Object Client, TS7OrderCode *pUsrData);\nint S7API Cli_GetCpuInfo(S7Object Client, TS7CpuInfo *pUsrData);\nint S7API Cli_GetCpInfo(S7Object Client, TS7CpInfo *pUsrData);\nint S7API Cli_ReadSZL(S7Object Client, int ID, int Index, TS7SZL *pUsrData, int *Size);\nint S7API Cli_ReadSZLList(S7Object Client, TS7SZLList *pUsrData, int *ItemsCount);\n// Control functions\nint S7API Cli_PlcHotStart(S7Object Client);\nint S7API Cli_PlcColdStart(S7Object Client);\nint S7API Cli_PlcStop(S7Object Client);\nint S7API Cli_CopyRamToRom(S7Object Client, int Timeout);\nint S7API Cli_Compress(S7Object Client, int Timeout);\nint S7API Cli_GetPlcStatus(S7Object Client, int *Status);\n// Security functions\nint S7API Cli_GetProtection(S7Object Client, TS7Protection *pUsrData);\nint S7API Cli_SetSessionPassword(S7Object Client, char *Password);\nint S7API Cli_ClearSessionPassword(S7Object Client);\n// Low level\nint S7API Cli_IsoExchangeBuffer(S7Object Client, void *pUsrData, int *Size);\n// Misc\nint S7API Cli_GetExecTime(S7Object Client, int *Time);\nint S7API Cli_GetLastError(S7Object Client, int *LastError);\nint S7API Cli_GetPduLength(S7Object Client, int *Requested, int *Negotiated);\nint S7API Cli_ErrorText(int Error, char *Text, int TextLen);\n// 1.1.0\nint S7API Cli_GetConnected(S7Object Client, int *Connected);\n//------------------------------------------------------------------------------\n//  Async functions\n//------------------------------------------------------------------------------\nint S7API Cli_AsReadArea(S7Object Client, int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData);\nint S7API Cli_AsWriteArea(S7Object Client, int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData);\nint S7API Cli_AsDBRead(S7Object Client, int DBNumber, int Start, int Size, void *pUsrData);\nint S7API Cli_AsDBWrite(S7Object Client, int DBNumber, int Start, int Size, void *pUsrData);\nint S7API Cli_AsMBRead(S7Object Client, int Start, int Size, void *pUsrData);\nint S7API Cli_AsMBWrite(S7Object Client, int Start, int Size, void *pUsrData);\nint S7API Cli_AsEBRead(S7Object Client, int Start, int Size, void *pUsrData);\nint S7API Cli_AsEBWrite(S7Object Client, int Start, int Size, void *pUsrData);\nint S7API Cli_AsABRead(S7Object Client, int Start, int Size, void *pUsrData);\nint S7API Cli_AsABWrite(S7Object Client, int Start, int Size, void *pUsrData);\nint S7API Cli_AsTMRead(S7Object Client, int Start, int Amount, void *pUsrData);\nint S7API Cli_AsTMWrite(S7Object Client, int Start, int Amount, void *pUsrData);\nint S7API Cli_AsCTRead(S7Object Client, int Start, int Amount, void *pUsrData);\nint S7API Cli_AsCTWrite(S7Object Client, int Start, int Amount, void *pUsrData);\nint S7API Cli_AsListBlocksOfType(S7Object Client, int BlockType, TS7BlocksOfType *pUsrData, int *ItemsCount);\nint S7API Cli_AsReadSZL(S7Object Client, int ID, int Index, TS7SZL *pUsrData, int *Size);\nint S7API Cli_AsReadSZLList(S7Object Client, TS7SZLList *pUsrData, int *ItemsCount);\nint S7API Cli_AsUpload(S7Object Client, int BlockType, int BlockNum, void *pUsrData, int *Size);\nint S7API Cli_AsFullUpload(S7Object Client, int BlockType, int BlockNum, void *pUsrData, int *Size);\nint S7API Cli_AsDownload(S7Object Client, int BlockNum, void *pUsrData, int Size);\nint S7API Cli_AsCopyRamToRom(S7Object Client, int Timeout);\nint S7API Cli_AsCompress(S7Object Client, int Timeout);\nint S7API Cli_AsDBGet(S7Object Client, int DBNumber, void *pUsrData, int *Size);\nint S7API Cli_AsDBFill(S7Object Client, int DBNumber, int FillChar);\nint S7API Cli_CheckAsCompletion(S7Object Client, int *opResult);\nint S7API Cli_WaitAsCompletion(S7Object Client, int Timeout);\n\n//******************************************************************************\n//                                   SERVER\n//******************************************************************************\nconst int OperationRead  = 0;\nconst int OperationWrite = 1;\n\nconst int mkEvent = 0;\nconst int mkLog   = 1;\n\n// Server Area ID  (use with Register/unregister - Lock/unlock Area)\nconst int srvAreaPE = 0;\nconst int srvAreaPA = 1;\nconst int srvAreaMK = 2;\nconst int srvAreaCT = 3;\nconst int srvAreaTM = 4;\nconst int srvAreaDB = 5;\n\n// Errors\nconst longword errSrvCannotStart        = 0x00100000; // Server cannot start\nconst longword errSrvDBNullPointer      = 0x00200000; // Passed null as PData\nconst longword errSrvAreaAlreadyExists  = 0x00300000; // Area Re-registration\nconst longword errSrvUnknownArea        = 0x00400000; // Unknown area\nconst longword errSrvInvalidParams      = 0x00500000; // Invalid param(s) supplied\nconst longword errSrvTooManyDB          = 0x00600000; // Cannot register DB\nconst longword errSrvInvalidParamNumber = 0x00700000; // Invalid param (srv_get/set_param)\nconst longword errSrvCannotChangeParam  = 0x00800000; // Cannot change because running\n\n// TCP Server Event codes\nconst longword evcServerStarted       = 0x00000001;\nconst longword evcServerStopped       = 0x00000002;\nconst longword evcListenerCannotStart = 0x00000004;\nconst longword evcClientAdded         = 0x00000008;\nconst longword evcClientRejected      = 0x00000010;\nconst longword evcClientNoRoom        = 0x00000020;\nconst longword evcClientException     = 0x00000040;\nconst longword evcClientDisconnected  = 0x00000080;\nconst longword evcClientTerminated    = 0x00000100;\nconst longword evcClientsDropped      = 0x00000200;\nconst longword evcReserved_00000400   = 0x00000400; // actually unused\nconst longword evcReserved_00000800   = 0x00000800; // actually unused\nconst longword evcReserved_00001000   = 0x00001000; // actually unused\nconst longword evcReserved_00002000   = 0x00002000; // actually unused\nconst longword evcReserved_00004000   = 0x00004000; // actually unused\nconst longword evcReserved_00008000   = 0x00008000; // actually unused\n// S7 Server Event Code\nconst longword evcPDUincoming  \t      = 0x00010000;\nconst longword evcDataRead            = 0x00020000;\nconst longword evcDataWrite    \t      = 0x00040000;\nconst longword evcNegotiatePDU        = 0x00080000;\nconst longword evcReadSZL             = 0x00100000;\nconst longword evcClock               = 0x00200000;\nconst longword evcUpload              = 0x00400000;\nconst longword evcDownload            = 0x00800000;\nconst longword evcDirectory           = 0x01000000;\nconst longword evcSecurity            = 0x02000000;\nconst longword evcControl             = 0x04000000;\nconst longword evcReserved_08000000   = 0x08000000; // actually unused\nconst longword evcReserved_10000000   = 0x10000000; // actually unused\nconst longword evcReserved_20000000   = 0x20000000; // actually unused\nconst longword evcReserved_40000000   = 0x40000000; // actually unused\nconst longword evcReserved_80000000   = 0x80000000; // actually unused\n// Masks to enable/disable all events\nconst longword evcAll                 = 0xFFFFFFFF;\nconst longword evcNone                = 0x00000000;\n// Event SubCodes\nconst word evsUnknown                 = 0x0000;\nconst word evsStartUpload             = 0x0001;\nconst word evsStartDownload           = 0x0001;\nconst word evsGetBlockList            = 0x0001;\nconst word evsStartListBoT            = 0x0002;\nconst word evsListBoT                 = 0x0003;\nconst word evsGetBlockInfo            = 0x0004;\nconst word evsGetClock                = 0x0001;\nconst word evsSetClock                = 0x0002;\nconst word evsSetPassword             = 0x0001;\nconst word evsClrPassword             = 0x0002;\n// Event Params : functions group\nconst word grProgrammer               = 0x0041;\nconst word grCyclicData               = 0x0042;\nconst word grBlocksInfo               = 0x0043;\nconst word grSZL                      = 0x0044;\nconst word grPassword                 = 0x0045;\nconst word grBSend                    = 0x0046;\nconst word grClock                    = 0x0047;\nconst word grSecurity                 = 0x0045;\n// Event Params : control codes\nconst word CodeControlUnknown         = 0x0000;\nconst word CodeControlColdStart       = 0x0001;\nconst word CodeControlWarmStart       = 0x0002;\nconst word CodeControlStop            = 0x0003;\nconst word CodeControlCompress        = 0x0004;\nconst word CodeControlCpyRamRom       = 0x0005;\nconst word CodeControlInsDel          = 0x0006;\n// Event Result\nconst word evrNoError                 = 0x0000;\nconst word evrFragmentRejected        = 0x0001;\nconst word evrMalformedPDU            = 0x0002;\nconst word evrSparseBytes             = 0x0003;\nconst word evrCannotHandlePDU         = 0x0004;\nconst word evrNotImplemented          = 0x0005;\nconst word evrErrException            = 0x0006;\nconst word evrErrAreaNotFound         = 0x0007;\nconst word evrErrOutOfRange           = 0x0008;\nconst word evrErrOverPDU              = 0x0009;\nconst word evrErrTransportSize        = 0x000A;\nconst word evrInvalidGroupUData       = 0x000B;\nconst word evrInvalidSZL              = 0x000C;\nconst word evrDataSizeMismatch        = 0x000D;\nconst word evrCannotUpload            = 0x000E;\nconst word evrCannotDownload          = 0x000F;\nconst word evrUploadInvalidID         = 0x0010;\nconst word evrResNotFound             = 0x0011;\n\ntypedef struct{\n\ttime_t EvtTime;    // Timestamp\n\tint EvtSender;     // Sender\n\tlongword EvtCode;  // Event code\n\tword EvtRetCode;   // Event result\n\tword EvtParam1;    // Param 1 (if available)\n\tword EvtParam2;    // Param 2 (if available)\n\tword EvtParam3;    // Param 3 (if available)\n\tword EvtParam4;    // Param 4 (if available)\n}TSrvEvent, *PSrvEvent;\n\n// Server Events callback\ntypedef void (S7API *pfn_SrvCallBack)(void *usrPtr, PSrvEvent PEvent, int Size);\n// Server Read/Write callback\ntypedef int(S7API *pfn_RWAreaCallBack)(void *usrPtr, int Sender, int Operation, PS7Tag PTag, void *pUsrData);\n\nS7Object S7API Srv_Create();\nvoid S7API Srv_Destroy(S7Object *Server);\nint S7API Srv_GetParam(S7Object Server, int ParamNumber, void *pValue);\nint S7API Srv_SetParam(S7Object Server, int ParamNumber, void *pValue);\nint S7API Srv_StartTo(S7Object Server, const char *Address);\nint S7API Srv_Start(S7Object Server);\nint S7API Srv_Stop(S7Object Server);\nint S7API Srv_RegisterArea(S7Object Server, int AreaCode, word Index, void *pUsrData, int Size);\nint S7API Srv_UnregisterArea(S7Object Server, int AreaCode, word Index);\nint S7API Srv_LockArea(S7Object Server, int AreaCode, word Index);\nint S7API Srv_UnlockArea(S7Object Server, int AreaCode, word Index);\nint S7API Srv_GetStatus(S7Object Server, int *ServerStatus, int *CpuStatus, int *ClientsCount);\nint S7API Srv_SetCpuStatus(S7Object Server, int CpuStatus);\nint S7API Srv_ClearEvents(S7Object Server);\nint S7API Srv_PickEvent(S7Object Server, TSrvEvent *pEvent, int *EvtReady);\nint S7API Srv_GetMask(S7Object Server, int MaskKind, longword *Mask);\nint S7API Srv_SetMask(S7Object Server, int MaskKind, longword Mask);\nint S7API Srv_SetEventsCallback(S7Object Server, pfn_SrvCallBack pCallback, void *usrPtr);\nint S7API Srv_SetReadEventsCallback(S7Object Server, pfn_SrvCallBack pCallback, void *usrPtr);\nint S7API Srv_SetRWAreaCallback(S7Object Server, pfn_RWAreaCallBack pCallback, void *usrPtr);\nint S7API Srv_EventText(TSrvEvent *Event, char *Text, int TextLen);\nint S7API Srv_ErrorText(int Error, char *Text, int TextLen);\n\n//******************************************************************************\n//                                   PARTNER\n//******************************************************************************\n\n// Status\nconst int par_stopped         = 0;   // stopped\nconst int par_connecting      = 1;   // running and active connecting\nconst int par_waiting         = 2;   // running and waiting for a connection\nconst int par_linked          = 3;   // running and connected : linked\nconst int par_sending         = 4;   // sending data\nconst int par_receiving       = 5;   // receiving data\nconst int par_binderror       = 6;   // error starting passive server\n\n// Errors\nconst longword errParAddressInUse       = 0x00200000;\nconst longword errParNoRoom             = 0x00300000;\nconst longword errServerNoRoom          = 0x00400000;\nconst longword errParInvalidParams      = 0x00500000;\nconst longword errParNotLinked          = 0x00600000;\nconst longword errParBusy               = 0x00700000;\nconst longword errParFrameTimeout       = 0x00800000;\nconst longword errParInvalidPDU         = 0x00900000;\nconst longword errParSendTimeout        = 0x00A00000;\nconst longword errParRecvTimeout        = 0x00B00000;\nconst longword errParSendRefused        = 0x00C00000;\nconst longword errParNegotiatingPDU     = 0x00D00000;\nconst longword errParSendingBlock       = 0x00E00000;\nconst longword errParRecvingBlock       = 0x00F00000;\nconst longword errParBindError          = 0x01000000;\nconst longword errParDestroying         = 0x01100000;\nconst longword errParInvalidParamNumber = 0x01200000; // Invalid param (par_get/set_param)\nconst longword errParCannotChangeParam  = 0x01300000; // Cannot change because running\nconst longword errParBufferTooSmall     = 0x01400000; // Raised by LabVIEW wrapper\n\n// Brecv Data incoming Callback\ntypedef void (S7API *pfn_ParRecvCallBack)(void * usrPtr, int opResult, longword R_ID, void *pData, int Size);\n// BSend Completion Callback\ntypedef void (S7API *pfn_ParSendCompletion)(void * usrPtr, int opResult);\n\nS7Object S7API Par_Create(int Active);\nvoid S7API Par_Destroy(S7Object *Partner);\nint S7API Par_GetParam(S7Object Partner, int ParamNumber, void *pValue);\nint S7API Par_SetParam(S7Object Partner, int ParamNumber, void *pValue);\nint S7API Par_StartTo(S7Object Partner, const char *LocalAddress, const char *RemoteAddress,\n    word LocTsap, word RemTsap);\nint S7API Par_Start(S7Object Partner);\nint S7API Par_Stop(S7Object Partner);\n// BSend\nint S7API Par_BSend(S7Object Partner, longword R_ID, void *pUsrData, int Size);\nint S7API Par_AsBSend(S7Object Partner, longword R_ID, void *pUsrData, int Size);\nint S7API Par_CheckAsBSendCompletion(S7Object Partner, int *opResult);\nint S7API Par_WaitAsBSendCompletion(S7Object Partner, longword Timeout);\nint S7API Par_SetSendCallback(S7Object Partner, pfn_ParSendCompletion pCompletion, void *usrPtr);\n// BRecv\nint S7API Par_BRecv(S7Object Partner, longword *R_ID, void *pData, int *Size, longword Timeout);\nint S7API Par_CheckAsBRecvCompletion(S7Object Partner, int *opResult, longword *R_ID,\n\tvoid *pData, int *Size);\nint S7API Par_SetRecvCallback(S7Object Partner, pfn_ParRecvCallBack pCompletion, void *usrPtr);\n// Stat\nint S7API Par_GetTimes(S7Object Partner, longword *SendTime, longword *RecvTime);\nint S7API Par_GetStats(S7Object Partner, longword *BytesSent, longword *BytesRecv,\n\tlongword *SendErrors, longword *RecvErrors);\nint S7API Par_GetLastError(S7Object Partner, int *LastError);\nint S7API Par_GetStatus(S7Object Partner, int *Status);\nint S7API Par_ErrorText(int Error, char *Text, int TextLen);\n\n\n#pragma pack()\n#ifdef __cplusplus\n }\n#endif // __cplusplus\n\n#ifdef __cplusplus\n\n//******************************************************************************\n//                           CLIENT CLASS DEFINITION\n//******************************************************************************\nclass TS7Client\n{\nprivate:\n    S7Object Client;\npublic:\n\tTS7Client();\n\t~TS7Client();\n    // Control functions\n    int Connect();\n    int ConnectTo(const char *RemAddress, int Rack, int Slot);\n    int SetConnectionParams(const char *RemAddress, word LocalTSAP, word RemoteTSAP);\n    int SetConnectionType(word ConnectionType);\n    int Disconnect();\n    int GetParam(int ParamNumber, void *pValue);\n    int SetParam(int ParamNumber, void *pValue);\n    // Data I/O Main functions\n    int ReadArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData);\n    int WriteArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData);\n    int ReadMultiVars(PS7DataItem Item, int ItemsCount);\n    int WriteMultiVars(PS7DataItem Item, int ItemsCount);\n    // Data I/O Lean functions\n    int DBRead(int DBNumber, int Start, int Size, void *pUsrData);\n    int DBWrite(int DBNumber, int Start, int Size, void *pUsrData);\n    int MBRead(int Start, int Size, void *pUsrData);\n    int MBWrite(int Start, int Size, void *pUsrData);\n    int EBRead(int Start, int Size, void *pUsrData);\n    int EBWrite(int Start, int Size, void *pUsrData);\n    int ABRead(int Start, int Size, void *pUsrData);\n    int ABWrite(int Start, int Size, void *pUsrData);\n    int TMRead(int Start, int Amount, void *pUsrData);\n    int TMWrite(int Start, int Amount, void *pUsrData);\n    int CTRead(int Start, int Amount, void *pUsrData);\n    int CTWrite(int Start, int Amount, void *pUsrData);\n    // Directory functions\n    int ListBlocks(PS7BlocksList pUsrData);\n    int GetAgBlockInfo(int BlockType, int BlockNum, PS7BlockInfo pUsrData);\n    int GetPgBlockInfo(void *pBlock, PS7BlockInfo pUsrData, int Size);\n    int ListBlocksOfType(int BlockType, TS7BlocksOfType *pUsrData, int *ItemsCount);\n    // Blocks functions\n    int Upload(int BlockType, int BlockNum, void *pUsrData, int *Size);\n    int FullUpload(int BlockType, int BlockNum, void *pUsrData, int *Size);\n    int Download(int BlockNum, void *pUsrData, int Size);\n    int Delete(int BlockType, int BlockNum);\n    int DBGet(int DBNumber, void *pUsrData, int *Size);\n    int DBFill(int DBNumber, int FillChar);\n    // Date/Time functions\n    int GetPlcDateTime(tm *DateTime);\n    int SetPlcDateTime(tm *DateTime);\n    int SetPlcSystemDateTime();\n    // System Info functions\n    int GetOrderCode(PS7OrderCode pUsrData);\n    int GetCpuInfo(PS7CpuInfo pUsrData);\n    int GetCpInfo(PS7CpInfo pUsrData);\n\tint ReadSZL(int ID, int Index, PS7SZL pUsrData, int *Size);\n\tint ReadSZLList(PS7SZLList pUsrData, int *ItemsCount);\n\t// Control functions\n\tint PlcHotStart();\n\tint PlcColdStart();\n\tint PlcStop();\n\tint CopyRamToRom(int Timeout);\n\tint Compress(int Timeout);\n\t// Security functions\n\tint GetProtection(PS7Protection pUsrData);\n\tint SetSessionPassword(char *Password);\n\tint ClearSessionPassword();\n\t// Properties\n\tint ExecTime();\n\tint LastError();\n\tint PDURequested();\n\tint PDULength();\n\tint PlcStatus();\n\tbool Connected();\n\t// Async functions\n\tint SetAsCallback(pfn_CliCompletion pCompletion, void *usrPtr);\n\tbool CheckAsCompletion(int *opResult);\n\tint WaitAsCompletion(longword Timeout);\n\tint AsReadArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData);\n\tint AsWriteArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData);\n\tint AsListBlocksOfType(int BlockType, PS7BlocksOfType pUsrData, int *ItemsCount);\n\tint AsReadSZL(int ID, int Index, PS7SZL pUsrData, int *Size);\n\tint AsReadSZLList(PS7SZLList pUsrData, int *ItemsCount);\n\tint AsUpload(int BlockType, int BlockNum, void *pUsrData, int *Size);\n\tint AsFullUpload(int BlockType, int BlockNum, void *pUsrData, int *Size);\n\tint AsDownload(int BlockNum, void *pUsrData,  int Size);\n\tint AsCopyRamToRom(int Timeout);\n\tint AsCompress(int Timeout);\n\tint AsDBRead(int DBNumber, int Start, int Size, void *pUsrData);\n\tint AsDBWrite(int DBNumber, int Start, int Size, void *pUsrData);\n\tint AsMBRead(int Start, int Size, void *pUsrData);\n\tint AsMBWrite(int Start, int Size, void *pUsrData);\n\tint AsEBRead(int Start, int Size, void *pUsrData);\n\tint AsEBWrite(int Start, int Size, void *pUsrData);\n\tint AsABRead(int Start, int Size, void *pUsrData);\n\tint AsABWrite(int Start, int Size, void *pUsrData);\n    int AsTMRead(int Start, int Amount, void *pUsrData);\n    int AsTMWrite(int Start, int Amount, void *pUsrData);\n    int AsCTRead(int Start, int Amount, void *pUsrData);\n\tint AsCTWrite(int Start, int Amount, void *pUsrData);\n    int AsDBGet(int DBNumber, void *pUsrData, int *Size);\n\tint AsDBFill(int DBNumber, int FillChar);\n};\ntypedef TS7Client *PS7Client;\n//******************************************************************************\n//                           SERVER CLASS DEFINITION\n//******************************************************************************\nclass TS7Server\n{\nprivate:\n    S7Object Server;\npublic:\n    TS7Server();\n    ~TS7Server();\n    // Control\n    int Start();\n    int StartTo(const char *Address);\n    int Stop();\n    int GetParam(int ParamNumber, void *pValue);\n    int SetParam(int ParamNumber, void *pValue);\n    // Events\n    int SetEventsCallback(pfn_SrvCallBack PCallBack, void *UsrPtr);\n\tint SetReadEventsCallback(pfn_SrvCallBack PCallBack, void *UsrPtr);\n\tint SetRWAreaCallback(pfn_RWAreaCallBack PCallBack, void *UsrPtr);\n    bool PickEvent(TSrvEvent *pEvent);\n    void ClearEvents();\n    longword GetEventsMask();\n    longword GetLogMask();\n    void SetEventsMask(longword Mask);\n    void SetLogMask(longword Mask);\n    // Resources\n    int RegisterArea(int AreaCode, word Index, void *pUsrData, word Size);\n    int UnregisterArea(int AreaCode, word Index);\n    int LockArea(int AreaCode, word Index);\n    int UnlockArea(int AreaCode, word Index);\n    // Properties\n    int ServerStatus();\n    int GetCpuStatus();\n    int SetCpuStatus(int Status);\n\tint ClientsCount();\n};\ntypedef TS7Server *PS7Server;\n\n//******************************************************************************\n//                          PARTNER CLASS DEFINITION\n//******************************************************************************\nclass TS7Partner\n{\nprivate:\n\tS7Object Partner; // Partner Handle\npublic:\n\tTS7Partner(bool Active);\n\t~TS7Partner();\n\t// Control\n\tint GetParam(int ParamNumber, void *pValue);\n\tint SetParam(int ParamNumber, void *pValue);\n\tint Start();\n\tint StartTo(const char *LocalAddress,\n\t\t\t\tconst char *RemoteAddress,\n\t\t\t\tint LocalTSAP,\n\t\t\t\tint RemoteTSAP);\n\tint Stop();\n\t// Data I/O functions : BSend\n\tint BSend(longword R_ID, void *pUsrData, int Size);\n\tint AsBSend(longword R_ID, void *pUsrData, int Size);\n\tbool CheckAsBSendCompletion(int *opResult);\n\tint WaitAsBSendCompletion(longword Timeout);\n\tint SetSendCallback(pfn_ParSendCompletion pCompletion, void *usrPtr);\n\t// Data I/O functions : BRecv\n\tint BRecv(longword *R_ID, void *pUsrData, int *Size, longword Timeout);\n\tbool CheckAsBRecvCompletion(int *opResult, longword *R_ID, void *pUsrData, int *Size);\n\tint SetRecvCallback(pfn_ParRecvCallBack pCallback, void *usrPtr);\n\t// Properties\n\tint Status();\n\tint LastError();\n\tint GetTimes(longword *SendTime, longword *RecvTime);\n\tint GetStats(longword *BytesSent,\n\t\t\t\t longword *BytesRecv,\n\t\t\t\t longword *ErrSend,\n\t\t\t\t longword *ErrRecv);\n\tbool Linked();\n};\ntypedef TS7Partner *PS7Partner;\n//******************************************************************************\n//                               TEXT ROUTINES\n// Only for C++, for pure C use xxx_ErrorText() which uses *char\n//******************************************************************************\n#define TextLen 1024\n\n// String type\n// Here we define generic TextString (by default mapped onto std::string).\n// So you can change it if needed (Unicodestring, Ansistring etc...)\n\ntypedef std::string TextString;\n\nTextString CliErrorText(int Error);\nTextString SrvErrorText(int Error);\nTextString ParErrorText(int Error);\nTextString SrvEventText(TSrvEvent *Event);\n\n\n#endif // __cplusplus\n#endif // snap7_h\n"
  }
]