public override Task SendAsync(byte[] buffer, Func <SocketAsyncState, Task> callback, ISpan span, ErrorMap errorMap)
        {
            SocketAsyncState state = null;

            try
            {
                var opaque = Converter.ToUInt32(buffer, HeaderIndexFor.Opaque);
                state = new SocketAsyncState
                {
                    Data          = MemoryStreamFactory.GetMemoryStream(),
                    Opaque        = opaque,
                    Buffer        = buffer,
                    Completed     = callback,
                    SendOffset    = _eventArgs.Offset,
                    DispatchSpan  = span,
                    ConnectionId  = ContextId,
                    LocalEndpoint = LocalEndPoint.ToString(),
                    ErrorMap      = errorMap,
                    Timeout       = Configuration.SendTimeout
                };

                _eventArgs.UserToken = state;
                Log.Debug("Sending {0} with {1} on server {2}", state.Opaque, Identity, EndPoint);

                //set the buffer
                var bufferLength = buffer.Length < Configuration.BufferSize
                    ? buffer.Length
                    : Configuration.BufferSize;

                _eventArgs.SetBuffer(state.SendOffset, bufferLength);
                Buffer.BlockCopy(buffer, 0, _eventArgs.Buffer, state.SendOffset, bufferLength);

                //Send the request
                if (!Socket.SendAsync(_eventArgs))
                {
                    OnCompleted(Socket, _eventArgs);
                }
            }
            catch (Exception e)
            {
                if (state == null)
                {
                    callback(new SocketAsyncState
                    {
                        Exception = e,
                        Status    = (e is SocketException) ?
                                    ResponseStatus.TransportFailure :
                                    ResponseStatus.ClientFailure
                    });
                }
                else
                {
                    state.Exception = e;
                    state.Completed(state);
                    Log.Debug(e);
                }
            }

            return(Task.FromResult(0));
        }
        /// <summary>
        /// 启动服务
        /// </summary>
        public void Start()
        {
            if (!IsRunning)
            {
                Init();

                IsRunning = true;

                // 创建监听socket
                _serverSock = new Socket(LocalEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

                if (LocalEndPoint.AddressFamily == AddressFamily.InterNetworkV6)
                {
                    // 配置监听socket为 dual-mode (IPv4 & IPv6)
                    // 27 is equivalent to IPV6_V6ONLY socket option in the winsock snippet below,
                    _serverSock.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, false);
                    _serverSock.Bind(new IPEndPoint(IPAddress.IPv6Any, LocalEndPoint.Port));
                }
                else
                {
                    _serverSock.Bind(LocalEndPoint);
                }
                // 开始监听
                _serverSock.Listen(this._maxClient);
                // 在监听Socket上投递一个接受请求。
                StartAccept(null);

                _daemonThread = new DaemonThread(this);

                Log4Debug("服务器已启动....[" + LocalEndPoint.ToString() + "]");
            }
        }
Пример #3
0
        protected Exception CreateTimeoutException(uint opaque)
        {
            const string kv            = "kv";
            var          correlationId = CreateCorrelationId(opaque);

            var context = new OperationContext(kv, correlationId)
            {
                BucketName          = Configuration.BucketName,
                LocalEndpoint       = LocalEndPoint.ToString(),
                RemoteEndpoint      = EndPoint.ToString(),
                TimeoutMicroseconds = Configuration.SendTimeout
            };

            var message = context.ToString();

            Log.Info(message);

            var exception = new SendTimeoutExpiredException(message);

            exception.Data.Add("ServiceType", kv);
            exception.Data.Add("CorrelationId", correlationId);
            exception.Data.Add("LocalEndpoint", LocalEndPoint.ToString());
            exception.Data.Add("Timeout", Configuration.SendTimeout);
            exception.Data.Add("RemoteEndpoint", EndPoint.ToString());
            return(exception);
        }
Пример #4
0
        protected Exception CreateTimeoutException(uint opaque)
        {
            const string format = ", {0}", kv = "kv";
            var          correlationId = CreateCorrelationId(opaque);

            var builder = new StringBuilder(ExceptionUtil.OperationTimeout);

            builder.AppendFormat(format, kv);
            builder.AppendFormat(format, correlationId);
            builder.AppendFormat(format, LocalEndPoint);
            builder.AppendFormat(format, Configuration.SendTimeout);
            builder.AppendFormat(format, EndPoint);

            var message = builder.ToString();

            Log.Info(message);

            var exception = new SendTimeoutExpiredException(message);

            exception.Data.Add("ServiceType", kv);
            exception.Data.Add("CorrelationId", correlationId);
            exception.Data.Add("LocalEndpoint", LocalEndPoint.ToString());
            exception.Data.Add("Timeout", Configuration.SendTimeout);
            exception.Data.Add("RemoteEndpoint", EndPoint.ToString());
            return(exception);
        }
 private GossipNodeConfiguration(Builder builder)
 {
     BroadcastFrequency = builder.BroadcastFrequency ?? TimeSpan.FromSeconds(2);
     CompressionType    = builder.CompressionType;
     LocalEndPoint      = builder.LocalEndPoint ?? new IPEndPoint(IPAddress.Loopback, 29803);
     Logger             = (builder.LoggerConfiguration ?? new LoggerConfiguration())
                          .Destructure.AsScalar <IPEndPoint>()
                          .CreateLogger();
     Metadata = builder.Metadata;
     Name     = builder.Name ?? LocalEndPoint.ToString();
 }
Пример #6
0
        /// <summary>
        /// Initializes a new instance of the <see cref="UdpListener"/> class.
        /// </summary>
        /// <param name="socket">The socket.</param>
        /// <param name="remote">The remote.</param>
        /// <param name="encoding">The encoding.</param>
        internal UdpListener(Socket socket, EndPoint remote, Encoding encoding)
        {
            this.socket = socket;

            LocalEndPoint  = socket.LocalEndPoint;
            RemoteEndPoint = remote;

            byte[] gb = Utils.Md5(LocalEndPoint.ToString());

            this.Guid = new Guid(gb);

            Sender = new UdpSender(socket, remote, this.Guid, encoding);
        }
Пример #7
0
        public ServerSocket Start()
        {
            Log.InfoFormat("ServerSocket:Start LocalEndPoint:{0}", LocalEndPoint.ToString());
            _socket.Bind(LocalEndPoint);
            _socket.Listen(Backlog);
            _socket.ReceiveBufferSize = _socketSetting.ReceiveBufferSize;
            _socket.ReceiveTimeout    = _socketSetting.ReceiveTimeout;
            _socket.SendBufferSize    = _socketSetting.SendBufferSize;
            _socket.SendTimeout       = _socketSetting.SendTimeout;

            AcceptAsync(_acceptSocketAsyncEventArgs);
            return(this);
        }
        /// <summary>
        /// Sends a memcached operation as a buffer to a the server.
        /// </summary>
        /// <param name="buffer">A memcached request buffer</param>
        /// <returns>A memcached response buffer.</returns>
        public override byte[] Send(byte[] buffer)
        {
            //create the state object and set it
            var opaque = Converter.ToUInt32(buffer, HeaderIndexFor.Opaque);
            var state  = new SocketAsyncState
            {
                Data          = MemoryStreamFactory.GetMemoryStream(),
                Opaque        = opaque,
                Buffer        = buffer,
                SendOffset    = _eventArgs.Offset,
                ConnectionId  = ContextId,
                LocalEndpoint = LocalEndPoint.ToString(),
                Timeout       = Configuration.SendTimeout
            };

            Log.Debug("Sending opaque{0} on {1}", state.Opaque, Identity);
            _eventArgs.UserToken = state;

            //set the buffer
            var bufferLength = buffer.Length < Configuration.BufferSize
                ? buffer.Length
                : Configuration.BufferSize;

            _eventArgs.SetBuffer(state.SendOffset, bufferLength);
            Buffer.BlockCopy(buffer, 0, _eventArgs.Buffer, state.SendOffset, bufferLength);

            //Send the request
            if (!Socket.SendAsync(_eventArgs))
            {
                OnCompleted(Socket, _eventArgs);
            }

            //wait for completion
            if (!_requestCompleted.WaitOne(Configuration.SendTimeout))
            {
                IsDead = true;
                throw CreateTimeoutException(opaque);
            }

            //Check if an IO error occurred
            if (state.Exception != null)
            {
                Log.Debug("Connection {0} has failed with {1}", Identity, state.Exception);
                IsDead = true;
                throw state.Exception;
            }

            Log.Debug("Complete opaque{0} on {1}", state.Opaque, Identity);
            //return the response bytes
            return(state.Data.ToArray());
        }
Пример #9
0
        /// <summary>
        /// Returns a string containing suitable information about this connection
        /// </summary>
        /// <returns>A string containing suitable information about this connection</returns>
        public override string ToString()
        {
            //Add a useful connection state identifier
            string connectionStateIdentifier;

            switch (ConnectionState)
            {
            case ConnectionState.Undefined:
                connectionStateIdentifier = "U";
                break;

            case ConnectionState.Establishing:
                connectionStateIdentifier = "I";
                break;

            case ConnectionState.Established:
                connectionStateIdentifier = "E";
                break;

            case ConnectionState.Shutdown:
                connectionStateIdentifier = "S";
                break;

            default:
                throw new Exception("Unexpected connection state.");
            }

            string returnString = "[" + ConnectionType.ToString() + "-" + (ApplicationLayerProtocol == ApplicationLayerProtocolStatus.Enabled ? "E" : "D") + "-" + connectionStateIdentifier + "] ";

            if (RemoteEndPoint != null && LocalEndPoint != null)
            {
                returnString += LocalEndPoint.ToString() + " -> " + RemoteEndPoint.ToString();
            }
            else if (RemoteEndPoint != null)
            {
                returnString += "Local -> " + RemoteEndPoint.ToString();
            }
            else if (LocalEndPoint != null)
            {
                returnString += LocalEndPoint.ToString() + " " + (IsConnectable ? "Connectable" : "NotConnectable");
            }

            if (NetworkIdentifier != ShortGuid.Empty)
            {
                returnString += " (" + NetworkIdentifier + ")";
            }

            return(returnString.Trim());
        }
 /// <summary>
 /// Returns a <see cref="System.String" /> that represents this instance.
 /// </summary>
 /// <returns>
 /// A <see cref="System.String" /> that represents this instance.
 /// </returns>
 public override string ToString()
 {
     return(String.Format(
                "LocalEndPoint: {1}{0}" +
                "RemoteEndPoint: {2}{0}" +
                "State: {3}{0}" +
                "Pid:{4}{0}" +
                "Process: {5}",
                Environment.NewLine,
                LocalEndPoint.ToString(),
                RemoteEndPoint.ToString(),
                State,
                ProcessId,
                Process.ProcessName));
 }
Пример #11
0
        /// <summary>
        /// Executes after listener was started.
        /// </summary>
        private static void ListenerService_OnStarted()
        {
            Service.NetworkListenerIsActive = true;

            // audit record
            DataProvider.DataBase.ServiceAudit
            (
                Settings.Default.ServiceUniqueID,
                ( byte )ServiceType.CacheService,
                ServiceAuditType.NetworkListenerStarted,
                LocalEndPoint.ToString()
            );

            Logger.WriteLine(Source.Listener, "Network listener started on {0}", m_ListenerService.LocalEndPoint);
        }
Пример #12
0
        public async Task SendAsync(ReadOnlyMemory <byte> request, Action <IMemoryOwner <byte>, ResponseStatus> callback, ErrorMap?errorMap = null)
        {
            if (request.Length >= MaxDocSize)
            {
                throw new ValueToolargeException("Encoded document exceeds the 20MB document size limit.");
            }
            if (_disposed)
            {
                throw new ObjectDisposedException(nameof(MultiplexingConnection));
            }

            var opaque = ByteConverter.ToUInt32(request.Span.Slice(HeaderOffsets.Opaque));
            var state  = new AsyncState(callback, opaque)
            {
                EndPoint      = (IPEndPoint)EndPoint,
                ConnectionId  = ConnectionId,
                ErrorMap      = errorMap,
                LocalEndpoint = LocalEndPoint.ToString()
            };

            _statesInFlight.Add(state, 75000);

            await _writeMutex.GetLockAsync().ConfigureAwait(false);

            try
            {
#if NETCOREAPP2_1 || NETCOREAPP3_0 || NETSTANDARD2_1
                await _stream.WriteAsync(request).ConfigureAwait(false);
#else
                if (!MemoryMarshal.TryGetArray <byte>(request, out var arraySegment))
                {
                    // Fallback in case we can't use the more efficient TryGetArray method
                    arraySegment = new ArraySegment <byte>(request.ToArray());
                }

                await _stream.WriteAsync(arraySegment.Array, arraySegment.Offset, arraySegment.Count)
                .ConfigureAwait(false);
#endif
            }
            catch (Exception e)
            {
                HandleDisconnect(e);
            }
            finally
            {
                _writeMutex.ReleaseLock();
            }
        }
Пример #13
0
        /// <summary>
        /// Sends the specified ArraySegment as a packet to the client.
        /// </summary>
        /// <param name="segment">packet</param>
        public override void Send(ArraySegment <byte> segment)
        {
            if (packetLog.IsInfoEnabled && segment.Count >= 4)
            {
                ShardServerOpcode opcode  = (ShardServerOpcode)BitConverter.ToUInt16(segment.Array, segment.Offset + 2);
                ushort            size    = BitConverter.ToUInt16(new byte[] { segment.Array[segment.Offset + 1], segment.Array[segment.Offset] }, 0); // big endian
                string            hexDump = Strings.HexDump(segment.Array, segment.Offset + 4, size - sizeof(ushort));                                 // sizeof the opcode

                packetLog.InfoFormat("Server [{0}] -> Client [{1}]", LocalEndPoint.ToString(), RemoteEndPoint.ToString());
                packetLog.InfoFormat("Opcode: {0} [0x{1:x4}]", opcode, (ushort)opcode);
                packetLog.InfoFormat("Length: {0}", size - sizeof(ushort));
                packetLog.InfoFormat("{1}{0}{1}", hexDump, Environment.NewLine);
            }

            Cipher.EncryptHeader(segment);
            base.Send(segment);
        }
Пример #14
0
        private async Task <byte[]> SendAsync(byte[] buffer, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var opaque = Converter.ToUInt32(buffer, HeaderIndexFor.Opaque);
            var state  = new SocketAsyncState
            {
                Data          = MemoryStreamFactory.GetMemoryStream(),
                Opaque        = opaque,
                ConnectionId  = ContextId,
                LocalEndpoint = LocalEndPoint.ToString(),
                Timeout       = Configuration.SendTimeout
            };

            await _sslStream.WriteAsync(buffer, 0, buffer.Length, cancellationToken).ContinueOnAnyContext();

            state.SetIOBuffer(_buffer);

            while (state.BytesReceived < state.BodyLength + OperationHeader.Length)
            {
                cancellationToken.ThrowIfCancellationRequested();

                var bytesReceived = await _sslStream
                                    .ReadAsync(state.Buffer, state.BufferOffset, state.BufferLength, cancellationToken)
                                    .ContinueOnAnyContext();

                state.BytesReceived += bytesReceived;

                if (state.BytesReceived == 0)
                {
                    // No more bytes were received, go ahead and exit the loop
                    break;
                }

                if (state.BodyLength == 0)
                {
                    // Reading header, so get the BodyLength
                    state.BodyLength = Converter.ToInt32(state.Buffer, state.BufferOffset + HeaderIndexFor.Body);
                }

                state.Data.Write(state.Buffer, state.BufferOffset, bytesReceived);
            }

            return(state.Data.ToArray());
        }
Пример #15
0
        public override Task SendAsync(byte[] request, Func <SocketAsyncState, Task> callback, ISpan span, ErrorMap errorMap)
        {
            var opaque = Converter.ToUInt32(request, HeaderIndexFor.Opaque);
            var state  = new AsyncState
            {
                Opaque        = opaque,
                Callback      = callback,
                Converter     = Converter,
                EndPoint      = (IPEndPoint)EndPoint,
                DispatchSpan  = span,
                ConnectionId  = ContextId,
                ErrorMap      = errorMap,
                Timeout       = Configuration.SendTimeout,
                LocalEndpoint = LocalEndPoint.ToString()
            };

            _statesInFlight.TryAdd(state.Opaque, state);

            state.Timer = new Timer(o =>
            {
                AsyncState a = (AsyncState)o;
                _statesInFlight.TryRemove(a.Opaque, out _);
                a.Cancel(ResponseStatus.OperationTimeout, CreateTimeoutException(opaque));
            }, state, Configuration.SendTimeout, Timeout.Infinite);

            var sentBytesCount = 0;

            lock (Socket)
            {
                try
                {
                    do
                    {
                        sentBytesCount += Socket.Send(request, sentBytesCount, request.Length - sentBytesCount,
                                                      SocketFlags.None);
                    } while (sentBytesCount < request.Length);
                }
                catch (Exception e)
                {
                    HandleDisconnect(e);
                }
            }

            return(Task.FromResult(0));
        }
Пример #16
0
        private EpoxyConnection(
            ConnectionType connectionType,
            EpoxyTransport parentTransport,
            EpoxyListener parentListener,
            ServiceHost serviceHost,
            Socket socket,
            Logger logger,
            Metrics metrics)
        {
            Debug.Assert(parentTransport != null);
            Debug.Assert(connectionType != ConnectionType.Server || parentListener != null, "Server connections must have a listener");
            Debug.Assert(serviceHost != null);
            Debug.Assert(socket != null);

            this.connectionType = connectionType;

            this.parentTransport = parentTransport;
            this.parentListener  = parentListener;
            this.serviceHost     = serviceHost;

            netSocket = new EpoxySocket(socket, logger);

            // cache these so we can use them after the socket has been shutdown
            LocalEndPoint  = (IPEndPoint)socket.LocalEndPoint;
            RemoteEndPoint = (IPEndPoint)socket.RemoteEndPoint;

            responseMap = new ResponseMap();

            state               = State.Created;
            startTask           = new TaskCompletionSource <bool>();
            stopTask            = new TaskCompletionSource <bool>();
            shutdownTokenSource = new CancellationTokenSource();

            // start at -1 or 0 so the first conversation ID is 1 or 2.
            prevConversationId = (connectionType == ConnectionType.Client) ? -1 : 0;

            connectionMetrics.connection_id   = Guid.NewGuid().ToString();
            connectionMetrics.local_endpoint  = LocalEndPoint.ToString();
            connectionMetrics.remote_endpoint = RemoteEndPoint.ToString();

            this.logger  = logger;
            this.metrics = metrics;
        }
Пример #17
0
        public void Connect(IPEndPoint remoteEndPoint, int timeoutMilliseconds)
        {
            _remoteEndPoint = remoteEndPoint;
            IAsyncResult asyncResult = BeginConnect(remoteEndPoint, null, null);

            // there is no other way to set a time out on a connection other than putting a time out on the wait here and manually throwing an exception
            if (!asyncResult.AsyncWaitHandle.WaitOne(timeoutMilliseconds, false))
            {
                Close();
                throw new SocketException((int)SocketError.HostUnreachable);
            }

            EndConnect(asyncResult);

            _localEndPoint = LocalEndPoint.ToString();

            BeginReceive(GetReceiveBuffer(_settings.ReceiveBufferSize), 0, _settings.ReceiveBufferSize, SocketFlags.None,
                         ReceiveCallback, null);                         //start a receive immediately so there's always one running. otherwise we have no way to detect if the connection is closed

            CheckServerCapabilities();
        }
Пример #18
0
        private EpoxyConnection(
            ConnectionType connectionType,
            EpoxyTransport parentTransport,
            EpoxyListener parentListener,
            ServiceHost serviceHost,
            EpoxyNetworkStream networkStream,
            Logger logger,
            Metrics metrics)
        {
            Debug.Assert(parentTransport != null);
            Debug.Assert(connectionType != ConnectionType.Server || parentListener != null, "Server connections must have a listener");
            Debug.Assert(serviceHost != null);
            Debug.Assert(networkStream != null);

            this.connectionType = connectionType;

            this.parentTransport = parentTransport;
            this.parentListener  = parentListener;
            this.serviceHost     = serviceHost;

            this.networkStream = networkStream;

            responseMap = new ResponseMap();

            state               = State.Created;
            startTask           = new TaskCompletionSource <bool>();
            stopTask            = new TaskCompletionSource <bool>();
            shutdownTokenSource = new CancellationTokenSource();

            // start at -1 or 0 so the first conversation ID is 1 or 2.
            prevConversationId = (connectionType == ConnectionType.Client) ? -1 : 0;

            ConnectionMetrics.local_endpoint  = LocalEndPoint.ToString();
            ConnectionMetrics.remote_endpoint = RemoteEndPoint.ToString();

            this.logger  = logger;
            this.metrics = metrics;
        }
        public MultiplexingConnection(Stream stream, EndPoint localEndPoint, EndPoint remoteEndPoint,
                                      ILogger <MultiplexingConnection> logger)
        {
            _stream       = stream ?? throw new ArgumentNullException(nameof(stream));
            LocalEndPoint = localEndPoint ?? throw new ArgumentNullException(nameof(localEndPoint));
            EndPoint      = remoteEndPoint ?? throw new ArgumentNullException(nameof(remoteEndPoint));
            _logger       = logger ?? throw new ArgumentNullException(nameof(logger));

            ConnectionId = ConnectionIdProvider.GetNextId();

            _endPointString      = EndPoint.ToString() ?? DiagnosticsReportProvider.UnknownEndpointValue;
            _localEndPointString = LocalEndPoint.ToString() ?? DiagnosticsReportProvider.UnknownEndpointValue;
            _connectionIdString  = ConnectionId.ToString(CultureInfo.InvariantCulture);

            _stopwatch = new Stopwatch();
            _stopwatch.Start();

            // We don't need the execution context to flow to the receive loop
            using (ExecutionContext.SuppressFlow())
            {
                Task.Run(ReceiveResponsesAsync);
            }
        }
Пример #20
0
        protected OperationContext CreateOperationContext(uint opaque)
        {
            var context = OperationContext.CreateKvContext(opaque);

            context.ConnectionId = ContextId;

            if (Configuration != null)
            {
                context.BucketName          = Configuration.BucketName;
                context.TimeoutMicroseconds = (uint)Configuration.SendTimeout * 1000;  // convert millis to micros
            }

            if (LocalEndPoint != null)
            {
                context.LocalEndpoint = LocalEndPoint.ToString();
            }

            if (EndPoint != null)
            {
                context.RemoteEndpoint = EndPoint.ToString();
            }

            return(context);
        }
Пример #21
0
        /// <summary>
        /// 连接到指定的接入端点,并广播“加入分布网络”消息。
        /// <para>注意,本方法执行中会为 ConnectionList 加锁。</para>
        /// </summary>
        /// <param name="pointInsertion">要连接的端点。</param>
        /// <param name="realPort">非零表示这是接入点要连接接入点,该端口是本机正在监听的端口;零表示只是普通用户连接接入点。</param>
        /// <param name="workerThread">返回发送用的 <see cref="System.Threading.Thread"/>。</param>
        /// <returns>一个 <see cref="System.Threading.WaitHandle"/>,通过此对象可以对发送操作进行等待。</returns>
        public WaitHandle EnterNetwork(IPEndPoint pointInsertion, ushort realPort, out Thread workerThread)
        {
            Logger.Log("KClient::EnterNetwork(IPEndPoint)" + Environment.NewLine + "接入点: " + pointInsertion.ToString());
            AutoResetEvent ev     = new AutoResetEvent(false);
            Thread         thread = new Thread(delegate()
            {
                try
                {
                    // 第一次发送信息,要使用以后用来接收信息的端口,这样才能让接入点知道你映射后的接收端口
                    //TcpClient client = new TcpClient();
                    // 那么就不能采取常规的方式,而应该用 TcpListener 的 socket 发出去
                    //TcpClient client = new TcpClient(new IPEndPoint(IPAddress.Loopback, LocalEndPoint.Port));
                    Socket enterSocket;
                    if (realPort == 0)
                    {
                        // 普通用户
                        enterSocket = _listener.Server;
                        if (!enterSocket.IsBound)
                        {
                            enterSocket.Bind(new IPEndPoint(IPAddress.Any, ((IPEndPoint)_listener.LocalEndpoint).Port));
                        }
                    }
                    else
                    {
                        enterSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    }
                    //Socket enterSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    //Socket enterSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
                    //enterSocket.Bind(new IPEndPoint(IPAddress.Loopback, LocalEndPoint.Port));
                    Logger.Log("尝试连接端点: " + pointInsertion.ToString());
                    //var iar = client.BeginConnect(pointInsertion.Address, pointInsertion.Port, null, null);
                    var iar = enterSocket.BeginConnect(pointInsertion, null, null);
                    if (!iar.IsCompleted)
                    {
                        iar.AsyncWaitHandle.WaitOne(SendTimeout);
                    }
                    if (!iar.IsCompleted)
                    {
                        Logger.Log("连接超时。");
                        // 未成功连接的话,直接返回
                        //return false;
                        ev.Set();
                        ev.Dispose();
                        return;
                        // 这里好像无法直接返回连接状态
                        // 但是应该可以判断连接列表是否为空来确定是否成功,非空则成功,否则失败
                    }
                    //client.EndConnect(iar);
                    enterSocket.EndConnect(iar);
                    Logger.Log("socket 本地端点: " + enterSocket.LocalEndPoint.ToString() + " 远程端点: " + enterSocket.RemoteEndPoint.ToString());
                    // 为了不干扰连接列表的报告,先发送信息
                    Logger.Log("连接成功,发送自己进入的消息。");

                    int origPortNumber;
                    string origAddress;

                    //var bs = client.GetStream();
                    {
                        // 写入
                        //bs.WriteMessage(MessageFactory.ClientEnterNetwork(LocalKEndPoint));
                        enterSocket.WriteMessage(MessageFactory.ClientEnterNetwork(LocalKEndPoint, realPort));

                        // 接下来接收接入点返回的当前连接信息
                        // 先是读取列表数据大小
                        Logger.Log("读取返回数据: 数据长度");
                        //int dataLength = bs.ReadInt32();
                        int dataLength = enterSocket.ReadInt32();
                        Logger.Log("长度: " + dataLength.ToString());
                        // 然后读列表
                        var dataBuffer      = new byte[1024];
                        var data            = new byte[dataLength];
                        int readLength      = 0;
                        int totalReadLength = 0;
                        // 确保全部读取
                        while (totalReadLength < dataLength)
                        {
                            //readLength = bs.Read(dataBuffer, 0, dataBuffer.Length);
                            readLength = enterSocket.Receive(dataBuffer);
                            if (readLength > 0)
                            {
                                Array.Copy(dataBuffer, 0, data, totalReadLength, readLength);
                                totalReadLength += readLength;
                            }
                        }
                        Logger.Log("数据读取完毕。准备解码。");

                        origPortNumber = LocalEndPoint.Port;
                        origAddress    = LocalEndPoint.Address.ToString();

                        // 解码并将自己的连接列表和用户列表同步为接入点的数据
                        DecodeTargetInformation(data);
                        Logger.Log("他人眼中的我: " + LocalEndPoint.ToString());

                        StringBuilder sb = new StringBuilder(100);
                        sb.AppendLine("刚刚收到的连接列表如下。");
                        lock (ConnectionList)
                        {
                            foreach (var item in ConnectionList)
                            {
                                sb.AppendLine(item.ToString());
                            }
                        }
                        sb.AppendLine("刚刚收到的用户列表如下。");
                        lock (TrackerServer.Seeds)
                        {
                            foreach (var item in TrackerServer.Seeds)
                            {
                                sb.AppendLine("[" + item.Key.ToHexString() + "]");
                                foreach (var peer in item.Value)
                                {
                                    sb.AppendLine(peer.EndPoint.ToString());
                                }
                            }
                        }
                        Logger.Log(sb.ToString());
                    }

                    Logger.Log("添加对方持有的连接信息结束,将对方加入自己的连接列表。");
                    // 然后将对方加入自己的连接列表
                    try
                    {
                        AddToConnectionList(KEndPoint.FromEndPoint(pointInsertion));
                    }
                    catch (Exception)
                    {
                    }

                    // 不需要
                    //if (ConnectionList.Count > 0)
                    //{
                    //    Logger.Log("尝试广播消息,让连接列表中的客户端报告他们存活。");
                    //    // 要其他人报告他们存活
                    //    // 能发送等价于存活,所以并不期望回音,只是测试能连接而已
                    //    BroadcastMessage(MessageFactory.ReportAlive(LocalKEndPoint));
                    //}

                    //client.Close();
                    enterSocket.Disconnect(false);
                    enterSocket.Close();
                    _listener.Stop();

                    // 说到底,要 EnterNetwork(),肯定是普通客户端,那么就请求端口映射吧
                    //if (origPortNumber != LocalEndPoint.Port)
                    {
                        if (PortMapping.CanUsePortMapping)
                        {
                            try
                            {
                                if (origPortNumber == LocalEndPoint.Port)
                                {
                                    Thread.Sleep(TimeSpan.FromSeconds(0.8));
                                }
                                //PortMapping.AddPortMapping((ushort)origPortNumber, (ushort)LocalEndPoint.Port, origAddress);
                                PortMapping.AddPortMapping((ushort)origPortNumber, (ushort)LocalEndPoint.Port);
                            }
                            catch (Exception ex)
                            {
                                System.Diagnostics.Debug.Print("AddPortMapping: " + ex.Message);
                                Logger.Log("AddPortMapping: " + ex.Message);
                            }
                        }
                    }

                    ev.Set();
                    ev.Dispose();
                    //return true;
                }
                catch (Exception ex)
                {
                    Logger.Log(ex.Message + Environment.NewLine + ex.StackTrace);
                }
            });

            thread.IsBackground = true;
            thread.Start();
            workerThread = thread;
            return(ev);
        }
Пример #22
0
 public override string ToString()
 {
     return($"{Socket?.Handle} local:{(LocalEndPoint == null ? "-" : LocalEndPoint.ToString())} remote:{(RemoteEndPoint == null ? "-" : RemoteEndPoint.ToString())} tag:{Tag ?? "-"} t:{TransmitSize} r:{ReceiveSize} time:{StartTime:yyyy-MM-dd HH:mm:ss.fff}");
 }
Пример #23
0
 /// <summary>
 /// Returns a <see cref="System.String" /> that represents this instance.
 /// </summary>
 /// <returns>
 /// A <see cref="System.String" /> that represents this instance.
 /// </returns>
 public override string ToString() => LocalEndPoint.ToString();
Пример #24
0
        public virtual void Bind(System.Net.IPEndPoint localEndPoint, System.Net.NetworkInformation.NetworkInterface networkInterface)
        {
            //Check not already attached.
            if (NetworkConnectionFlags.HasFlag(NetworkConnectionState.Bound).Equals(false))
            {
                //Check for a null input
                if (object.ReferenceEquals(LocalEndPoint, null))
                {
                    throw new System.ArgumentNullException("localEndPoint");
                }

                //Ensure the latest details are availble.
                Refresh();

                //Double check not bound
                if (IsBound)
                {
                    throw new System.InvalidOperationException("Already Bound on: " + LocalEndPoint.ToString());
                }

                //Assign the end point
                LocalEndPoint = localEndPoint;

                //Assign the network interface
                NetworkInterface = networkInterface ?? Common.Extensions.NetworkInterface.NetworkInterfaceExtensions.GetNetworkInterface(localEndPoint);

                //Indicate Bound
                FlagBound();
            }
        }
Пример #25
0
        public Task SendAsync(ReadOnlyMemory <byte> request, Func <SocketAsyncState, Task> callback, ErrorMap errorMap)
        {
            var opaque = Converter.ToUInt32(request.Span.Slice(HeaderOffsets.Opaque));
            var state  = new AsyncState
            {
                Opaque        = opaque,
                Callback      = callback,
                Converter     = Converter,
                EndPoint      = (IPEndPoint)EndPoint,
                ConnectionId  = ConnectionId,
                ErrorMap      = errorMap,
                LocalEndpoint = LocalEndPoint.ToString()
            };

            _statesInFlight.TryAdd(state.Opaque, state);

            state.Timer = new Timer(o =>
            {
                AsyncState a = (AsyncState)o;
                _statesInFlight.TryRemove(a.Opaque, out _);
                a.Cancel(ResponseStatus.OperationTimeout, new TimeoutException());
            }, state, 75000, Timeout.Infinite);


            lock (Socket)
            {
                try
                {
                    #if NETCOREAPP2_1
                    var requestSpan = request.Span;
                    while (requestSpan.Length > 0)
                    {
                        var sentBytesCount = Socket.Send(requestSpan, SocketFlags.None);

                        requestSpan = requestSpan.Slice(sentBytesCount);
                    }
                    #else
                    if (!MemoryMarshal.TryGetArray <byte>(request, out var arraySegment))
                    {
                        // Fallback in case we can't use the more efficient TryGetArray method
                        arraySegment = new ArraySegment <byte>(request.ToArray());
                    }

                    var sentBytesCount = 0;
                    do
                    {
                        // ReSharper disable once AssignNullToNotNullAttribute
                        sentBytesCount += Socket.Send(arraySegment.Array,
                                                      arraySegment.Offset + sentBytesCount,
                                                      arraySegment.Count - sentBytesCount,
                                                      SocketFlags.None);
                    } while (sentBytesCount < arraySegment.Count);
                    #endif
                }
                catch (Exception e)
                {
                    HandleDisconnect(e);
                }
            }

            return(Task.FromResult(0));
        }
Пример #26
0
        public async Task SendAsync(ReadOnlyMemory <byte> request, Func <SocketAsyncState, Task> callback, ErrorMap errorMap)
        {
            ExceptionDispatchInfo capturedException = null;
            SocketAsyncState      state             = null;

            try
            {
                var opaque = ByteConverter.ToUInt32(request.Span.Slice(HeaderOffsets.Opaque));
                state = new SocketAsyncState
                {
                    Opaque        = opaque,
                    EndPoint      = (IPEndPoint)EndPoint,
                    ConnectionId  = ConnectionId,
                    LocalEndpoint = LocalEndPoint.ToString()
                };

                if (!MemoryMarshal.TryGetArray <byte>(request, out var arraySegment))
                {
                    // Fallback in case we can't use the more efficient TryGetArray method
                    arraySegment = new ArraySegment <byte>(request.ToArray());
                }

                // write data to stream
                await _sslStream.WriteAsync(arraySegment.Array, 0, request.Length).ConfigureAwait(false);

                // wait for response
                var received = await _sslStream.ReadAsync(_receiveBuffer, 0, _receiveBuffer.Length).ConfigureAwait(false);

                var responseSize = ByteConverter.ToInt32(_receiveBuffer.AsSpan(HeaderOffsets.BodyLength)) + HeaderOffsets.HeaderLength;

                // create memory slice and copy first segment
                var response = MemoryPool <byte> .Shared.RentAndSlice(responseSize);

                _receiveBuffer.AsMemory(0, received).CopyTo(response.Memory);

                // append any further segments as required
                while (received < responseSize)
                {
                    var segmentLength = await _sslStream.ReadAsync(_receiveBuffer, 0, _receiveBuffer.Length).ConfigureAwait(false);

                    _receiveBuffer.AsMemory(0, segmentLength).CopyTo(response.Memory);
                    received += segmentLength;
                }

                // write response to state and complete callback
                state.SetData(response);
                await callback(state).ConfigureAwait(false);
            }
            catch (Exception e)
            {
                IsDead            = true;
                capturedException = ExceptionDispatchInfo.Capture(e);
            }

            if (capturedException != null)
            {
                var sourceException = capturedException.SourceException;
                if (state == null)
                {
                    await callback(new SocketAsyncState
                    {
                        Exception = capturedException.SourceException,
                        Status    = (sourceException is SocketException)
                            ? ResponseStatus.TransportFailure
                            : ResponseStatus.ClientFailure
                    }).ConfigureAwait(false);
                }
                else
                {
                    state.Exception = sourceException;
                    await state.Completed(state).ConfigureAwait(false);

                    Log.LogDebug(sourceException, "");
                }
            }
        }
Пример #27
0
        public override async Task SendAsync(byte[] request, Func <SocketAsyncState, Task> callback, ISpan span, ErrorMap errorMap)
        {
            ExceptionDispatchInfo capturedException = null;
            SocketAsyncState      state             = null;

            try
            {
                var opaque = Converter.ToUInt32(request, HeaderIndexFor.Opaque);
                state = new SocketAsyncState
                {
                    Data          = MemoryStreamFactory.GetMemoryStream(),
                    Opaque        = opaque,
                    Buffer        = request,
                    Completed     = callback,
                    DispatchSpan  = span,
                    ConnectionId  = ContextId,
                    LocalEndpoint = LocalEndPoint.ToString(),
                    ErrorMap      = errorMap,
                    Timeout       = Configuration.SendTimeout
                };

                await _sslStream.WriteAsync(request, 0, request.Length).ContinueOnAnyContext();

                state.SetIOBuffer(_buffer);
                state.BytesReceived = await _sslStream.ReadAsync(state.Buffer, state.BufferOffset, state.BufferLength).ContinueOnAnyContext();

                //write the received buffer to the state obj
                await state.Data.WriteAsync(state.Buffer, state.BufferOffset, state.BytesReceived).ContinueOnAnyContext();

                state.BodyLength = Converter.ToInt32(state.Buffer, state.BufferOffset + HeaderIndexFor.BodyLength);
                while (state.BytesReceived < state.BodyLength + OperationHeader.Length)
                {
                    var bufferLength = state.BufferLength - state.BytesSent < state.BufferLength
                        ? state.BufferLength - state.BytesSent
                        : state.BufferLength;

                    state.BytesReceived += await _sslStream.ReadAsync(state.Buffer, state.BufferOffset, bufferLength).ContinueOnAnyContext();

                    await state.Data.WriteAsync(state.Buffer, state.BufferOffset, state.BytesReceived - (int)state.Data.Length).ContinueOnAnyContext();
                }
                await callback(state).ContinueOnAnyContext();
            }
            catch (Exception e)
            {
                IsDead            = true;
                capturedException = ExceptionDispatchInfo.Capture(e);
            }
            finally
            {
                ConnectionPool.Release(this);
            }

            if (capturedException != null)
            {
                var sourceException = capturedException.SourceException;
                if (state == null)
                {
                    await callback(new SocketAsyncState
                    {
                        Exception = capturedException.SourceException,
                        Status    = (sourceException is SocketException)
                            ? ResponseStatus.TransportFailure
                            : ResponseStatus.ClientFailure
                    }).ContinueOnAnyContext();
                }
                else
                {
                    state.Exception = sourceException;
                    await state.Completed(state).ContinueOnAnyContext();

                    Log.Debug(sourceException);
                }
            }
        }
Пример #28
0
 /// <summary>
 ///     Returns a <see cref="System.String" /> that represents this instance.
 /// </summary>
 /// <returns>
 ///     A <see cref="System.String" /> that represents this instance.
 /// </returns>
 public override string ToString()
 {
     return(LocalEndPoint.ToString());
 }
Пример #29
0
 public override string ToString()
 {
     return
         ($"LocalEndPoint:{LocalEndPoint?.ToString() ?? "NULL"}   RemoteEndPoint:{RemoteEndPoint?.ToString() ?? "NULL"}");
 }
Пример #30
0
 public override string ToString() =>
 $"{{ {LocalEndPoint?.ToString() ?? "unknown"} -> {RemoteEndPoint?.ToString() ?? "unknown"} }}";