< Summary

Information
Class: Ice.Internal.UdpTransceiver
Assembly: Ice
File(s): /home/runner/work/ice/ice/csharp/src/Ice/Internal/UdpTransceiver.cs
Tag: 71_18251537082
Line coverage
56%
Covered lines: 199
Uncovered lines: 151
Coverable lines: 350
Total lines: 845
Line coverage: 56.8%
Branch coverage
36%
Covered branches: 69
Total branches: 191
Branch coverage: 36.1%
Method coverage
82%
Covered methods: 19
Total methods: 23
Method coverage: 82.6%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
fd()100%210%
initialize(...)50%11.46646.67%
closing(...)100%210%
close()100%2.09271.43%
bind()50%9.21873.33%
destroy()100%11100%
write(...)33.33%46.151238.1%
read(...)4.17%506.86245.71%
startRead(...)25%15.891270%
finishRead(...)30%76.82047.83%
startWrite(...)0%156120%
finishWrite(...)0%272160%
protocol()100%11100%
getInfo(...)68.75%16.011696.55%
checkSendSize(...)100%22100%
setBufferSize(...)100%11100%
ToString()83.33%12.671283.33%
toDetailedString()100%44100%
effectivePort()100%11100%
.ctor(...)83.33%6696.77%
.ctor(...)0%4.08482.76%
setBufSize(...)42.86%47.022871.05%
ioCompleted(...)28.57%13.13750%

File(s)

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

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3using System.Diagnostics;
 4using System.Net;
 5using System.Net.Sockets;
 6using System.Text;
 7
 8namespace Ice.Internal;
 9
 10#pragma warning disable CA1001 // _readEventArgs and _writeEventArgs are disposed by destroy.
 11internal sealed class UdpTransceiver : Transceiver
 12#pragma warning restore CA1001
 13{
 014    public Socket fd() => _fd;
 15
 16    public int initialize(Buffer readBuffer, Buffer writeBuffer, ref bool hasMoreData)
 17    {
 118        if (_state == StateNeedConnect)
 19        {
 120            _state = StateConnectPending;
 21            try
 22            {
 123                if (_sourceAddr != null)
 24                {
 025                    _fd.Bind(_sourceAddr);
 26                }
 127                _fd.Connect(_addr);
 128            }
 029            catch (System.Net.Sockets.SocketException ex)
 30            {
 031                if (Network.wouldBlock(ex))
 32                {
 033                    return SocketOperation.Connect;
 34                }
 035                throw new Ice.ConnectFailedException(ex);
 36            }
 037            catch (System.Exception ex)
 38            {
 039                throw new Ice.ConnectFailedException(ex);
 40            }
 141            _state = StateConnected;
 42        }
 43
 44        Debug.Assert(_state >= StateConnected);
 145        return SocketOperation.None;
 046    }
 47
 48    public int closing(bool initiator, Ice.LocalException ex) =>
 49        //
 50        // Nothing to do.
 51        //
 052        SocketOperation.None;
 53
 54    public void close()
 55    {
 156        if (_fd != null)
 57        {
 58            try
 59            {
 160                _fd.Close();
 161            }
 062            catch (System.IO.IOException)
 63            {
 064            }
 165            _fd = null;
 66        }
 167    }
 68
 69    public EndpointI bind()
 70    {
 171        if (Network.isMulticast((IPEndPoint)_addr))
 72        {
 173            Network.setReuseAddress(_fd, true);
 174            _mcastAddr = (IPEndPoint)_addr;
 175            if (AssemblyUtil.isWindows)
 76            {
 77                // Windows does not allow binding to the mcast address itself so we bind to INADDR_ANY instead.
 078                _addr = new IPEndPoint(
 079                    _addr.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any,
 080                    _port);
 81            }
 82
 183            _addr = Network.doBind(_fd, _addr);
 184            if (_port == 0)
 85            {
 086                _mcastAddr.Port = ((IPEndPoint)_addr).Port;
 87            }
 188            Network.setMcastGroup(_fd, _mcastAddr.Address, _mcastInterface);
 89        }
 90        else
 91        {
 192            _addr = Network.doBind(_fd, _addr);
 93        }
 194        _bound = true;
 195        _endpoint = _endpoint.endpoint(this);
 196        return _endpoint;
 97    }
 98
 99    public void destroy()
 100    {
 1101        _readEventArgs.Dispose();
 1102        _writeEventArgs.Dispose();
 1103    }
 104
 105    public int write(Buffer buf)
 106    {
 1107        if (!buf.b.hasRemaining())
 108        {
 0109            return SocketOperation.None;
 110        }
 111
 112        Debug.Assert(buf.b.position() == 0);
 113        Debug.Assert(_fd != null && _state >= StateConnected);
 114
 115        // The caller is supposed to check the send size before by calling checkSendSize
 116        Debug.Assert(Math.Min(_maxPacketSize, _sndSize - _udpOverhead) >= buf.size());
 117
 118        int ret;
 119        while (true)
 120        {
 121            try
 122            {
 1123                if (_state == StateConnected)
 124                {
 1125                    ret = _fd.Send(buf.b.rawBytes(), 0, buf.size(), SocketFlags.None);
 126                }
 127                else
 128                {
 1129                    if (_peerAddr == null)
 130                    {
 0131                        throw new Ice.SocketException();
 132                    }
 1133                    ret = _fd.SendTo(buf.b.rawBytes(), 0, buf.size(), SocketFlags.None, _peerAddr);
 134                }
 1135                break;
 136            }
 0137            catch (System.Net.Sockets.SocketException ex)
 138            {
 0139                if (Network.interrupted(ex))
 140                {
 0141                    continue;
 142                }
 143
 0144                if (Network.wouldBlock(ex))
 145                {
 0146                    return SocketOperation.Write;
 147                }
 148
 0149                if (Network.connectionLost(ex))
 150                {
 0151                    throw new Ice.ConnectionLostException(ex);
 152                }
 153                else
 154                {
 0155                    throw new Ice.SocketException(ex);
 156                }
 157            }
 0158            catch (System.Exception e)
 159            {
 0160                throw new Ice.SyscallException(e);
 161            }
 162        }
 163
 164        Debug.Assert(ret > 0);
 165        Debug.Assert(ret == buf.b.limit());
 1166        buf.b.position(buf.b.limit());
 1167        return SocketOperation.None;
 0168    }
 169
 170    public int read(Buffer buf, ref bool hasMoreData)
 171    {
 1172        if (!buf.b.hasRemaining())
 173        {
 1174            return SocketOperation.None;
 175        }
 176
 177        Debug.Assert(buf.b.position() == 0);
 178        Debug.Assert(_fd != null);
 179
 0180        int packetSize = Math.Min(_maxPacketSize, _rcvSize - _udpOverhead);
 0181        buf.resize(packetSize, true);
 0182        buf.b.position(0);
 183
 184        int ret;
 185        while (true)
 186        {
 187            try
 188            {
 0189                EndPoint peerAddr = _peerAddr;
 0190                if (peerAddr == null)
 191                {
 0192                    if (_addr.AddressFamily == AddressFamily.InterNetwork)
 193                    {
 0194                        peerAddr = new IPEndPoint(IPAddress.Any, 0);
 195                    }
 196                    else
 197                    {
 198                        Debug.Assert(_addr.AddressFamily == AddressFamily.InterNetworkV6);
 0199                        peerAddr = new IPEndPoint(IPAddress.IPv6Any, 0);
 200                    }
 201                }
 202
 203                // TODO: Workaround for https://github.com/dotnet/corefx/issues/31182
 0204                if (_state == StateConnected ||
 0205                   (AssemblyUtil.isMacOS && _fd.AddressFamily == AddressFamily.InterNetworkV6 && _fd.DualMode))
 206                {
 0207                    ret = _fd.Receive(buf.b.rawBytes(), 0, buf.b.limit(), SocketFlags.None);
 208                }
 209                else
 210                {
 0211                    ret = _fd.ReceiveFrom(buf.b.rawBytes(), 0, buf.b.limit(), SocketFlags.None, ref peerAddr);
 0212                    _peerAddr = (IPEndPoint)peerAddr;
 213                }
 0214                break;
 215            }
 0216            catch (System.Net.Sockets.SocketException e)
 217            {
 0218                if (Network.recvTruncated(e))
 219                {
 220                    // The message was truncated and the whole buffer is filled. We ignore
 221                    // this error here, it will be detected at the connection level when
 222                    // the Ice message size is checked against the buffer size.
 0223                    ret = buf.size();
 0224                    break;
 225                }
 226
 0227                if (Network.interrupted(e))
 228                {
 0229                    continue;
 230                }
 231
 0232                if (Network.wouldBlock(e))
 233                {
 0234                    return SocketOperation.Read;
 235                }
 236
 0237                if (Network.connectionLost(e))
 238                {
 0239                    throw new ConnectionLostException(e);
 240                }
 241                else
 242                {
 0243                    throw new Ice.SocketException(e);
 244                }
 245            }
 0246            catch (System.Exception e)
 247            {
 0248                throw new SyscallException(e);
 249            }
 250        }
 251
 0252        if (ret == 0)
 253        {
 0254            throw new Ice.ConnectionLostException();
 255        }
 256
 257        Debug.Assert(_state != StateNeedConnect);
 258
 0259        buf.resize(ret, true);
 0260        buf.b.position(ret);
 261
 0262        return SocketOperation.None;
 0263    }
 264
 265    public bool startRead(Buffer buf, AsyncCallback callback, object state)
 266    {
 267        Debug.Assert(buf.b.position() == 0);
 268
 1269        int packetSize = Math.Min(_maxPacketSize, _rcvSize - _udpOverhead);
 1270        buf.resize(packetSize, true);
 1271        buf.b.position(0);
 272
 273        try
 274        {
 275            // TODO: Workaround for https://github.com/dotnet/corefx/issues/31182
 1276            if (_state == StateConnected ||
 1277               (AssemblyUtil.isMacOS && _fd.AddressFamily == AddressFamily.InterNetworkV6 && _fd.DualMode))
 278            {
 1279                _readCallback = callback;
 1280                _readEventArgs.UserToken = state;
 1281                _readEventArgs.SetBuffer(buf.b.rawBytes(), buf.b.position(), packetSize);
 1282                return !_fd.ReceiveAsync(_readEventArgs);
 283            }
 284            else
 285            {
 286                Debug.Assert(_incoming);
 1287                _readCallback = callback;
 1288                _readEventArgs.UserToken = state;
 1289                _readEventArgs.SetBuffer(buf.b.rawBytes(), 0, buf.b.limit());
 1290                return !_fd.ReceiveFromAsync(_readEventArgs);
 291            }
 292        }
 0293        catch (System.Net.Sockets.SocketException ex)
 294        {
 0295            if (Network.recvTruncated(ex))
 296            {
 297                // Nothing todo
 0298                return true;
 299            }
 300            else
 301            {
 0302                if (Network.connectionLost(ex))
 303                {
 0304                    throw new Ice.ConnectionLostException(ex);
 305                }
 306                else
 307                {
 0308                    throw new Ice.SocketException(ex);
 309                }
 310            }
 311        }
 1312    }
 313
 314    public void finishRead(Buffer buf)
 315    {
 1316        if (_fd == null)
 317        {
 0318            return;
 319        }
 320
 321        int ret;
 322        try
 323        {
 1324            if (_readEventArgs.SocketError != SocketError.Success)
 325            {
 0326                throw new System.Net.Sockets.SocketException((int)_readEventArgs.SocketError);
 327            }
 1328            ret = _readEventArgs.BytesTransferred;
 329            // TODO: Workaround for https://github.com/dotnet/corefx/issues/31182
 1330            if (_state != StateConnected &&
 1331               !(AssemblyUtil.isMacOS && _fd.AddressFamily == AddressFamily.InterNetworkV6 && _fd.DualMode))
 332            {
 1333                _peerAddr = _readEventArgs.RemoteEndPoint;
 334            }
 1335        }
 0336        catch (System.Net.Sockets.SocketException ex)
 337        {
 0338            if (Network.recvTruncated(ex))
 339            {
 340                // The message was truncated and the whole buffer is filled. We ignore
 341                // this error here, it will be detected at the connection level when
 342                // the Ice message size is checked against the buffer size.
 0343                ret = buf.size();
 344            }
 345            else
 346            {
 0347                if (Network.connectionLost(ex))
 348                {
 0349                    throw new Ice.ConnectionLostException(ex);
 350                }
 351
 0352                if (Network.connectionRefused(ex))
 353                {
 0354                    throw new Ice.ConnectionRefusedException(ex);
 355                }
 356                else
 357                {
 0358                    throw new Ice.SocketException(ex);
 359                }
 360            }
 0361        }
 362
 1363        if (ret == 0)
 364        {
 0365            throw new Ice.ConnectionLostException();
 366        }
 367
 368        Debug.Assert(_state != StateNeedConnect);
 1369        buf.resize(ret, true);
 1370        buf.b.position(ret);
 1371    }
 372
 373    public bool startWrite(Buffer buf, AsyncCallback callback, object state, out bool messageWritten)
 374    {
 0375        if (!_incoming && _state < StateConnected)
 376        {
 377            Debug.Assert(_addr != null);
 0378            messageWritten = false;
 0379            if (_sourceAddr != null)
 380            {
 0381                _fd.Bind(_sourceAddr);
 382            }
 0383            _writeEventArgs.UserToken = state;
 0384            return !_fd.ConnectAsync(_writeEventArgs);
 385        }
 386
 387        Debug.Assert(_fd != null);
 388
 389        // The caller is supposed to check the send size before by calling checkSendSize
 390        Debug.Assert(Math.Min(_maxPacketSize, _sndSize - _udpOverhead) >= buf.size());
 391
 392        Debug.Assert(buf.b.position() == 0);
 393
 394        bool completedSynchronously;
 395        try
 396        {
 0397            _writeCallback = callback;
 398
 0399            if (_state == StateConnected)
 400            {
 0401                _writeEventArgs.UserToken = state;
 0402                _writeEventArgs.SetBuffer(buf.b.rawBytes(), 0, buf.b.limit());
 0403                completedSynchronously = !_fd.SendAsync(_writeEventArgs);
 404            }
 405            else
 406            {
 0407                if (_peerAddr == null)
 408                {
 0409                    throw new Ice.SocketException();
 410                }
 0411                _writeEventArgs.RemoteEndPoint = _peerAddr;
 0412                _writeEventArgs.UserToken = state;
 0413                _writeEventArgs.SetBuffer(buf.b.rawBytes(), 0, buf.b.limit());
 0414                completedSynchronously = !_fd.SendToAsync(_writeEventArgs);
 415            }
 0416        }
 0417        catch (System.Net.Sockets.SocketException ex)
 418        {
 0419            if (Network.connectionLost(ex))
 420            {
 0421                throw new Ice.ConnectionLostException(ex);
 422            }
 423            else
 424            {
 0425                throw new Ice.SocketException(ex);
 426            }
 427        }
 428
 0429        messageWritten = true;
 0430        return completedSynchronously;
 431    }
 432
 433    public void finishWrite(Buffer buf)
 434    {
 0435        if (_fd == null)
 436        {
 0437            buf.b.position(buf.size()); // Assume all the data was sent for at-most-once semantics.
 0438            _writeEventArgs = null;
 0439            return;
 440        }
 441
 0442        if (!_incoming && _state < StateConnected)
 443        {
 0444            if (_writeEventArgs.SocketError != SocketError.Success)
 445            {
 0446                var ex =
 0447                    new System.Net.Sockets.SocketException((int)_writeEventArgs.SocketError);
 0448                if (Network.connectionRefused(ex))
 449                {
 0450                    throw new Ice.ConnectionRefusedException(ex);
 451                }
 452                else
 453                {
 0454                    throw new Ice.ConnectFailedException(ex);
 455                }
 456            }
 0457            return;
 458        }
 459
 460        int ret;
 461        try
 462        {
 0463            if (_writeEventArgs.SocketError != SocketError.Success)
 464            {
 0465                throw new System.Net.Sockets.SocketException((int)_writeEventArgs.SocketError);
 466            }
 0467            ret = _writeEventArgs.BytesTransferred;
 0468        }
 0469        catch (System.Net.Sockets.SocketException ex)
 470        {
 0471            if (Network.connectionLost(ex))
 472            {
 0473                throw new Ice.ConnectionLostException(ex);
 474            }
 475            else
 476            {
 0477                throw new Ice.SocketException(ex);
 478            }
 479        }
 480
 0481        if (ret == 0)
 482        {
 0483            throw new Ice.ConnectionLostException();
 484        }
 485
 486        Debug.Assert(ret > 0);
 487        Debug.Assert(ret == buf.b.limit());
 0488        buf.b.position(buf.b.position() + ret);
 0489    }
 490
 1491    public string protocol() => _instance.protocol();
 492
 493    public ConnectionInfo getInfo(bool incoming, string adapterName, string connectionId)
 494    {
 1495        if (_fd is null)
 496        {
 0497            return new UDPConnectionInfo(incoming, adapterName, connectionId);
 498        }
 499        else
 500        {
 1501            EndPoint localEndpoint = Network.getLocalAddress(_fd);
 502
 1503            if (_state == StateNotConnected) // a server connection
 504            {
 505                Debug.Assert(incoming);
 506
 507                // Since this info is cached in the Connection object shared by all the clients, we don't store the
 508                // remote address/port of the latest client in this info.
 1509                return new UDPConnectionInfo(
 1510                    incoming,
 1511                    adapterName,
 1512                    connectionId,
 1513                    Network.endpointAddressToString(localEndpoint),
 1514                    Network.endpointPort(localEndpoint),
 1515                    remoteAddress: "",
 1516                    remotePort: -1,
 1517                    _mcastAddr is not null ? Network.endpointAddressToString(_mcastAddr) : "",
 1518                    _mcastAddr is not null ? Network.endpointPort(_mcastAddr) : -1,
 1519                    _rcvSize,
 1520                    _sndSize);
 521            }
 522            else // client connection
 523            {
 524                Debug.Assert(!incoming);
 1525                EndPoint remoteEndpoint = Network.getRemoteAddress(_fd);
 526
 1527                return new UDPConnectionInfo(
 1528                    incoming,
 1529                    adapterName,
 1530                    connectionId,
 1531                    Network.endpointAddressToString(localEndpoint),
 1532                    Network.endpointPort(localEndpoint),
 1533                    remoteEndpoint is not null ? Network.endpointAddressToString(remoteEndpoint) : "",
 1534                    remoteEndpoint is not null ? Network.endpointPort(remoteEndpoint) : -1,
 1535                    _mcastAddr is not null ? Network.endpointAddressToString(_mcastAddr) : "",
 1536                    _mcastAddr is not null ? Network.endpointPort(_mcastAddr) : -1,
 1537                    _rcvSize,
 1538                    _sndSize);
 539            }
 540        }
 541    }
 542
 543    public void checkSendSize(Buffer buf)
 544    {
 545        //
 546        // The maximum packetSize is either the maximum allowable UDP packet size, or
 547        // the UDP send buffer size (which ever is smaller).
 548        //
 1549        int packetSize = Math.Min(_maxPacketSize, _sndSize - _udpOverhead);
 1550        if (packetSize < buf.size())
 551        {
 1552            throw new Ice.DatagramLimitException();
 553        }
 1554    }
 555
 1556    public void setBufferSize(int rcvSize, int sndSize) => setBufSize(rcvSize, sndSize);
 557
 558    public override string ToString()
 559    {
 1560        if (_fd == null)
 561        {
 0562            return "<closed>";
 563        }
 564
 565        string s;
 1566        if (_incoming && !_bound)
 567        {
 1568            s = "local address = " + Network.addrToString(_addr);
 569        }
 1570        else if (_state == StateNotConnected)
 571        {
 1572            s = "local address = " + Network.localAddrToString(Network.getLocalAddress(_fd));
 1573            if (_peerAddr != null)
 574            {
 0575                s += "\nremote address = " + Network.addrToString(_peerAddr);
 576            }
 577        }
 578        else
 579        {
 1580            s = Network.fdToString(_fd);
 581        }
 582
 1583        if (_mcastAddr != null)
 584        {
 1585            s += "\nmulticast address = " + Network.addrToString(_mcastAddr);
 586        }
 1587        return s;
 588    }
 589
 590    public string toDetailedString()
 591    {
 1592        var s = new StringBuilder(ToString());
 1593        if (_mcastAddr is not null)
 594        {
 1595            List<string> intfs = Network.getInterfacesForMulticast(
 1596                _mcastInterface,
 1597                Network.getProtocolSupport(_mcastAddr.Address));
 1598            if (intfs.Count != 0)
 599            {
 1600                s.Append("\nlocal interfaces = ");
 1601                s.Append(string.Join(", ", intfs.ToArray()));
 602            }
 603        }
 1604        return s.ToString();
 605    }
 606
 1607    public int effectivePort() => Network.endpointPort(_addr);
 608
 609    //
 610    // Only for use by UdpConnector.
 611    //
 1612    internal UdpTransceiver(
 1613        ProtocolInstance instance,
 1614        EndPoint addr,
 1615        EndPoint sourceAddr,
 1616        string mcastInterface,
 1617        int mcastTtl)
 618    {
 1619        _instance = instance;
 1620        _addr = addr;
 1621        _sourceAddr = sourceAddr;
 622
 1623        _readEventArgs = new SocketAsyncEventArgs();
 1624        _readEventArgs.RemoteEndPoint = _addr;
 1625        _readEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(ioCompleted);
 626
 1627        _writeEventArgs = new SocketAsyncEventArgs();
 1628        _writeEventArgs.RemoteEndPoint = _addr;
 1629        _writeEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(ioCompleted);
 630
 1631        _mcastInterface = mcastInterface;
 1632        _state = StateNeedConnect;
 1633        _incoming = false;
 634
 635        try
 636        {
 1637            _fd = Network.createSocket(true, _addr.AddressFamily);
 1638            setBufSize(-1, -1);
 1639            Network.setBlock(_fd, false);
 1640            if (Network.isMulticast((IPEndPoint)_addr))
 641            {
 1642                if (_mcastInterface.Length > 0)
 643                {
 1644                    Network.setMcastInterface(_fd, _mcastInterface, _addr.AddressFamily);
 645                }
 1646                if (mcastTtl != -1)
 647                {
 0648                    Network.setMcastTtl(_fd, mcastTtl, _addr.AddressFamily);
 649                }
 650            }
 1651        }
 1652        catch (Ice.LocalException)
 653        {
 1654            _fd = null;
 1655            throw;
 656        }
 1657    }
 658
 659    //
 660    // Only for use by UdpEndpoint.
 661    //
 1662    internal UdpTransceiver(
 1663        UdpEndpointI endpoint,
 1664        ProtocolInstance instance,
 1665        string host,
 1666        int port,
 1667        string mcastInterface)
 668    {
 1669        _endpoint = endpoint;
 1670        _instance = instance;
 1671        _state = StateNotConnected;
 1672        _mcastInterface = mcastInterface;
 1673        _incoming = true;
 1674        _port = port;
 675
 676        try
 677        {
 1678            _addr = Network.getAddressForServer(host, port, instance.protocolSupport(), instance.preferIPv6());
 679
 1680            _readEventArgs = new SocketAsyncEventArgs();
 1681            _readEventArgs.RemoteEndPoint = _addr;
 1682            _readEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(ioCompleted);
 683
 1684            _writeEventArgs = new SocketAsyncEventArgs();
 1685            _writeEventArgs.RemoteEndPoint = _addr;
 1686            _writeEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(ioCompleted);
 687
 1688            _fd = Network.createServerSocket(true, _addr.AddressFamily, instance.protocolSupport());
 1689            setBufSize(-1, -1);
 1690            Network.setBlock(_fd, false);
 1691        }
 0692        catch (Ice.LocalException)
 693        {
 0694            _readEventArgs?.Dispose();
 0695            _writeEventArgs?.Dispose();
 0696            _fd = null;
 0697            throw;
 698        }
 1699    }
 700
 701    private void setBufSize(int rcvSize, int sndSize)
 702    {
 703        Debug.Assert(_fd != null);
 704
 1705        for (int i = 0; i < 2; ++i)
 706        {
 707            bool isSnd;
 708            string direction;
 709            string prop;
 710            int dfltSize;
 711            int sizeRequested;
 1712            if (i == 0)
 713            {
 1714                isSnd = false;
 1715                direction = "receive";
 1716                prop = "Ice.UDP.RcvSize";
 1717                dfltSize = Network.getRecvBufferSize(_fd);
 1718                sizeRequested = rcvSize;
 1719                _rcvSize = dfltSize;
 720            }
 721            else
 722            {
 1723                isSnd = true;
 1724                direction = "send";
 1725                prop = "Ice.UDP.SndSize";
 1726                dfltSize = Network.getSendBufferSize(_fd);
 1727                sizeRequested = sndSize;
 1728                _sndSize = dfltSize;
 729            }
 730
 731            //
 732            // Get property for buffer size if size not passed in.
 733            //
 1734            if (sizeRequested == -1)
 735            {
 1736                sizeRequested = _instance.properties().getPropertyAsIntWithDefault(prop, dfltSize);
 737            }
 738            //
 739            // Check for sanity.
 740            //
 1741            if (sizeRequested < (_udpOverhead + Protocol.headerSize))
 742            {
 0743                _instance.logger().warning("Invalid " + prop + " value of " + sizeRequested + " adjusted to " +
 0744                                           dfltSize);
 0745                sizeRequested = dfltSize;
 746            }
 747
 1748            if (sizeRequested != dfltSize)
 749            {
 750                //
 751                // Try to set the buffer size. The kernel will silently adjust
 752                // the size to an acceptable value. Then read the size back to
 753                // get the size that was actually set.
 754                //
 755                int sizeSet;
 1756                if (i == 0)
 757                {
 1758                    Network.setRecvBufferSize(_fd, sizeRequested);
 1759                    _rcvSize = Network.getRecvBufferSize(_fd);
 1760                    sizeSet = _rcvSize;
 761                }
 762                else
 763                {
 1764                    Network.setSendBufferSize(_fd, sizeRequested);
 1765                    _sndSize = Network.getSendBufferSize(_fd);
 1766                    sizeSet = _sndSize;
 767                }
 768
 769                //
 770                // Warn if the size that was set is less than the requested size
 771                // and we have not already warned
 772                //
 1773                if (sizeSet < sizeRequested)
 774                {
 0775                    BufSizeWarnInfo winfo = _instance.getBufSizeWarn(Ice.UDPEndpointType.value);
 0776                    if ((isSnd && (!winfo.sndWarn || winfo.sndSize != sizeRequested)) ||
 0777                       (!isSnd && (!winfo.rcvWarn || winfo.rcvSize != sizeRequested)))
 778                    {
 0779                        _instance.logger().warning("UDP " + direction + " buffer size: requested size of " +
 0780                                                   sizeRequested + " adjusted to " + sizeSet);
 781
 0782                        if (isSnd)
 783                        {
 0784                            _instance.setSndBufSizeWarn(Ice.UDPEndpointType.value, sizeRequested);
 785                        }
 786                        else
 787                        {
 0788                            _instance.setRcvBufSizeWarn(Ice.UDPEndpointType.value, sizeRequested);
 789                        }
 790                    }
 791                }
 792            }
 793        }
 1794    }
 795
 796    internal void ioCompleted(object sender, SocketAsyncEventArgs e)
 797    {
 1798        switch (e.LastOperation)
 799        {
 800            case SocketAsyncOperation.Receive:
 801            case SocketAsyncOperation.ReceiveFrom:
 1802                _readCallback(e.UserToken);
 1803                break;
 804            case SocketAsyncOperation.Send:
 805            case SocketAsyncOperation.Connect:
 0806                _writeCallback(e.UserToken);
 0807                break;
 808            default:
 0809                throw new ArgumentException("The last operation completed on the socket was not a receive or send");
 810        }
 811    }
 812
 813    private UdpEndpointI _endpoint;
 814    private readonly ProtocolInstance _instance;
 815    private int _state;
 816    private readonly bool _incoming;
 817    private int _rcvSize;
 818    private int _sndSize;
 819    private Socket _fd;
 820    private EndPoint _addr;
 821    private readonly EndPoint _sourceAddr;
 822    private IPEndPoint _mcastAddr;
 823    private EndPoint _peerAddr;
 824    private readonly string _mcastInterface;
 825
 826    private readonly int _port;
 827    private bool _bound;
 828
 829    private SocketAsyncEventArgs _writeEventArgs;
 830    private readonly SocketAsyncEventArgs _readEventArgs;
 831    private AsyncCallback _writeCallback;
 832    private AsyncCallback _readCallback;
 833
 834    private const int StateNeedConnect = 0;
 835    private const int StateConnectPending = 1;
 836    private const int StateConnected = 2;
 837    private const int StateNotConnected = 3;
 838
 839    //
 840    // The maximum IP datagram size is 65535. Subtract 20 bytes for the IP header and 8 bytes for the UDP header
 841    // to get the maximum payload.
 842    //
 843    private const int _udpOverhead = 20 + 8;
 844    private const int _maxPacketSize = 65535 - _udpOverhead;
 845}