From c0a5494de53f66d75c98c553cf61e32a5a8d5076 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 7 Oct 2016 14:15:01 +0200 Subject: Replaced code usage of libuv with asio library (nw) --- src/osd/modules/ipc/tcp_server.cpp | 279 ------------------------------------- 1 file changed, 279 deletions(-) delete mode 100644 src/osd/modules/ipc/tcp_server.cpp (limited to 'src/osd/modules/ipc/tcp_server.cpp') diff --git a/src/osd/modules/ipc/tcp_server.cpp b/src/osd/modules/ipc/tcp_server.cpp deleted file mode 100644 index 2c8f11e384b..00000000000 --- a/src/osd/modules/ipc/tcp_server.cpp +++ /dev/null @@ -1,279 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Inaki Baz Castillo,Miodrag Milanovic - -#include "emu.h" -#include "tcp_server.h" - -/* Static methods for UV callbacks. */ - -static inline void on_connection(uv_stream_t* handle, int status) -{ - static_cast(handle->data)->on_uv_connection(status); -} - -static inline void on_close(uv_handle_t* handle) -{ - static_cast(handle->data)->on_uv_closed(); -} - -static inline void on_error_close(uv_handle_t* handle) -{ - delete handle; -} - -/* Instance methods. */ - -tcp_server::tcp_server(uv_loop_t* loop, const std::string &ip, uint16_t port, int backlog) - : m_uv_handle(nullptr), - m_loop(nullptr), - m_is_closing(false), - m_local_port(0) -{ - int err; - int flags = 0; - - m_uv_handle = new uv_tcp_t; - m_uv_handle->data = (void*)this; - m_loop = loop; - - err = uv_tcp_init(loop, m_uv_handle); - if (err) - { - delete m_uv_handle; - m_uv_handle = nullptr; - throw emu_fatalerror("uv_tcp_init() failed: %s", uv_strerror(err)); - } - - struct sockaddr_storage bind_addr; - - - err = uv_ip4_addr(ip.c_str(), (int)port, (struct sockaddr_in*)&bind_addr); - if (err) - throw emu_fatalerror("uv_ipv4_addr() failed: %s", uv_strerror(err)); - - err = uv_tcp_bind(m_uv_handle, (const struct sockaddr*)&bind_addr, flags); - if (err) - { - uv_close((uv_handle_t*)m_uv_handle, (uv_close_cb)on_error_close); - throw emu_fatalerror("uv_tcp_bind() failed: %s", uv_strerror(err)); - } - - err = uv_listen((uv_stream_t*)m_uv_handle, backlog, (uv_connection_cb)on_connection); - if (err) - { - uv_close((uv_handle_t*)m_uv_handle, (uv_close_cb)on_error_close); - throw emu_fatalerror("uv_listen() failed: %s", uv_strerror(err)); - } - - // Set local address. - if (!set_local_address()) - { - uv_close((uv_handle_t*)m_uv_handle, (uv_close_cb)on_error_close); - throw emu_fatalerror("error setting local IP and port"); - } -} - -tcp_server::~tcp_server() -{ - if (m_uv_handle) - delete m_uv_handle; -} - -void tcp_server::close() -{ - if (m_is_closing) - return; - - m_is_closing = true; - - // If there are no connections then close now. - if (m_connections.empty()) - { - uv_close((uv_handle_t*)m_uv_handle, (uv_close_cb)on_close); - } - // Otherwise close all the connections (but not the TCP server). - else - { - osd_printf_verbose("closing %d active connections\n", (int)m_connections.size()); - - for (auto it = m_connections.begin(); it != m_connections.end(); ++it) - { - tcp_connection* connection = *it; - connection->close(); - } - } -} - -void tcp_server::terminate() -{ - if (m_is_closing) - return; - - m_is_closing = true; - - // If there are no connections then close now. - if (m_connections.empty()) - { - uv_close((uv_handle_t*)m_uv_handle, (uv_close_cb)on_close); - } - // Otherwise close all the connections (but not the TCP server). - else - { - osd_printf_verbose("closing %d active connections\n", (int)m_connections.size()); - - for (auto it = m_connections.begin(); it != m_connections.end(); ++it) - { - tcp_connection* connection = *it; - connection->terminate(); - } - } -} - -void tcp_server::send_to_all(const uint8_t* data, size_t len) -{ - // If there are no connections then close now. - if (!m_connections.empty()) - { - for (auto it = m_connections.begin(); it != m_connections.end(); ++it) - { - tcp_connection* connection = *it; - connection->write(data, len); - } - } -} - -void tcp_server::dump() -{ - osd_printf_verbose("[TCP, local:%s :%d, status:%s, connections:%d]", - m_local_ip.c_str(), (uint16_t)m_local_port, - (!m_is_closing) ? "open" : "closed", - (int)m_connections.size()); -} - -const sockaddr* tcp_server::get_local_address() -{ - return (const struct sockaddr*)&m_local_addr; -} - -const std::string& tcp_server::get_local_ip() -{ - return m_local_ip; -} - -uint16_t tcp_server::get_local_port() -{ - return m_local_port; -} - -bool tcp_server::set_local_address() -{ - int err; - int len = sizeof(m_local_addr); - - err = uv_tcp_getsockname(m_uv_handle, (struct sockaddr*)&m_local_addr, &len); - if (err) - { - osd_printf_error("uv_tcp_getsockname() failed: %s\n", uv_strerror(err)); - - return false; - } - - int family; - GetAddressInfo((const struct sockaddr*)&m_local_addr, &family, m_local_ip, &m_local_port); - - return true; -} - -inline void tcp_server::on_uv_connection(int status) -{ - if (m_is_closing) - return; - - int err; - - if (status) - { - osd_printf_error("error while receiving a new TCP connection: %s\n", uv_strerror(status)); - - return; - } - - // Notify the subclass so it provides an allocated derived class of TCPConnection. - tcp_connection* connection = nullptr; - user_on_tcp_connection_alloc(&connection); - if (connection == nullptr) - osd_printf_error("tcp_server pointer was not allocated by the user\n"); - - try - { - connection->setup(m_loop, this, &(m_local_addr), m_local_ip, m_local_port); - } - catch (...) - { - delete connection; - return; - } - - // Accept the connection. - err = uv_accept((uv_stream_t*)m_uv_handle, (uv_stream_t*)connection->get_uv_handle()); - if (err) - throw emu_fatalerror("uv_accept() failed: %s\n", uv_strerror(err)); - - // Insert the TCPConnection in the set. - m_connections.insert(connection); - - // Start receiving data. - try - { - connection->start(); - } - catch (emu_exception &error) - { - osd_printf_error("cannot run the TCP connection, closing the connection: %s\n", error.what()); - connection->close(); - // NOTE: Don't return here so the user won't be notified about a "onclose" for a TCP connection - // for which there was not a previous "onnew" event. - } - - osd_printf_verbose("new TCP connection:\n"); - connection->dump(); - - // Notify the subclass. - user_on_new_tcp_connection(connection); -} - -void tcp_server::on_uv_closed() -{ - // Motify the subclass. - user_on_tcp_server_closed(); -} - -void tcp_server::on_tcp_connection_closed(tcp_connection* connection, bool is_closed_by_peer) -{ - // NOTE: - // Worst scenario is that in which this is the latest connection, - // which is remotely closed (no tcp_server.Close() was called) and the user - // call tcp_server.Close() on userOnTCPConnectionClosed() callback, so Close() - // is called with zero connections and calls uv_close(), but then - // onTCPConnectionClosed() continues and finds that isClosing is true and - // there are zero connections, so calls uv_close() again and get a crash. - // - // SOLUTION: - // Check isClosing value *before* onTCPConnectionClosed() callback. - - bool wasClosing = m_is_closing; - - osd_printf_verbose("TCP connection closed:\n"); - connection->dump(); - - // Remove the TCPConnection from the set. - m_connections.erase(connection); - - // Notify the subclass. - user_on_tcp_connection_closed(connection, is_closed_by_peer); - - // Check if the server was closing connections, and if this is the last - // connection then close the server now. - if (wasClosing && m_connections.empty()) - uv_close((uv_handle_t*)m_uv_handle, (uv_close_cb)on_close); -} -- cgit v1.2.3-70-g09d2