/// <summary> /// レスポンス文字列をパースする /// </summary> public static SSTPResponse Parse(string message) { var headerPattern = new Regex(Message.HeaderPattern); if (message == null) { throw new ArgumentNullException("message"); } // メッセージを改行で分割 var lines = message.Split(new[] { "\r\n" }, StringSplitOptions.None); // 1行目のステータス行が正しければ有効なSSTPレスポンス var matched = Regex.Match(lines[0], @"^(SSTP/[0-9.]+)\s+(\d{1,7})(?:\s+(.+))?"); // 仕様上ステータスコードの桁数には記載がないため、一応7桁まで受け付ける if (matched.Success) { var version = matched.Groups[1].Value; var statusCode = int.Parse(matched.Groups[2].Value); string explanation = null; if (matched.Groups[3].Success) { explanation = matched.Groups[3].Value; } var res = new SSTPResponse(); res.Version = version; res.StatusCode = statusCode; res.StatusExplanation = explanation; // 2行目以降の行をパース var additionalLines = new List <string>(); for (var i = 1; i < lines.Length; i++) { var line = lines[i]; // 空行は読み飛ばす if (line == "") { continue; } // 追加情報として格納 additionalLines.Add(line); } // 追加情報があればセット if (additionalLines.Any()) { res.AdditionalData = string.Join("\r\n", additionalLines); } return(res); } else { throw new BadRequestException(string.Format("有効なSSTPレスポンスではありません。 (コマンド行: {1})", lines[0])); } }
/// <summary> /// SSTPリクエストを送信し、レスポンスを得る /// </summary> /// <param name="req">リクエストオブジェクト</param> /// <remarks> /// khskさんの作成されたソースを参考にしています。 /// https://qiita.com/khsk/items/177741a6c573790a9379 /// </remarks> /// <returns>成功した場合はResponseオブジェクト、失敗した場合はnull</returns> public virtual SSTPResponse SendRequest(SSTPRequest req) { // Charset未指定のリクエストには対応しない if (req.Encoding == null) { new ArgumentException(string.Format("{0} でSSTPリクエストを送信する場合は、リクエストに有効なCharsetを指定する必要があります。", MethodBase.GetCurrentMethod().Name)); } if (DebugLogging) { Debug.WriteLine("[SSTP Request]"); Debug.WriteLine(req.ToString()); } var data = req.Encoding.GetBytes(req.ToString()); using (var client = new TcpClient(ToHost, ToPort)) { using (var ns = client.GetStream()) { ns.ReadTimeout = 10 * 1000; // 読み込みタイムアウト10秒 ns.WriteTimeout = 10 * 1000; // 書き込みタイムアウト10秒 // リクエストを送信する ns.Write(data, 0, data.Length); // リクエスト //サーバーから送られたデータを受信する using (var ms = new System.IO.MemoryStream()) { var resBytes = new byte[256]; var resSize = 0; do { //データの一部を受信する resSize = ns.Read(resBytes, 0, resBytes.Length); //Readが0を返した時はサーバーが切断したと判断 if (resSize == 0) { break; } //受信したデータを蓄積する ms.Write(resBytes, 0, resSize); //まだ読み取れるデータがあるか、データの最後が\nでない時は、受信を続ける } while (ns.DataAvailable || resBytes[resSize - 1] != '\n'); // 受信したデータを文字列に変換 var resMsg = req.Encoding.GetString(ms.GetBuffer(), 0, (int)ms.Length); // 末尾の\0, \nを削除 resMsg = resMsg.TrimEnd('\0').TrimEnd(); if (DebugLogging) { Debug.WriteLine("[SSTP Response]"); Debug.WriteLine(resMsg); } return(SSTPResponse.Parse(resMsg)); } } } }