private static void RegisterNeighbourContext(HttpListenerContext http_ctx) { Guid otherGuid; string otherHostname; int otherPort; using (var bodyReader = new StreamReader(http_ctx.Request.InputStream, http_ctx.Request.ContentEncoding ?? Encoding.ASCII)) { otherGuid = Guid.Parse(bodyReader.ReadLine()); otherHostname = bodyReader.ReadLine(); otherPort = int.Parse(bodyReader.ReadLine()); } if (nodeGuid.CompareTo(otherGuid) < 0) outgoingNodeConnections[otherGuid] = new NetworkNode { Hostname = otherHostname, Port = otherPort }; else incomingNodeConnections[otherGuid] = new NetworkNode { Hostname = otherHostname, Port = otherPort }; var respBodyString = GetNodeSpecString(http_ctx); var repsBodyData = Encoding.ASCII.GetBytes(respBodyString); http_ctx.Response.StatusCode = (int)HttpStatusCode.OK; http_ctx.Response.ContentType = MediaTypeNames.Text.Plain; http_ctx.Response.ContentEncoding = Encoding.ASCII; http_ctx.Response.Close(repsBodyData, willBlock: false); }
private static async Task ExchangeWithNode(Uri otherNodeUri, byte[] nodeSpecData, string contentType) { var req = WebRequest.Create(new Uri(otherNodeUri, "/registerNeighbour")) as HttpWebRequest; req.Method = WebRequestMethods.Http.Post; req.ContentType = contentType; req.ContentLength = nodeSpecData.Length; using (var reqStream = await req.GetRequestStreamAsync()) { await reqStream.WriteAsync(nodeSpecData, 0, nodeSpecData.Length); await reqStream.FlushAsync(); } Guid otherGuid; string otherHostname; int otherPort; using (var resp = await req.GetResponseAsync() as HttpWebResponse) { var respEncoding = string.IsNullOrWhiteSpace(resp.ContentEncoding) ? Encoding.ASCII : Encoding.GetEncoding(resp.ContentEncoding); using (var respReader = new StreamReader(resp.GetResponseStream(), respEncoding)) { otherGuid = Guid.Parse(await respReader.ReadLineAsync()); otherHostname = await respReader.ReadLineAsync(); otherPort = int.Parse(await respReader.ReadLineAsync()); } } if (nodeGuid.CompareTo(otherGuid) < 0) outgoingNodeConnections[otherGuid] = new NetworkNode { Hostname = otherHostname, Port = otherPort }; else incomingNodeConnections[otherGuid] = new NetworkNode { Hostname = otherHostname, Port = otherPort }; }
private static Task SendLeaderElectionResponse(LeaderElectionState electionState, NetworkNode nodeTuple, bool responseState, bool uniqueState, bool uselessState) { var uriBuilder = new UriBuilder(Uri.UriSchemeHttp, nodeTuple.Hostname, nodeTuple.Port, "/secondYo/Response"); var reqDataString = string.Join(Environment.NewLine, electionState.Guid, electionState.CreationTime.ToString("o"), nodeGuid, responseState, uniqueState, uselessState); var reqDataBytes = Encoding.ASCII.GetBytes(reqDataString); return SendNotificationPostRequestToNode(uriBuilder.Uri, reqDataBytes); }
private static Task SendLeaderElectionAdvertisement(LeaderElectionState electionState, NetworkNode nodeTuple, Guid advertGuid) { var uriBuilder = new UriBuilder(Uri.UriSchemeHttp, nodeTuple.Hostname, nodeTuple.Port, "/firstYo/Advertise"); var reqDataString = string.Join(Environment.NewLine, electionState.Guid, electionState.CreationTime.ToString("o"), nodeGuid, advertGuid); var reqDataBytes = Encoding.ASCII.GetBytes(reqDataString); return SendNotificationPostRequestToNode(uriBuilder.Uri, reqDataBytes); }
private static async Task SendSecondYoFlipNode(NetworkNode nodeTuple) { var uriBuilder = new UriBuilder(Uri.UriSchemeHttp, nodeTuple.Hostname, nodeTuple.Port, "/secondYo/Flip"); var req = WebRequest.Create(uriBuilder.Uri) as HttpWebRequest; req.Method = WebRequestMethods.Http.Post; req.ContentType = new ContentType(MediaTypeNames.Text.Plain) { CharSet = Encoding.ASCII.WebName }.ToString(); var reqDataString = nodeGuid.ToString() + Environment.NewLine; var reqDataBytes = Encoding.ASCII.GetBytes(reqDataString); req.ContentLength = reqDataBytes.LongLength; try { using (var reqStream = await req.GetRequestStreamAsync()) { await reqStream.WriteAsync(reqDataBytes, 0, reqDataBytes.Length); await reqStream.FlushAsync(); } using (var resp = await req.GetResponseAsync()) { } } catch (WebException) { } }
private static async void HandleHttpContext(HttpListener http_listener) { HttpListenerContext http_ctx; try { http_ctx = await http_listener.GetContextAsync(); } catch (Exception) { return; } //nodeStateLock.EnterReadLock(); try { HandleHttpContext(http_listener); var path = http_ctx.Request.Url.AbsolutePath; if (string.Equals("/getCurrentLeader", path, StringComparison.OrdinalIgnoreCase)) { var inNodeKvps = incomingNodeConnections.ToArray(); var outNodeKvps = outgoingNodeConnections.ToArray(); var newElectionState = new LeaderElectionState(inNodeKvps.Where(kvp => !kvp.Value.IsUselessConnection).Select(kvp => kvp.Key), outNodeKvps.Where(kvp => !kvp.Value.IsUselessConnection).Select(kvp => kvp.Key)) { Guid = Guid.NewGuid(), CreationTime = DateTime.Now, FirstYoMinimum = nodeGuid }; leaderElections[newElectionState.Guid] = newElectionState; SendLeaderElectionAdvertisementRequest(newElectionState, new NetworkNode { Hostname = "localhost", Port = portNumber }).Wait(); Guid? currentLeader; do { Task.Delay(42).Wait(); currentLeader = leaderGuid; } while (currentLeader == null); NetworkNode leaderNode; if (currentLeader == nodeGuid) leaderNode = new NetworkNode { Hostname = http_ctx.Request.LocalEndPoint.Address.ToString(), Port = portNumber }; else if (!incomingNodeConnections.TryGetValue(currentLeader.GetValueOrDefault(), out leaderNode)) { http_ctx.Response.StatusCode = (int)HttpStatusCode.NotFound; http_ctx.Response.Close(); } http_ctx.Response.ContentType = MediaTypeNames.Text.Plain; http_ctx.Response.ContentEncoding = Encoding.ASCII; http_ctx.Response.StatusCode = (int)HttpStatusCode.OK; http_ctx.Response.Close(Encoding.ASCII.GetBytes(string.Format("{0}:{1}", leaderNode.Hostname, leaderNode.Port)), willBlock: false); } else if (string.Equals("/getNodes", path, StringComparison.OrdinalIgnoreCase)) { GetNodesContext(http_ctx); } else if (string.Equals("/getNodesWithGuids", path, StringComparison.OrdinalIgnoreCase)) { GetNodesContext(http_ctx, withGuids: true); } else if (string.Equals("/getGuid", path, StringComparison.OrdinalIgnoreCase)) { GetGuidContext(http_ctx); } else if (string.Equals("/connectToNodes", path, StringComparison.OrdinalIgnoreCase)) { await ConnectToNodesContext(http_ctx); } else if (string.Equals("/registerNeighbour", path, StringComparison.OrdinalIgnoreCase)) { RegisterNeighbourContext(http_ctx); } else if (string.Equals("/clearConnections", path, StringComparison.OrdinalIgnoreCase)) { ClearConnectionsContext(http_ctx); } else if (string.Equals("/deregisterNode", path, StringComparison.OrdinalIgnoreCase)) { await DeregisterNodeContext(http_ctx); } else if (string.Equals("/firstYo/Advertise", path, StringComparison.OrdinalIgnoreCase)) { FirstYoAdvertisementContext(http_ctx); } else if (string.Equals("/firstYo/RequestAdvertisement", path, StringComparison.OrdinalIgnoreCase)) { FirstYoRequestAdvertisementContext(http_ctx); } else if (string.Equals("/secondYo/Response", path, StringComparison.OrdinalIgnoreCase)) { SecondYoResponseContext(http_ctx); } else if (string.Equals("/secondYo/Flip", path, StringComparison.OrdinalIgnoreCase)) { SecondYoFlipContext(http_ctx); } else { http_ctx.Response.ContentType = MediaTypeNames.Text.Plain; http_ctx.Response.ContentEncoding = Encoding.ASCII; http_ctx.Response.StatusCode = (int)HttpStatusCode.NotFound; http_ctx.Response.Close(Encoding.ASCII.GetBytes("The requested resource could not be found."), willBlock: false); } } finally { //nodeStateLock.ExitReadLock(); } }