예제 #1
0
        /// <summary>
        /// Send byte data to a peer and await a response.
        /// </summary>
        /// <param name="peer">Peer IP address.</param>
        /// <param name="data">Peer port number.</param>
        /// <param name="response">Byte data returned by the peer.</param>
        /// <returns>True if successful.</returns>
        public bool SendSync(string ip, int port, int timeoutMs, byte[] data, out byte[] response)
        {
            response = null;
            if (String.IsNullOrEmpty(ip))
            {
                throw new ArgumentNullException(nameof(ip));
            }
            if (port < 0)
            {
                throw new ArgumentException("Port must be zero or greater.");
            }
            if (timeoutMs < 1)
            {
                throw new ArgumentException("Timeout must be zero or greater.");
            }
            if (data == null || data.Length < 1)
            {
                throw new ArgumentNullException(nameof(data));
            }

            MeshClient currClient = GetMeshClientByIpPort(ip, port);

            if (currClient == null || currClient == default(MeshClient))
            {
                return(false);
            }
            return(SendSyncRequestInternal(currClient, MessageType.Data, timeoutMs, data, out response));
        }
예제 #2
0
        /// <summary>
        /// Send byte data to a peer asynchronously using a stream.
        /// </summary>
        /// <param name="ip">Peer IP address.</param>
        /// <param name="port">Peer port number.</param>
        /// <param name="contentLength">The number of bytes to read from the stream.</param>
        /// <param name="stream">The stream containing the data.</param>
        /// <returns>True if successful.</returns>
        public bool SendAsync(string ip, int port, long contentLength, Stream stream)
        {
            if (String.IsNullOrEmpty(ip))
            {
                throw new ArgumentNullException(nameof(ip));
            }
            if (port < 0)
            {
                throw new ArgumentException("Port must be zero or greater.");
            }
            if (contentLength < 1)
            {
                throw new ArgumentException("Content length must be at least one byte.");
            }
            if (stream == null || !stream.CanRead)
            {
                throw new ArgumentException("Cannot read from supplied stream.");
            }

            MeshClient currClient = GetMeshClientByIpPort(ip, port);

            if (currClient == null || currClient == default(MeshClient))
            {
                return(false);
            }
            return(SendAsyncInternal(currClient, MessageType.Data, contentLength, stream));
        }
예제 #3
0
        /// <summary>
        /// Remove a peer from the network.
        /// </summary>
        /// <param name="peer">Peer.</param>
        public void Remove(Peer peer)
        {
            if (peer == null)
            {
                throw new ArgumentNullException(nameof(peer));
            }

            lock (_PeerLock)
            {
                Peer currPeer = _Peers.Where(p => p.Ip.Equals(peer.Ip) && p.Port.Equals(peer.Port)).FirstOrDefault();
                if (currPeer == null || currPeer == default(Peer))
                {
                }
                else
                {
                    _Peers.Remove(currPeer);
                }
            }

            lock (_ClientsLock)
            {
                MeshClient currClient = _Clients.Where(c => c.Peer.Ip.Equals(peer.Ip) && c.Peer.Port.Equals(peer.Port)).FirstOrDefault();
                if (currClient == null || currClient == default(MeshClient))
                {
                }
                else
                {
                    currClient.Dispose();
                    _Clients.Remove(currClient);
                }
            }
        }
예제 #4
0
        private bool MeshServerMessageReceived(string ipPort, byte[] data)
        {
            try
            {
                Message currMsg = new Message(data, true);
                // Console.WriteLine(currMsg.ToString());

                Peer currPeer = GetPeerByIpPort(currMsg.SourceIp, currMsg.SourcePort);
                if (currPeer == null || currPeer == default(Peer))
                {
                    // Console.WriteLine("Unable to find peer " + currMsg.SourceIp + ":" + currMsg.SourcePort);
                    return(false);
                }

                if (currMsg.SyncRequest)
                {
                    if (SyncMessageReceived != null)
                    {
                        SyncResponse syncResponse = SyncMessageReceived(currPeer, currMsg.Data);
                        Message      responseMsg  = new Message(_Self.Ip, _Self.Port, currPeer.Ip, currPeer.Port, currMsg.TimeoutMs, false, true, currMsg.Type, syncResponse.Data);
                        responseMsg.Id = currMsg.Id;
                        MeshClient currClient = GetMeshClientByIpPort(currPeer.Ip, currPeer.Port);
                        return(SendSyncResponseInternal(currClient, responseMsg));
                    }
                }
                else if (currMsg.SyncResponse)
                {
                    // add to sync responses
                    PendingResponse pendingResp = new PendingResponse(DateTime.Now.AddMilliseconds(currMsg.TimeoutMs), currMsg);
                    _PendingResponses.TryAdd(currMsg.Id, pendingResp);
                    return(true);
                }
                else
                {
                    if (AsyncMessageReceived != null)
                    {
                        return(AsyncMessageReceived(currPeer, currMsg.Data));
                    }
                }

                return(true);
            }
            catch (Exception e)
            {
                Console.WriteLine("ClientMessageReceived exception: " + Environment.NewLine + Common.SerializeJson(e, true));
                return(false);
            }
        }
예제 #5
0
        private bool SendAsyncInternal(MeshClient client, MessageType msgType, long contentLength, Stream stream)
        {
            try
            {
                Message msg     = new Message(_Self.Ip, _Self.Port, client.Peer.Ip, client.Peer.Port, 0, false, false, msgType, contentLength, stream);
                byte[]  msgData = msg.ToBytes();
                return(client.Send(msgData).Result);
            }
            catch (Exception e)
            {
                if (_Settings.Debug)
                {
                    Console.WriteLine(Common.SerializeJson(e, true));
                }

                return(false);
            }
        }
예제 #6
0
        private bool SendAsyncInternal(MeshClient client, MessageType msgType, byte[] data)
        {
            try
            {
                Message msg     = new Message(_Self.Ip, _Self.Port, client.Peer.Ip, client.Peer.Port, 0, false, false, msgType, data);
                byte[]  msgData = msg.ToBytes();
                return(client.Send(msgData).Result);
            }
            catch (Exception e)
            {
                if (_Settings.Debug)
                {
                    Console.WriteLine("SendAsyncInternal Exception " + Environment.NewLine + Common.SerializeJson(e, true));
                }

                return(false);
            }
        }
예제 #7
0
        /// <summary>
        /// Check if a specific remote server connection is alive.
        /// </summary>
        /// <param name="ip">Peer IP address.</param>
        /// <param name="port">Peer port number.</param>
        /// <returns>True if healthy.</returns>
        public bool IsHealthy(string ip, int port)
        {
            if (String.IsNullOrEmpty(ip))
            {
                throw new ArgumentNullException(nameof(ip));
            }
            if (port < 0)
            {
                throw new ArgumentException("Port must be zero or greater.");
            }

            MeshClient currClient = GetMeshClientByIpPort(ip, port);

            if (currClient == null)
            {
                return(false);
            }
            return(currClient.Connected);
        }
예제 #8
0
        private bool MeshClientStreamReceived(Peer peer, long contentLength, Stream stream)
        {
            try
            {
                Message currMsg = new Message(stream, _Settings.ReadStreamBufferSize);

                if (currMsg.SyncRequest)
                {
                    if (SyncMessageReceived != null)
                    {
                        SyncResponse syncResponse = SyncStreamReceived(peer, currMsg.ContentLength, currMsg.DataStream);
                        Console.WriteLine("ServerStreamReceived received sync response");
                        Message responseMsg = new Message(_Self.Ip, _Self.Port, peer.Ip, peer.Port, currMsg.TimeoutMs, false, true, currMsg.Type, syncResponse.Data);
                        Console.WriteLine("ServerStreamReceived built message");
                        responseMsg.Id = currMsg.Id;
                        MeshClient currClient = GetMeshClientByIpPort(peer.Ip, peer.Port);
                        return(SendSyncResponseInternal(currClient, responseMsg));
                    }
                }
                else if (currMsg.SyncResponse)
                {
                    // add to sync responses
                    PendingResponse pendingResp = new PendingResponse(DateTime.Now.AddMilliseconds(currMsg.TimeoutMs), currMsg);
                    _PendingResponses.TryAdd(currMsg.Id, pendingResp);
                }
                else
                {
                    if (AsyncStreamReceived != null)
                    {
                        return(AsyncStreamReceived(peer, currMsg.ContentLength, currMsg.DataStream));
                    }
                }

                return(true);
            }
            catch (Exception e)
            {
                Console.WriteLine("ServerStreamReceived exception: " + Environment.NewLine + Common.SerializeJson(e, true));
                return(false);
            }
        }
예제 #9
0
        private MeshClient GetMeshClientByIpPort(string ip, int port)
        {
            if (String.IsNullOrEmpty(ip))
            {
                throw new ArgumentNullException(nameof(ip));
            }
            if (port < 0)
            {
                throw new ArgumentException("Port must be zero or greater.");
            }

            lock (_ClientsLock)
            {
                MeshClient currClient = _Clients.Where(c => c.Peer.Ip.Equals(ip) && c.Peer.Port.Equals(port)).FirstOrDefault();
                if (currClient == null || currClient == default(MeshClient))
                {
                    return(null);
                }
                return(currClient);
            }
        }
예제 #10
0
        /// <summary>
        /// Add a peer to the network.
        /// </summary>
        /// <param name="peer">Peer.</param>
        public void Add(Peer peer)
        {
            if (peer == null)
            {
                throw new ArgumentNullException(nameof(peer));
            }

            lock (_PeerLock)
            {
                bool exists = _Peers.Any(p => p.Ip.Equals(peer.Ip) && p.Port.Equals(peer.Port));
                if (exists)
                {
                    _Peers = _Peers.Where(p => !p.Ip.Equals(peer.Ip) && !p.Port.Equals(peer.Port)).ToList();
                }
                _Peers.Add(peer);
            }

            lock (_ClientsLock)
            {
                bool exists = _Clients.Any(c => c.Peer.Ip.Equals(peer.Ip) && c.Peer.Port.Equals(peer.Port));
                if (exists)
                {
                    return;
                }
                else
                {
                    MeshClient currClient = new MeshClient(_Settings, peer);
                    currClient.ServerConnected    = MeshClientServerConnected;
                    currClient.ServerDisconnected = MeshClientServerDisconnected;
                    currClient.MessageReceived    = MeshClientMessageReceived;
                    currClient.StreamReceived     = MeshClientStreamReceived;

                    Task.Run(() => currClient.Start());

                    _Clients.Add(currClient);
                }
            }
        }
예제 #11
0
        /// <summary>
        /// Send byte data to a peer asynchronously.
        /// </summary>
        /// <param name="ip">Peer IP address.</param>
        /// <param name="port">Peer port number.</param>
        /// <param name="data">Byte data to send.</param>
        /// <returns>True if successful.</returns>
        public bool SendAsync(string ip, int port, byte[] data)
        {
            if (String.IsNullOrEmpty(ip))
            {
                throw new ArgumentNullException(nameof(ip));
            }
            if (port < 0)
            {
                throw new ArgumentException("Port must be zero or greater.");
            }
            if (data == null || data.Length < 1)
            {
                throw new ArgumentNullException(nameof(data));
            }

            MeshClient currClient = GetMeshClientByIpPort(ip, port);

            if (currClient == null || currClient == default(MeshClient))
            {
                return(false);
            }
            return(SendAsyncInternal(currClient, MessageType.Data, data));
        }
예제 #12
0
        private bool SendSyncRequestInternal(MeshClient client, MessageType msgType, int timeoutMs, byte[] data, out byte[] response)
        {
            response = null;
            Message msg = new Message(_Self.Ip, _Self.Port, client.Peer.Ip, client.Peer.Port, timeoutMs, true, false, msgType, data);

            byte[] msgData = msg.ToBytes();

            try
            {
                if (!AddSyncRequest(msg.Id, timeoutMs))
                {
                    return(false);
                }
                if (!client.Send(msgData).Result)
                {
                    return(false);
                }
                return(GetSyncResponse(msg.Id, timeoutMs, out response));
            }
            catch (Exception e)
            {
                if (_Settings.Debug)
                {
                    Console.WriteLine(Common.SerializeJson(e, true));
                }

                return(false);
            }
            finally
            {
                DateTime ts;
                if (_SyncRequests.ContainsKey(msg.Id))
                {
                    _SyncRequests.TryRemove(msg.Id, out ts);
                }
            }
        }
예제 #13
0
 private bool SendSyncResponseInternal(MeshClient client, Message msg)
 {
     byte[] msgData = msg.ToBytes();
     return(client.Send(msgData).Result);
 }