예제 #1
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);
        }
예제 #2
0
        public void GetBytes_Result_NotSameAsInput()
        {
            var id     = new ToxId(this.validTestId);
            var result = id.GetBytes();

            Assert.AreNotSame(this.validTestId, result);
        }
예제 #3
0
        public new int AddFriend(ToxId id, string message)
        {
            var friendNumber = base.AddFriend(id, message);

            FriendListChanged(friendNumber, FriendListChangedAction.Add);
            return(friendNumber);
        }
예제 #4
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);
        }
예제 #5
0
        public async Task <bool> HandShake(ToxId target, int timeout = 20)
        {
            string reqid = Guid.NewGuid().ToString();

            Utils.Utils.Log("Event: Start Handshake , ReqId: " + reqid, true);
            Console.WriteLine("Event: Start Handshake , ReqId: " + reqid);
            bool status;
            var  res = await sendRequest(target, new ToxRequest
            {
                url        = "/handshake",
                method     = "get",
                uuid       = reqid,
                fromNodeId = reqid,
                fromToxId  = tox.Id.ToString(),
                toToxId    = target.ToString(),
                toNodeId   = "",
                time       = Utils.Utils.UnixTimeNow(),
            }, out status, timeout);

            if (res == null)
            {
                Utils.Utils.Log("Event: Handshake Failed, ReqId: " + reqid, true);
                Console.WriteLine("Event: Handshake failed, ReqId: " + reqid);
                return(false);
            }
            else
            {
                Utils.Utils.Log("Event: Handshake Success, ReqId: " + reqid, true);
                Console.WriteLine("Event: Handshake Success, ReqId: " + reqid);
                return(true);
            }
        }
예제 #6
0
 public ProfileViewModel(ToxDataInfo profile)
 {
     Name          = profile.Name;
     UserStatus    = profile.Status;
     StatusMessage = profile.StatusMessage;
     ToxId         = profile.Id;
 }
예제 #7
0
        public void GetBytes_Result_AreEqualAsInput()
        {
            var id     = new ToxId(this.validTestId);
            var result = id.GetBytes();

            Assert.AreEqual(this.validTestId, result);
        }
예제 #8
0
        public LinkClient(SkynetAndroid.Base.SkynetAndroid mSkynet, string targetToxId, IPAddress ip, int port)
        {
            this.targetToxId = targetToxId;
            this.ip          = ip;
            this.port        = port;
            serverToxId      = new ToxId(targetToxId);
            clientId         = Guid.NewGuid().ToString();
            this.mSkynet     = mSkynet;
            messageQueue     = new Queue <ToxRequest>();
            lastActiveTime   = DateTime.UtcNow;

            // send message to local loop
            Task.Run(() =>
            {
                ToxRequest mReq;
                // if idle for 600s, shutdown
                while (runningFlag && (long)(DateTime.UtcNow - lastActiveTime).TotalMilliseconds < 600 * 1000)
                {
                    mReq = getRequestToSend();
                    if (mReq != null && msgHandler != null)
                    {
                        lastActiveTime = DateTime.UtcNow;
                        msgHandler(mReq.content);
                        Utils.Log("Event: Received Message Complete, ClientId: " + clientId + ", MessageId: " + mReq.uuid);
                        var response = mReq.createResponse(Encoding.UTF8.GetBytes("OK"));
                        mSkynet.sendResponse(response, new ToxId(response.toToxId));
                    }
                    else
                    {
                        Thread.Sleep(1);
                    }
                }
            });
        }
예제 #9
0
        public bool sendMsg(ToxId toxid, string msg)
        {
            // check if this message is send to itself
            if (toxid.ToString() == tox.Id.ToString())
            {
                return(false); // this is not allowed
            }
            // wait toxcore online
            int maxOnlineWaitTime = 20000; // 20s
            int onlineWaitCount   = 0;

            while (!tox.IsConnected)
            {
                Thread.Sleep(10);
                onlineWaitCount += 10;
                if (onlineWaitCount > maxOnlineWaitTime)
                {
                    return(false);
                }
            }

            ToxKey toxkey    = toxid.PublicKey;
            int    friendNum = tox.GetFriendByPublicKey(toxkey);

            if (friendNum == -1)
            {
                int res = tox.AddFriend(toxid, "add friend");
                if (res != (int)ToxErrorFriendAdd.Ok)
                {
                    return(false);
                }
                friendNum = tox.GetFriendByPublicKey(toxkey);
            }
            int waitCount = 0;
            int maxCount  = 500;

            if (connectedList.IndexOf(toxkey.GetString()) == -1)
            {
                maxCount = 200 * 1000; // first time wait for 200s
            }
            while (tox.GetFriendConnectionStatus(friendNum) == ToxConnectionStatus.None && waitCount < maxCount)
            {
                if (waitCount % 1000 == 0)
                {
                    Console.WriteLine("target is offline." + waitCount / 1000);
                }
                waitCount += 10;
                Thread.Sleep(10);
            }
            if (waitCount == maxCount)
            {
                Console.WriteLine("Connect Failed");
                connectedList.Remove(toxkey.GetString());
                return(false);
            }
            connectedList.Add(toxkey.GetString());
            int msgRes = tox.SendMessage(friendNum, msg, ToxMessageType.Message);

            return(msgRes > 0);
        }
예제 #10
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;
            }));
        }
예제 #11
0
        public int AddFriend(ToxId id, string message, out bool success)
        {
            ToxErrorFriendAdd error;
            var retVal = _tox.AddFriend(id, message, out error);

            ToxErrorViewModel.Instance.RelayError(error);
            success = error == ToxErrorFriendAdd.Ok;
            return(retVal);
        }
예제 #12
0
 public LinkClient(Skynet.Base.Skynet mSkynet, string targetToxId, IPAddress ip, int port)
 {
     this.targetToxId = targetToxId;
     this.ip          = ip;
     this.port        = port;
     serverToxId      = new ToxId(targetToxId);
     clientId         = Guid.NewGuid().ToString();
     this.mSkynet     = mSkynet;
 }
예제 #13
0
        public new int AddFriend(ToxId id, string message, out ToxErrorFriendAdd error)
        {
            var friendNumber = base.AddFriend(id, message, out error);

            if (error == ToxErrorFriendAdd.Ok)
            {
                FriendListChanged(friendNumber, FriendListChangedAction.Add);
            }
            return(friendNumber);
        }
예제 #14
0
        public void TestToxId()
        {
            var tox   = new Tox(ToxOptions.Default);
            var toxId = new ToxId(tox.Id.PublicKey.GetBytes(), tox.Id.Nospam);

            if (toxId != tox.Id)
            {
                Assert.Fail("Tox id's are not equal");
            }
        }
예제 #15
0
        public bool sendMsgDebug(ToxId toxid, Package mPackage, int timeout = 20)
        {
            Utils.Utils.Log("Event: Start Send Msg Req ID: "
                            + mPackage.uuid + " totalNum: " + mPackage.totalCount
                            + " currentNum: " + mPackage.currentCount);
            var res = sendMsg(toxid, mPackage.toBytes(), timeout);

            Utils.Utils.Log("Event: End Send Msg Req ID: "
                            + mPackage.uuid + " totalNum: " + mPackage.totalCount
                            + " currentNum: " + mPackage.currentCount);
            return(res);
        }
예제 #16
0
        public void sendRequestNoReplay(ToxId toxid, ToxRequest req, out bool status)
        {
            status = true;

            try
            {
                if (toxid.ToString() == tox.Id.ToString())
                {
                    // request was sent to itself
                    status = true;
                }
            }
            catch (ObjectDisposedException)
            {
                status = false;
                return;
            }


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

            for (int i = 0; i < packageNum; i++)
            {
                byte[] mcontent = null;
                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;
                }
            }
        }
예제 #17
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",
                       }
            };
        }
예제 #18
0
        public void IsValid_InvalidId_IsFalse()
        {
            var result = ToxId.IsValid(this.invalidTestId);

            Assert.IsFalse(result);
        }
예제 #19
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));
        }
예제 #20
0
        public bool sendMsg(ToxId toxid, byte[] msg, int timeout = 20)
        {
            try
            {
                lock (sendLock)
                {
                    // check if this message is send to itself
                    if (toxid.ToString() == tox.Id.ToString())
                    {
                        return(false); // this is not allowed
                    }

                    // wait toxcore online
                    int maxOnlineWaitTime = 200000; // 200s
                    int onlineWaitCount   = 0;
                    while (!tox.IsConnected)
                    {
                        Thread.Sleep(10);
                        onlineWaitCount += 10;
                        if (onlineWaitCount > maxOnlineWaitTime)
                        {
                            return(false);
                        }
                    }

                    ToxKey toxkey    = toxid.PublicKey;
                    int    friendNum = tox.GetFriendByPublicKey(toxkey);
                    if (friendNum == -1)
                    {
                        int res = tox.AddFriend(toxid, "add friend");
                        if (res != (int)ToxErrorFriendAdd.Ok)
                        {
                            return(false);
                        }
                        friendNum = tox.GetFriendByPublicKey(toxkey);
                    }

                    if (tox.GetFriendConnectionStatus(friendNum) == ToxConnectionStatus.None)
                    {
                        return(false);
                    }

                    var mesError = new ToxErrorFriendCustomPacket();
                    // retry send message
                    int retryCount = 0;
                    while (retryCount < 60)
                    {
                        byte[] msgToSend = new byte[msg.Length + 1];
                        msgToSend[0] = 170; // The first byte must be in the range 160-191.
                        msg.CopyTo(msgToSend, 1);
                        bool msgRes = tox.FriendSendLosslessPacket(friendNum, msgToSend, out mesError);
                        if (msgRes)
                        {
                            break;
                        }

                        Utils.Utils.Log("Event: " + mesError, true);
                        Console.WriteLine(Utils.Utils.UnixTimeNow() + " Event: " + mesError);
                        if (mesError == ToxErrorFriendCustomPacket.SendQ)
                        {
                            Thread.Sleep(20);
                            continue;
                        }
                        retryCount++;
                        Thread.Sleep(100);
                    }
                    if (retryCount == 60)
                    {
                        tox.DeleteFriend(friendNum);
                        return(false);
                    }

                    return(true);
                }
            }
            catch (Exception e)
            {
                Utils.Utils.Log(e.StackTrace, true);
                return(false);
            }
        }
예제 #21
0
        public void IsValid_ValidIdString_IsTrue()
        {
            var result = ToxId.IsValid(ToxTools.HexBinToString(this.validTestId));

            Assert.IsTrue(result);
        }
예제 #22
0
        public bool sendMsg(ToxId toxid, byte[] msg)
        {
            lock (sendLock) {
                // check if this message is send to itself
                if (toxid.ToString() == tox.Id.ToString())
                {
                    return(false);                    // this is not allowed
                }

                // wait toxcore online
                int maxOnlineWaitTime = 20000;                 // 20s
                int onlineWaitCount   = 0;
                while (!tox.IsConnected)
                {
                    Thread.Sleep(10);
                    onlineWaitCount += 10;
                    if (onlineWaitCount > maxOnlineWaitTime)
                    {
                        return(false);
                    }
                }

                ToxKey toxkey    = toxid.PublicKey;
                int    friendNum = tox.GetFriendByPublicKey(toxkey);
                if (friendNum == -1)
                {
                    int res = tox.AddFriend(toxid, "add friend");
                    if (res != (int)ToxErrorFriendAdd.Ok)
                    {
                        return(false);
                    }
                    friendNum = tox.GetFriendByPublicKey(toxkey);
                }

                int waitCount = 0;
                int maxCount  = 500;
                if (connectedList.IndexOf(toxkey.GetString()) == -1)
                {
                    maxCount = 200 * 1000;                     // first time wait for 200s
                }
                while (tox.GetFriendConnectionStatus(friendNum) == ToxConnectionStatus.None && waitCount < maxCount)
                {
                    if (waitCount % 1000 == 0)
                    {
                        Utils.Utils.LogUtils("Event: target is offline " + waitCount / 1000);
                    }
                    waitCount += 10;
                    Thread.Sleep(10);
                }
                if (waitCount == maxCount)
                {
                    Utils.Utils.LogUtils("Event: Connect Failed");
                    connectedList.Remove(toxkey.GetString());
                    return(false);
                }
                if (connectedList.IndexOf(toxkey.GetString()) == -1)
                {
                    connectedList.Add(toxkey.GetString());
                }

                var mesError = new ToxErrorFriendCustomPacket();
                // retry send message
                int retryCount = 0;
                while (retryCount < 10)
                {
                    byte[] msgToSend = new byte[msg.Length + 1];
                    msgToSend [0] = 170;                     // The first byte must be in the range 160-191.
                    msg.CopyTo(msgToSend, 1);
                    bool msgRes = tox.FriendSendLosslessPacket(friendNum, msgToSend, out mesError);
                    if (msgRes)
                    {
                        break;
                    }

                    Utils.Utils.LogUtils("Event: " + mesError);
                    if (mesError == ToxErrorFriendCustomPacket.SendQ)
                    {
                        Thread.Sleep(10);
                        continue;
                    }
                    retryCount++;
                    Thread.Sleep(100);
                }
                if (retryCount == 10)
                {
                    return(false);
                }
                return(true);
            }
        }
예제 #23
0
 public int AddFriend(ToxId id, string message, out bool success)
 {
     success = true;
     return(0);
 }
예제 #24
0
        private async void ButtonAddFriend_Click(object sender, RoutedEventArgs e)
        {
            string id      = TextBoxFriendId.Text.Trim();
            string message = TextBoxMessage.Text.Trim();

            if (string.IsNullOrEmpty(id))
            {
                ShowError("The Tox ID field is empty.");
                return;
            }

            if (string.IsNullOrEmpty(message))
            {
                message = (string)TextBoxMessage.Tag;
            }

            if (Config.Instance.EnableToxDns && id.Contains("@"))
            {
                //try resolving 3 times
                for (int tries = 0; tries < 3; tries++)
                {
                    try
                    {
                        string toxId = DnsUtils.DiscoverToxID(id, Config.Instance.NameServices, !Config.Instance.AllowPublicKeyLookups, !Config.Instance.AllowTox1Lookups);
                        if (!string.IsNullOrEmpty(toxId))
                        {
                            //show the tox id to the user before actually adding it to the friend list
                            TextBoxFriendId.Text = toxId;
                            return;
                        }
                    }
                    catch (Exception ex)
                    {
                        Debugging.Write(string.Format("Could not resolve {0}: {1}", id, ex.Message));
                    }
                }

                //if we got this far the discovery must have failed
                ShowError("Could not resolve tox username.");
                return;
            }

            if (!ToxId.IsValid(id))
            {
                ShowError("The entered Tox ID is invalid.");
                return;
            }

            var error        = ToxErrorFriendAdd.Ok;
            int friendNumber = ProfileManager.Instance.Tox.AddFriend(new ToxId(id), message, out error);

            if (error != ToxErrorFriendAdd.Ok)
            {
                ShowError(error.ToString());
                return;
            }

            var model = new FriendControlViewModel(MainWindow.Instance.ViewModel.CurrentFriendListView);

            model.ChatNumber    = friendNumber;
            model.Name          = id;
            model.StatusMessage = "Friend request sent";

            MainWindow.Instance.ViewModel.CurrentFriendListView.AddObject(model);
            MainWindow.Instance.ViewModel.CurrentFriendListView.SortObject(model);
            MainWindow.Instance.ViewModel.CurrentFriendListView.SelectObject(model);

            await ProfileManager.Instance.SaveAsync();
        }
예제 #25
0
        public FriendAddViewModel(Tox tox)
        {
            if (tox == null)
            {
                throw new ArgumentNullException(nameof(tox));
            }

            this.Add = ReactiveCommand.Create(() => tox.AddFriend(new ToxId(this.ID), this.Message, out _), this.WhenAnyValue(x => x.ID, (string id) => ToxId.IsValid(id)));
        }
예제 #26
0
        public void Connect(string[] args)
        {
            if (args.Length != 4 && args.Length != 0)
            {
                Console.WriteLine("usage: SharpLink [local_port] [target_tox_id] [target_ip] [target_port]");
                return;
            }

            // 线程监控程序
            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);
                    Utils.Log("CurrentThreads: " + (workerThreadsMax - workerThreads), true);
                    Thread.Sleep(2000);
                }
            });

            if (args.Length == 4)
            {
                if (localPort == Convert.ToInt32(args[0]) && targetToxId == args[1] && targetIP == args[2] && targetPort == Convert.ToInt32(args[3]))
                {
                    // already started
                    return;
                }

                localPort   = Convert.ToInt32(args[0]);
                targetToxId = args[1];
                targetIP    = args[2];
                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;
                }

                // start check connection task
                Task.Run(() =>
                {
                    while (runningFlag)
                    {
                        bool 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)
                            {
                                mSkynet.tox.DeleteFriend(friendNum);
                                Utils.Log("Event: can not connect, resend friend request");
                            }

                            mSkynet.HandShake(new ToxId(targetToxId)).GetAwaiter().GetResult();
                        }
                        Thread.Sleep(60 * 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, localPort));
                serverSocket.Listen(1000);
                Task.Factory.StartNew(() =>
                {
                    while (runningFlag)
                    {
                        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(() =>
                            {
                                while (runningFlag)
                                {
                                    byte[] buf = new byte[1024 * 512];
                                    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)
                                        {
                                            var res = mlink.Send(buf, size);
                                            if (!res && !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;
                                            }
                                        }
                                    }
                                    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), 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(() =>
                            {
                                while (runningFlag)
                                {
                                    byte[] buf = new byte[1024 * 512];
                                    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);
                                        }
                                        var res = mlink.Send(buf, size);
                                        if (!res)
                                        {
                                            // 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;
                                            }
                                        }
                                    }
                                    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, true);
                    Utils.Log("Event: Send HandShake response " + response.uuid + ", ToxId: " + response.toToxId, true);
                    Console.WriteLine("Event: HandShake from " + response.toToxId + ", MessageID: " + req.uuid);
                    mSkynet.sendResponse(response, new ToxId(response.toToxId));
                }
            });

            while (runningFlag)
            {
                Thread.Sleep(10);
            }

            mSkynet.stop();
        }
예제 #27
0
        public void IsValid_ValidId_IsTrue()
        {
            var result = ToxId.IsValid(this.validTestId);

            Assert.IsTrue(result);
        }
예제 #28
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);
            }
        }
예제 #29
0
        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);

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

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

            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;
                }

                // 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(() => {
                                while (true)
                                {
                                    byte[] buf = new byte[1024 * 512];
                                    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();
                                            }

                                            if (!closeFlag && clientSocket.Connected)
                                            {
                                                closeFlag = true;
                                                clientSocket.Shutdown(SocketShutdown.Both);
                                                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)
                                        {
                                            var res = mlink.Send(buf, size);
                                            if (!res && !closeFlag && clientSocket.Connected)
                                            {
                                                closeFlag = true;
                                                clientSocket.Shutdown(SocketShutdown.Both);
                                                clientSocket.Close();
                                                Utils.Log("Event: Tox send message failed, ClientId: " + mlink.clientId + ", ConnectId: " + tempConnectId);
                                                Utils.Log("Event: Close Connection, ClientId: " + mlink.clientId + ", ConnectId: " + tempConnectId);
                                                break;
                                            }
                                        }
                                    } catch (Exception e) {
                                        Utils.Log("Event: ERROR " + e.Message);
                                        Utils.Log(e.StackTrace);
                                        if (mlink != null)
                                        {
                                            mlink.CloseRemote();
                                        }
                                        if (!closeFlag && clientSocket.Connected)
                                        {
                                            closeFlag = true;
                                            clientSocket.Shutdown(SocketShutdown.Both);
                                            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();
                                    if (!closeFlag && clientSocket.Connected)
                                    {
                                        closeFlag = true;
                                        clientSocket.Shutdown(SocketShutdown.Both);
                                        clientSocket.Close();
                                        Utils.Log("Event: Close Connection, ClientId: " + mlink.clientId + ", ConnectId: " + tempConnectId);
                                    }
                                }
                            },
                                                       // close handler
                                                       () => {
                                if (!closeFlag && clientSocket.Connected)
                                {
                                    closeFlag = true;
                                    clientSocket.Shutdown(SocketShutdown.Both);
                                    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;
                                    clientSocket.Shutdown(SocketShutdown.Both);
                                    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();
                            }
                        }).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.Run(() => {
                        // 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();
                                    if (!closeFlag && mClientSocket.Connected)
                                    {
                                        closeFlag = true;
                                        mClientSocket.Shutdown(SocketShutdown.Both);
                                        mClientSocket.Close();
                                        Utils.Log("Event: Close Socket" + ipstr + " " + port + " mLinkID " + mlink.clientId);
                                    }
                                }
                            });
                            mlink.OnClose(() => {
                                if (!closeFlag && mClientSocket.Connected)
                                {
                                    closeFlag = true;
                                    mClientSocket.Shutdown(SocketShutdown.Both);
                                    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(() => {
                                while (true)
                                {
                                    byte[] buf = new byte[1024 * 512];
                                    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;
                                                mClientSocket.Shutdown(SocketShutdown.Both);
                                                mClientSocket.Close();
                                            }
                                            mlink.CloseRemote();
                                            break;
                                        }
                                        else
                                        {
                                            Utils.Log("Event: Read Data " + size + ", Clientid: " + mlink.clientId);
                                        }
                                        var res = mlink.Send(buf, size);
                                        if (!res)
                                        {
                                            // send failed
                                            if (!closeFlag && mClientSocket.Connected)
                                            {
                                                closeFlag = true;
                                                mClientSocket.Shutdown(SocketShutdown.Both);
                                                mClientSocket.Close();
                                                Utils.Log("Event: Tox send message failed, Clientid: " + mlink.clientId);
                                                break;
                                            }
                                        }
                                    } 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();
                                        if (!closeFlag && mClientSocket.Connected)
                                        {
                                            closeFlag = true;
                                            mClientSocket.Shutdown(SocketShutdown.Both);
                                            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));
                        }
                    }).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);
            }
        }
예제 #30
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));
        }