//キャッシュ確認 public void CacheWrite(Cache cache) { if (!_isCacheTarget)//キャッシュ対象外 { return; } if (_response.Code != 200)//レスポンスコードが200のものだけが対象 { return; } //Ver5.6.1 if (!_oneObj.Body[CS.Server].CanUse) { return; } var oneCache = new OneCache(_oneObj.Request.HostName, _oneObj.Request.Port, _oneObj.Request.Uri); oneCache.Add(_oneObj.Header[CS.Server], _oneObj.Body[CS.Server].Get()); cache.Add(oneCache); }
//キャッシュ確認 public void CacheWrite(Cache cache) { if (!_isCacheTarget)//キャッシュ対象外 return; if (_response.Code != 200)//レスポンスコードが200のものだけが対象 return; //Ver5.6.1 if (!_oneObj.Body[CS.Server].CanUse) return; var oneCache = new OneCache(_oneObj.Request.HostName, _oneObj.Request.Port, _oneObj.Request.Uri); oneCache.Add(_oneObj.Header[CS.Server], _oneObj.Body[CS.Server].Get()); cache.Add(oneCache); }
//*************************************************************** // パイプ(HTTP/SSL) //*************************************************************** void PipeHttp(Dictionary <CS, TcpObj> sock, Dictionary <CS, byte[]> buf, Request request, Dictionary <CS, Header> header, OneCache oneCache) { Response response = new Response();//サーバからのレスポンスを処理するクラス //*************************************************************** // パイプ //*************************************************************** bool serverHeda = false; if (request.Protocol == PROXY_PROTOCOL.HTTP) { serverHeda = true; //ヘッダ受信するのはHTTPの時だけ } bool isText = false; //コンテンツ制限の対象かどうかのフラグ CHARSET charset = CHARSET.UNKNOWN; long contentLength = 0; //サーバのヘッダで示される受信データのサイズ long sendLength = 0; //クライアント側へ送信完了したデータのサイズ long timeoutCounter = 0; //タイムアウトカウンタ CS cs = CS.SERVER; while (life) { Thread.Sleep(0); cs = Reverse(cs);//サーバ側とクライアント側を交互に処理する //Thread.Sleep(0);//Ver5.0.0-a19 // クライアントの切断の確認 if (sock[CS.CLIENT].State != SOCKET_OBJ_STATE.CONNECT) { if (buf[CS.SERVER].Length == 0) { cache.Add(oneCache); } //クライアントが切断された場合は、処理を継続する意味が無い this.Logger.Set(LOG_KIND.DETAIL, null, 8, "close client"); break; } //******************************************************* //処理するデータが到着していない場合の処理 //******************************************************* if (sock[CS.CLIENT].Length() == 0 && sock[CS.SERVER].Length() == 0 && buf[CS.CLIENT].Length == 0 && buf[CS.SERVER].Length == 0) { // サーバの切断の確認 if (sock[CS.SERVER].State != SOCKET_OBJ_STATE.CONNECT) { cache.Add(oneCache); //送信するべきデータがなく、サーバが切断された場合は、処理終了 this.Logger.Set(LOG_KIND.DETAIL, null, 8, "close server"); break; } //Ver5.0.0-a3 HTTP/1.1対応(次のリクエスト待ちへ進む) if (!serverHeda) { int x = 10; } //Ver5.0.0-a11 //if (response.Code != 0 && <response.Code != 200) { if (response.Code != 0 && (response.Code < 200 && 300 <= response.Code)) { //見切り切断 this.Logger.Set(LOG_KIND.DETAIL, sock[CS.SERVER], 8, string.Format("Response Code = {0}", response.Code)); break; } //Thread.Sleep(50); Thread.Sleep(1);//Ver5.0.0-a19 //タイムアウトカウンタのインクリメント timeoutCounter++; //if(timeoutCounter*50>timeout*1000){ if (timeoutCounter > timeout * 1000) { //タイムアウト this.Logger.Set(LOG_KIND.NOMAL, sock[CS.SERVER], 3, string.Format("option TIMEOUT={0}sec", timeout)); break; } } else { timeoutCounter = 0;//タイムアウトカウンタのリセット } //******************************************************* // 受信処理 //******************************************************* if (buf[cs].Length == 0) //バッファが空の時だけ処理する { if (!serverHeda && cs == CS.CLIENT && buf[CS.SERVER].Length == 0) //次のリクエスト { int x = 10; } if (cs == CS.SERVER && serverHeda) // HTTPのヘッダ受信 { while (life && sock[CS.SERVER].State == SOCKET_OBJ_STATE.CONNECT && sock[CS.CLIENT].State == SOCKET_OBJ_STATE.CONNECT && sock[CS.SERVER].Length() == 0) { Thread.Sleep(30); } //レスポンスの取得 if (!response.Recv(this.Logger, sock[CS.SERVER], timeout, ref life)) { this.Logger.Set(LOG_KIND.ERROR, sock[CS.SERVER], 6, ""); break; } if (oneCache != null) { if (response.Code != 200) //200以外は、キャッシュ保存の対象にならないので無効化する //this.Logger.Set(LOG_KIND.DEBUG, 222, string.Format("response code [{0}]", response.Code)); { oneCache = null; } } //ヘッダの受信 v2.1.6 すべてのレスポンスをConnectint: close にして、リクエストの抜けを排除する HTTP/1.1でも擬似的に使用できるようになる if (!header[cs].Recv(sock[cs], timeout, ref life)) { this.Logger.Set(LOG_KIND.ERROR, sock[CS.SERVER], 7, ""); break; } //Ver5.0.0-a22 //サーバからのヘッダにno-cacheが指定されている場合も、キャッシュ対象からはずす string headerStr = header[cs].ToString(); if (headerStr.ToLower().IndexOf("no-cache") >= 0) { this.Logger.Set(LOG_KIND.DETAIL, null, 16, request.Uri); cache.Remove(request.HostName, request.Port, request.Uri);//存在する場合は、無効化する oneCache = null; } if (oneCache != null) { oneCache.Add(header[CS.SERVER]); } //サーバから受信したレスポンス及びヘッダをバッファに展開する buf[cs] = Bytes.Create(response.ToString(), "\r\n", header[cs].GetBytes()); serverHeda = false;//ヘッダ処理終了 string str = header[CS.SERVER].GetVal("Content-Length"); if (str != null) { contentLength = Convert.ToInt32(str); //Ver5.0.0-a19 //クライアントに送信するのは、本体+ヘッダとなるので contentLength += buf[cs].Length; } //コンテンツ制限の対象かどうかのフラグを設定する if (limitString != null)//コンテンツ制限に文字列が設定されている場合 { string contentType = header[CS.SERVER].GetVal("Content-Type"); if (contentType != null) { if (contentType.ToLower().IndexOf("text/h") == 0) { isText = true; } if (contentType.ToLower().IndexOf("text/t") == 0) { isText = true; } } } } else { //処理すべきデータ数の取得 int len = sock[cs].Length(); byte[] b = sock[cs].Recv(len, timeout); if (b != null) { if (cs == CS.CLIENT) { string s = Encoding.ASCII.GetString(b); int x = 10; } buf[cs] = Bytes.Create(buf[cs], b); //logger.Set(LOG_KIND.DEBUG, 0, string.Format("cs={0} Recv()={1}", cs, b.Length)); if (cs == CS.SERVER) { if (oneCache != null) { oneCache.Add(b);//キャッシュ } //コンテンツ制限 if (isText) { if (charset == CHARSET.UNKNOWN) { string s = Encoding.ASCII.GetString(b); int index = s.ToLower().IndexOf("charset"); if (0 <= index) { s = s.Substring(index + 8); if (s.ToLower().IndexOf("x-sjis") >= 0) { charset = CHARSET.SJIS; } else if (s.ToLower().IndexOf("shift_jis") >= 0) { charset = CHARSET.SJIS; } else if (s.ToLower().IndexOf("x-euc-jp") >= 0) { charset = CHARSET.EUC; } else if (s.ToLower().IndexOf("euc-jp") >= 0) { charset = CHARSET.EUC; } else if (s.ToLower().IndexOf("utf-8") >= 0) { charset = CHARSET.UTF8; } else if (s.ToLower().IndexOf("utf-7") >= 0) { charset = CHARSET.UTF7; } else if (s.ToLower().IndexOf("iso-2022-jp") >= 0) { charset = CHARSET.JIS; } else { //int k = 0; } } } string str = ""; switch (charset) { case CHARSET.ASCII: str = Encoding.ASCII.GetString(b); break; case CHARSET.SJIS: str = Encoding.GetEncoding("shift-jis").GetString(b); break; case CHARSET.EUC: str = Encoding.GetEncoding("euc-jp").GetString(b); break; case CHARSET.JIS: str = Encoding.GetEncoding(50222).GetString(b); break; case CHARSET.UTF8: str = Encoding.UTF8.GetString(b); break; case CHARSET.UTF7: str = Encoding.UTF7.GetString(b); break; case CHARSET.UNKNOWN: str = Encoding.ASCII.GetString(b); break; } //コンテンツ制限 string hitStr = limitString.IsHit(str); if (hitStr != null) { //制限にヒットした場合 this.Logger.Set(LOG_KIND.NOMAL, sock[CS.SERVER], 21, hitStr); break; } } } } } } //******************************************************* // 送信処理 //******************************************************* if (buf[cs].Length != 0) //バッファにデータが入っている場合だけ処理する { int c = 0; c = sock[Reverse(cs)].Send(buf[cs]); if (cs == CS.SERVER) //サーバ側から受信したデータをクライアント側に送信した分だけカウントする { if (contentLength != 0) { sendLength += c; //クライアント側への送信完了時に確認する //受信データサイズのすべてがクライアントへ送信完了したとき切断する if (contentLength <= sendLength) { cache.Add(oneCache); this.Logger.Set(LOG_KIND.DETAIL, sock[CS.SERVER], 8, "compleate"); break; } } } //logger.Set(LOG_KIND.DEBUG, 0, string.Format("cs={0} Send()={1}", Reverse(cs), c)); if (c == buf[cs].Length) { buf[cs] = new byte[0]; //クライアント側への送信完了時に確認する //if(cs==CS.SERVER){ // //受信データサイズのすべてがクライアントへ送信完了したとき切断する // if (contentLength != 0 && contentLength <= sendLength) { // cache.Add(oneCache); // this.Logger.Set(LOG_KIND.DETAIL,sock[CS.SERVER],8,"compleate"); // break; // } //} } else { this.Logger.Set(LOG_KIND.ERROR, sock[CS.SERVER], 9, string.Format("sock.Send() return {0}", c)); break; } } } }