精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

格物致知-記一次Nodejs源碼分析的經歷

開發 前端
昨天分析http模塊相關的代碼時,遇到了一個晦澀的邏輯,看了想,想了看還是沒看懂。百度、谷歌了很多帖子也沒看到合適的答案。

 [[353532]]

本文轉載自微信公眾號「編程雜技」,作者theanarkh。轉載本文請聯系編程雜技公眾號。 

昨天分析http模塊相關的代碼時,遇到了一個晦澀的邏輯,看了想,想了看還是沒看懂。百度、谷歌了很多帖子也沒看到合適的答案。突然看到一個題目有點相識的搜索結果,點進去是Stack Overflow上的帖子,但是已經404,最后還是通過快照功能成功看到內容。這個帖子[1]和我的疑惑不相關,但是突然給了我一些靈感。沿著這個靈感去看了代碼,最后下載nodejs源碼,加了一些log,編譯了一夜(太久了,等不及編譯完成,得睡覺了)。上午起來驗證,終于揭開了疑惑。這個問題源于下面這段代碼。

  1. function connectionListenerInternal(server, socket) { 
  2.   socket.server = server; 
  3.   // 分配一個http解析器 
  4.   const parser = parsers.alloc(); 
  5.   // 解析請求報文 
  6.   parser.initialize( 
  7.     HTTPParser.REQUEST, 
  8.     new HTTPServerAsyncResource('HTTPINCOMINGMESSAGE', socket), 
  9.     server.maxHeaderSize || 0, 
  10.     server.insecureHTTPParser === undefined ? 
  11.       isLenient() : server.insecureHTTPParser, 
  12.   ); 
  13.   parser.socket = socket; 
  14.   // 開始解析頭部的開始時間 
  15.   parser.parsingHeadersStart = nowDate(); 
  16.   socket.parser = parser; 
  17.   const state = { 
  18.     onData: null
  19.     onEnd: null
  20.     onClose: null
  21.     onDrain: null
  22.     // 同一tcp連接上,請求和響應的的隊列 
  23.     outgoing: [], 
  24.     incoming: [], 
  25.     outgoingData: 0, 
  26.     keepAliveTimeoutSet: false 
  27.   }; 
  28.   state.onData = socketOnData.bind(undefined, server, socket, parser, state); 
  29.   socket.on('data', state.onData); 
  30.  
  31.   if (socket._handle && socket._handle.isStreamBase && 
  32.       !socket._handle._consumed) { 
  33.     parser._consumed = true
  34.     socket._handle._consumed = true
  35.     parser.consume(socket._handle); 
  36.   } 
  37.   parser[kOnExecute] = 
  38.     onParserExecute.bind(undefined, server, socket, parser, state); 
  39.  
  40.   socket._paused = false

這段代碼看起來很多,這是啟動http服務器后,有新的tcp連接建立時執行的回調。問題在于tcp上有數據到來時,是怎么處理的,上面代碼中nodejs監聽了socket的data事件,同時注冊了鉤子kOnExecute。data事件我們都知道是流上有數據到來時觸發的事件。我們看一下socketOnData做了什么事情。

  1. function socketOnData(server, socket, parser, state, d) { 
  2.   // 交給http解析器處理,返回已經解析的字節數 
  3.   const ret = parser.execute(d); 
  4.   onParserExecuteCommon(server, socket, parser, state, ret, d); 

這看起來沒有問題,socket上有數據,然后交給http解析器處理。幾乎所有http模塊源碼解析的文章也是這樣分析的,我第一反應也覺得這個沒問題,那kOnExecute是做什么的呢?kOnExecute鉤子函數的值是onParserExecute,這個看起來也是解析tcp上的數據的,看起來和onSocketData是一樣的作用,難道tcp上的數據有兩個消費者?我們看一下kOnExecute什么時候被回調的。

  1. void OnStreamRead(ssize_t nread, const uv_buf_t& buf) override { 
  2.  
  3.     Local<Value> ret = Execute(buf.base, nread); 
  4.     Local<Value> cb = 
  5.         object()->Get(env()->context(), kOnExecute).ToLocalChecked(); 
  6.     MakeCallback(cb.As<Function>(), 1, &ret); 
  7.   } 

在node_http_parser.cc中的OnStreamRead中被回調,那么OnStreamRead又是什么時候被回調的呢?OnStreamRead是nodejs中c++層流操作的通用函數,當流有數據的時候就會執行該回調。而且OnStreamRead中也會把數據交給http解析器解析。這看起來真的有兩個消費者?這就很奇怪,為什么一份數據會交給http解析器處理兩次?這時候我的想法就是這兩個地方肯定是互斥的。但是我一直沒有找到是哪里做了處理。最后在connectionListenerInternal的一段代碼中找到了答案。

  1. if (socket._handle && socket._handle.isStreamBase && !socket._handle._consumed) { 
  2.     parser._consumed = true
  3.     socket._handle._consumed = true
  4.     parser.consume(socket._handle); 
  5.   } 

因為tcp流是繼承StreamBase類的,所以if成立(后面會具體分析)。我們看一下consume的實現。

  1. static void Consume(const FunctionCallbackInfo<Value>& args) { 
  2.     Parser* parser; 
  3.     ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder()); 
  4.     CHECK(args[0]->IsObject()); 
  5.     StreamBase* stream = StreamBase::FromObjject(args[0].As<Object>()); 
  6.     CHECK_NOT_NULL(stream); 
  7.     stream->PushStreamListener(parser); 
  8.   } 

http解析器把自己注冊為tcp stream的一個listener。這里涉及到了c++層對流的設計。我們從頭開始。看一下PushStreamListener做了什么事情。c++層中,流的操作由類StreamResource進行了封裝。

  1. class StreamResource { 
  2.  public
  3.   virtual ~StreamResource(); 
  4.   virtual int ReadStart() = 0; 
  5.   virtual int ReadStop() = 0; 
  6.   virtual int DoShutdown(ShutdownWrap* req_wrap) = 0; 
  7.   virtual int DoTryWrite(uv_buf_t** bufs, size_t* count); 
  8.   virtual int DoWrite(WriteWrap* w, 
  9.                       uv_buf_t* bufs, 
  10.                       size_t count
  11.                       uv_stream_t* send_handle) = 0; 
  12.   void PushStreamListener(StreamListener* listener); 
  13.   void RemoveStreamListener(StreamListener* listener); 
  14.  
  15.  protected: 
  16.   uv_buf_t EmitAlloc(size_t suggested_size); 
  17.   void EmitRead(ssize_t nread, const uv_buf_t& buf = uv_buf_init(nullptr, 0)); 
  18.  
  19.   StreamListener* listener_ = nullptr; 
  20.   uint64_t bytes_read_ = 0; 
  21.   uint64_t bytes_written_ = 0; 
  22.   friend class StreamListener; 
  23. }; 

我們看到StreamResource是一個基類,定義了操作流的公共方法。其中有一個成員是StreamListener類的實例。我們看看StreamListener的實現。

  1. class StreamListener { 
  2.  public
  3.   virtual ~StreamListener(); 
  4.   virtual uv_buf_t OnStreamAlloc(size_t suggested_size) = 0; 
  5.   virtual void OnStreamRead(ssize_t nread, 
  6.                             const uv_buf_t& buf) = 0; 
  7.   virtual void OnStreamDestroy() {} 
  8.   inline StreamResource* stream() { return stream_; } 
  9.  
  10.  protected: 
  11.   void PassReadErrorToPreviousListener(ssize_t nread); 
  12.  
  13.   StreamResource* stream_ = nullptr; 
  14.   StreamListener* previous_listener_ = nullptr; 
  15.   friend class StreamResource; 
  16. }; 

StreamListener是一個負責消費流數據的類。StreamListener 和StreamResource類的關系如下。

null我們看到一個流可以注冊多個listener,多個listener形成一個鏈表。接著我們看一下創建一個c++層的tcp對象是怎樣的。下面是TCPWrap的繼承關系。

  1. class TCPWrap : public ConnectionWrap<TCPWrap, uv_tcp_t>{} 
  2. class ConnectionWrap : public LibuvStreamWrap{} 
  3. class LibuvStreamWrap : public HandleWrap, public StreamBase{} 
  4. class StreamBase : public StreamResource {} 

我們看到tcp流是繼承于StreamResource的。新建一個tcp的c++的對象時(tcp_wrap.cc),會不斷往上調用父類的構造函數,其中在StreamBase中有一個關鍵的操作。

  1. inline StreamBase::StreamBase(Environment* env) : env_(env) { 
  2.   PushStreamListener(&default_listener_); 
  3.  
  4. EmitToJSStreamListener default_listener_; 

StreamBase會默認給流注冊一個listener。我們看下EmitToJSStreamListener 具體的定義。

  1. class ReportWritesToJSStreamListener : public StreamListener { 
  2.  public
  3.   void OnStreamAfterWrite(WriteWrap* w, int status) override; 
  4.   void OnStreamAfterShutdown(ShutdownWrap* w, int status) override; 
  5.  
  6.  private: 
  7.   void OnStreamAfterReqFinished(StreamReq* req_wrap, int status); 
  8. }; 
  9.  
  10. class EmitToJSStreamListener : public ReportWritesToJSStreamListener { 
  11.  public
  12.   uv_buf_t OnStreamAlloc(size_t suggested_size) override; 
  13.   void OnStreamRead(ssize_t nread, const uv_buf_t& buf) override; 
  14. }; 

EmitToJSStreamListener繼承StreamListener ,定義了分配內存和讀取接收數據的函數。接著我們看一下PushStreamListener做了什么事情。

  1. inline void StreamResource::PushStreamListener(StreamListener* listener) { 
  2.   // 頭插法  
  3.   listener->previous_listener_ = listener_; 
  4.   listener->stream_ = this; 
  5.   listener_ = listener; 

PushStreamListener就是構造出上圖的結構。對應到創建一個c++層的tcp對象中,如下圖。

然后我們看一下對于流來說,讀取數據的整個鏈路。首先是js層調用readStart

  1. function tryReadStart(socket) { 
  2.   socket._handle.reading = true
  3.   const err = socket._handle.readStart(); 
  4.   if (err) 
  5.     socket.destroy(errnoException(err, 'read')); 
  6.  
  7. // 注冊等待讀事件 
  8. Socket.prototype._read = function(n) { 
  9.   tryReadStart(this); 
  10. }; 

我們看看readStart

  1. int LibuvStreamWrap::ReadStart() { 
  2.   return uv_read_start(stream(), [](uv_handle_t* handle, 
  3.                                     size_t suggested_size, 
  4.                                     uv_buf_t* buf) { 
  5.     static_cast<LibuvStreamWrap*>(handle->data)->OnUvAlloc(suggested_size, buf); 
  6.   }, [](uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { 
  7.     static_cast<LibuvStreamWrap*>(stream->data)->OnUvRead(nread, buf); 
  8.   }); 

ReadStart調用libuv的uv_read_start注冊等待可讀事件,并且注冊了兩個回調函數OnUvAlloc和OnUvRead。

  1. void LibuvStreamWrap::OnUvRead(ssize_t nread, const uv_buf_t* buf) { 
  2.    EmitRead(nread, *buf); 
  3.  
  4. inline void StreamResource::EmitRead(ssize_t nread, const uv_buf_t& buf) { 
  5.   // bytes_read_表示已讀的字節數 
  6.   if (nread > 0) 
  7.     bytes_read_ += static_cast<uint64_t>(nread); 
  8.   listener_->OnStreamRead(nread, buf); 

通過層層調用最后會調用listener_的OnStreamRead。我們看看tcp的OnStreamRead

  1. void EmitToJSStreamListener::OnStreamRead(ssize_t nread, const uv_buf_t& buf_) { 
  2.   StreamBase* stream = static_cast<StreamBase*>(stream_); 
  3.   Environment* env = stream->stream_env(); 
  4.   HandleScope handle_scope(env->isolate()); 
  5.   Context::Scope context_scope(env->context()); 
  6.   AllocatedBuffer buf(env, buf_); 
  7.   stream->CallJSOnreadMethod(nread, buf.ToArrayBuffer()); 

繼續回調CallJSOnreadMethod

  1. MaybeLocal<Value> StreamBase::CallJSOnreadMethod(ssize_t nread, 
  2.                                                  Local<ArrayBuffer> ab, 
  3.                                                  size_t offset, 
  4.                                                  StreamBaseJSChecks checks) { 
  5.   Environment* env = env_; 
  6.   // ... 
  7.   AsyncWrap* wrap = GetAsyncWrap(); 
  8.   CHECK_NOT_NULL(wrap); 
  9.   Local<Value> onread = wrap->object()->GetInternalField(kOnReadFunctionField); 
  10.   CHECK(onread->IsFunction()); 
  11.   return wrap->MakeCallback(onread.As<Function>(), arraysize(argv), argv); 

CallJSOnreadMethod會回調js層的onread回調函數。onread會把數據push到流中,然后觸發data事件。這是tcp里默認的數據讀取過程。而文章開頭講到的parser.consume打破了這個默認行為。stream->PushStreamListener(parser);修改了tcp流的listener鏈,http parser把自己作為數據的接收者。所以這時候tcp流上的數據是直接由node_http_parser.cc的OnStreamRead消費的。而不是觸發socket的data事件,最后通過在nodejs源碼中加log,重新編譯驗證的確如文中所述。最后提一個這個過程中還有一個關鍵的地方是調用consume函數的前提是socket._handle.isStreamBase為true。isStreamBase是在StreamBase::AddMethods中定義為true的,而tcp對象創建的過程中,調用了這個方法,所以tcp的isStreamBase是true,才會執行consume,才會執行kOnExecute回調。

References

[1] 帖子: http://cache.baiducontent.com/c?m=rZy2XovtTdJJuXWLM-s8wgpaz8NFubewtolyiC19iAKFJrbGdx2EFnArzlAIDisNP70zWWsCPv-4jwMHTGNcLaUsMVr-lvLqYmmHD-w_fUYz6a5K6OQRC9kZmLYN5RXsb34OdINb8xHIJsdyClaEWOtCGKMQ2saYK7ed7OG8v0E1pRKR4K46phl0rCBrw6amXE3QpPo62dMhvu_VASYYqq&p=cb77c64ad49111a05bee9e264d5693&newp=882a9646dc9712a05ab7cc374f0ccc231615d70e3ad3d501298ffe0cc4241a1a1a3aecbf2d29170ed6c27f630bae4856ecf630723d0834f1f689df08d2ecce7e7b&s=cfcd208495d565ef&user=baidu&fm=sc&query=onParserExecute&qid=869f73bc002e44f5&p1=11

 

責任編輯:武曉燕 來源: 編程雜技
相關推薦

2013-04-01 10:27:37

程序員失業

2013-01-17 10:31:13

JavaScriptWeb開發firebug

2021-01-22 05:35:19

Lvm模塊Multipath

2012-08-28 09:21:59

Ajax查錯經歷Web

2018-12-06 16:25:39

數據庫服務器線程池

2020-02-10 10:15:31

技術研發指標

2021-01-08 13:52:15

Consul微服務服務注冊中心

2023-03-31 09:22:40

Hi3861芯片Flash

2025-03-17 10:01:07

2023-03-29 09:36:32

2021-12-06 19:29:17

LRU內存算法

2014-08-06 11:24:24

Elasticsear劫持掛馬

2011-08-08 13:31:44

數據分析數據倉庫

2016-12-06 09:34:33

線程框架經歷

2011-04-13 09:21:30

死鎖SQL Server

2021-04-13 18:17:48

Hbase集群配置

2023-06-26 00:12:46

2024-12-27 13:31:18

.NETdump調試

2023-04-26 12:48:58

.NET程序類型

2023-04-06 10:52:18

點贊
收藏

51CTO技術棧公眾號

91丝袜呻吟高潮美腿白嫩在线观看| 欧美三级第一页| 在线免费观看日本一区| 日韩美女一区| 国产国语亲子伦亲子| 狠狠色狠狠色综合日日tαg| 日韩精品丝袜在线| 激情 小说 亚洲 图片: 伦| 超鹏97在线| 91麻豆国产福利在线观看| 国产日韩在线视频| 日韩久久久久久久久| 日韩理论电影| 精品国产3级a| www.se五月| 人成在线免费网站| 日韩美女视频一区| 免费精品视频一区二区三区| 精品欧美一区二区精品少妇| 丝袜亚洲另类丝袜在线| 欧美日韩爱爱视频| 免费看的黄色录像| 亚洲精品456| 日韩免费成人网| 亚洲免费av一区| 成人片免费看| 亚洲18女电影在线观看| dy888午夜| jizz在线观看视频| 91麻豆国产精品久久| 国产二区一区| 99在线精品视频免费观看20| 久久精品国产**网站演员| 欧美怡春院一区二区三区| 精品一级少妇久久久久久久| 婷婷综合亚洲| www.日韩视频| 无码少妇一区二区| 精品在线99| 精品在线欧美视频| 欲求不满的岳中文字幕| 9国产精品午夜| 日韩一级片网址| 99九九99九九九99九他书对| www.久久| 欧美怡红院视频| 亚洲一区二区蜜桃| 免费精品一区| 成人精品鲁一区一区二区| 国产精品一区二区在线| 亚洲黄色激情视频| 亚洲黄色一区| 欧美国产日韩在线| 欧美黑吊大战白妞| 欧美一区二区| 国产精品suv一区二区三区| 色天天久久综合婷婷女18| 亚洲午夜国产成人av电影男同| 亚洲麻豆一区二区三区| 999久久精品| 日韩精品一区二区三区四区| 熟妇无码乱子成人精品| 国产精品777777在线播放| 欧美精品国产精品| 午夜剧场高清版免费观看| 亚洲精品tv| 91精品国产综合久久婷婷香蕉 | 欧美午夜精品一区二区| 欧美特黄不卡| 精品国产百合女同互慰| 中文字幕免费高清视频| 天堂99x99es久久精品免费| 日韩av在线一区二区| 免费污网站在线观看| 欧美日韩一区二区三区视频播放| 一区二区三区视频观看| 美国一级片在线观看| 综合激情在线| 国产91成人video| 最好看的日本字幕mv视频大全| 日韩国产在线观看一区| 成人免费高清完整版在线观看| 国产精品一区二区黑人巨大| 国产成人av电影| 久久精品女人的天堂av| 国产乱子伦三级在线播放| 国产精品久久一卡二卡| 欧美黑人在线观看| 免费日韩电影| 51久久夜色精品国产麻豆| 精品人妻二区中文字幕| 亚洲精品亚洲人成在线观看| 中文字幕亚洲一区| 免费视频网站www| 免费在线成人| 成人黄色片在线| 少妇av在线播放| 国产精品萝li| 福利视频一二区| 国产欧美自拍| 亚洲国产高清高潮精品美女| 一级在线观看视频| 亚洲黄色毛片| 国产成人极品视频| 黄色片网站免费在线观看| 国产精品婷婷午夜在线观看| 真人做人试看60分钟免费| 亚洲欧美一区二区三区| 91精品国产黑色紧身裤美女| 波多野结衣办公室33分钟| 中文字幕免费一区二区| 国产成人激情小视频| 成人毛片在线免费观看| 国产精品家庭影院| 青青青在线播放| 成人av综合网| 久久激情视频久久| 久草视频在线免费| 99国产麻豆精品| 日本福利视频在线观看| 欧美成人影院| 亚洲精品97久久| 18岁成人毛片| 美女高潮久久久| 农村寡妇一区二区三区| 欧美高清另类hdvideosexjaⅴ | 国产wwwwwww| 国产精品久久久久久久久久久免费看| 国产一区二区网| 一区二区三区四区精品视频| 久久精品国产清自在天天线| 国产精品熟女视频| www久久久久| 久久久久久久久久久视频| 超碰在线成人| 欧美激情18p| 国产成人精品a视频| 亚洲婷婷综合色高清在线| 在线观看亚洲色图| 青青草原综合久久大伊人精品 | 一区二区www| 亚洲国产精品成人综合| 91激情视频在线| av伊人久久| 国产精品久久久久久久久| 久久精品色图| 色成年激情久久综合| 91欧美激情另类亚洲| 殴美一级黄色片| 日日夜夜精品视频天天综合网| 精品国产91亚洲一区二区三区www 精品国产_亚洲人成在线 | 欧美性资源免费| 丰满人妻av一区二区三区| 97久久中文字幕| 少妇av一区二区三区| 波多野结衣一区二区三区在线 | 国产一级特黄a大片99| 三级网站视频在在线播放| 日韩一区二区电影| 日本熟伦人妇xxxx| 91一区二区在线| 国产真实乱子伦| 精品少妇av| 成人h猎奇视频网站| a黄色片在线观看| 亚洲精品在线三区| 国产视频91在线| 久久精品一区蜜桃臀影院| 杨幂毛片午夜性生毛片| 国产精品国产一区| 97se亚洲综合| 男人久久天堂| 中文字幕最新精品| www黄色在线观看| 亚洲超碰97人人做人人爱| 亚洲av无码一区二区二三区| 日韩精品电影在线观看| 五月天男人天堂| 国产成人一二| 国产精品高清网站| 中文字幕在线观看播放| 亚洲精品国产欧美| 中文字幕人妻精品一区| 夜夜精品浪潮av一区二区三区| 性久久久久久久久久久| 日本系列欧美系列| 欧美亚洲色图视频| 久久av网址| 99一区二区三区| 日韩欧美精品电影| 欧美激情视频三区| 国产系列电影在线播放网址| 欧美一区二区三区视频在线观看| 日韩三级av在线| 中文字幕一区二区三区在线不卡| 亚洲黄色小说在线观看| 日韩电影网1区2区| 国产成a人亚洲精v品在线观看| 一区二区三区日本久久久| 91视频九色网站| 成人看片在线观看| 久久久视频在线| 欧美成人二区| 亚洲欧洲午夜一线一品| 亚洲精品综合网| 欧美天堂一区二区三区| 日韩美女视频网站| 亚洲精品视频在线看| 久久亚洲无码视频| 99这里只有久久精品视频| 中文字幕在线视频一区二区三区 | 午夜激情av在线| 国产日韩欧美一区| 加勒比海盗1在线观看免费国语版| 欧美热在线视频精品999| 成人黄色在线免费观看| 黑人一区二区三区| 日本不卡免费高清视频| 成年人视频免费在线播放| xxxx欧美18另类的高清| 黄色片在线看| 亚洲成人av中文字幕| 国产喷水福利在线视频| 欧美性猛交xxxx乱大交退制版| 精品国产免费观看| 亚洲夂夂婷婷色拍ww47| 极品魔鬼身材女神啪啪精品| 国产日韩欧美在线一区| 美女又爽又黄视频毛茸茸| 成人亚洲精品久久久久软件| 91精产国品一二三产区别沈先生| 日本亚洲欧美天堂免费| 久久久久免费精品| 久久成人在线| 精品99在线视频| 在线亚洲成人| 精品久久久久久久久久中文字幕| 国内精品久久久久久久97牛牛 | 国内外成人在线| 亚洲精品午夜在线观看| 美女网站色91| xxx国产在线观看| 久久国产精品色| 午夜视频在线网站| 久久99国产精品久久99果冻传媒| 9久久婷婷国产综合精品性色 | 欧美体内谢she精2性欧美| 国产一国产二国产三| 亚洲综合色噜噜狠狠| 欧美成人精品激情在线视频| 亚洲色图一区二区| 日本老熟俱乐部h0930| 一区二区三区在线播| 免费又黄又爽又色的视频| 亚洲综合色噜噜狠狠| 日本一二三区不卡| 欧美日韩亚洲精品内裤| 精品国产xxx| 欧美私人免费视频| 国产情侣在线播放| 欧美成人伊人久久综合网| 亚洲乱码精品久久久久..| 精品国产乱码久久久久久1区2区| 色婷婷视频在线| 亚洲欧美日韩一区二区在线 | 欧美综合在线观看视频| 免费久久精品视频| 五月天国产视频| 成人免费看视频| 国产美女精品久久| 国产精品黄色在线观看| 黄色一级片中国| 天天免费综合色| 最近中文字幕在线观看视频| 在线播放国产精品二区一二区四区| 国产三级精品在线观看| 亚洲成人激情视频| 极品美乳网红视频免费在线观看| 成人精品一二区| 亚洲s码欧洲m码国产av| 色综合天天综合狠狠| 少妇大叫太大太粗太爽了a片小说| 天天影视欧美综合在线观看| 成人黄色片免费| 亚洲欧美日韩在线观看a三区| www.色就是色| 国产成人免费视频一区| 少妇按摩一区二区三区| 97成人超碰| 日本中文字幕不卡免费| 91麻豆精品一二三区在线| 风间由美一区二区三区| 男男gay无套免费视频欧美| 中文字幕中文字幕在线中一区高清| 欧美jjzz| 国产熟女高潮视频| 国产精品99精品久久免费| 波多野结衣 在线| 亚洲欧美偷拍三级| 日本韩国欧美中文字幕| 欧美老女人第四色| 无码国产伦一区二区三区视频 | 色视频一区二区| 97人妻一区二区精品免费视频| 亚洲精品999| 成人av福利| 国产精品91免费在线| 日韩欧美中文在线观看| 日韩欧美一区二区三区四区| 欧美天堂亚洲电影院在线观看| 999精品视频在线| 99久久精品国产精品久久| 91视频最新网址| 色呦呦国产精品| 免费观看a视频| 久久久精品一区| 97精品国产99久久久久久免费| 国产精品免费区二区三区观看| 999精品在线| 北条麻妃av高潮尖叫在线观看| 成人黄色综合网站| 超碰手机在线观看| 欧美日韩小视频| 电影av在线| 欧美综合一区第一页| 国产精品白丝一区二区三区| 免费观看国产视频在线| 日本va欧美va精品| 成人性生交大免费看| 精品久久久久久久久久ntr影视| 国产福利视频导航| 久久色免费在线视频| 国产一区二区色噜噜| 欧美午夜精品理论片a级大开眼界 欧美午夜精品久久久久免费视 | 久久国产一级片| 91精品国产综合久久久久久| 在线看免费av| 国产精品色悠悠| 欧美日韩在线二区| www.日本xxxx| 国产欧美一区二区精品性色| jizz国产在线观看| 国产丝袜一区二区三区| 理论不卡电影大全神| 久久精品国产综合精品| 免费一级欧美片在线播放| 一二三不卡视频| 一本到不卡免费一区二区| 免费av在线电影| 国产成人极品视频| 精品香蕉视频| 男人的天堂最新网址| 亚洲欧洲精品一区二区三区不卡| 一级黄色片免费| xxxxx成人.com| 欧州一区二区三区| www.夜夜爱| 91麻豆福利精品推荐| 亚洲精品中文字幕乱码三区91| 亚洲精品一区在线观看香蕉 | 91色视频在线观看| 欧美日本一区| 中国免费黄色片| 欧美性色xo影院| 成人动漫在线免费观看| 91精品久久久久久久久久久久久久| 忘忧草精品久久久久久久高清| www.亚洲自拍| 夜夜嗨av一区二区三区四季av| 黄色一级大片在线免费看国产| 91国内揄拍国内精品对白| 欧美人妖在线| 久国产精品视频| 亚洲午夜电影网| 韩日视频在线| 91久久久久久久久久久久久| 午夜精品剧场| 野花社区视频在线观看| 欧美在线高清视频| 在线中文字幕电影| 麻豆av福利av久久av| 免费观看成人av| 久久国产免费观看| 亚洲视频一区二区三区| 亚洲男女网站| 欧美变态另类刺激| 国产精品久久久一区麻豆最新章节| 国产成人久久精品77777综合| 57pao成人永久免费视频| 日韩视频在线观看| 95视频在线观看| 欧美影院午夜播放| hd国产人妖ts另类视频| 亚州欧美一区三区三区在线| 国产高清精品久久久久| 成人一二三四区| 久久理论片午夜琪琪电影网| 精品久久影院| 午夜视频在线观看国产| 欧美日韩国产成人在线免费|