< Summary

Information
Class: Ice.Internal.StreamSocket
Assembly: Ice
File(s): /home/runner/work/ice/ice/csharp/src/Ice/Internal/StreamSocket.cs
Tag: 71_18251537082
Line coverage
80%
Covered lines: 158
Uncovered lines: 39
Coverable lines: 197
Total lines: 450
Line coverage: 80.2%
Branch coverage
76%
Covered branches: 70
Total branches: 92
Branch coverage: 76%
Method coverage
100%
Covered methods: 19
Total methods: 19
Method coverage: 100%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%22100%
.ctor(...)100%1.02172.73%
connect(...)93.75%16.021695.65%
fd()100%11100%
setBufferSize(...)100%11100%
read(...)83.33%6.05688.89%
write(...)37.5%26.97833.33%
startRead(...)0%2.35255.56%
finishRead(...)80%10.931078.95%
startWrite(...)62.5%11.38862.5%
finishWrite(...)78.57%17.971472.73%
close()100%11100%
destroy()100%11100%
ToString()100%11100%
read(...)80%10.141088.89%
write(...)83.33%6.01692.86%
ioCompleted(...)83.33%6.17683.33%
init()100%11100%
toState(...)75%4.07483.33%

File(s)

/home/runner/work/ice/ice/csharp/src/Ice/Internal/StreamSocket.cs

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3using System.Diagnostics;
 4using System.Net;
 5using System.Net.Sockets;
 6
 7namespace Ice.Internal;
 8
 9#pragma warning disable CA1001 // _readEventArgs and _writeEventArgs are disposed by destroy.
 10internal sealed class StreamSocket
 11#pragma warning restore CA1001
 12{
 113    public StreamSocket(ProtocolInstance instance, NetworkProxy proxy, EndPoint addr, EndPoint sourceAddr)
 14    {
 115        _instance = instance;
 116        _proxy = proxy;
 117        _addr = addr;
 118        _sourceAddr = sourceAddr;
 119        _fd = Network.createSocket(false, (_proxy != null ? _proxy.getAddress() : _addr).AddressFamily);
 120        _state = StateNeedConnect;
 21
 122        init();
 123    }
 24
 125    public StreamSocket(ProtocolInstance instance, Socket fd)
 26    {
 127        _instance = instance;
 128        _fd = fd;
 129        _state = StateConnected;
 30        try
 31        {
 132            _desc = Network.fdToString(_fd);
 133        }
 034        catch (System.Exception)
 35        {
 036            Network.closeSocketNoThrow(_fd);
 037            throw;
 38        }
 139        init();
 140    }
 41
 42    public int connect(Buffer readBuffer, Buffer writeBuffer, ref bool moreData)
 43    {
 144        if (_state == StateNeedConnect)
 45        {
 146            _state = StateConnectPending;
 147            return SocketOperation.Connect;
 48        }
 149        else if (_state <= StateConnectPending)
 50        {
 151            if (_writeEventArgs.SocketError != SocketError.Success)
 52            {
 153                var ex = new System.Net.Sockets.SocketException((int)_writeEventArgs.SocketError);
 154                if (Network.connectionRefused(ex))
 55                {
 156                    throw new Ice.ConnectionRefusedException(ex);
 57                }
 58                else
 59                {
 060                    throw new Ice.ConnectFailedException(ex);
 61                }
 62            }
 163            _desc = Network.fdToString(_fd, _proxy, _addr);
 164            _state = _proxy != null ? StateProxyWrite : StateConnected;
 65        }
 66
 167        if (_state == StateProxyWrite)
 68        {
 169            _proxy.beginWrite(_addr, writeBuffer);
 170            return SocketOperation.Write;
 71        }
 172        else if (_state == StateProxyRead)
 73        {
 174            _proxy.beginRead(readBuffer);
 175            return SocketOperation.Read;
 76        }
 177        else if (_state == StateProxyConnected)
 78        {
 179            _proxy.finish(readBuffer, writeBuffer);
 80
 181            readBuffer.clear();
 182            writeBuffer.clear();
 83
 184            _state = StateConnected;
 85        }
 86
 87        Debug.Assert(_state == StateConnected);
 188        return SocketOperation.None;
 89    }
 90
 191    public Socket fd() => _fd;
 92
 193    public void setBufferSize(int rcvSize, int sndSize) => Network.setTcpBufSize(_fd, rcvSize, sndSize, _instance);
 94
 95    public int read(Buffer buf)
 96    {
 197        if (_state == StateProxyRead)
 98        {
 99            while (true)
 100            {
 1101                int ret = read(buf.b);
 1102                if (ret == 0)
 103                {
 0104                    return SocketOperation.Read;
 105                }
 106
 1107                _state = toState(_proxy.endRead(buf));
 1108                if (_state != StateProxyRead)
 109                {
 1110                    return SocketOperation.None;
 111                }
 112            }
 113        }
 1114        read(buf.b);
 1115        return buf.b.hasRemaining() ? SocketOperation.Read : SocketOperation.None;
 116    }
 117
 118    public int write(Buffer buf)
 119    {
 1120        if (_state == StateProxyWrite)
 121        {
 122            while (true)
 123            {
 0124                int ret = write(buf.b);
 0125                if (ret == 0)
 126                {
 0127                    return SocketOperation.Write;
 128                }
 0129                _state = toState(_proxy.endWrite(buf));
 0130                if (_state != StateProxyWrite)
 131                {
 0132                    return SocketOperation.None;
 133                }
 134            }
 135        }
 1136        write(buf.b);
 1137        return buf.b.hasRemaining() ? SocketOperation.Write : SocketOperation.None;
 138    }
 139
 140    public bool startRead(Buffer buf, AsyncCallback callback, object state)
 141    {
 142        Debug.Assert(_fd != null && _readEventArgs != null);
 143
 144        try
 145        {
 1146            _readCallback = callback;
 1147            _readEventArgs.UserToken = state;
 1148            _readEventArgs.SetBuffer(buf.b.rawBytes(), buf.b.position(), buf.b.remaining());
 1149            return !_fd.ReceiveAsync(_readEventArgs);
 150        }
 0151        catch (System.Net.Sockets.SocketException ex)
 152        {
 0153            if (Network.connectionLost(ex))
 154            {
 0155                throw new Ice.ConnectionLostException(ex);
 156            }
 0157            throw new Ice.SocketException(ex);
 158        }
 1159    }
 160
 161    public void finishRead(Buffer buf)
 162    {
 1163        if (_fd == null) // Transceiver was closed
 164        {
 0165            return;
 166        }
 167
 168        Debug.Assert(_fd != null && _readEventArgs != null);
 169        try
 170        {
 1171            if (_readEventArgs.SocketError != SocketError.Success)
 172            {
 1173                throw new System.Net.Sockets.SocketException((int)_readEventArgs.SocketError);
 174            }
 1175            int ret = _readEventArgs.BytesTransferred;
 1176            _readEventArgs.SetBuffer(null, 0, 0);
 177
 1178            if (ret == 0)
 179            {
 1180                throw new Ice.ConnectionLostException();
 181            }
 182
 183            Debug.Assert(ret > 0);
 1184            buf.b.position(buf.b.position() + ret);
 185
 1186            if (_state == StateProxyRead)
 187            {
 1188                _state = toState(_proxy.endRead(buf));
 189            }
 1190        }
 1191        catch (System.Net.Sockets.SocketException ex)
 192        {
 1193            if (Network.connectionLost(ex))
 194            {
 1195                throw new Ice.ConnectionLostException(ex);
 196            }
 0197            throw new Ice.SocketException(ex);
 198        }
 0199        catch (ObjectDisposedException ex)
 200        {
 0201            throw new Ice.ConnectionLostException(ex);
 202        }
 1203    }
 204
 205    public bool startWrite(Buffer buf, AsyncCallback callback, object state, out bool messageWritten)
 206    {
 207        Debug.Assert(_fd != null && _writeEventArgs != null);
 1208        if (_state == StateConnectPending)
 209        {
 1210            messageWritten = false;
 1211            _writeCallback = callback;
 212            try
 213            {
 1214                EndPoint addr = _proxy != null ? _proxy.getAddress() : _addr;
 1215                if (_sourceAddr != null)
 216                {
 0217                    Network.doBind(_fd, _sourceAddr);
 218                }
 1219                _writeEventArgs.RemoteEndPoint = addr;
 1220                _writeEventArgs.UserToken = state;
 1221                return !_fd.ConnectAsync(_writeEventArgs);
 222            }
 0223            catch (System.Exception ex)
 224            {
 0225                throw new Ice.SocketException(ex);
 226            }
 227        }
 228
 229        try
 230        {
 1231            _writeCallback = callback;
 1232            _writeEventArgs.UserToken = state;
 1233            _writeEventArgs.SetBuffer(buf.b.rawBytes(), buf.b.position(), buf.b.remaining());
 1234            bool completedSynchronously = !_fd.SendAsync(_writeEventArgs);
 1235            messageWritten = true;
 1236            return completedSynchronously;
 237        }
 0238        catch (System.Net.Sockets.SocketException ex)
 239        {
 0240            if (Network.connectionLost(ex))
 241            {
 0242                throw new Ice.ConnectionLostException(ex);
 243            }
 0244            throw new Ice.SocketException(ex);
 245        }
 0246        catch (ObjectDisposedException ex)
 247        {
 0248            throw new Ice.ConnectionLostException(ex);
 249        }
 1250    }
 251
 252    public void finishWrite(Buffer buf)
 253    {
 1254        if (_fd == null) // Transceiver was closed
 255        {
 0256            buf.b.position(buf.b.limit()); // Assume all the data was sent for at-most-once semantics.
 0257            return;
 258        }
 259
 260        Debug.Assert(_fd != null && _writeEventArgs != null);
 261
 1262        if (_state < StateConnected && _state != StateProxyWrite)
 263        {
 1264            return;
 265        }
 266
 267        try
 268        {
 1269            if (_writeEventArgs.SocketError != SocketError.Success)
 270            {
 1271                throw new System.Net.Sockets.SocketException((int)_writeEventArgs.SocketError);
 272            }
 1273            int ret = _writeEventArgs.BytesTransferred;
 1274            _writeEventArgs.SetBuffer(null, 0, 0);
 1275            if (ret == 0)
 276            {
 0277                throw new Ice.ConnectionLostException();
 278            }
 279
 280            Debug.Assert(ret > 0);
 1281            buf.b.position(buf.b.position() + ret);
 282
 1283            if (_state == StateProxyWrite)
 284            {
 1285                _state = toState(_proxy.endWrite(buf));
 286            }
 1287        }
 1288        catch (System.Net.Sockets.SocketException ex)
 289        {
 1290            if (Network.connectionLost(ex))
 291            {
 1292                throw new Ice.ConnectionLostException(ex);
 293            }
 294
 0295            throw new Ice.SocketException(ex);
 296        }
 0297        catch (ObjectDisposedException ex)
 298        {
 0299            throw new Ice.ConnectionLostException(ex);
 300        }
 1301    }
 302
 303    public void close()
 304    {
 305        Debug.Assert(_fd != null);
 306        try
 307        {
 1308            Network.closeSocket(_fd);
 1309        }
 310        finally
 311        {
 1312            _fd = null;
 1313        }
 1314    }
 315
 316    public void destroy()
 317    {
 318        Debug.Assert(_readEventArgs != null && _writeEventArgs != null);
 1319        _readEventArgs.Dispose();
 1320        _writeEventArgs.Dispose();
 1321    }
 322
 1323    public override string ToString() => _desc;
 324
 325    private int read(ByteBuffer buf)
 326    {
 327        Debug.Assert(_fd != null);
 1328        int read = 0;
 1329        while (buf.hasRemaining())
 330        {
 331            try
 332            {
 1333                int ret = _fd.Receive(buf.rawBytes(), buf.position(), buf.remaining(), SocketFlags.None);
 1334                if (ret == 0)
 335                {
 1336                    throw new Ice.ConnectionLostException();
 337                }
 1338                read += ret;
 1339                buf.position(buf.position() + ret);
 1340            }
 1341            catch (System.Net.Sockets.SocketException ex)
 342            {
 1343                if (Network.wouldBlock(ex))
 344                {
 1345                    return read;
 346                }
 1347                else if (Network.interrupted(ex))
 348                {
 0349                    continue;
 350                }
 1351                else if (Network.connectionLost(ex))
 352                {
 1353                    throw new ConnectionLostException(ex);
 354                }
 355
 0356                throw new SocketException(ex);
 357            }
 358        }
 1359        return read;
 1360    }
 361
 362    private int write(ByteBuffer buf)
 363    {
 364        Debug.Assert(_fd != null);
 1365        int sent = 0;
 1366        while (buf.hasRemaining())
 367        {
 368            try
 369            {
 1370                int ret = _fd.Send(buf.rawBytes(), buf.position(), buf.remaining(), SocketFlags.None);
 371                Debug.Assert(ret > 0);
 372
 1373                sent += ret;
 1374                buf.position(buf.position() + ret);
 1375            }
 1376            catch (System.Net.Sockets.SocketException ex)
 377            {
 1378                if (Network.wouldBlock(ex))
 379                {
 1380                    return sent;
 381                }
 1382                else if (Network.connectionLost(ex))
 383                {
 1384                    throw new Ice.ConnectionLostException(ex);
 385                }
 0386                throw new Ice.SocketException(ex);
 387            }
 388        }
 1389        return sent;
 1390    }
 391
 392    private void ioCompleted(object sender, SocketAsyncEventArgs e)
 393    {
 1394        switch (e.LastOperation)
 395        {
 396            case SocketAsyncOperation.Receive:
 1397                _readCallback(e.UserToken);
 1398                break;
 399            case SocketAsyncOperation.Send:
 400            case SocketAsyncOperation.Connect:
 1401                _writeCallback(e.UserToken);
 1402                break;
 403            default:
 0404                throw new ArgumentException("The last operation completed on the socket was not a receive or send");
 405        }
 406    }
 407
 408    private void init()
 409    {
 1410        Network.setBlock(_fd, false);
 1411        Network.setTcpBufSize(_fd, _instance);
 412
 1413        _readEventArgs = new SocketAsyncEventArgs();
 1414        _readEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(ioCompleted);
 415
 1416        _writeEventArgs = new SocketAsyncEventArgs();
 1417        _writeEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(ioCompleted);
 1418    }
 419
 420    private int toState(int operation)
 421    {
 1422        return operation switch
 1423        {
 1424            SocketOperation.Read => StateProxyRead,
 0425            SocketOperation.Write => StateProxyWrite,
 1426            _ => StateProxyConnected,
 1427        };
 428    }
 429
 430    private readonly ProtocolInstance _instance;
 431    private readonly NetworkProxy _proxy;
 432    private readonly EndPoint _addr;
 433    private readonly EndPoint _sourceAddr;
 434
 435    private Socket _fd;
 436    private int _state;
 437    private string _desc;
 438
 439    private SocketAsyncEventArgs _writeEventArgs;
 440    private SocketAsyncEventArgs _readEventArgs;
 441    private AsyncCallback _writeCallback;
 442    private AsyncCallback _readCallback;
 443
 444    private const int StateNeedConnect = 0;
 445    private const int StateConnectPending = 1;
 446    private const int StateProxyWrite = 2;
 447    private const int StateProxyRead = 3;
 448    private const int StateProxyConnected = 4;
 449    private const int StateConnected = 5;
 450}