public bool close(UdpSocket fan) { try { close(); return true; } catch { return false; } }
////////////////////////////////////////////////////////////////////////// // Communication ////////////////////////////////////////////////////////////////////////// public UdpSocket bind(UdpSocket fan, IpAddr addr, Long port) { try { if (m_dotnet == null) m_dotnet = createSocket(); IPAddress dotnetAddr = (addr == null) ? IPAddress.Any : addr.m_peer.m_dotnet; int dotnetPort = (port == null) ? 0 : port.intValue(); m_dotnet.Bind(new IPEndPoint(dotnetAddr, dotnetPort)); return fan; } catch (SocketException e) { throw IOErr.make(e).val; } }
internal UdpSocketReceiveManager(UdpSocket[] receiveSockets, int maxPendingReceivesPerSocket, BufferManager bufferManager, IUdpReceiveHandler receiveHandler) { Fx.Assert(receiveSockets != null, "receiveSockets parameter is null"); Fx.Assert(receiveSockets.Length > 0, "receiveSockets parameter is empty"); Fx.Assert(maxPendingReceivesPerSocket > 0, "maxPendingReceivesPerSocket can't be <= 0"); Fx.Assert(receiveHandler.MaxReceivedMessageSize > 0, "maxReceivedMessageSize must be > 0"); Fx.Assert(bufferManager != null, "bufferManager argument should not be null"); Fx.Assert(receiveHandler != null, "receiveHandler should not be null"); this.receiveHandler = receiveHandler; this.thisLock = new object(); this.bufferManager = bufferManager; this.receiveSockets = receiveSockets; this.maxPendingReceivesPerSocket = maxPendingReceivesPerSocket; this.messageBufferSize = UdpUtility.ComputeMessageBufferSize(receiveHandler.MaxReceivedMessageSize); int maxPendingReceives = maxPendingReceivesPerSocket * receiveSockets.Length; this.receiveBufferPool = new ConnectionBufferPool(this.messageBufferSize, maxPendingReceives); }
public void setReceiveTimeout(UdpSocket fan, Duration v) { m_receiveTimeout = (v == null) ? 0 : (int)v.millis(); }
public void setReuseAddr(UdpSocket fan, bool v) { m_reuseAddr = v; }
public ServerUdpOutputChannel(ChannelManagerBase factory, MessageEncoder encoder, BufferManager bufferManager, UdpSocket[] sendSockets, UdpRetransmissionSettings retransmissionSettings, Uri via, bool isMulticast) : base(factory, encoder, bufferManager, sendSockets, retransmissionSettings, via, isMulticast) { }
public bool getReuseAddr(UdpSocket fan) { return m_reuseAddr; }
////////////////////////////////////////////////////////////////////////// // State ////////////////////////////////////////////////////////////////////////// public bool isBound(UdpSocket fan) { return (m_dotnet == null) ? false : m_dotnet.IsBound; }
public UdpSocketReceiveState(UdpSocket socket, byte[] receiveBuffer) { Fx.Assert(socket != null, "UdpSocketReceiveState.ctor: socket should not be null"); this.Socket = socket; this.ReceiveBuffer = receiveBuffer; }
public UdpPacket receive(UdpSocket fan, UdpPacket packet) { // create packet if null if (packet == null) packet = UdpPacket.make(null, null, new MemBuf(1024)); // map buf bytes to packet MemBuf data = (MemBuf)packet.data(); byte[] buf = data.m_buf; int off = data.m_pos; int len = buf.Length - off; int recv = 0; EndPoint sender = new IPEndPoint(IPAddress.Any, 0); // receive if (isConnected(fan)) { try { recv = m_dotnet.Receive(buf, off, len, SocketFlags.None); sender = m_dotnet.RemoteEndPoint; } catch (SocketException e) { // .NET will truncate contents correctly, but still throws a // SocketException, so catch that specific case and allow it if (e.Message.StartsWith("A message sent on a datagram socket was larger")) { recv = len; sender = m_dotnet.RemoteEndPoint; } else { throw IOErr.make(e).val; } } } else { try { if (m_dotnet == null) m_dotnet = createSocket(); recv = m_dotnet.ReceiveFrom(buf, off, len, SocketFlags.None, ref sender); } catch (SocketException e) { // .NET will truncate contents correctly, but still throws a // SocketException, so catch that specific case and allow it if (e.Message.StartsWith("A message sent on a datagram socket was larger")) recv = len; else throw IOErr.make(e).val; } } // update packet with received message IPEndPoint endPoint = sender as IPEndPoint; packet.addr(IpAddrPeer.make(endPoint.Address)); packet.port(Long.valueOf(endPoint.Port)); data.m_pos += recv; data.m_size += recv; return packet; }
////////////////////////////////////////////////////////////////////////// // Peer Factory ////////////////////////////////////////////////////////////////////////// public static UdpSocketPeer make(UdpSocket fan) { return new UdpSocketPeer(); }
public Long localPort(UdpSocket fan) { if (!isBound(fan)) return null; IPEndPoint pt = m_dotnet.LocalEndPoint as IPEndPoint; if (pt == null) return null; // TODO - default port? return Long.valueOf(pt.Port); }
////////////////////////////////////////////////////////////////////////// // Socket Options ////////////////////////////////////////////////////////////////////////// public SocketOptions options(UdpSocket fan) { if (m_options == null) m_options = SocketOptions.make(fan); return m_options; }
////////////////////////////////////////////////////////////////////////// // End Points ////////////////////////////////////////////////////////////////////////// public IpAddr localAddr(UdpSocket fan) { if (!isBound(fan)) return null; IPEndPoint pt = m_dotnet.LocalEndPoint as IPEndPoint; if (pt == null) return null; return IpAddrPeer.make(pt.Address); }
public bool isConnected(UdpSocket fan) { return (m_dotnet == null) ? false : m_dotnet.Connected; }
public bool isClosed(UdpSocket fan) { return m_closed; }
public void setSendBufferSize(UdpSocket fan, long v) { m_sendBufferSize = v; }
public long getSendBufferSize(UdpSocket fan) { return m_sendBufferSize; }
public void setTrafficClass(UdpSocket fan, long v) { m_trafficClass = v; }
//returns true if receive completed synchronously, false otherwise bool StartAsyncReceive(UdpSocket socket) { Fx.Assert(socket != null, "UdpSocketReceiveManager.StartAsyncReceive: Socket should never be null"); bool completedSync = false; ArraySegment<byte> messageBytes = default(ArraySegment<byte>); UdpSocketReceiveState state = null; lock (this.thisLock) { if (!this.IsDisposed && socket.PendingReceiveCount < this.maxPendingReceivesPerSocket) { IAsyncResult result = null; byte[] receiveBuffer = this.receiveBufferPool.Take(); try { state = new UdpSocketReceiveState(socket, receiveBuffer); EndPoint remoteEndpoint = socket.CreateIPAnyEndPoint(); result = socket.BeginReceiveFrom(receiveBuffer, 0, receiveBuffer.Length, ref remoteEndpoint, onReceiveFrom, state); } catch (Exception e) { if (!Fx.IsFatal(e)) { this.receiveBufferPool.Return(receiveBuffer); } throw; } if (result.CompletedSynchronously) { completedSync = true; messageBytes = EndReceiveFrom(result, state); } } } if (completedSync) { messageBytes = this.CopyMessageIntoBufferManager(messageBytes); //if HandleDataReceived returns false, it means that the max pending message count was hit. //when receiveHandler.HandleDataReceived is called (whether now or later), it will return the buffer to the buffer manager. return this.receiveHandler.HandleDataReceived(messageBytes, state.RemoteEndPoint, state.Socket.InterfaceIndex, this.onMessageDequeued); } return false; }
public IpAddr remoteAddr(UdpSocket fan) { if (!isConnected(fan)) return null; return m_remoteAddr; }
public long getTrafficClass(UdpSocket fan) { return m_trafficClass; }
public UdpSocket connect(UdpSocket fan, IpAddr addr, long port) { try { if (m_dotnet == null) m_dotnet = createSocket(); m_dotnet.Connect(addr.m_peer.m_dotnet, (int)port); IPEndPoint endPoint = m_dotnet.RemoteEndPoint as IPEndPoint; m_remoteAddr = IpAddrPeer.make(endPoint.Address); m_remotePort = endPoint.Port; return fan; } catch (SocketException e) { throw IOErr.make(e).val; } }
public Long remotePort(UdpSocket fan) { if (!isConnected(fan)) return null; return Long.valueOf(m_remotePort); }
public void send(UdpSocket fan, UdpPacket packet) { // map buf bytes to packet MemBuf data = (MemBuf)packet.data(); byte[] buf = data.m_buf; int off = data.m_pos; int len = data.m_size - off; // map address, port IpAddr addr = packet.addr(); Long port = packet.port(); if (isConnected(fan)) { if (addr != null || port != null) throw ArgErr.make("Address and port must be null to send while connected").val; try { m_dotnet.Send(buf, off, len, SocketFlags.None); } catch (SocketException e) { throw IOErr.make(e).val; } } else { if (addr == null || port == null) throw ArgErr.make("Address or port is null").val; try { if (m_dotnet == null) m_dotnet = createSocket(); IPEndPoint endPoint = new IPEndPoint(addr.m_peer.m_dotnet, port.intValue()); m_dotnet.SendTo(buf, off, len, SocketFlags.None, endPoint); } catch (SocketException e) { throw IOErr.make(e).val; } } // lastly drain buf data.m_pos += len; }
public void setBroadcast(UdpSocket fan, bool v) { m_enableBroadcast = v; }
//returns the port number used... public static int CreateListenSocketsOnUniquePort(IPAddress ipv4Address, IPAddress ipv6Address, int receiveBufferSize, int timeToLive, out UdpSocket ipv4Socket, out UdpSocket ipv6Socket) { // We need both IPv4 and IPv6 on the same port. We can't atomicly bind for IPv4 and IPv6, // so we try 10 times, which even with a 50% failure rate will statistically succeed 99.9% of the time. // // We look in the range of 49152-65534 for Vista default behavior parity. // http://www.iana.org/assignments/port-numbers // // We also grab the 10 random numbers in a row to reduce collisions between multiple people somehow // colliding on the same seed. const int retries = 10; const int lowWatermark = 49152; const int highWatermark = 65535; ipv4Socket = null; ipv6Socket = null; int[] portNumbers = new int[retries]; Random randomNumberGenerator = new Random(AppDomain.CurrentDomain.GetHashCode() | Environment.TickCount); for (int i = 0; i < retries; i++) { portNumbers[i] = randomNumberGenerator.Next(lowWatermark, highWatermark); } int port = -1; for (int i = 0; i < retries; i++) { port = portNumbers[i]; try { ipv4Socket = UdpUtility.CreateUnicastListenSocket(ipv4Address, ref port, receiveBufferSize, timeToLive); ipv6Socket = UdpUtility.CreateUnicastListenSocket(ipv6Address, ref port, receiveBufferSize, timeToLive); break; } catch (AddressAlreadyInUseException) { if (ipv4Socket != null) { ipv4Socket.Close(); ipv4Socket = null; } ipv6Socket = null; } catch (AddressAccessDeniedException) { if (ipv4Socket != null) { ipv4Socket.Close(); ipv4Socket = null; } ipv6Socket = null; } } if (ipv4Socket == null) { throw FxTrace.Exception.AsError(new AddressAlreadyInUseException(SR.UniquePortNotAvailable)); } Fx.Assert(ipv4Socket != null, "An exception should have been thrown if the ipv4Socket socket is null"); Fx.Assert(ipv6Socket != null, "An exception should have been thrown if the ipv6Socket socket is null"); Fx.Assert(port > 0, "The port number should have been greater than 0. Actual value was " + port); return port; }
public void setReceiveBufferSize(UdpSocket fan, long v) { m_receiveBufferSize = v; }
// Must return non-null/non-empty array unless exceptionToBeThrown is has been set protected override UdpSocket[] GetSendSockets(Message message, out IPEndPoint remoteEndPoint, out Exception exceptionToBeThrown) { Fx.Assert(message != null, "message can't be null"); UdpSocket[] socketList = null; exceptionToBeThrown = null; remoteEndPoint = null; Uri destination; bool isVia = false; if (message.Properties.Via != null) { destination = message.Properties.Via; isVia = true; } else if (message.Headers.To != null) { destination = message.Headers.To; } else { throw FxTrace.Exception.AsError(new InvalidOperationException(SR.ToOrViaRequired)); } this.ValidateDestinationUri(destination, isVia); if (destination.HostNameType == UriHostNameType.IPv4 || destination.HostNameType == UriHostNameType.IPv6) { remoteEndPoint = new IPEndPoint(IPAddress.Parse(destination.DnsSafeHost), destination.Port); if (this.IsMulticast) { UdpSocket socket = this.GetSendSocketUsingInterfaceIndex(message.Properties, out exceptionToBeThrown); if (socket != null) { if (socket.AddressFamily == remoteEndPoint.AddressFamily) { socketList = new UdpSocket[] { socket }; } else { exceptionToBeThrown = new InvalidOperationException(SR.RemoteAddressUnreachableDueToIPVersionMismatch(destination.DnsSafeHost)); } } } else { UdpSocket socket = this.GetSendSocket(remoteEndPoint.Address, destination, out exceptionToBeThrown); if (socket != null) { socketList = new UdpSocket[] { socket }; } } } else { IPAddress[] remoteAddresses = DnsCache.Resolve(destination).AddressList; if (this.IsMulticast) { UdpSocket socket = this.GetSendSocketUsingInterfaceIndex(message.Properties, out exceptionToBeThrown); if (socket != null) { socketList = new UdpSocket[] { socket }; for (int i = 0; i < remoteAddresses.Length; i++) { if (remoteAddresses[i].AddressFamily == socket.AddressFamily) { remoteEndPoint = new IPEndPoint(remoteAddresses[i], destination.Port); break; } } if (remoteEndPoint == null) { // for multicast, we only listen on either IPv4 or IPv6 (not both). // if we didn't find a matching remote endpoint, then it would indicate that // the remote host didn't resolve to an address we can use... exceptionToBeThrown = new InvalidOperationException(SR.RemoteAddressUnreachableDueToIPVersionMismatch(destination.DnsSafeHost)); } } } else { bool useIPv4 = true; bool useIPv6 = true; for (int i = 0; i < remoteAddresses.Length; i++) { IPAddress address = remoteAddresses[i]; if (address.AddressFamily == AddressFamily.InterNetwork && useIPv4) { UdpSocket socket = this.GetSendSocket(address, destination, out exceptionToBeThrown); if (socket == null) { if (this.State != CommunicationState.Opened) { // time to exit, the channel is closing down. break; } else { // no matching socket on IPv4, so ignore future IPv4 addresses // in the remoteAddresses list useIPv4 = false; } } else { remoteEndPoint = new IPEndPoint(address, destination.Port); socketList = new UdpSocket[] { socket }; break; } } else if (address.AddressFamily == AddressFamily.InterNetworkV6 && useIPv6) { UdpSocket socket = this.GetSendSocket(address, destination, out exceptionToBeThrown); if (socket == null) { if (this.State != CommunicationState.Opened) { // time to exit, the channel is closing down. break; } else { // no matching socket on IPv6, so ignore future IPv6 addresses // in the remoteAddresses list useIPv6 = false; } } else { remoteEndPoint = new IPEndPoint(address, destination.Port); socketList = new UdpSocket[] { socket }; break; } } } } } return socketList; }
public Duration getReceiveTimeout(UdpSocket fan) { if (m_receiveTimeout <= 0) return null; return Duration.makeMillis(m_receiveTimeout); }