Пример #1
0
        void newReqReceived(Package receivedPackage, int friendNum)
        {
            string mcontentCache = "";

            if (mPackageCache.ContainsKey(receivedPackage.uuid))
            {
                mcontentCache = mPackageCache[receivedPackage.uuid].content;
            }
            mcontentCache += receivedPackage.content;
            // check if this is a response
            if (mPendingReqList.ContainsKey(receivedPackage.uuid))
            {
                mPendingReqList[receivedPackage.uuid](JsonConvert.DeserializeObject <ToxResponse>(mcontentCache));
                mPendingReqList.Remove(receivedPackage.uuid);
                return;
            }

            ToxRequest newReq = JsonConvert.DeserializeObject <ToxRequest>(mcontentCache);

            Task.Factory.StartNew(async() =>
            {
                // send response to http server
                Console.WriteLine("new Req: " + JsonConvert.SerializeObject(newReq));
                ToxResponse mRes = await RequestProxy.sendRequest(this, newReq);
                sendResponse(mRes, tox.GetFriendPublicKey(friendNum));
            });
        }
Пример #2
0
        public bool sendResponse(ToxResponse res, ToxId toxid)
        {
            byte[] resContent = res.getBytes();
            int    packageNum = resContent.Length / MAX_MSG_LENGTH + 1;
            bool   result     = false;

            for (int i = 0; i < packageNum; i++)
            {
                byte[] mcontent;
                if (i * MAX_MSG_LENGTH + MAX_MSG_LENGTH > resContent.Length)
                {
                    mcontent = Utils.Utils.subArray(resContent, i * MAX_MSG_LENGTH);
                }
                else
                {
                    mcontent = Utils.Utils.subArray(resContent, i * MAX_MSG_LENGTH, MAX_MSG_LENGTH);
                }
                result = sendMsg(toxid, new Package
                {
                    uuid         = res.uuid,
                    totalCount   = packageNum,
                    currentCount = i,
                    content      = mcontent,
                    totalSize    = (uint)resContent.Length,
                    startIndex   = (uint)(i * MAX_MSG_LENGTH),
                }.toBytes());
            }
            return(result);
        }
Пример #3
0
        public void setParentNode()
        {
            Task.Run(() => {
                Skynet.Base.Skynet sender = new Skynet.Base.Skynet();
                Node mNode = new Node(new List <NodeId>(), mSkynet);
                Task.Run(async() => {
                    // create a node

                    Node parentNode = new Node(new List <NodeId>(), sender);

                    long timeStamp  = Skynet.Utils.Utils.UnixTimeNow();
                    ToxResponse res = await RequestProxy.sendRequest(mSkynet, new ToxRequest
                    {
                        uuid       = Guid.NewGuid().ToString(),
                        url        = "node/" + mNode.selfNode.uuid + "/parent",
                        method     = "put",
                        content    = JsonConvert.SerializeObject(parentNode.selfNode),
                        fromNodeId = parentNode.selfNode.uuid,
                        fromToxId  = sender.tox.Id.ToString(),
                        toNodeId   = mNode.selfNode.uuid,
                        toToxId    = mSkynet.tox.Id.ToString(),
                        time       = timeStamp,
                    });
                    NodeResponse mRes = JsonConvert.DeserializeObject <NodeResponse>(res.content);
                    Console.WriteLine("value: " + mRes.value);
                    Assert.AreEqual(mRes.statusCode, NodeResponseCode.OK);
                    Assert.AreEqual(timeStamp, mRes.time);
                    Assert.AreEqual(timeStamp, mNode.parentModifiedTime);
                }).GetAwaiter().GetResult();
            });
        }
Пример #4
0
        bool sendResponse(ToxResponse res, ToxId toxid)
        {
            string resContent = JsonConvert.SerializeObject(res);
            int    packageNum = resContent.Length / MAX_MSG_LENGTH + 1;
            bool   result     = false;

            for (int i = 0; i < packageNum; i++)
            {
                string mcontent = "";
                if (i * MAX_MSG_LENGTH + MAX_MSG_LENGTH > resContent.Length)
                {
                    mcontent = resContent.Substring(i * MAX_MSG_LENGTH);
                }
                else
                {
                    mcontent = resContent.Substring(i * MAX_MSG_LENGTH, MAX_MSG_LENGTH);
                }
                result = sendMsg(toxid, JsonConvert.SerializeObject(new Package
                {
                    uuid         = res.uuid,
                    totalCount   = packageNum,
                    currentCount = i,
                    content      = mcontent,
                }));
            }
            return(result);
        }
Пример #5
0
        public void PutTest()
        {
            Node node1 = new Node(mSkynet);
            Node node2 = new Node(mSkynet);
            Node node3 = new Node(mSkynet);

            node2.parent             = node1.selfNode;
            node2.parentModifiedTime = Skynet.Utils.Utils.UnixTimeNow();
            Task.Run(async() => {
                ToxResponse response = await RequestProxy.sendRequest(mSkynet, new ToxRequest {
                    uuid       = Guid.NewGuid().ToString(),
                    url        = "node/" + node3.selfNode.uuid + "/grandParents",
                    content    = JsonConvert.SerializeObject(node1.selfNode),
                    method     = "put",
                    fromNodeId = node2.selfNode.uuid,
                    fromToxId  = node2.selfNode.toxid,
                    toNodeId   = node3.selfNode.uuid,
                    toToxId    = node3.selfNode.toxid,
                    time       = node2.parentModifiedTime
                });

                NodeResponse res = JsonConvert.DeserializeObject <NodeResponse>(response.content);
                Assert.AreEqual(node1.selfNode.uuid, node3.grandParents.uuid);
                Assert.AreEqual(node2.parentModifiedTime, node3.grandParentsModifiedTime);
            }).GetAwaiter().GetResult();
        }
Пример #6
0
        public void TestSendMsgToSelf()
        {
            Node Node1  = new Node(mSkynet);
            Node Node2  = new Node(mSkynet);
            bool status = false;

            Task.Run(async() => {
                ToxResponse res = await mSkynet.sendRequest(mSkynet.tox.Id, new ToxRequest
                {
                    url        = "tox/" + mSkynet.tox.Id.ToString(),
                    uuid       = Guid.NewGuid().ToString(),
                    method     = "get",
                    content    = "",
                    fromNodeId = Node1.selfNode.uuid,
                    fromToxId  = mSkynet.tox.Id.ToString(),
                    toNodeId   = Node2.selfNode.uuid,
                    toToxId    = mSkynet.tox.Id.ToString(),
                }, out status);
                Console.WriteLine("status: " + status);
                Assert.AreEqual(true, status);
                if (status)
                {
                    NodeResponse nodeRes = JsonConvert.DeserializeObject <NodeResponse>(res.content);
                    Assert.AreEqual(nodeRes.statusCode, NodeResponseCode.OK);
                }
            }).GetAwaiter().GetResult();
        }
Пример #7
0
        public void TestHandShake()
        {
            while (!mSkynet.tox.IsConnected)
            {
                Thread.Sleep(10);
            }
            Skynet.Base.Skynet mSkynet2 = new Skynet.Base.Skynet();
            Node mNode1 = new Node(new List <NodeId>(), mSkynet);
            Node mNode2 = new Node(new List <NodeId>(), mSkynet2);

            bool status = false;

            Task.Run(async() =>
            {
                ToxResponse res = await mSkynet2.sendRequest(mSkynet.tox.Id, new ToxRequest
                {
                    url        = "tox/" + mSkynet.tox.Id.ToString(),
                    uuid       = Guid.NewGuid().ToString(),
                    method     = "get",
                    content    = "",
                    fromNodeId = mNode2.selfNode.uuid,
                    fromToxId  = mNode2.selfNode.toxid,
                    toNodeId   = mNode1.selfNode.uuid,
                    toToxId    = mNode1.selfNode.toxid,
                }, out status);
                Console.WriteLine("status " + status);
                Assert.AreEqual(status, true);
                if (status)
                {
                    NodeResponse nodeRes = JsonConvert.DeserializeObject <NodeResponse>(res.content);
                    Assert.AreEqual(nodeRes.statusCode, NodeResponseCode.OK);
                }
            }).GetAwaiter().GetResult();
        }
Пример #8
0
        public Task <ToxResponse> sendRequest(ToxId toxid, ToxRequest req, out bool status)
        {
            if (toxid.ToString() == tox.Id.ToString())
            {
                // request was sent to itself
                status = true;
                return(RequestProxy.sendRequest(this, req));
            }

            string reqContent = JsonConvert.SerializeObject(req);
            int    packageNum = reqContent.Length / MAX_MSG_LENGTH + 1;
            bool   res        = false;

            for (int i = 0; i < packageNum; i++)
            {
                string mcontent = "";
                if (i * MAX_MSG_LENGTH + MAX_MSG_LENGTH > reqContent.Length)
                {
                    mcontent = reqContent.Substring(i * MAX_MSG_LENGTH);
                }
                else
                {
                    mcontent = reqContent.Substring(i * MAX_MSG_LENGTH, MAX_MSG_LENGTH);
                }
                res = sendMsg(toxid, JsonConvert.SerializeObject(new Package
                {
                    uuid         = req.uuid,
                    totalCount   = packageNum,
                    currentCount = i,
                    content      = mcontent,
                }));
                if (!res)
                {
                    status = false;
                    return(Task.Factory.StartNew <ToxResponse>(() => {
                        return null;
                    }));
                }
            }
            status = res;
            bool        isResponseReceived = false;
            ToxResponse mRes = null;

            if (res)
            {
                mPendingReqList.Add(req.uuid, (response) => {
                    isResponseReceived = true;
                    mRes = response;
                });
            }
            return(Task.Factory.StartNew(() =>
            {
                while (!isResponseReceived)
                {
                    Thread.Sleep(10);
                }
                return mRes;
            }));
        }
Пример #9
0
        private void newReqReceived(Package receivedPackage)
        {
            Utils.Utils.Log("Event: newReqReceived reqId: " + receivedPackage.uuid);
            byte[] mcontentCache = new byte[receivedPackage.totalSize];
            lock (mPackageCacheLock)
            {
                if (mPackageCache.ContainsKey(receivedPackage.uuid))
                {
                    mcontentCache = mPackageCache[receivedPackage.uuid];
                    mPackageCache.Remove(receivedPackage.uuid);
                }
            }
            receivedPackage.content.CopyTo(mcontentCache, receivedPackage.startIndex);
            // check if this is a response
            lock (mPendingReqLock)
            {
                if (mPendingReqList.ContainsKey(receivedPackage.uuid))
                {
                    Utils.Utils.Log("Event: newResponse Received reqId: " + receivedPackage.uuid);
                    mPendingReqList[receivedPackage.uuid](ToxResponse.fromBytes(mcontentCache));
                    mPendingReqList.Remove(receivedPackage.uuid);
                    return;
                }
            }
            ToxRequest newReq = ToxRequest.fromBytes(mcontentCache);

            if (newReq.method == "")
            {
                Console.WriteLine("this happends, this is an ugly hack");
                return;
            }

            if (newReq == null)
            {
                Utils.Utils.Log("Event: Invalid Request Data: receivedPackage " + receivedPackage.uuid);
                return;
            }
            Utils.Utils.Log("Event: Start callbacks reqId: " + newReq.uuid);
            Utils.Utils.Log("Event: Begin Process MessageID: " + newReq.uuid);
            if (newReq.url == "/msg")
            {
                Utils.Utils.Log("Event: Message toNodeID: " + newReq.toNodeId + ", totoxid:" + newReq.toToxId);
            }
            lock (reqListnerLock)
            {
                if (reqCallbacks.Keys.Contains(newReq.toNodeId))
                {
                    reqCallbacks[newReq.toNodeId](newReq);
                }
            }
            Utils.Utils.Log("Event: End callbacks");
        }
Пример #10
0
        public async Task <NodeResponse> Get(string id)
        {
            Skynet curHost = Skynet.allInstance.Where(x => x.httpPort == Request.RequestUri.Port).FirstOrDefault();

            if (!ToxId.IsValid(id))
            {
                return(new NodeResponse
                {
                    statusCode = NodeResponseCode.InvalidRequest,
                    description = "your tox id is invalid",
                });
            }

            // check if target tox client is local client
            if (curHost.tox.Id.ToString() == id)
            {
                // list all nodes on target tox client
                return(new NodeResponse
                {
                    statusCode = NodeResponseCode.OK,
                    description = "success",
                    value = JsonConvert.SerializeObject(new ToxClient
                    {
                        Id = id,
                        nodes = Node.AllLocalNodes.Select(x => x.getInfo()).ToList()
                    })
                });
            }
            // if not, send tox req to target tox client
            bool        reqStatus    = false;
            ToxResponse nodeResponse = await curHost.sendRequest(new ToxId(id), RequestProxy.toNodeRequest(Request), out reqStatus);

            if (nodeResponse != null)
            {
                return(JsonConvert.DeserializeObject <NodeResponse>(Encoding.UTF8.GetString(nodeResponse.content)));
            }
            else
            {
                return new NodeResponse
                       {
                           statusCode  = NodeResponseCode.NotFound,
                           description = "target does not exist or target is current offline",
                       }
            };
        }
Пример #11
0
        void newReqReceived(Package receivedPackage)
        {
            byte[] mcontentCache = new byte[receivedPackage.totalSize];
            if (mPackageCache.ContainsKey(receivedPackage.uuid))
            {
                mcontentCache = mPackageCache [receivedPackage.uuid];
                mPackageCache.Remove(receivedPackage.uuid);
            }
            receivedPackage.content.CopyTo(mcontentCache, receivedPackage.startIndex);
            // check if this is a response
            lock (mPendingReqLock) {
                if (mPendingReqList.ContainsKey(receivedPackage.uuid))
                {
                    mPendingReqList [receivedPackage.uuid] (ToxResponse.fromBytes(mcontentCache));
                    mPendingReqList.Remove(receivedPackage.uuid);
                    return;
                }
            }
            ToxRequest newReq = ToxRequest.fromBytes(mcontentCache);

            if (newReq == null)
            {
                Utils.Utils.LogUtils("Event: Invalid Request Data: receivedPackage " + receivedPackage.uuid);
                return;
            }
            List <Action <ToxRequest> > tempReqList;

            lock (reqListnerLock) {
                tempReqList = new List <Action <ToxRequest> > (reqCallbacks);
            }
            Utils.Utils.LogUtils("Event: Start callbacks");
            foreach (var cb in tempReqList)
            {
                Utils.Utils.LogUtils("Event: Begin Process MessageID: " + newReq.uuid);
                if (newReq.url == "/msg")
                {
                    Utils.Utils.LogUtils("Event: Message toNodeID: " + newReq.toNodeId + ", totoxid:" + newReq.toToxId);
                }
                cb(newReq);
            }
            Utils.Utils.LogUtils("Event: End callbacks");
        }
Пример #12
0
        public NodeResponse Put(string nodeId, [FromBody] NodeId values)
        {
            IEnumerable <string> requestTime = new List <string>();

            if (!Request.Headers.TryGetValues("Skynet-Time", out requestTime))
            {
                return(new NodeResponse
                {
                    statusCode = NodeResponseCode.InvalidRequest,
                    description = "you need to add some http headers"
                });
            }

            if (!Utils.Utils.isValidGuid(nodeId))
            {
                return(new NodeResponse
                {
                    statusCode = NodeResponseCode.InvalidRequest,
                    description = "your node id is invalid",
                });
            }
            Node targetNode = Node.AllLocalNodes.Where(x => x.selfNode.uuid == nodeId).DefaultIfEmpty(null).FirstOrDefault();

            if (targetNode == null)
            {
                return(new NodeResponse
                {
                    statusCode = NodeResponseCode.NotFound,
                    description = "target node cannot be found on the client",
                });
            }
            // check lock
            if (targetNode.nodeChangeLock.isLocked == true)
            {
                // target is locked, cannot be changed at this time
                return(new NodeResponse
                {
                    statusCode = NodeResponseCode.TargetLocked,
                    description = "target is locked",
                });
            }
            else
            {
                long reqTime = long.Parse(requestTime.DefaultIfEmpty("0").FirstOrDefault());
                if (reqTime < targetNode.brotherModifiedTime)
                {
                    return(new NodeResponse
                    {
                        statusCode = NodeResponseCode.OutOfDate,
                        description = "Your data is outofdate",
                    });
                }
                targetNode.parentModifiedTime = reqTime;
                targetNode.parent             = values;

                Task.Run(async() =>
                {
                    // get parent node info, set grandparents
                    Skynet host = Skynet.allInstance.Where(x => x.httpPort == Request.RequestUri.Port).FirstOrDefault();
                    bool status = false;
                    ToxResponse getParentInfo = await host.sendRequest(new ToxId(values.toxid), new ToxRequest
                    {
                        url        = "node/" + values.uuid,
                        method     = "get",
                        content    = null,
                        fromNodeId = targetNode.selfNode.uuid,
                        fromToxId  = targetNode.selfNode.toxid,
                        toNodeId   = values.uuid,
                        toToxId    = values.toxid,
                        time       = Utils.Utils.UnixTimeNow(),
                        uuid       = Guid.NewGuid().ToString()
                    }, out status);
                    NodeResponse getParentInfoRes       = JsonConvert.DeserializeObject <NodeResponse>(Encoding.UTF8.GetString(getParentInfo.content));
                    NodeInfo parentInfo                 = JsonConvert.DeserializeObject <NodeInfo>(getParentInfoRes.value);
                    targetNode.grandParents             = parentInfo.parent;
                    targetNode.grandParentsModifiedTime = parentInfo.parentModifiedTime;
                    await BoardCastChanges(targetNode);
                });

                return(new NodeResponse
                {
                    statusCode = NodeResponseCode.OK,
                    description = "set parent success",
                    value = JsonConvert.SerializeObject(values),
                    time = reqTime,
                });
            }
        }
Пример #13
0
        public Task <ToxResponse> sendRequest(ToxId toxid, ToxRequest req, out bool status, int timeout = 200)
        {
            try
            {
                if (toxid.ToString() == tox.Id.ToString())
                {
                    // request was sent to itself
                    status = true;
                    return(RequestProxy.sendRequest(this, req));
                }
            }
            catch (ObjectDisposedException)
            {
                status = false;
                return(Task.Factory.StartNew <ToxResponse>(() =>
                {
                    return null;
                }, TaskCreationOptions.LongRunning));
            }

            byte[] reqContent = req.getBytes();
            int    packageNum = reqContent.Length / MAX_MSG_LENGTH + 1;
            bool   res        = false;

            ToxResponse mRes    = null;
            object      reslock = new object();
            bool        resFlag = false;

            lock (mPendingReqLock)
            {
                mPendingReqList.Add(req.uuid, (response) =>
                {
                    mRes = response;
                    lock (reslock)
                    {
                        resFlag = true;
                        Utils.Utils.Log("Event: Callback called, ReqId: " + req.uuid);
                        Monitor.PulseAll(reslock);
                        Utils.Utils.Log("Event: Pulse Lock, ReqId: " + req.uuid);
                    }
                });
            }

            for (int i = 0; i < packageNum; i++)
            {
                byte[] mcontent;
                if (i * MAX_MSG_LENGTH + MAX_MSG_LENGTH > reqContent.Length)
                {
                    mcontent = Utils.Utils.subArray(reqContent, i * MAX_MSG_LENGTH);
                }
                else
                {
                    mcontent = Utils.Utils.subArray(reqContent, i * MAX_MSG_LENGTH, MAX_MSG_LENGTH);
                }
                res = sendMsgDebug(toxid, new Package
                {
                    uuid         = req.uuid,
                    totalCount   = packageNum,
                    currentCount = i,
                    content      = mcontent,
                    totalSize    = (uint)reqContent.Length,
                    startIndex   = (uint)(i * MAX_MSG_LENGTH),
                }, timeout);

                if (!res)
                {
                    status = false;
                    return(Task.Factory.StartNew <ToxResponse>(() =>
                    {
                        lock (mPendingReqLock)
                        {
                            mPendingReqList.Remove(req.uuid);
                        }
                        return null;
                    }, TaskCreationOptions.LongRunning));
                }
            }
            status = res;

            Utils.Utils.Log("Event: return async, ReqId: " + req.uuid);

            return(Task.Factory.StartNew(() =>
            {
                Task.Run(() =>
                {
                    // timeout count thread
                    int timeoutCount = 0;
                    while (timeoutCount < timeout * 1000)
                    {
                        Thread.Sleep(1);
                        timeoutCount += 1;
                        lock (mPendingReqLock)
                        {
                            if (!mPendingReqList.Keys.Contains(req.uuid))
                            {
                                // already received response
                                return;
                            }
                        }
                    }
                    Console.WriteLine(Utils.Utils.UnixTimeNow() + " Timeout Happends ReqId: " + req.uuid);
                    lock (mPendingReqLock)
                    {
                        if (mPendingReqList.Keys.Contains(req.uuid))
                        {
                            mRes = null;
                            mPendingReqList.Remove(req.uuid);
                            lock (reslock)
                            {
                                resFlag = true;
                                Utils.Utils.Log("Event: Callback Timeout, ReqId: " + req.uuid);
                                Monitor.PulseAll(reslock);
                                Utils.Utils.Log("Event: Pulse Lock, ReqId: " + req.uuid);
                            }
                        }
                    }
                });
                Utils.Utils.Log("Event: Response locked, ReqId: " + req.uuid);
                lock (reslock)
                {
                    while (!resFlag)
                    {
                        Monitor.Wait(reslock);
                    }
                }
                Utils.Utils.Log("Event: Response unlocked, ReqId: " + req.uuid);
                return mRes;
            }, TaskCreationOptions.LongRunning));
        }
Пример #14
0
 public bool sendResponse(ToxResponse res, ToxKey toxkey)
 {
     return(sendResponse(res, new ToxId(toxkey.GetBytes(), 100)));
 }
Пример #15
0
        private static void Main(string[] args)
        {
            if (args.Length != 4 && args.Length != 0)
            {
                Console.WriteLine("usage: SharpLink [local_port] [target_tox_id] [target_ip] [target_port]");
                return;
            }
            Skynet.Base.Skynet mSkynet = null;
            string             exeDir  = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

            string AppDataFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
            string toxFolder     = Path.Combine(AppDataFolder, "ToxTunnel");
            string toxFile       = Path.Combine(toxFolder, "tox.dat");

            //Directory.SetCurrentDirectory(exeDir);
            if (args.Length == 0)
            {
                // log to file
                Utils.setLogFile("toxtunnel_server.log");
            }
            else
            {
                // log to file
                Utils.setLogFile("toxtunnel_client.log");
            }

            // Save tox data for server
            if (args.Length == 0 && File.Exists(toxFile))
            {
                mSkynet = new Skynet.Base.Skynet(toxFile);
            }
            else if (args.Length == 0 && !File.Exists(toxFile))
            {
                mSkynet = new Skynet.Base.Skynet();
                mSkynet.Save(toxFile);
            }
            else
            {
                mSkynet = new Skynet.Base.Skynet();
            }

            // 线程监控程序
            Task.Run(() =>
            {
                while (runningFlag)
                {
                    int workerThreads, completionPortThreads;
                    ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads);
                    int workerThreadsMax, completionPortThreadsMax;
                    ThreadPool.GetMaxThreads(out workerThreadsMax, out completionPortThreadsMax);
                    int workerThreadsMin, completionPortThreadsMin;
                    ThreadPool.GetMinThreads(out workerThreadsMin, out completionPortThreadsMin);
                    ThreadPool.SetMinThreads(workerThreadsMax - workerThreads + 40, workerThreadsMax - workerThreads + 40);
                    Thread.Sleep(2000);
                }
            });

            if (args.Length == 4)
            {
                string localPort   = args[0];
                string targetToxId = args[1];
                string targetIP    = args[2];
                int    targetPort  = Convert.ToInt32(args[3]);

                if (!ToxId.IsValid(targetToxId))
                {
                    Console.WriteLine("not a valid id");
                    Console.WriteLine("usage: SharpLink [local_port] [target_tox_id] [target_ip] [target_port]");
                    return;
                }

                // 连接维护程序
                Task.Run(() =>
                {
                    int disconnectCount = 0;
                    while (runningFlag)
                    {
                        IsConnected = mSkynet.HandShake(new ToxId(targetToxId)).GetAwaiter().GetResult();
                        if (!IsConnected)
                        {
                            var toxid     = new ToxId(targetToxId);
                            ToxKey toxkey = toxid.PublicKey;
                            int friendNum = mSkynet.tox.GetFriendByPublicKey(toxkey);
                            if (friendNum != -1 && disconnectCount > 15)
                            { // wait 150s
                                Utils.Log("delete friend " + targetToxId);
                                Console.WriteLine("delete friend " + targetToxId);
                                disconnectCount = 0;
                                mSkynet.DeleteFriend(friendNum);
                            }
                            disconnectCount += 1;
                        }
                        else
                        {
                            disconnectCount = 0;
                        }
                        Thread.Sleep(10 * 1000);
                    }
                });

                // create local socket server
                IPAddress ip           = IPAddress.Parse("0.0.0.0");
                var       serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                serverSocket.Bind(new IPEndPoint(ip, Convert.ToInt32(localPort)));
                serverSocket.Listen(1000);
                Task.Factory.StartNew(() =>
                {
                    while (true)
                    {
                        Utils.Log("Event: Waiting socket");
                        List <byte> tempData = new List <byte>();
                        Socket clientSocket  = serverSocket.Accept();
                        Task.Factory.StartNew(() =>
                        {
                            bool closeFlag       = false;
                            LinkClient mlink     = null;
                            string tempConnectId = Guid.NewGuid().ToString();
                            Task.Factory.StartNew(async() =>
                            {
                                Task <ToxResponse> sendTask = null;
                                ToxResponse sendRes         = null;
                                while (true)
                                {
                                    byte[] buf = new byte[32 * 1024];
                                    try
                                    {
                                        int size = 0;
                                        if (clientSocket != null && clientSocket.Connected)
                                        {
                                            size = clientSocket.Receive(buf);
                                        }
                                        else
                                        {
                                            break;
                                        }
                                        if (mlink == null)
                                        {
                                            tempData.AddRange(buf.Take(size));
                                        }
                                        if (size == 0)
                                        {
                                            // socket closed
                                            if (mlink != null)
                                            {
                                                mlink.CloseRemote();
                                                mlink.Close();
                                            }

                                            if (!closeFlag && clientSocket.Connected)
                                            {
                                                closeFlag = true;
                                                try
                                                {
                                                    clientSocket.Shutdown(SocketShutdown.Both);
                                                }
                                                catch (SocketException ex)
                                                {
                                                    Utils.Log("Event ERROR: " + ex.Message);
                                                }

                                                clientSocket.Close();
                                                if (mlink != null)
                                                {
                                                    Utils.Log("Event: Close Connection, ClientId: " + mlink.clientId + ", ConnectId: " + tempConnectId);
                                                }
                                                else
                                                {
                                                    Utils.Log("Event: Close Connection, ClinetId: null" + ", ConnectId: " + tempConnectId);
                                                }
                                            }
                                            break;
                                        }
                                        if (mlink != null)
                                        {
                                            if (sendTask != null)
                                            {
                                                sendRes = await sendTask;
                                            }
                                            if (sendTask != null && sendRes == null && !closeFlag && clientSocket.Connected)
                                            {
                                                closeFlag = true;
                                                try
                                                {
                                                    clientSocket.Shutdown(SocketShutdown.Both);
                                                }
                                                catch (SocketException ex)
                                                {
                                                    Utils.Log("Event ERROR: " + ex.Message);
                                                }
                                                clientSocket.Close();
                                                mlink.CloseRemote();
                                                mlink.Close();
                                                Utils.Log("Event: Tox send message failed, ClientId: " + mlink.clientId + ", ConnectId: " + tempConnectId);
                                                Utils.Log("Event: Close Connection, ClientId: " + mlink.clientId + ", ConnectId: " + tempConnectId);
                                                break;
                                            }
                                            Utils.Log("Event: LinkClient Start Send Data");
                                            sendTask = mlink.SendAsync(buf, size);
                                            Utils.Log("Event: LinkClient Stop Send Data");
                                        }
                                    }
                                    catch (Exception e)
                                    {
                                        Utils.Log("Event: ERROR " + e.Message);
                                        Utils.Log(e.StackTrace);
                                        if (mlink != null)
                                        {
                                            mlink.CloseRemote();
                                            mlink.Close();
                                        }

                                        if (!closeFlag && clientSocket.Connected)
                                        {
                                            closeFlag = true;
                                            try
                                            {
                                                clientSocket.Shutdown(SocketShutdown.Both);
                                            }
                                            catch (SocketException ex)
                                            {
                                                Utils.Log("Event ERROR: " + ex.Message);
                                            }
                                            clientSocket.Close();
                                            if (mlink != null)
                                            {
                                                Utils.Log("Event: Close Connection, ClientId: " + mlink.clientId + ", ConnectId: " + tempConnectId);
                                            }
                                            else
                                            {
                                                Utils.Log("Event: Close Connection, ClinetId: null" + ", ConnectId: " + tempConnectId);
                                            }
                                        }
                                        break;
                                    }
                                }
                            }, TaskCreationOptions.LongRunning).ForgetOrThrow();
                            mlink = LinkClient.Connect(mSkynet, targetToxId, IPAddress.Parse(targetIP), Convert.ToInt32(targetPort),
                                                       // message handler
                                                       (msg) =>
                            {
                                try
                                {
                                    if (clientSocket != null && clientSocket.Connected)
                                    {
                                        clientSocket.Send(msg, SocketFlags.None);
                                    }
                                }
                                catch (Exception e)
                                {
                                    Utils.Log("ERROR " + e.Message);
                                    Utils.Log(e.StackTrace);
                                    mlink.CloseRemote();
                                    mlink.Close();
                                    if (!closeFlag && clientSocket.Connected)
                                    {
                                        closeFlag = true;
                                        try
                                        {
                                            clientSocket.Shutdown(SocketShutdown.Both);
                                        }
                                        catch (SocketException ex)
                                        {
                                            Utils.Log("Event ERROR: " + ex.Message);
                                        }
                                        clientSocket.Close();
                                        Utils.Log("Event: Close Connection, ClientId: " + mlink.clientId + ", ConnectId: " + tempConnectId);
                                    }
                                }
                            },
                                                       // close handler
                                                       () =>
                            {
                                if (!closeFlag && clientSocket.Connected)
                                {
                                    closeFlag = true;
                                    try
                                    {
                                        clientSocket.Shutdown(SocketShutdown.Both);
                                    }
                                    catch (SocketException ex)
                                    {
                                        Utils.Log("Event ERROR: " + ex.Message);
                                    }
                                    clientSocket.Close();
                                    Utils.Log("Event: Close Connection, ClientId: " + mlink.clientId + ", ConnectId: " + tempConnectId);
                                }
                            }
                                                       );
                            if (mlink == null)
                            {
                                // connected failed
                                Utils.Log("Event: Connected failed, ClientId: null" + ", ConnectId: " + tempConnectId);
                                if (!closeFlag && clientSocket.Connected)
                                {
                                    closeFlag = true;
                                    try
                                    {
                                        clientSocket.Shutdown(SocketShutdown.Both);
                                    }
                                    catch (SocketException ex)
                                    {
                                        Utils.Log("Event ERROR: " + ex.Message);
                                    }
                                    clientSocket.Close();
                                    Utils.Log("Event: Close Connection, ClientId: null" + ", ConnectId: " + tempConnectId);
                                }
                                return;
                            }
                            if (tempData.Count != 0)
                            {
                                mlink.Send(tempData.ToArray(), tempData.Count);
                            }
                            // check if socket has closed
                            if (closeFlag)
                            {
                                // socket has closed
                                Utils.Log("Event: Close Remote, ClientId: " + mlink.clientId + ", ConnectId: " + tempConnectId);
                                mlink.CloseRemote();
                                mlink.Close();
                            }
                        }, TaskCreationOptions.LongRunning).ForgetOrThrow();
                    }
                }, TaskCreationOptions.LongRunning).ForgetOrThrow();
            }

            mSkynet.addNewReqListener("", (req) =>
            {
                // handle
                if (req.toNodeId == "" && req.url == "/connect")
                {
                    Utils.Log("Event: Task Connect to " + req.fromNodeId + ", MessageId: " + req.uuid);
                    Task.Factory.StartNew(() =>
                    {
                        // connect to server received, create sockets
                        Utils.Log("Event: Task Started Connect to " + req.fromNodeId);
                        try
                        {
                            string reqStr = Encoding.UTF8.GetString(req.content);
                            string ipstr  = reqStr.Split('\n')[0];
                            string port   = reqStr.Split('\n')[1];
                            Utils.Log("Event: Connect to " + ipstr + " " + port + " " + req.fromNodeId);
                            IPAddress targetIp   = IPAddress.Parse(ipstr);
                            Socket mClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                            bool closeFlag       = false;
                            mClientSocket.Connect(new IPEndPoint(targetIp, Convert.ToInt32(port)));
                            Utils.Log("Event: Connect to " + ipstr + " " + port + " Success " + req.fromNodeId);
                            var mlink    = LinkClient.Connect(mSkynet, req.fromToxId, req.fromNodeId);
                            req.toNodeId = mlink.clientId;
                            Utils.Log("Event: Connect to " + ipstr + " " + port + " Success " + req.fromNodeId + " , mLinkID: " + mlink.clientId);

                            mlink.OnMessage((msg) =>
                            {
                                try
                                {
                                    Utils.Log("Event: Start Write Message, mLinkID: " + mlink.clientId);
                                    if (mClientSocket != null && mClientSocket.Connected)
                                    {
                                        mClientSocket.Send(msg, SocketFlags.None);
                                    }
                                    Utils.Log("Event: Write Message Success, mLinkID: " + mlink.clientId);
                                }
                                catch (Exception e)
                                {
                                    Utils.Log("Event: ERROR " + e.Message);
                                    Utils.Log(e.StackTrace);
                                    mlink.CloseRemote();
                                    mlink.Close();
                                    if (!closeFlag && mClientSocket.Connected)
                                    {
                                        closeFlag = true;
                                        try
                                        {
                                            mClientSocket.Shutdown(SocketShutdown.Both);
                                        }
                                        catch (SocketException ex)
                                        {
                                            Utils.Log("Event: " + ex.Message);
                                        }

                                        mClientSocket.Close();
                                        Utils.Log("Event: Close Socket" + ipstr + " " + port + " mLinkID " + mlink.clientId);
                                    }
                                }
                            });
                            mlink.OnClose(() =>
                            {
                                if (!closeFlag && mClientSocket.Connected)
                                {
                                    closeFlag = true;
                                    try
                                    {
                                        mClientSocket.Shutdown(SocketShutdown.Both);
                                    }
                                    catch (SocketException ex)
                                    {
                                        Utils.Log("Event: " + ex.Message);
                                    }
                                    mClientSocket.Close();
                                    Utils.Log("Event: Close Socket" + ipstr + " " + port + " mLinkID " + mlink.clientId);
                                }
                            });
                            // send response after all handler has been set
                            mSkynet.sendResponse(req.createResponse(Encoding.UTF8.GetBytes("OK")), new ToxId(req.fromToxId));
                            Task.Factory.StartNew(async() =>
                            {
                                Task <ToxResponse> sendTask = null;
                                ToxResponse sendRes         = null;
                                while (true)
                                {
                                    byte[] buf = new byte[1024 * 32];
                                    try
                                    {
                                        Utils.Log("Event: Start Read Data, Clientid: " + mlink.clientId);
                                        int size = 0;
                                        if (mClientSocket != null && mClientSocket.Connected)
                                        {
                                            size = mClientSocket.Receive(buf);
                                        }
                                        else
                                        {
                                            Utils.Log("Event: Socket already closed" + ipstr + " " + port + " mLinkID " + mlink.clientId);

                                            break;
                                        }

                                        if (size == 0)
                                        {
                                            if (!closeFlag && mClientSocket.Connected)
                                            {
                                                Utils.Log("Event: Close Connection, Clientid: " + mlink.clientId);
                                                closeFlag = true;
                                                try
                                                {
                                                    mClientSocket.Shutdown(SocketShutdown.Both);
                                                }
                                                catch (SocketException ex)
                                                {
                                                    Utils.Log("Event: " + ex.Message);
                                                }
                                                mClientSocket.Close();
                                            }
                                            mlink.CloseRemote();
                                            mlink.Close();
                                            break;
                                        }
                                        else
                                        {
                                            Utils.Log("Event: Read Data " + size + ", Clientid: " + mlink.clientId);
                                        }

                                        if (sendTask != null)
                                        {
                                            sendRes = await sendTask;
                                        }
                                        if (sendTask != null && sendRes == null)
                                        {
                                            // send failed
                                            if (!closeFlag && mClientSocket.Connected)
                                            {
                                                closeFlag = true;
                                                try
                                                {
                                                    mClientSocket.Shutdown(SocketShutdown.Both);
                                                }
                                                catch (SocketException ex)
                                                {
                                                    Utils.Log("Event: " + ex.Message);
                                                }
                                                mClientSocket.Close();
                                                mlink.Close();
                                                Utils.Log("Event: Tox send message failed, Clientid: " + mlink.clientId);
                                                break;
                                            }
                                        }
                                        sendTask = mlink.SendAsync(buf, size);
                                    }
                                    catch (Exception e)
                                    {
                                        /*if (e.ErrorCode != 10004) // this is not an error
                                         * {
                                         *  Console.WriteLine("Time: " + Utils.UnixTimeNow() + " Event: ERROR " + e.Message);
                                         *  Console.WriteLine(e.StackTrace);
                                         * }*/
                                        Utils.Log("Event: ERROR " + e.Message);
                                        Utils.Log(e.StackTrace);
                                        mlink.CloseRemote();
                                        mlink.Close();
                                        if (!closeFlag && mClientSocket.Connected)
                                        {
                                            closeFlag = true;
                                            try
                                            {
                                                mClientSocket.Shutdown(SocketShutdown.Both);
                                            }
                                            catch (SocketException ex)
                                            {
                                                Utils.Log("Event: " + ex.Message);
                                            }
                                            mClientSocket.Close();
                                            Utils.Log("Event: Close Connection, ClientId: " + mlink.clientId);
                                        }
                                        break;
                                    }
                                }
                            }, TaskCreationOptions.LongRunning).ForgetOrThrow();
                            Utils.Log("Event: Connect to " + ipstr + " " + port + " All Success " + req.fromNodeId + ", mLinkID: " + mlink.clientId);
                        }
                        catch (Exception e)
                        {
                            Utils.Log("Event: ERROR " + e.Message);
                            Utils.Log(e.StackTrace);

                            // connected failed
                            string reqStr = Encoding.UTF8.GetString(req.content);
                            string ipstr  = reqStr.Split('\n')[0];
                            string port   = reqStr.Split('\n')[1];
                            Utils.Log("Event: Connect to " + ipstr + " " + port + " failed");
                            var response = req.createResponse(Encoding.UTF8.GetBytes("failed"));
                            mSkynet.sendResponse(response, new ToxId(response.toToxId));
                        }
                    }, TaskCreationOptions.LongRunning).ForgetOrThrow();
                }
                else if (req.toNodeId == "" && req.url == "/handshake")
                {
                    var response = req.createResponse(Encoding.UTF8.GetBytes("OK"));
                    Utils.Log("Event: HandShake from " + response.toToxId + ", MessageID: " + req.uuid);
                    Utils.Log("Event: Send HandShake response " + response.uuid + ", ToxId: " + response.toToxId);
                    mSkynet.sendResponse(response, new ToxId(response.toToxId));
                }
            });

            while (true)
            {
                Thread.Sleep(10);
            }
        }
Пример #16
0
        public Task <ToxResponse> sendRequest(ToxId toxid, ToxRequest req, out bool status)
        {
            if (toxid.ToString() == tox.Id.ToString())
            {
                // request was sent to itself
                status = true;
                return(RequestProxy.sendRequest(this, req));
            }

            byte[] reqContent = req.getBytes();
            int    packageNum = reqContent.Length / MAX_MSG_LENGTH + 1;
            bool   res        = false;

            ToxResponse mRes    = null;
            object      reslock = new object();
            bool        resFlag = false;

            lock (mPendingReqLock) {
                mPendingReqList.Add(req.uuid, (response) => {
                    mRes = response;
                    lock (reslock) {
                        resFlag = true;
                        Utils.Utils.LogUtils("Event: Callback called, ReqId: " + req.uuid);
                        Monitor.PulseAll(reslock);
                        Utils.Utils.LogUtils("Event: Pulse Lock, ReqId: " + req.uuid);
                    }
                });
            }

            for (int i = 0; i < packageNum; i++)
            {
                byte[] mcontent;
                if (i * MAX_MSG_LENGTH + MAX_MSG_LENGTH > reqContent.Length)
                {
                    mcontent = Utils.Utils.subArray(reqContent, i * MAX_MSG_LENGTH);
                }
                else
                {
                    mcontent = Utils.Utils.subArray(reqContent, i * MAX_MSG_LENGTH, MAX_MSG_LENGTH);
                }
                res = sendMsg(toxid, new Package {
                    uuid         = req.uuid,
                    totalCount   = packageNum,
                    currentCount = i,
                    content      = mcontent,
                    totalSize    = (uint)reqContent.Length,
                    startIndex   = (uint)(i * MAX_MSG_LENGTH),
                }.toBytes());
                if (!res)
                {
                    status = false;
                    return(Task.Factory.StartNew <ToxResponse> (() => {
                        mPendingReqList.Remove(req.uuid);
                        return null;
                    }, TaskCreationOptions.LongRunning));
                }
            }
            status = res;

            Utils.Utils.LogUtils("Event: return async, ReqId: " + req.uuid);

            return(Task.Factory.StartNew(() => {
                Utils.Utils.LogUtils("Event: Response locked, ReqId: " + req.uuid);
                lock (reslock) {
                    while (!resFlag)
                    {
                        Monitor.Wait(reslock);
                    }
                }
                Utils.Utils.LogUtils("Event: Response unlocked, ReqId: " + req.uuid);
                return mRes;
            }, TaskCreationOptions.LongRunning));
        }