diff --git a/include/odva_ethernetip/connection.h b/include/odva_ethernetip/connection.h index 17ad9df..3a180b0 100644 --- a/include/odva_ethernetip/connection.h +++ b/include/odva_ethernetip/connection.h @@ -92,7 +92,17 @@ class Connection /** * Create the forward open request from the data in this connection object */ - shared_ptr createForwardOpenRequest(); + shared_ptr createForwardOpenRequest() + { + // Maintains backwards compatability + return createForwardOpenRequest(false); + } + + /** + * Create the forward open request from the data in this connection object + * @param use_legacy_forward_open_request use 16 bit connection parameters instead of news 32 bit parameters + */ + shared_ptr createForwardOpenRequest(bool use_legacy_forward_open_request); /** * Create a forward close request from the data in this connection object diff --git a/include/odva_ethernetip/forward_open_request.h b/include/odva_ethernetip/forward_open_request.h index 6489282..8fdc518 100644 --- a/include/odva_ethernetip/forward_open_request.h +++ b/include/odva_ethernetip/forward_open_request.h @@ -77,12 +77,26 @@ class ForwardOpenRequest : public Serializable EIP_USINT timeout_multiplyer; EIP_UDINT o_to_t_rpi; EIP_DWORD o_to_t_conn_params; + EIP_WORD o_to_t_conn_params_legacy; EIP_UDINT t_to_o_rpi; EIP_DWORD t_to_o_conn_params; + EIP_WORD t_to_o_conn_params_legacy; EIP_BYTE conn_type; + bool use_legacy_forward_open_request; + + ForwardOpenRequest() + : use_legacy_forward_open_request(false) + { + } + + ForwardOpenRequest(bool use_legacy_forward_open_request) + : use_legacy_forward_open_request(use_legacy_forward_open_request) + { + } + /** - * Helper to calculate connection parameters + * Helper to calculate connection parameters for current 32 bit connection parameters * @param size Maximum size of the messages in the connection in byte * @param variable if set to true, variable message sizes * @param priority Priority value for the connection @@ -96,13 +110,35 @@ class ForwardOpenRequest : public Serializable | (type & 0x03) << 29 | (shared ? 0x80000000 : 0); } + /** + * Helper to calculate connection parameters for legacy 16 bit connection parameters + * @param size Maximum size of the messages in the connection in byte + * @param variable if set to true, variable message sizes + * @param priority Priority value for the connection + * @param type Connection type / class info + * @param shared If set to true, then a shared connection + */ + static EIP_WORD calcConnectionParamsLegacy(EIP_UINT size, bool variable, EIP_BYTE priority, + EIP_BYTE type, bool shared) + { + return (size & 0x1FF) | (variable ? 0x200 : 0) | (priority & 0x03) << 10 + | (type & 0x03) << 13 | (shared ? 0x8000 : 0); + } + /** * Shortcut to set the origin to target parameters. */ EIP_DWORD setOriginToTargetParams(EIP_UINT size, bool variable, EIP_BYTE priority, EIP_BYTE type, bool shared) { - o_to_t_conn_params = calcConnectionParams(size, variable, priority, type, shared); + if (use_legacy_forward_open_request) + { + o_to_t_conn_params_legacy = calcConnectionParamsLegacy(size, variable, priority, type, shared); + } + else + { + o_to_t_conn_params = calcConnectionParams(size, variable, priority, type, shared); + } return 0; } @@ -112,7 +148,14 @@ class ForwardOpenRequest : public Serializable EIP_DWORD setTargetToOriginParams(EIP_UINT size, bool variable, EIP_BYTE priority, EIP_BYTE type, bool shared) { - t_to_o_conn_params = calcConnectionParams(size, variable, priority, type, shared); + if (use_legacy_forward_open_request) + { + t_to_o_conn_params_legacy = calcConnectionParamsLegacy(size, variable, priority, type, shared); + } + else + { + t_to_o_conn_params = calcConnectionParams(size, variable, priority, type, shared); + } return 0; } @@ -131,21 +174,36 @@ class ForwardOpenRequest : public Serializable */ virtual size_t getLength() const { - return sizeof(timeout_tick_size) - + sizeof(timeout_ticks) - + sizeof(o_to_t_connection_id) - + sizeof(t_to_o_connection_id) - + sizeof(connection_sn) - + sizeof(originator_vendor_id) - + sizeof(originator_sn) - + sizeof(timeout_multiplyer) - + sizeof(o_to_t_rpi) - + sizeof(o_to_t_conn_params) - + sizeof(t_to_o_rpi) - + sizeof(t_to_o_conn_params) - + sizeof(conn_type) - + 3 // reserved bytes - + path_.getLength(); + size_t ret = sizeof(timeout_tick_size); + ret += sizeof(timeout_ticks); + ret += sizeof(o_to_t_connection_id); + ret += sizeof(t_to_o_connection_id); + ret += sizeof(connection_sn); + ret += sizeof(originator_vendor_id); + ret += sizeof(originator_sn); + ret += sizeof(timeout_multiplyer); + ret += sizeof(o_to_t_rpi); + if (use_legacy_forward_open_request) + { + ret += sizeof(o_to_t_conn_params_legacy); + } + else + { + ret += sizeof(o_to_t_conn_params); + } + ret += sizeof(t_to_o_rpi); + if (use_legacy_forward_open_request) + { + ret += sizeof(t_to_o_conn_params_legacy); + } + else + { + ret += sizeof(t_to_o_conn_params); + } + ret += sizeof(conn_type); + ret += 3; // reserved bytes + ret += path_.getLength(); + return ret; } /** @@ -169,9 +227,23 @@ class ForwardOpenRequest : public Serializable writer.write(reserved); writer.write(reserved); writer.write(o_to_t_rpi); - writer.write(o_to_t_conn_params); + if (use_legacy_forward_open_request) + { + writer.write(o_to_t_conn_params_legacy); + } + else + { + writer.write(o_to_t_conn_params); + } writer.write(t_to_o_rpi); - writer.write(t_to_o_conn_params); + if (use_legacy_forward_open_request) + { + writer.write(t_to_o_conn_params_legacy); + } + else + { + writer.write(t_to_o_conn_params); + } writer.write(conn_type); path_.serialize(writer); return writer; diff --git a/include/odva_ethernetip/session.h b/include/odva_ethernetip/session.h index 4963c64..60d8214 100644 --- a/include/odva_ethernetip/session.h +++ b/include/odva_ethernetip/session.h @@ -87,6 +87,11 @@ class Session */ void close(); + /** + * Close the session without unregistering the session and just closing the port + */ + void closeWithoutUnregister(); + /** * Get the ID number assigned to this session by the target * @return session ID number @@ -153,7 +158,23 @@ class Session * @param t_to_o Target to origin connection info */ int createConnection(const EIP_CONNECTION_INFO_T& o_to_t, - const EIP_CONNECTION_INFO_T& t_to_o); + const EIP_CONNECTION_INFO_T& t_to_o) + { + // Maintains backwards compatability + return createConnection(o_to_t, t_to_o, 0x5B, false); + } + + /** + * Create an Ethernet/IP Connection for sending implicit messages + * @param o_to_t Origin to target connection info + * @param t_to_o Target to origin connection info + * @param service Service code to send + * @param use_legacy_forward_open_request use 16 bit connection parameters instead of news 32 bit parameters + */ + int createConnection(const EIP_CONNECTION_INFO_T& o_to_t, + const EIP_CONNECTION_INFO_T& t_to_o, + EIP_USINT service, + bool use_legacy_forward_open_request); /** * Close the given connection number diff --git a/include/odva_ethernetip/socket/socket.h b/include/odva_ethernetip/socket/socket.h index 102fcc3..460e0c5 100644 --- a/include/odva_ethernetip/socket/socket.h +++ b/include/odva_ethernetip/socket/socket.h @@ -29,6 +29,12 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSI #include #include +#if BOOST_VERSION >= 107000 +#define GET_IO_SERVICE(s) ((boost::asio::io_context&)(s)->get_executor().context()) +#else +#define GET_IO_SERVICE(s) ((s)->get_io_service()) +#endif + #include "odva_ethernetip/serialization/serializable.h" #include "odva_ethernetip/serialization/buffer_writer.h" diff --git a/include/odva_ethernetip/socket/tcp_socket.h b/include/odva_ethernetip/socket/tcp_socket.h index a4f065d..79f63f3 100644 --- a/include/odva_ethernetip/socket/tcp_socket.h +++ b/include/odva_ethernetip/socket/tcp_socket.h @@ -55,7 +55,7 @@ class TCPSocket : public Socket */ virtual void open(string hostname, string port) { - tcp::resolver resolver(socket_.get_io_service()); + tcp::resolver resolver(GET_IO_SERVICE(&socket_)); tcp::resolver::query query(hostname, port); tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); connect(socket_, endpoint_iterator); diff --git a/include/odva_ethernetip/socket/udp_socket.h b/include/odva_ethernetip/socket/udp_socket.h index 9e77b25..689f60a 100644 --- a/include/odva_ethernetip/socket/udp_socket.h +++ b/include/odva_ethernetip/socket/udp_socket.h @@ -56,7 +56,7 @@ class UDPSocket : public Socket */ virtual void open(string hostname, string port) { - udp::resolver resolver(socket_.get_io_service()); + udp::resolver resolver(GET_IO_SERVICE(&socket_)); udp::resolver::query query(udp::v4(), hostname, port); remote_endpoint_ = *resolver.resolve(query); socket_.open(udp::v4()); diff --git a/src/connection.cpp b/src/connection.cpp index 6884d80..f838945 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -56,9 +56,9 @@ void Connection::setConnectionPoints(EIP_USINT origin, EIP_USINT target) path_.addLogicalConnectionPoint(target); } -shared_ptr Connection::createForwardOpenRequest() +shared_ptr Connection::createForwardOpenRequest(bool use_legacy_forward_open_request) { - shared_ptr req = make_shared (); + shared_ptr req = make_shared (use_legacy_forward_open_request); req->originator_vendor_id = originator_vendor_id; req->originator_sn = originator_sn; diff --git a/src/io_scanner.cpp b/src/io_scanner.cpp index 7890ffb..5503623 100644 --- a/src/io_scanner.cpp +++ b/src/io_scanner.cpp @@ -35,6 +35,7 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSI #include "odva_ethernetip/cpf_packet.h" #include "odva_ethernetip/cpf_item.h" #include "odva_ethernetip/identity_item_data.h" +#include "odva_ethernetip/socket/socket.h" using namespace boost::asio; using boost::asio::ip::udp; @@ -60,7 +61,7 @@ IOScanner::IOScanner(io_service& io_service, string hostname) void IOScanner::sendListIdentityRequest() { CONSOLE_BRIDGE_logInform("Sending List Identity Request... "); - udp::resolver r(socket_.get_io_service()); + udp::resolver r(GET_IO_SERVICE(&socket_)); udp::resolver::query q(udp::v4(), hostname_, "44818"); udp::endpoint receiver_endpoint = *r.resolve(q); @@ -160,7 +161,7 @@ void IOScanner::run() { sendListIdentityRequest(); CONSOLE_BRIDGE_logInform("Waiting for responses."); - socket_.get_io_service().run(); + GET_IO_SERVICE(&socket_).run(); } } // namespace eip diff --git a/src/session.cpp b/src/session.cpp index d1ffd30..19499c6 100644 --- a/src/session.cpp +++ b/src/session.cpp @@ -158,6 +158,11 @@ void Session::close() CONSOLE_BRIDGE_logInform("Session closed"); + closeWithoutUnregister(); +} + +void Session::closeWithoutUnregister() +{ socket_->close(); io_socket_->close(); session_id_ = 0; @@ -294,7 +299,9 @@ RRDataResponse Session::sendRRDataCommand(EIP_USINT service, const Path& path, } int Session::createConnection(const EIP_CONNECTION_INFO_T& o_to_t, - const EIP_CONNECTION_INFO_T& t_to_o) + const EIP_CONNECTION_INFO_T& t_to_o, + EIP_USINT service, + bool use_legacy_forward_open_request) { Connection conn(o_to_t, t_to_o); conn.originator_vendor_id = my_vendor_id_; @@ -303,8 +310,8 @@ int Session::createConnection(const EIP_CONNECTION_INFO_T& o_to_t, conn.o_to_t_connection_id = next_connection_id_++; conn.t_to_o_connection_id = next_connection_id_++; - shared_ptr req = conn.createForwardOpenRequest(); - RRDataResponse resp_data = sendRRDataCommand(0x5B, Path(0x06, 1), req); + shared_ptr req = conn.createForwardOpenRequest(use_legacy_forward_open_request); + RRDataResponse resp_data = sendRRDataCommand(service, Path(0x06, 1), req); ForwardOpenSuccess result; resp_data.getResponseDataAs(result); if (!conn.verifyForwardOpenResult(result))