| 87 | } |
| 88 | |
| 89 | void TCPConnectionImpl::close(const Error& error) { |
| 90 | Shared<ITCPConnectionDisconnectListener> listener; |
| 91 | |
| 92 | { |
| 93 | std::lock_guard<Mutex> guard(_mutex); |
| 94 | |
| 95 | if (_closed) { |
| 96 | return; |
| 97 | } |
| 98 | |
| 99 | _closed = true; |
| 100 | |
| 101 | if (_socket.is_open()) { |
| 102 | boost::system::error_code ec; |
| 103 | _socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec); |
| 104 | _socket.close(ec); |
| 105 | } |
| 106 | |
| 107 | listener = _disconnectListener; |
| 108 | } |
| 109 | |
| 110 | // Call listener outside the lock to avoid potential deadlocks |
| 111 | if (listener != nullptr) { |
| 112 | listener->onDisconnected(strongSmallRef(this), error); |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | void TCPConnectionImpl::setDataListener(Shared<ITCPConnectionDataListener> listener) { |
| 117 | std::lock_guard<Mutex> guard(_mutex); |
nothing calls this directly
no test coverage detected