private void FrameReceivedHandler(object sender, FrameReceivedEventArgs args) { var stream = args.Stream; var method = stream.Headers.GetValue(":method").ToLower(); try { switch (method) { case "dir": case "get": if (args.Frame is DataFrame) { SaveDataFrame(stream, (DataFrame)args.Frame); } else if (args.Frame is HeadersFrame) { Http2Logger.LogConsole("Headers received for stream: " + args.Frame.StreamId + " status:" + ((HeadersFrame)args.Frame).Headers.GetValue(":status")); } break; } } catch (Exception) { stream.WriteRst(ResetStatusCode.InternalError); stream.Dispose(); } }
//Method for future usage in server push private void SendDataTo(Http2Stream stream, byte[] binaryData) { int i = 0; Http2Logger.LogConsole("Transfer begin"); do { bool isLastData = binaryData.Length - i < Constants.MaxDataFrameContentSize; int chunkSize = stream.WindowSize > 0 ? MathEx.Min(binaryData.Length - i, Constants.MaxDataFrameContentSize, stream.WindowSize) : MathEx.Min(binaryData.Length - i, Constants.MaxDataFrameContentSize); var chunk = new byte[chunkSize]; Buffer.BlockCopy(binaryData, i, chunk, 0, chunk.Length); stream.WriteDataFrame(chunk, isLastData); i += chunkSize; } while (binaryData.Length > i); //It was not send exactly. Some of the data frames could be pushed to the unshipped frames collection Http2Logger.LogConsole("File sent: " + stream.Headers.GetValue(":path")); }
public void SendRequestAsync(Uri request, string method, string localPath = null, string serverPostAct = null) { if (!_socket.IsClosed) { if (_host != request.Host || _port != request.Port || _scheme != request.Scheme) { throw new InvalidOperationException("Trying to send request to non connected address"); } if (_useHttp20 == false) { Http2Logger.LogConsole("Download with Http/1.1"); //Download with http11 in another thread. Http11Manager.Http11DownloadResource(_socket, request); return; } //Submit request if http2 was chosen Http2Logger.LogConsole("Submitting request"); //Submit request in the current thread, response will be handled in the session thread. SubmitRequest(request, method, localPath, serverPostAct); } }
private void SaveDataFrame(Http2Stream stream, DataFrame dataFrame) { string originalPath = stream.Headers.GetValue(CommonHeaders.Path.ToLower()); //If user sets the empty file in get command we return notFound webpage string fileName = string.IsNullOrEmpty(Path.GetFileName(originalPath)) ? Index : Path.GetFileName(originalPath); string path = Path.Combine(AssemblyPath, fileName); try { _fileHelper.SaveToFile(dataFrame.Data.Array, dataFrame.Data.Offset, dataFrame.Data.Count, path, stream.ReceivedDataAmount != 0); } catch (IOException) { Http2Logger.LogError("File is still downloading. Repeat request later"); stream.Close(ResetStatusCode.InternalError); return; } stream.ReceivedDataAmount += dataFrame.Data.Count; if (dataFrame.IsEndStream) { if (stream.HalfClosedRemote) { //send terminator stream.WriteDataFrame(new ArraySegment <byte>(new byte[0]), true); Http2Logger.LogConsole("Terminator was sent"); } _fileHelper.RemoveStream(path); Http2Logger.LogConsole("Bytes received: " + stream.ReceivedDataAmount); } }
private void SaveDataFrame(Http2Stream stream, DataFrame dataFrame) { lock (_writeLock) { string originalPath = stream.Headers.GetValue(":path".ToLower()); //If user sets the empty file in get command we return notFound webpage string fileName = string.IsNullOrEmpty(Path.GetFileName(originalPath)) ? NotFound : Path.GetFileName(originalPath); string path = Path.Combine(AssemblyPath, fileName); try { _fileHelper.SaveToFile(dataFrame.Data.Array, dataFrame.Data.Offset, dataFrame.Data.Count, path, stream.ReceivedDataAmount != 0); } catch (IOException) { Http2Logger.LogError("File is still downloading. Repeat request later"); stream.WriteDataFrame(new byte[0], true); stream.Dispose(); } stream.ReceivedDataAmount += dataFrame.FrameLength; if (dataFrame.IsEndStream) { if (!stream.EndStreamSent) { //send terminator stream.WriteDataFrame(new byte[0], true); Http2Logger.LogConsole("Terminator was sent"); } _fileHelper.RemoveStream(path); Http2Logger.LogConsole("Bytes received " + stream.ReceivedDataAmount); #if DEBUG const string wayToServerRoot1 = @"..\..\..\..\..\Drop\Root"; const string wayToServerRoot2 = @".\Root"; var areFilesEqual = _fileHelper.CompareFiles(path, wayToServerRoot1 + originalPath) || _fileHelper.CompareFiles(path, wayToServerRoot2 + originalPath); if (!areFilesEqual) { Console.ForegroundColor = ConsoleColor.Red; Http2Logger.LogError("Files are NOT EQUAL!"); } else { Console.ForegroundColor = ConsoleColor.Green; Http2Logger.LogConsole("Files are EQUAL!"); } Console.ForegroundColor = ConsoleColor.Gray; #endif } } }
public void SendRequestAsync(Uri request, string method) { if (!_sessionAdapter.IsDisposed) { if (_host != request.Host || _port != request.Port || _scheme != request.Scheme) { throw new InvalidOperationException("Trying to send request to non connected address"); } if (!_useHttp20) { Http2Logger.LogConsole("Download with Http/1.1"); } //Submit request in the current thread, response will be handled in the session thread. SubmitRequest(request, method); } }
//localPath should be provided only for post and put cmds //serverPostAct should be provided only for post cmd private void SubmitRequest(Uri request, string method) { //Submit request if http2 was chosen Http2Logger.LogConsole("Submitting request"); var headers = new HeadersList { new KeyValuePair <string, string>(CommonHeaders.Method, method.ToLower()), new KeyValuePair <string, string>(CommonHeaders.Path, request.PathAndQuery.ToLower()), new KeyValuePair <string, string>(CommonHeaders.Authority, _host.ToLower()), new KeyValuePair <string, string>(CommonHeaders.Scheme, _scheme.ToLower()), }; Http2Logger.LogHeaders(headers); //Sending request with default priority _sessionAdapter.SendRequest(headers, Constants.DefaultStreamPriority, true); Http2Logger.LogConsole("Request sent"); }
public static void Main(string[] args) { Console.SetWindowSize(125, 29); Http2Logger.WriteToFile = false; _sessions = new Dictionary <string, Http2SessionHandler>(); _environment = ArgsHelper.GetEnvironment(args); var isTestsEnabled = ConfigurationManager.AppSettings["testModeEnabled"] == "true"; var waitForTestsFinish = new ManualResetEvent(!isTestsEnabled); Console.WriteLine(); Console.WriteLine(); Http2Logger.LogDebug("Tests enabled: " + isTestsEnabled); ThreadPool.SetMaxThreads(10, 10); var uri = ArgsHelper.TryGetUri(args); if (!isTestsEnabled) { HelpDisplayer.ShowMainMenuHelp(); Console.WriteLine("Enter command"); } do { try { Command cmd; string command; if (uri != null) { command = Verbs.Get + " " + uri; //TODO set up method correctly } else { Console.Write(">"); command = Console.ReadLine(); } try { cmd = CommandParser.CommandParser.Parse(command); } catch (Exception ex) { Http2Logger.LogError(ex.Message); continue; } //Scheme and port were checked during parsing get cmd. switch (cmd.GetCmdType()) { case CommandType.Put: case CommandType.Post: case CommandType.Get: case CommandType.Delete: case CommandType.Dir: Http2Logger.LogConsole("Uri command detected"); var uriCmd = (IUriCommand)cmd; string method = uriCmd.Method; //Only unique sessions can be opened if (_sessions.ContainsKey(uriCmd.Uri.Authority)) { Http2Logger.LogConsole("Session already exists"); _sessions[uriCmd.Uri.Authority].SendRequestAsync(uriCmd.Uri, method); break; } Http2Logger.LogConsole("Creating new session"); var sessionHandler = new Http2SessionHandler(_environment); _sessions.Add(uriCmd.Uri.Authority, sessionHandler); sessionHandler.OnClosed += (sender, eventArgs) => { _sessions.Remove(sessionHandler.ServerUri); Http2Logger.LogDebug("Session deleted from collection: " + sessionHandler.ServerUri); waitForTestsFinish.Set(); }; //Get cmd is equivalent for connect -> get. This means, that each get request //will open new session. Console.WriteLine(uriCmd.Uri.ToString()); bool success = sessionHandler.Connect(uriCmd.Uri); if (!success) { Http2Logger.LogError("Connection failed"); break; } if (!sessionHandler.WasHttp1Used) { sessionHandler.StartConnection(); if (sessionHandler.Protocol != SslProtocols.None) { sessionHandler.SendRequestAsync(uriCmd.Uri, method); } } break; case CommandType.Help: ((HelpCommand)cmd).ShowHelp.Invoke(); break; case CommandType.Ping: string url = ((PingCommand)cmd).Uri.Authority; if (_sessions.ContainsKey(url)) { _sessions[url].Ping(); } else { Http2Logger.LogError("Can't ping until session is opened."); } break; case CommandType.Exit: var sessionsDictCopy = new Dictionary <string, Http2SessionHandler>(_sessions); foreach (var sessionUri in sessionsDictCopy.Keys) { sessionsDictCopy[sessionUri].Dispose(false); } sessionsDictCopy.Clear(); return; } } catch (Exception e) { Http2Logger.LogError("Problems occurred - please restart client. Error: " + e.Message); } } while (!isTestsEnabled); waitForTestsFinish.WaitOne(5000); Http2Logger.LogDebug("Exiting"); Console.WriteLine(); Console.WriteLine(); }