diff --git a/csharp/src/Ice/Connection.cs b/csharp/src/Ice/Connection.cs index ea5ad2ba9eb..7c2f69f88fd 100644 --- a/csharp/src/Ice/Connection.cs +++ b/csharp/src/Ice/Connection.cs @@ -138,48 +138,128 @@ public class ConnectionInfo /// /// The underlying connection information. /// - public ConnectionInfo? underlying; + public readonly ConnectionInfo? underlying; /// /// Whether the connection is an incoming connection (true) or an outgoing connection (false). /// - public bool incoming; + public readonly bool incoming; /// /// The name of the adapter associated with the connection. /// - public string adapterName = ""; + public readonly string adapterName; /// /// The connection id. /// - public string connectionId = ""; + public readonly string connectionId; + + protected ConnectionInfo(ConnectionInfo underlying) + { + this.underlying = underlying; + incoming = underlying.incoming; + adapterName = underlying.adapterName; + connectionId = underlying.connectionId; + } + + protected ConnectionInfo(bool incoming, string adapterName, string connectionId) + { + this.incoming = incoming; + this.adapterName = adapterName; + this.connectionId = connectionId; + } } public class IPConnectionInfo : ConnectionInfo { - public string localAddress = ""; - public int localPort = -1; - public string remoteAddress = ""; - public int remotePort = -1; + public readonly string localAddress; + public readonly int localPort; + public readonly string remoteAddress; + public readonly int remotePort; + + protected IPConnectionInfo( + bool incoming, + string adapterName, + string connectionId, + string localAddress, + int localPort, + string remoteAddress, + int remotePort) + : base(incoming, adapterName, connectionId) + { + this.localAddress = localAddress; + this.localPort = localPort; + this.remoteAddress = remoteAddress; + this.remotePort = remotePort; + } } public sealed class TCPConnectionInfo : IPConnectionInfo { - public int rcvSize; - public int sndSize; + public readonly int rcvSize; + public readonly int sndSize; + + internal TCPConnectionInfo( + bool incoming, + string adapterName, + string connectionId, + string localAddress, + int localPort, + string remoteAddress, + int remotePort, + int rcvSize, + int sndSize) + : base(incoming, adapterName, connectionId, localAddress, localPort, remoteAddress, remotePort) + { + this.rcvSize = rcvSize; + this.sndSize = sndSize; + } + + internal TCPConnectionInfo(bool incoming, string adapterName, string connectionId) + : this(incoming, adapterName, connectionId, "", -1, "", -1, 0, 0) + { + } } public sealed class UDPConnectionInfo : IPConnectionInfo { - public string mcastAddress = ""; - public int mcastPort = -1; - public int rcvSize; - public int sndSize; + public readonly string mcastAddress; + public readonly int mcastPort; + public readonly int rcvSize; + public readonly int sndSize; + + internal UDPConnectionInfo( + bool incoming, + string adapterName, + string connectionId, + string localAddress, + int localPort, + string remoteAddress, + int remotePort, + string mcastAddress, + int mcastPort, + int rcvSize, + int sndSize) + : base(incoming, adapterName, connectionId, localAddress, localPort, remoteAddress, remotePort) + { + this.mcastAddress = mcastAddress; + this.mcastPort = mcastPort; + this.rcvSize = rcvSize; + this.sndSize = sndSize; + } + + internal UDPConnectionInfo(bool incoming, string adapterName, string connectionId) + : this(incoming, adapterName, connectionId, "", -1, "", -1, "", -1, 0, 0) + { + } } public sealed class WSConnectionInfo : ConnectionInfo { - public Dictionary headers = []; + public readonly Dictionary headers; + + internal WSConnectionInfo(ConnectionInfo underlying, Dictionary headers) + : base(underlying) => this.headers = headers; } } diff --git a/csharp/src/Ice/ConnectionI.cs b/csharp/src/Ice/ConnectionI.cs index 5f5145637cb..5160c21d879 100644 --- a/csharp/src/Ice/ConnectionI.cs +++ b/csharp/src/Ice/ConnectionI.cs @@ -2660,25 +2660,14 @@ private void closeTimedOut(System.Threading.Timer closeTimer) private ConnectionInfo initConnectionInfo() { + // Called with _mutex locked. + if (_state > StateNotInitialized && _info is not null) // Update the connection info until it's initialized { return _info; } - try - { - _info = _transceiver.getInfo(); - } - catch (LocalException) - { - _info = new ConnectionInfo(); - } - for (ConnectionInfo info = _info; info is not null; info = info.underlying) - { - info.connectionId = _endpoint.connectionId(); - info.adapterName = _adapter?.getName() ?? ""; - info.incoming = _connector is null; - } + _info = _transceiver.getInfo(incoming: _connector is null, _endpoint.connectionId(), _adapter?.getName() ?? ""); return _info; } diff --git a/csharp/src/Ice/Internal/IdleTimeoutTransceiverDecorator.cs b/csharp/src/Ice/Internal/IdleTimeoutTransceiverDecorator.cs index d84c1c1a2bb..5fea1c58cc4 100644 --- a/csharp/src/Ice/Internal/IdleTimeoutTransceiverDecorator.cs +++ b/csharp/src/Ice/Internal/IdleTimeoutTransceiverDecorator.cs @@ -58,7 +58,8 @@ public void finishRead(Buffer buf) // We call write after finishWrite, so no need to do anything here. public void finishWrite(Buffer buf) => _decoratee.finishWrite(buf); - public ConnectionInfo getInfo() => _decoratee.getInfo(); + public ConnectionInfo getInfo(bool incoming, string connectionId, string adapterName) => + _decoratee.getInfo(incoming, connectionId, adapterName); public int initialize(Buffer readBuffer, Buffer writeBuffer, ref bool hasMoreData) => _decoratee.initialize(readBuffer, writeBuffer, ref hasMoreData); diff --git a/csharp/src/Ice/Internal/TcpTransceiver.cs b/csharp/src/Ice/Internal/TcpTransceiver.cs index 41d8effc839..39ef60fa5be 100644 --- a/csharp/src/Ice/Internal/TcpTransceiver.cs +++ b/csharp/src/Ice/Internal/TcpTransceiver.cs @@ -76,21 +76,28 @@ public string protocol() return _instance.protocol(); } - public Ice.ConnectionInfo getInfo() + public ConnectionInfo getInfo(bool incoming, string connectionId, string adapterName) { - Ice.TCPConnectionInfo info = new Ice.TCPConnectionInfo(); - if (_stream.fd() != null) + if (_stream.fd() is null) + { + return new TCPConnectionInfo(incoming, adapterName, connectionId); + } + else { EndPoint localEndpoint = Network.getLocalAddress(_stream.fd()); - info.localAddress = Network.endpointAddressToString(localEndpoint); - info.localPort = Network.endpointPort(localEndpoint); EndPoint remoteEndpoint = Network.getRemoteAddress(_stream.fd()); - info.remoteAddress = Network.endpointAddressToString(remoteEndpoint); - info.remotePort = Network.endpointPort(remoteEndpoint); - info.rcvSize = Network.getRecvBufferSize(_stream.fd()); - info.sndSize = Network.getSendBufferSize(_stream.fd()); + + return new TCPConnectionInfo( + incoming, + adapterName, + connectionId, + Network.endpointAddressToString(localEndpoint), + Network.endpointPort(localEndpoint), + Network.endpointAddressToString(remoteEndpoint), + Network.endpointPort(remoteEndpoint), + Network.getRecvBufferSize(_stream.fd()), + Network.getSendBufferSize(_stream.fd())); } - return info; } public void checkSendSize(Buffer buf) diff --git a/csharp/src/Ice/Internal/Transceiver.cs b/csharp/src/Ice/Internal/Transceiver.cs index 85000d2a48d..3eb392c4eb5 100644 --- a/csharp/src/Ice/Internal/Transceiver.cs +++ b/csharp/src/Ice/Internal/Transceiver.cs @@ -53,7 +53,7 @@ public interface Transceiver string toDetailedString(); - Ice.ConnectionInfo getInfo(); + ConnectionInfo getInfo(bool incoming, string connectionId, string adapterName); void checkSendSize(Buffer buf); diff --git a/csharp/src/Ice/Internal/UdpTransceiver.cs b/csharp/src/Ice/Internal/UdpTransceiver.cs index ea79bb8672a..e5335cdd6d0 100644 --- a/csharp/src/Ice/Internal/UdpTransceiver.cs +++ b/csharp/src/Ice/Internal/UdpTransceiver.cs @@ -544,41 +544,49 @@ public string protocol() return _instance.protocol(); } - public Ice.ConnectionInfo getInfo() + public ConnectionInfo getInfo(bool incoming, string connectionId, string adapterName) { - Ice.UDPConnectionInfo info = new Ice.UDPConnectionInfo(); - if (_fd != null) + if (_fd is null) + { + return new UDPConnectionInfo(incoming, connectionId, adapterName); + } + else { EndPoint localEndpoint = Network.getLocalAddress(_fd); - info.localAddress = Network.endpointAddressToString(localEndpoint); - info.localPort = Network.endpointPort(localEndpoint); - if (_state == StateNotConnected) - { - if (_peerAddr != null) - { - info.remoteAddress = Network.endpointAddressToString(_peerAddr); - info.remotePort = Network.endpointPort(_peerAddr); - } + + if (_state == StateNotConnected) // TODO: eliminate all these states + { + return new UDPConnectionInfo( + incoming, + connectionId, + adapterName, + Network.endpointAddressToString(localEndpoint), + Network.endpointPort(localEndpoint), + _peerAddr is not null ? Network.endpointAddressToString(_peerAddr) : "", + _peerAddr is not null ? Network.endpointPort(_peerAddr) : -1, + _mcastAddr is not null ? Network.endpointAddressToString(_mcastAddr) : "", + _mcastAddr is not null ? Network.endpointPort(_mcastAddr) : -1, + _rcvSize, + _sndSize); } else { EndPoint remoteEndpoint = Network.getRemoteAddress(_fd); - if (remoteEndpoint != null) - { - info.remoteAddress = Network.endpointAddressToString(remoteEndpoint); - info.remotePort = Network.endpointPort(remoteEndpoint); - } - } - info.rcvSize = Network.getRecvBufferSize(_fd); - info.sndSize = Network.getSendBufferSize(_fd); - } - if (_mcastAddr != null) - { - info.mcastAddress = Network.endpointAddressToString(_mcastAddr); - info.mcastPort = Network.endpointPort(_mcastAddr); + return new UDPConnectionInfo( + incoming, + connectionId, + adapterName, + Network.endpointAddressToString(localEndpoint), + Network.endpointPort(localEndpoint), + remoteEndpoint is not null ? Network.endpointAddressToString(remoteEndpoint) : "", + remoteEndpoint is not null ? Network.endpointPort(remoteEndpoint) : -1, + _mcastAddr is not null ? Network.endpointAddressToString(_mcastAddr) : "", + _mcastAddr is not null ? Network.endpointPort(_mcastAddr) : -1, + _rcvSize, + _sndSize); + } } - return info; } public void checkSendSize(Buffer buf) diff --git a/csharp/src/Ice/Internal/WSTransceiver.cs b/csharp/src/Ice/Internal/WSTransceiver.cs index a8e77b31122..2adfd56a400 100644 --- a/csharp/src/Ice/Internal/WSTransceiver.cs +++ b/csharp/src/Ice/Internal/WSTransceiver.cs @@ -655,13 +655,8 @@ public string protocol() return _instance.protocol(); } - public Ice.ConnectionInfo getInfo() - { - Ice.WSConnectionInfo info = new Ice.WSConnectionInfo(); - info.headers = _parser.getHeaders(); - info.underlying = _delegate.getInfo(); - return info; - } + public ConnectionInfo getInfo(bool incoming, string connectionId, string adapterName) => + new WSConnectionInfo(_delegate.getInfo(incoming, connectionId, adapterName), _parser.getHeaders()); public void checkSendSize(Buffer buf) { diff --git a/csharp/src/Ice/SSL/ConnectionInfo.cs b/csharp/src/Ice/SSL/ConnectionInfo.cs index 61b2e5df641..e7ac74719f6 100644 --- a/csharp/src/Ice/SSL/ConnectionInfo.cs +++ b/csharp/src/Ice/SSL/ConnectionInfo.cs @@ -8,7 +8,15 @@ namespace Ice.SSL; public sealed class ConnectionInfo : Ice.ConnectionInfo { - public string cipher = ""; - public X509Certificate2[] certs = []; - public bool verified; + public readonly string cipher; + public readonly X509Certificate2[] certs; + public readonly bool verified; + + internal ConnectionInfo(Ice.ConnectionInfo underlying, string cipher, X509Certificate2[] certs, bool verified) + : base(underlying) + { + this.cipher = cipher; + this.certs = certs; + this.verified = verified; + } } diff --git a/csharp/src/Ice/SSL/TransceiverI.cs b/csharp/src/Ice/SSL/TransceiverI.cs index b188b76f0f5..22eaabd6a07 100644 --- a/csharp/src/Ice/SSL/TransceiverI.cs +++ b/csharp/src/Ice/SSL/TransceiverI.cs @@ -60,7 +60,7 @@ public int initialize(Ice.Internal.Buffer readBuffer, Ice.Internal.Buffer writeB _authenticated = true; _cipher = _sslStream.CipherAlgorithm.ToString(); - _instance.verifyPeer((ConnectionInfo)getInfo(), ToString()); + _instance.verifyPeer((ConnectionInfo)getInfo(_incoming, connectionId: "", _adapterName), ToString()); if (_instance.securityTraceLevel() >= 1) { @@ -309,23 +309,17 @@ public void finishWrite(Ice.Internal.Buffer buf) public string protocol() => _delegate.protocol(); - public Ice.ConnectionInfo getInfo() + public Ice.ConnectionInfo getInfo(bool incoming, string connectionId, string adapterName) { - var info = new ConnectionInfo(); - info.underlying = _delegate.getInfo(); - info.incoming = _incoming; - info.adapterName = _adapterName; - info.cipher = _cipher; - if (_sslStream is SslStream sslStream && sslStream.RemoteCertificate is X509Certificate2 remoteCertificate) - { - info.certs = [remoteCertificate]; - } - else - { - info.certs = []; - } - info.verified = _verified; - return info; + Debug.Assert(incoming == _incoming); + Debug.Assert(adapterName == _adapterName); + + return new Ice.SSL.ConnectionInfo( + _delegate.getInfo(incoming, connectionId, adapterName), + _cipher, + _sslStream is SslStream sslStream && sslStream.RemoteCertificate is X509Certificate2 remoteCertificate ? + [remoteCertificate] : [], + _verified); } public void checkSendSize(Ice.Internal.Buffer buf) => _delegate.checkSendSize(buf); diff --git a/csharp/test/Ice/background/Transceiver.cs b/csharp/test/Ice/background/Transceiver.cs index 21fbae185bd..97ab49ab811 100644 --- a/csharp/test/Ice/background/Transceiver.cs +++ b/csharp/test/Ice/background/Transceiver.cs @@ -197,9 +197,9 @@ public string protocol() return "test-" + _transceiver.protocol(); } - public Ice.ConnectionInfo getInfo() + public Ice.ConnectionInfo getInfo(bool incoming, string connectionId, string adapterName) { - return _transceiver.getInfo(); + return _transceiver.getInfo(incoming, connectionId, adapterName); } public override string ToString()