void newReqReceived(Package receivedPackage, int friendNum) { string mcontentCache = ""; if (mPackageCache.ContainsKey(receivedPackage.uuid)) { mcontentCache = mPackageCache[receivedPackage.uuid].content; } mcontentCache += receivedPackage.content; // check if this is a response if (mPendingReqList.ContainsKey(receivedPackage.uuid)) { mPendingReqList[receivedPackage.uuid](JsonConvert.DeserializeObject <ToxResponse>(mcontentCache)); mPendingReqList.Remove(receivedPackage.uuid); return; } ToxRequest newReq = JsonConvert.DeserializeObject <ToxRequest>(mcontentCache); Task.Factory.StartNew(async() => { // send response to http server Console.WriteLine("new Req: " + JsonConvert.SerializeObject(newReq)); ToxResponse mRes = await RequestProxy.sendRequest(this, newReq); sendResponse(mRes, tox.GetFriendPublicKey(friendNum)); }); }
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); }
public void setParentNode() { Task.Run(() => { Skynet.Base.Skynet sender = new Skynet.Base.Skynet(); Node mNode = new Node(new List <NodeId>(), mSkynet); Task.Run(async() => { // create a node Node parentNode = new Node(new List <NodeId>(), sender); long timeStamp = Skynet.Utils.Utils.UnixTimeNow(); ToxResponse res = await RequestProxy.sendRequest(mSkynet, new ToxRequest { uuid = Guid.NewGuid().ToString(), url = "node/" + mNode.selfNode.uuid + "/parent", method = "put", content = JsonConvert.SerializeObject(parentNode.selfNode), fromNodeId = parentNode.selfNode.uuid, fromToxId = sender.tox.Id.ToString(), toNodeId = mNode.selfNode.uuid, toToxId = mSkynet.tox.Id.ToString(), time = timeStamp, }); NodeResponse mRes = JsonConvert.DeserializeObject <NodeResponse>(res.content); Console.WriteLine("value: " + mRes.value); Assert.AreEqual(mRes.statusCode, NodeResponseCode.OK); Assert.AreEqual(timeStamp, mRes.time); Assert.AreEqual(timeStamp, mNode.parentModifiedTime); }).GetAwaiter().GetResult(); }); }
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); }
public void PutTest() { Node node1 = new Node(mSkynet); Node node2 = new Node(mSkynet); Node node3 = new Node(mSkynet); node2.parent = node1.selfNode; node2.parentModifiedTime = Skynet.Utils.Utils.UnixTimeNow(); Task.Run(async() => { ToxResponse response = await RequestProxy.sendRequest(mSkynet, new ToxRequest { uuid = Guid.NewGuid().ToString(), url = "node/" + node3.selfNode.uuid + "/grandParents", content = JsonConvert.SerializeObject(node1.selfNode), method = "put", fromNodeId = node2.selfNode.uuid, fromToxId = node2.selfNode.toxid, toNodeId = node3.selfNode.uuid, toToxId = node3.selfNode.toxid, time = node2.parentModifiedTime }); NodeResponse res = JsonConvert.DeserializeObject <NodeResponse>(response.content); Assert.AreEqual(node1.selfNode.uuid, node3.grandParents.uuid); Assert.AreEqual(node2.parentModifiedTime, node3.grandParentsModifiedTime); }).GetAwaiter().GetResult(); }
public void TestSendMsgToSelf() { Node Node1 = new Node(mSkynet); Node Node2 = new Node(mSkynet); bool status = false; Task.Run(async() => { ToxResponse res = await mSkynet.sendRequest(mSkynet.tox.Id, new ToxRequest { url = "tox/" + mSkynet.tox.Id.ToString(), uuid = Guid.NewGuid().ToString(), method = "get", content = "", fromNodeId = Node1.selfNode.uuid, fromToxId = mSkynet.tox.Id.ToString(), toNodeId = Node2.selfNode.uuid, toToxId = mSkynet.tox.Id.ToString(), }, out status); Console.WriteLine("status: " + status); Assert.AreEqual(true, status); if (status) { NodeResponse nodeRes = JsonConvert.DeserializeObject <NodeResponse>(res.content); Assert.AreEqual(nodeRes.statusCode, NodeResponseCode.OK); } }).GetAwaiter().GetResult(); }
public void TestHandShake() { while (!mSkynet.tox.IsConnected) { Thread.Sleep(10); } Skynet.Base.Skynet mSkynet2 = new Skynet.Base.Skynet(); Node mNode1 = new Node(new List <NodeId>(), mSkynet); Node mNode2 = new Node(new List <NodeId>(), mSkynet2); bool status = false; Task.Run(async() => { ToxResponse res = await mSkynet2.sendRequest(mSkynet.tox.Id, new ToxRequest { url = "tox/" + mSkynet.tox.Id.ToString(), uuid = Guid.NewGuid().ToString(), method = "get", content = "", fromNodeId = mNode2.selfNode.uuid, fromToxId = mNode2.selfNode.toxid, toNodeId = mNode1.selfNode.uuid, toToxId = mNode1.selfNode.toxid, }, out status); Console.WriteLine("status " + status); Assert.AreEqual(status, true); if (status) { NodeResponse nodeRes = JsonConvert.DeserializeObject <NodeResponse>(res.content); Assert.AreEqual(nodeRes.statusCode, NodeResponseCode.OK); } }).GetAwaiter().GetResult(); }
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; })); }
private void newReqReceived(Package receivedPackage) { Utils.Utils.Log("Event: newReqReceived reqId: " + receivedPackage.uuid); byte[] mcontentCache = new byte[receivedPackage.totalSize]; lock (mPackageCacheLock) { if (mPackageCache.ContainsKey(receivedPackage.uuid)) { mcontentCache = mPackageCache[receivedPackage.uuid]; mPackageCache.Remove(receivedPackage.uuid); } } receivedPackage.content.CopyTo(mcontentCache, receivedPackage.startIndex); // check if this is a response lock (mPendingReqLock) { if (mPendingReqList.ContainsKey(receivedPackage.uuid)) { Utils.Utils.Log("Event: newResponse Received reqId: " + receivedPackage.uuid); mPendingReqList[receivedPackage.uuid](ToxResponse.fromBytes(mcontentCache)); mPendingReqList.Remove(receivedPackage.uuid); return; } } ToxRequest newReq = ToxRequest.fromBytes(mcontentCache); if (newReq.method == "") { Console.WriteLine("this happends, this is an ugly hack"); return; } if (newReq == null) { Utils.Utils.Log("Event: Invalid Request Data: receivedPackage " + receivedPackage.uuid); return; } Utils.Utils.Log("Event: Start callbacks reqId: " + newReq.uuid); Utils.Utils.Log("Event: Begin Process MessageID: " + newReq.uuid); if (newReq.url == "/msg") { Utils.Utils.Log("Event: Message toNodeID: " + newReq.toNodeId + ", totoxid:" + newReq.toToxId); } lock (reqListnerLock) { if (reqCallbacks.Keys.Contains(newReq.toNodeId)) { reqCallbacks[newReq.toNodeId](newReq); } } Utils.Utils.Log("Event: End callbacks"); }
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", } }; }
void newReqReceived(Package receivedPackage) { byte[] mcontentCache = new byte[receivedPackage.totalSize]; if (mPackageCache.ContainsKey(receivedPackage.uuid)) { mcontentCache = mPackageCache [receivedPackage.uuid]; mPackageCache.Remove(receivedPackage.uuid); } receivedPackage.content.CopyTo(mcontentCache, receivedPackage.startIndex); // check if this is a response lock (mPendingReqLock) { if (mPendingReqList.ContainsKey(receivedPackage.uuid)) { mPendingReqList [receivedPackage.uuid] (ToxResponse.fromBytes(mcontentCache)); mPendingReqList.Remove(receivedPackage.uuid); return; } } ToxRequest newReq = ToxRequest.fromBytes(mcontentCache); if (newReq == null) { Utils.Utils.LogUtils("Event: Invalid Request Data: receivedPackage " + receivedPackage.uuid); return; } List <Action <ToxRequest> > tempReqList; lock (reqListnerLock) { tempReqList = new List <Action <ToxRequest> > (reqCallbacks); } Utils.Utils.LogUtils("Event: Start callbacks"); foreach (var cb in tempReqList) { Utils.Utils.LogUtils("Event: Begin Process MessageID: " + newReq.uuid); if (newReq.url == "/msg") { Utils.Utils.LogUtils("Event: Message toNodeID: " + newReq.toNodeId + ", totoxid:" + newReq.toToxId); } cb(newReq); } Utils.Utils.LogUtils("Event: End callbacks"); }
public NodeResponse Put(string nodeId, [FromBody] NodeId values) { IEnumerable <string> requestTime = new List <string>(); if (!Request.Headers.TryGetValues("Skynet-Time", out requestTime)) { return(new NodeResponse { statusCode = NodeResponseCode.InvalidRequest, description = "you need to add some http headers" }); } if (!Utils.Utils.isValidGuid(nodeId)) { return(new NodeResponse { statusCode = NodeResponseCode.InvalidRequest, description = "your node id is invalid", }); } Node targetNode = Node.AllLocalNodes.Where(x => x.selfNode.uuid == nodeId).DefaultIfEmpty(null).FirstOrDefault(); if (targetNode == null) { return(new NodeResponse { statusCode = NodeResponseCode.NotFound, description = "target node cannot be found on the client", }); } // check lock if (targetNode.nodeChangeLock.isLocked == true) { // target is locked, cannot be changed at this time return(new NodeResponse { statusCode = NodeResponseCode.TargetLocked, description = "target is locked", }); } else { long reqTime = long.Parse(requestTime.DefaultIfEmpty("0").FirstOrDefault()); if (reqTime < targetNode.brotherModifiedTime) { return(new NodeResponse { statusCode = NodeResponseCode.OutOfDate, description = "Your data is outofdate", }); } targetNode.parentModifiedTime = reqTime; targetNode.parent = values; Task.Run(async() => { // get parent node info, set grandparents Skynet host = Skynet.allInstance.Where(x => x.httpPort == Request.RequestUri.Port).FirstOrDefault(); bool status = false; ToxResponse getParentInfo = await host.sendRequest(new ToxId(values.toxid), new ToxRequest { url = "node/" + values.uuid, method = "get", content = null, fromNodeId = targetNode.selfNode.uuid, fromToxId = targetNode.selfNode.toxid, toNodeId = values.uuid, toToxId = values.toxid, time = Utils.Utils.UnixTimeNow(), uuid = Guid.NewGuid().ToString() }, out status); NodeResponse getParentInfoRes = JsonConvert.DeserializeObject <NodeResponse>(Encoding.UTF8.GetString(getParentInfo.content)); NodeInfo parentInfo = JsonConvert.DeserializeObject <NodeInfo>(getParentInfoRes.value); targetNode.grandParents = parentInfo.parent; targetNode.grandParentsModifiedTime = parentInfo.parentModifiedTime; await BoardCastChanges(targetNode); }); return(new NodeResponse { statusCode = NodeResponseCode.OK, description = "set parent success", value = JsonConvert.SerializeObject(values), time = reqTime, }); } }
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)); }
public bool sendResponse(ToxResponse res, ToxKey toxkey) { return(sendResponse(res, new ToxId(toxkey.GetBytes(), 100))); }
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); } }
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)); }