// Copyright(c) 2017, Intel Corporation // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // * Neither the name of Intel Corporation nor the names of its contributors // may be used to endorse or promote products derived from this software // without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. //**************************************************************************** /// @file mmlink_server.h /// @brief Basic AFU interaction. /// @ingroup SigTap /// @verbatim //**************************************************************************** #ifndef MMLINK_SERVER_H #define MMLINK_SERVER_H #include #include #include class mmlink_connection; class mm_debug_link_interface; class mmlink_server { public: mmlink_server(struct sockaddr_in *sock, mm_debug_link_interface *driver); ~mmlink_server(); int run(unsigned char* stpAddr); void stop(void) { m_running = false; } int get_server_id(void) { return m_server_id; } mm_debug_link_interface *get_driver_fd(void) { return m_driver; } void print_stats(void); protected: mmlink_server(const mmlink_server& mm_server) { m_listen = mm_server.m_listen; m_server_id = mm_server.m_server_id; m_num_bound_connections = mm_server.m_num_bound_connections; m_num_connections = mm_server.m_num_connections; m_t2h_pending = mm_server.m_t2h_pending; m_h2t_pending = mm_server.m_h2t_pending; m_t2h_stats = mm_server.m_t2h_stats; m_h2t_stats = mm_server.m_h2t_stats; m_addr = mm_server.m_addr; m_running = mm_server.m_running; m_driver = mm_server.m_driver; m_conn = new mmlink_connection*[MAX_CONNECTIONS]; for (size_t i = 0; i < MAX_CONNECTIONS; ++i) m_conn[i] = mm_server.m_conn[i]; } mmlink_server& operator=(const mmlink_server& mm_server) { if( this != &mm_server) { m_listen = mm_server.m_listen; m_server_id = mm_server.m_server_id; m_num_bound_connections = mm_server.m_num_bound_connections; m_num_connections = mm_server.m_num_connections; m_t2h_pending = mm_server.m_t2h_pending; m_h2t_pending = mm_server.m_h2t_pending; m_t2h_stats = mm_server.m_t2h_stats; m_h2t_stats = mm_server.m_h2t_stats; m_addr = mm_server.m_addr; m_running = mm_server.m_running; m_driver = mm_server.m_driver; if(m_conn) delete[] m_conn; m_conn = new mmlink_connection*[MAX_CONNECTIONS]; for (size_t i = 0; i < MAX_CONNECTIONS; ++i) m_conn[i] = mm_server.m_conn[i]; } return *this; } private: int m_listen; int m_server_id; static const size_t MAX_CONNECTIONS = 2; int m_num_bound_connections; int m_num_connections; bool m_t2h_pending; bool m_h2t_pending; int handle_t2h(mmlink_connection *data_conn, bool can_read_driver, bool can_write_host); int handle_h2t(mmlink_connection *data_conn, bool can_read_host, bool can_write_driver); struct sockaddr_in m_addr; bool m_running; mm_debug_link_interface *m_driver; class mmlink_stats; mmlink_stats *m_t2h_stats; mmlink_stats *m_h2t_stats; int setup_listen_socket(); void get_welcome_message(char *msg, size_t msg_len); mmlink_connection **m_conn; mmlink_connection *get_unused_connection(); mmlink_connection *handle_accept(); void close_other_data_connection(mmlink_connection *pc); mmlink_connection *get_data_connection(void); #undef ENABLE_MMLINK_STATS // #define ENABLE_MMLINK_STATS class mmlink_stats { public: #ifdef ENABLE_MMLINK_STATS mmlink_stats(const char *name) { m_name = name; init(); } void init(void) { m_num_bytes = 0; m_last_count = 0; m_num_packets = 0; m_overflow_size = 0; m_min_count = UINT_MAX; m_max_count = 0; for (int i = 0; i < BUFSIZE; i++) m_histogram[i] = 0; } void print(void) { DPRINT("%s stats:\n", m_name); DPRINT_RAW("total packets transmitted: %u\n", m_num_packets); DPRINT_RAW("total bytes transmitted: %u\n", m_num_bytes); DPRINT_RAW("last transmission: (%u bytes):\n", m_last_count); DPRINT_RAW("min count: %u\n", m_min_count); DPRINT_RAW("max count: %u\n", m_max_count); for (int i = 0; i < m_last_count; ++i) DPRINT_RAW("0x%02X ", m_last_buf[i]); DPRINT_RAW("\n"); DPRINT_RAW("histogram of count values:\n"); for (int i = 0; i < m_max_count; i++) if (m_histogram[i]) DPRINT_RAW("%d: %u\n", i, m_histogram[i]); if (m_overflow_size) { DPRINT_RAW("Warning: input data was larger than BUFSIZE; packet counts may be inaccurate.\n"); DPRINT_RAW("Consider changing BUFSIZE to %u (largest input data seen\n", BUFSIZE); } } void update(int count, char *buf) { m_num_bytes += count; m_last_count = MIN(count, BUFSIZE); m_histogram[m_last_count]++; memcpy(m_last_buf, buf, m_last_count); m_min_count = MIN(m_min_count, count); m_max_count = MAX(m_max_count, count); for (int i = 0; i < count; ++i) { if (count > BUFSIZE) { m_overflow_size = MAX(m_overflow_size, count); break; } if (buf[i] == 0x7B) m_num_packets++; } } private: const char *m_name; unsigned int m_num_bytes; static const size_t BUFSIZE = 1073741824; unsigned char m_last_buf[BUFSIZE]; unsigned int m_histogram[BUFSIZE]; unsigned char m_last_count; unsigned int m_num_packets; unsigned int m_overflow_size; unsigned m_min_count; unsigned m_max_count; #else #define UNUSED_PARAM(x) (void)x mmlink_stats(const char *name) { UNUSED_PARAM(name); } void init(void) { } void print(void) { } void update(int count, char *buf) { UNUSED_PARAM(count); UNUSED_PARAM(buf); } #endif }; }; #endif