nimbuscontrols / EIPScanner

Free implementation of EtherNet/IP in C++
https://eipscanner.readthedocs.io/en/latest/
MIT License
224 stars 90 forks source link

IO Timeout? #99

Closed nicktramp closed 10 months ago

nicktramp commented 11 months ago

When establishing implicit comms with a Brooks SLA5800-series MFC, IO packets are sent back and forth (per Wireshark), but the receiving data listener isn't called and the connection times out before a Forward_Close request is made. Examining the Wireshark trace, the O->T connection uses a randomly chosen source port and udp/2222 for destination port, but the device uses udp/2222 for both source and destination ports. Does this mean the library is listening for connections on the randomly chosen UDP port, rather than udp/2222? I realize there are 2 connections being made (O->T & T->O); how can I check which port the library is listening on?

Here's the code, only a slightly modified version of the implicit messaging example:


  /* Implicit Messaging Exmple */
#include <sstream>
#include <cip/connectionManager/NetworkConnectionParams.h>
#include "SessionInfo.h"
#include "ConnectionManager.h"
#include "utils/Logger.h"
#include "utils/Buffer.h"
#include "cip/Types.h"

using namespace eipScanner::cip;
using eipScanner::SessionInfo;
using eipScanner::MessageRouter;
using eipScanner::ConnectionManager;
using eipScanner::cip::connectionManager::ConnectionParameters;
using eipScanner::cip::connectionManager::NetworkConnectionParams;
using eipScanner::utils::Buffer;
using eipScanner::utils::Logger;
using eipScanner::utils::LogLevel;

int main() {
        Logger::setLogLevel(LogLevel::DEBUG);
        ConnectionManager connectionManager;
        auto si = std::make_shared<SessionInfo>("192.168.1.100", 0xAF12);

        ConnectionParameters parameters;
        parameters.connectionPath = {0x20, 0x04, 0x2C, 0x65, 0x2C, 0xC9}; // output Assm101, intput Assm201
        parameters.o2tRealTimeFormat = true;
        parameters.originatorVendorId = 342;
        parameters.originatorSerialNumber = 32423;
        parameters.t2oNetworkConnectionParams |= NetworkConnectionParams::P2P;
        parameters.t2oNetworkConnectionParams |= NetworkConnectionParams::SCHEDULED_PRIORITY;
        parameters.t2oNetworkConnectionParams |= 28; //size of Assm201
        parameters.o2tNetworkConnectionParams |= NetworkConnectionParams::P2P;
        parameters.o2tNetworkConnectionParams |= NetworkConnectionParams::SCHEDULED_PRIORITY;
        parameters.o2tNetworkConnectionParams |= 24; //size of Assm101
        parameters.originatorSerialNumber = 0x12345;
        parameters.o2tRPI = 1000000;
        parameters.t2oRPI = 1000000;
        parameters.transportTypeTrigger |= NetworkConnectionParams::CLASS1;

        auto io = connectionManager.forwardOpen(si, parameters);
        if (auto ptr = io.lock()) {
            Buffer assm101;
            CipReal setpoint = 10.0;
            CipDint valveOverrideMode = 0;
            CipDint controlMode = 0;        // auto
            CipReal controlVal = 0.0;      // not used for auto
            CipDint totalizerControl = 2;   // 1:run, 2:stop, reset:3
            CipDint calInstance = 1;        // calibration instance
            assm101 << setpoint << valveOverrideMode << controlMode << controlVal << totalizerControl << calInstance;
            ptr->setDataToSend(assm101.data());
            ptr->setReceiveDataListener([](auto realTimeHeader, auto sequence, auto data) {
                    std::ostringstream ss;
                    ss << "secNum=" << sequence << " data=";
                    for (auto &byte : data) {
                            ss << "[" << std::hex << (int) byte << "]";
                    }
                    Logger(LogLevel::INFO) << "Received: " << ss.str();
            });
            ptr->setCloseListener([]() {
                    Logger(LogLevel::INFO) << "Closed";
            });
        }
        int count = 200;
        while (connectionManager.hasOpenConnections() && count-- > 0) {
            connectionManager.handleConnections(std::chrono::milliseconds(100));
        }
        connectionManager.forwardClose(si, io);
        return 0;
}

I don't see any Socket Address Info Items being sent to the device, so I expected spec-defined defaults to be used and a Forward Close request after seeing the received data logged from the listener/callback.

Logs [DEBUG] Opened TCP socket fd=3 [DEBUG] Connecting to 192.168.1.100:44818 [INFO] Registered session 1 [INFO] Send request: service=0x54 epath=[classId=6 objectId=1] [INFO] Open IO connection O2T_ID=7798808 T2O_ID=3790471169 SerialNumber 1 [DEBUG] Opened UDP socket fd=4 [INFO] Open UDP socket to send data to 192.168.1.100:2222 [DEBUG] Opened UDP socket fd=5 [WARNING] Connection SeriaNumber=1 is closed by timeout [INFO] Closed [DEBUG] Close UDP socket fd=4 [WARNING] Attempt to close an already closed connection [INFO] Unregistered session 1 [DEBUG] Close TCP socket fd=3 [DEBUG] Close UDP socket fd=5

Environment:

IO_notClosing.pcapng.txt

nicktramp commented 10 months ago

Since I'm seeing a similar (maybe even the exact same) problem as in #64 (though the fix there did not work), I'll close this in favor of that one. If I can find a fix, I'll update that thread and submit a PR for it.