Go to the documentation of this file.00001
00026 #include <iostream>
00027 #include <boost/bind.hpp>
00028
00029 #include "odva_ethernetip/io_scanner.h"
00030 #include "odva_ethernetip/eip_types.h"
00031 #include "odva_ethernetip/serialization/buffer_reader.h"
00032 #include "odva_ethernetip/serialization/buffer_writer.h"
00033 #include "odva_ethernetip/encap_packet.h"
00034 #include "odva_ethernetip/cpf_packet.h"
00035 #include "odva_ethernetip/cpf_item.h"
00036 #include "odva_ethernetip/identity_item_data.h"
00037
00038 using namespace boost::asio;
00039 using boost::asio::ip::udp;
00040 using std::cerr;
00041 using std::cout;
00042 using std::endl;
00043
00044 namespace eip {
00045
00046 using serialization::BufferReader;
00047 using serialization::BufferWriter;
00048
00049 IOScanner::IOScanner(io_service& io_service, string hostname)
00050 : socket_(io_service), hostname_(hostname)
00051 {
00052 cout << "Opening UDP socket... ";
00053 socket_.open(udp::v4());
00054 socket_.async_receive_from(buffer(recv_buf_), device_endpoint_,
00055 boost::bind(&IOScanner::handleListIdentityResponse, this,
00056 boost::asio::placeholders::error,
00057 boost::asio::placeholders::bytes_transferred));
00058 cout << "done." << endl;
00059 }
00060
00061 void IOScanner::sendListIdentityRequest()
00062 {
00063 cout << "Sending List Identity Request... ";
00064 udp::resolver r(socket_.get_io_service());
00065 udp::resolver::query q(udp::v4(), hostname_, "44818");
00066 udp::endpoint receiver_endpoint = *r.resolve(q);
00067
00068 EncapPacket pkt(EIP_CMD_LIST_IDENTITY);
00069 char d[128];
00070 BufferWriter w(buffer(d));
00071 pkt.serialize(w);
00072 socket_.send_to(buffer(d, w.getByteCount()), receiver_endpoint);
00073 cout << "done." << endl;
00074 }
00075
00076 void IOScanner::handleListIdentityResponse(const boost::system::error_code& ec,
00077 std::size_t num_bytes)
00078 {
00079 if (ec)
00080 {
00081 cerr << "Error receiving list identity response message" << endl;
00082 return;
00083 }
00084
00085 try
00086 {
00087 BufferReader r(buffer(recv_buf_, num_bytes));
00088 EncapPacket pkt;
00089 pkt.deserialize(r);
00090 if (r.getByteCount() != num_bytes)
00091 {
00092 cerr << "Warning: packet received with " << num_bytes <<
00093 " bytes, but only " << r.getByteCount() << " bytes used" << endl;
00094 }
00095
00096 if (pkt.getHeader().command != EIP_CMD_LIST_IDENTITY)
00097 {
00098 cerr << "Reply received with wrong command. Expected "
00099 << EIP_CMD_LIST_IDENTITY << ", received " << pkt.getHeader().command << endl;
00100 return;
00101 }
00102 if (pkt.getHeader().session_handle != 0)
00103 {
00104 cerr << "Warning: Non-zero session handle received: " << pkt.getHeader().session_handle << endl;
00105 }
00106 if (pkt.getHeader().status != 0)
00107 {
00108 cerr << "Warning: Non-zero status received: " << pkt.getHeader().status << endl;
00109 }
00110 if (pkt.getHeader().context[0] != 0 || pkt.getHeader().context[1] != 0)
00111 {
00112 cerr << "Warning: Non-zero sender context received: "
00113 << pkt.getHeader().context[0] << ", " << pkt.getHeader().context[1] << endl;
00114 }
00115 if (pkt.getHeader().options != 0)
00116 {
00117 cerr << "Warning: Non-zero options received: " << pkt.getHeader().options << endl;
00118 }
00119
00120 CPFPacket payload;
00121 pkt.getPayloadAs(payload);
00122
00123 if (payload.getItemCount() < 1)
00124 {
00125 cerr << "No items in list identity payload!" << endl;
00126 return;
00127 }
00128 if (payload.getItemCount() > 1)
00129 {
00130 cerr << "Warning: more than one item in list identity payload " << payload.getItemCount() << endl;
00131 }
00132
00133 if (payload.getItems().at(0).getItemType() != EIP_ITEM_LIST_IDENTITY_RESPONSE)
00134 {
00135 cerr << "Error: Payload response received with the wrong item type. Expected: "
00136 << EIP_ITEM_LIST_IDENTITY_RESPONSE << ", received: " <<
00137 payload.getItems().at(0).getItemType() << endl;
00138 return;
00139 }
00140
00141 IdentityItemData id;
00142 payload.getItems().at(0).getDataAs(id);
00143
00144 cout << "=== Received ID Message ===" << endl;
00145 cout << "Encapsulation Protocol Version: " << (int)id.encap_protocol_version << endl;
00146 cout << "Address: " << inet_ntoa(id.sockaddr.sin_addr) << " : " << ntohs(id.sockaddr.sin_port) << endl;
00147 cout << "Vendor ID: " << (int)id.vendor_id << endl;
00148 cout << "Device Type: " << (int)id.device_type << endl;
00149 cout << "Product Code: " << (int)id.product_code << endl;
00150 cout << "Revision: " << (int)id.revision[0] << "." << (int)id.revision[1] << endl;
00151 cout << "Status: " << (int)id.status << endl;
00152 cout << "Serial Number: " << (int)id.serial_number << endl;
00153 cout << "Product Name: " << id.product_name << endl;
00154 cout << "State: " << (int)id.state << endl;
00155 }
00156 catch (std::length_error e)
00157 {
00158 printf("ERROR: Packet too short for identity response\n");
00159 }
00160 }
00161
00162 void IOScanner::run()
00163 {
00164 sendListIdentityRequest();
00165 cout << "Waiting for responses." << endl;
00166 socket_.get_io_service().run();
00167 }
00168
00169 }