亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 網站 > Nginx > 正文

詳解Nginx的核心配置模塊中對于請求體的接受流程

2024-08-30 12:27:51
字體:
來源:轉載
供稿:網友
這篇文章主要介紹了詳解Nginx的核心配置模塊中對于請求體的接受流程,包括其丟棄請求的過程,需要的朋友可以參考下
 

本篇文章主要會介紹nginx中請求的接收流程,包括請求頭的解析和請求體的讀取流程。


首先介紹一下rfc2616中定義的http請求基本格式:

Request = Request-Line     *(( general-header            | request-header            | entity-header ) CRLF)       CRLF      [ message-body ]  </span> 

 

第一行是請求行(request line),用來說明請求方法,要訪問的資源以及所使用的HTTP版本:
Request-Line   = Method SP Request-URI SP HTTP-Version CRLF</span> 

請求方法(Method)的定義如下,其中最常用的是GET,POST方法:

Method = "OPTIONS"  | "GET"  | "HEAD"  | "POST"  | "PUT"  | "DELETE"  | "TRACE"  | "CONNECT"  | extension-method  extension-method = token

要訪問的資源由統一資源地位符URI(Uniform Resource Identifier)確定,它的一個比較通用的組成格式(rfc2396)如下:

<scheme>://<authority><path>?<query> 

一般來說根據請求方法(Method)的不同,請求URI的格式會有所不同,通常只需寫出path和query部分。

http版本(version)定義如下,現在用的一般為1.0和1.1版本:

HTTP/<major>.<minor> 


請求行的下一行則是請求頭,rfc2616中定義了3種不同類型的請求頭,分別為general-header,request-header和entity-header,每種類型rfc中都定義了一些通用的頭,其中entity-header類型可以包含自定義的頭。


現在開始介紹nginx中請求頭的解析,nginx的請求處理流程中,會涉及到2個非常重要的數據結構,ngx_connection_t和ngx_http_request_t,分別用來表示連接和請求,這2個數據結構在本書的前篇中已經做了比較詳細的介紹,沒有印象的讀者可以翻回去復習一下,整個請求處理流程從頭到尾,對應著這2個數據結構的分配,初始化,使用,重用和銷毀。


nginx在初始化階段,具體是在init process階段的ngx_event_process_init函數中會為每一個監聽套接字分配一個連接結構(ngx_connection_t),并將該連接結構的讀事件成員(read)的事件處理函數設置為ngx_event_accept,并且如果沒有使用accept互斥鎖的話,在這個函數中會將該讀事件掛載到nginx的事件處理模型上(poll或者epoll等),反之則會等到init process階段結束,在工作進程的事件處理循環中,某個進程搶到了accept鎖才能掛載該讀事件。

static ngx_int_t ngx_event_process_init(ngx_cycle_t *cycle) {   ...     /* 初始化用來管理所有定時器的紅黑樹 */   if (ngx_event_timer_init(cycle->log) == NGX_ERROR) {     return NGX_ERROR;   }   /* 初始化事件模型 */   for (m = 0; ngx_modules[m]; m++) {     if (ngx_modules[m]->type != NGX_EVENT_MODULE) {       continue;     }       if (ngx_modules[m]->ctx_index != ecf->use) {       continue;     }       module = ngx_modules[m]->ctx;       if (module->actions.init(cycle, ngx_timer_resolution) != NGX_OK) {       /* fatal */       exit(2);     }       break;   }     ...     /* for each listening socket */   /* 為每個監聽套接字分配一個連接結構 */   ls = cycle->listening.elts;   for (i = 0; i < cycle->listening.nelts; i++) {       c = ngx_get_connection(ls[i].fd, cycle->log);       if (c == NULL) {       return NGX_ERROR;     }       c->log = &ls[i].log;       c->listening = &ls[i];     ls[i].connection = c;       rev = c->read;       rev->log = c->log;     /* 標識此讀事件為新請求連接事件 */     rev->accept = 1;       ...   #if (NGX_WIN32)       /* windows環境下不做分析,但原理類似 */   #else     /* 將讀事件結構的處理函數設置為ngx_event_accept */     rev->handler = ngx_event_accept;     /* 如果使用accept鎖的話,要在后面搶到鎖才能將監聽句柄掛載上事件處理模型上 */     if (ngx_use_accept_mutex) {       continue;     }     /* 否則,將該監聽句柄直接掛載上事件處理模型 */     if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {       if (ngx_add_conn(c) == NGX_ERROR) {         return NGX_ERROR;       }       } else {       if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {         return NGX_ERROR;       }     }   #endif     }     return NGX_OK; }

當一個工作進程在某個時刻將監聽事件掛載上事件處理模型之后,nginx就可以正式的接收并處理客戶端過來的請求了。這時如果有一個用戶在瀏覽器的地址欄內輸入一個域名,并且域名解析服務器將該域名解析到一臺由nginx監聽的服務器上,nginx的事件處理模型接收到這個讀事件之后,會速度交由之前注冊好的事件處理函數ngx_event_accept來處理。


在ngx_event_accept函數中,nginx調用accept函數,從已連接隊列得到一個連接以及對應的套接字,接著分配一個連接結構(ngx_connection_t),并將新得到的套接字保存在該連接結構中,這里還會做一些基本的連接初始化工作:
首先給該連接分配一個內存池,初始大小默認為256字節,可通過connection_pool_size指令設置;
分配日志結構,并保存在其中,以便后續的日志系統使用;
初始化連接相應的io收發函數,具體的io收發函數和使用的事件模型及操作系統相關;
分配一個套接口地址(sockaddr),并將accept得到的對端地址拷貝在其中,保存在sockaddr字段;
將本地套接口地址保存在local_sockaddr字段,因為這個值是從監聽結構ngx_listening_t中可得,而監聽結構中保存的只是配置文件中設置的監聽地址,但是配置的監聽地址可能是通配符*,即監聽在所有的地址上,所以連接中保存的這個值最終可能還會變動,會被確定為真正的接收地址;
將連接的寫事件設置為已就緒,即設置ready為1,nginx默認連接第一次為可寫;
如果監聽套接字設置了TCP_DEFER_ACCEPT屬性,則表示該連接上已經有數據包過來,于是設置讀事件為就緒;
將sockaddr字段保存的對端地址格式化為可讀字符串,并保存在addr_text字段;
最后調用ngx_http_init_connection函數初始化該連接結構的其他部分。


ngx_http_init_connection函數最重要的工作是初始化讀寫事件的處理函數:將該連接結構的寫事件的處理函數設置為ngx_http_empty_handler,這個事件處理函數不會做任何操作,實際上nginx默認連接第一次可寫,不會掛載寫事件,如果有數據需要發送,nginx會直接寫到這個連接,只有在發生一次寫不完的情況下,才會掛載寫事件到事件模型上,并設置真正的寫事件處理函數,這里后面的章節還會做詳細介紹;讀事件的處理函數設置為ngx_http_init_request,此時如果該連接上已經有數據過來(設置了deferred accept),則會直接調用ngx_http_init_request函數來處理該請求,反之則設置一個定時器并在事件處理模型上掛載一個讀事件,等待數據到來或者超時。當然這里不管是已經有數據到來,或者需要等待數據到來,又或者等待超時,最終都會進入讀事件的處理函數-ngx_http_init_request。
 

ngx_http_init_request函數主要工作即是初始化請求,由于它是一個事件處理函數,它只有唯一一個ngx_event_t *類型的參數,ngx_event_t 結構在nginx中表示一個事件,事件處理的上下文類似于一個中斷處理的上下文,為了在這個上下文得到相關的信息,nginx中一般會將連接結構的引用保存在事件結構的data字段,請求結構的引用則保存在連接結構的data字段,這樣在事件處理函數中可以方便的得到對應的連接結構和請求結構。進入函數內部看一下,首先判斷該事件是否是超時事件,如果是的話直接關閉連接并返回;反之則是指之前accept的連接上有請求過來需要處理,ngx_http_init_request函數首先在連接的內存池中為該請求分配一個ngx_http_request_t結構,這個結構將用來保存該請求所有的信息。分配完之后,這個結構的引用會被包存在連接的hc成員的request字段,以便于在長連接或pipelined請求中復用該請求結構。在這個函數中,nginx根據該請求的接收端口和地址找到一個默認虛擬服務器配置(listen指令的default_server屬性用來標識一個默認虛擬服務器,否則監聽在相同端口和地址的多個虛擬服務器,其中第一個定義的則為默認),因為在nginx配置文件中可以設置多個監聽在不同端口和地址的虛擬服務器(每個server塊對應一個虛擬服務器),另外還根據域名(server_name指令可以配置該虛擬服務器對應的域名)來區分監聽在相同端口和地址的虛擬服務器,每個虛擬服務器可以擁有不同的配置內容,而這些配置內容決定了nginx在接收到一個請求之后如何處理該請求。找到之后,相應的配置被保存在該請求對應的ngx_http_request_t結構中。注意這里根據端口和地址找到的默認配置只是臨時使用一下,最終nginx會根據域名找到真正的虛擬服務器配置,隨后的初始化工作還包括:

將連接的讀事件的處理函數設置為ngx_http_process_request_line函數,這個函數用來解析請求行,將請求的read_event_handler設置為ngx_http_block_reading函數,這個函數實際上什么都不做(當然在事件模型設置為水平觸發時,唯一做的事情就是將事件從事件模型監聽列表中刪除,防止該事件一直被觸發),后面會說到這里為什么會將read_event_handler設置為此函數;
為這個請求分配一個緩沖區用來保存它的請求頭,地址保存在header_in字段,默認大小為1024個字節,可以使用client_header_buffer_size指令修改,這里需要注意一下,nginx用來保存請求頭的緩沖區是在該請求所在連接的內存池中分配,而且會將地址保存一份在連接的buffer字段中,這樣做的目的也是為了給該連接的下一次請求重用這個緩沖區,另外如果客戶端發過來的請求頭大于1024個字節,nginx會重新分配更大的緩存區,默認用于大請求的頭的緩沖區最大為8K,最多4個,這2個值可以用large_client_header_buffers指令設置,后面還會說到請求行和一個請求頭都不能超過一個最大緩沖區的大??;
同樣的nginx會為這個請求分配一個內存池,后續所有與該請求相關的內存分配一般都會使用該內存池,默認大小為4096個字節,可以使用request_pool_size指令修改;
為這個請求分配響應頭鏈表,初始大小為20;
創建所有模塊的上下文ctx指針數組,變量數據;
將該請求的main字段設置為它本身,表示這是一個主請求,nginx中對應的還有子請求概念,后面的章節會做詳細的介紹;
將該請求的count字段設置為1,count字段表示請求的引用計數;
將當前時間保持在start_sec和start_msec字段,這個時間是該請求的起始時刻,將被用來計算一個請求的處理時間(request time),nginx使用的這個起始點和apache略有差別,nginx中請求的起始點是接收到客戶端的第一個數據包開始,而apache則是接收到客戶端的整個request line后開始算起;
初始化請求的其他字段,比如將uri_changes設置為11,表示最多可以將該請求的uri改寫10次,subrequests被設置為201,表示一個請求最多可以發起200個子請求;
做完所有這些初始化工作之后,ngx_http_init_request函數會調用讀事件的處理函數來真正的解析客戶端發過來的數據,也就是會進入ngx_http_process_request_line函數中處理。


ngx_http_process_request_line函數的主要作用即是解析請求行,同樣由于涉及到網絡IO操作,即使是很短的一行請求行可能也不能被一次讀完,所以在之前的ngx_http_init_request函數中,ngx_http_process_request_line函數被設置為讀事件的處理函數,它也只擁有一個唯一的ngx_event_t *類型參數,并且在函數的開頭,同樣需要判斷是否是超時事件,如果是的話,則關閉這個請求和連接;否則開始正常的解析流程。先調用ngx_http_read_request_header函數讀取數據。


由于可能多次進入ngx_http_process_request_line函數,ngx_http_read_request_header函數首先檢查請求的header_in指向的緩沖區內是否有數據,有的話直接返回;否則從連接讀取數據并保存在請求的header_in指向的緩存區,而且只要緩沖區有空間的話,會一次盡可能多的讀數據,讀到多少返回多少;如果客戶端暫時沒有發任何數據過來,并返回NGX_AGAIN,返回之前會做2件事情:1,設置一個定時器,時長默認為60s,可以通過指令client_header_timeout設置,如果定時事件到達之前沒有任何可讀事件,nginx將會關閉此請求;2,調用ngx_handle_read_event函數處理一下讀事件-如果該連接尚未在事件處理模型上掛載讀事件,則將其掛載上;如果客戶端提前關閉了連接或者讀取數據發生了其他錯誤,則給客戶端返回一個400錯誤(當然這里并不保證客戶端能夠接收到響應數據,因為客戶端可能都已經關閉了連接),最后函數返回NGX_ERROR;


如果ngx_http_read_request_header函數正常的讀取到了數據,ngx_http_process_request_line函數將調用ngx_http_parse_request_line函數來解析,這個函數根據http協議規范中對請求行的定義實現了一個有限狀態機,經過這個狀態機,nginx會記錄請求行中的請求方法(Method),請求uri以及http協議版本在緩沖區中的起始位置,在解析過程中還會記錄一些其他有用的信息,以便后面的處理過程中使用。如果解析請求行的過程中沒有產生任何問題,該函數會返回NGX_OK;如果請求行不滿足協議規范,該函數會立即終止解析過程,并返回相應錯誤號;如果緩沖區數據不夠,該函數返回NGX_AGAIN。在整個解析http請求的狀態機中始終遵循著兩條重要的原則:減少內存拷貝和回溯。內存拷貝是一個相對比較昂貴的操作,大量的內存拷貝會帶來較低的運行時效率。nginx在需要做內存拷貝的地方盡量只拷貝內存的起始和結束地址而不是內存本身,這樣做的話僅僅只需要兩個賦值操作而已,大大降低了開銷,當然這樣帶來的影響是后續的操作不能修改內存本身,如果修改的話,會影響到所有引用到該內存區間的地方,所以必須很小心的管理,必要的時候需要拷貝一份。這里不得不提到nginx中最能體現這一思想的數據結構,ngx_buf_t,它用來表示nginx中的緩存,在很多情況下,只需要將一塊內存的起始地址和結束地址分別保存在它的pos和last成員中,再將它的memory標志置1,即可表示一塊不能修改的內存區間,在另外的需要一塊能夠修改的緩存的情形中,則必須分配一塊所需大小的內存并保存其起始地址,再將ngx_bug_t的temprary標志置1,表示這是一塊能夠被修改的內存區域。


再回到ngx_http_process_request_line函數中,如果ngx_http_parse_request_line函數返回了錯誤,則直接給客戶端返回400錯誤;
如果返回NGX_AGAIN,則需要判斷一下是否是由于緩沖區空間不夠,還是已讀數據不夠。如果是緩沖區大小不夠了,nginx會調用ngx_http_alloc_large_header_buffer函數來分配另一塊大緩沖區,如果大緩沖區還不夠裝下整個請求行,nginx則會返回414錯誤給客戶端,否則分配了更大的緩沖區并拷貝之前的數據之后,繼續調用ngx_http_read_request_header函數讀取數據來進入請求行自動機處理,直到請求行解析結束;
如果返回了NGX_OK,則表示請求行被正確的解析出來了,這時先記錄好請求行的起始地址以及長度,并將請求uri的path和參數部分保存在請求結構的uri字段,請求方法起始位置和長度保存在method_name字段,http版本起始位置和長度記錄在http_protocol字段。還要從uri中解析出參數以及請求資源的拓展名,分別保存在args和exten字段。

丟棄請求體

一個模塊想要主動的丟棄客戶端發過的請求體,可以調用nginx核心提供的ngx_http_discard_request_body()接口,主動丟棄的原因可能有很多種,如模塊的業務邏輯壓根不需要請求體 ,客戶端發送了過大的請求體,另外為了兼容http1.1協議的pipeline請求,模塊有義務主動丟棄不需要的請求體??傊疄榱吮3至己玫目蛻舳思嫒菪?,nginx必須主動丟棄無用的請求體。下面開始分析ngx_http_discard_request_body()函數:

ngx_int_t ngx_http_discard_request_body(ngx_http_request_t *r) {   ssize_t    size;   ngx_event_t *rev;    if (r != r->main || r->discard_body) {     return NGX_OK;   }    if (ngx_http_test_expect(r) != NGX_OK) {     return NGX_HTTP_INTERNAL_SERVER_ERROR;   }    rev = r->connection->read;    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http set discard body");    if (rev->timer_set) {     ngx_del_timer(rev);   }    if (r->headers_in.content_length_n <= 0 || r->request_body) {     return NGX_OK;   }    size = r->header_in->last - r->header_in->pos;    if (size) {     if (r->headers_in.content_length_n > size) {       r->header_in->pos += size;       r->headers_in.content_length_n -= size;      } else {       r->header_in->pos += (size_t) r->headers_in.content_length_n;       r->headers_in.content_length_n = 0;       return NGX_OK;     }   }    r->read_event_handler = ngx_http_discarded_request_body_handler;    if (ngx_handle_read_event(rev, 0) != NGX_OK) {     return NGX_HTTP_INTERNAL_SERVER_ERROR;   }    if (ngx_http_read_discarded_request_body(r) == NGX_OK) {     r->lingering_close = 0;    } else {     r->count++;     r->discard_body = 1;   }    return NGX_OK; } 

由于函數不長,這里把它完整的列出來了,函數的開始同樣先判斷了不需要再做處理的情況:子請求不需要處理,已經調用過此函數的也不需要再處理。接著調用ngx_http_test_expect() 處理http1.1 expect的情況,根據http1.1的expect機制,如果客戶端發送了expect頭,而服務端不希望接收請求體時,必須返回417(Expectation Failed)錯誤。nginx并沒有這樣做,它只是簡單的讓客戶端把請求體發送過來,然后丟棄掉。接下來,函數刪掉了讀事件上的定時器,因為這時本身就不需要請求體,所以也無所謂客戶端發送的快還是慢了,當然后面還會將到,當nginx已經處理完該請求但客戶端還沒有發送完無用的請求體時,nginx會在讀事件上再掛上定時器。
函數同樣還會檢查請求頭中的content-length頭,客戶端如果打算發送請求體,就必須發送content-length頭,同時還會查看其他地方是不是已經讀取了請求體。如果確實有待處理的請求體,函數接著檢查請求頭buffer中預讀的數據,預讀的數據會直接被丟掉,當然如果請求體已經被全部預讀,函數就直接返回了。

接下來,如果還有剩余的請求體未處理,該函數調用ngx_handle_read_event()在事件處理機制中掛載好讀事件,并把讀事件的處理函數設置為ngx_http_discarded_request_body_handler。做好這些準備之后,該函數最后調用ngx_http_read_discarded_request_body()接口讀取客戶端過來的請求體并丟棄。如果客戶端并沒有一次將請求體發過來,函數會返回,剩余的數據等到下一次讀事件過來時,交給ngx_http_discarded_request_body_handler()來處理,這時,請求的discard_body將被設置為1用來標識這種情況。另外請求的引用數(count)也被加1,這樣做的目的是客戶端可能在nginx處理完請求之后仍未完整發送待發送的請求體,增加引用是防止nginx核心在處理完請求后直接釋放了請求的相關資源。

ngx_http_read_discarded_request_body()函數非常簡單,它循環的從鏈接中讀取數據并丟棄,直到讀完接收緩沖區的所有數據,如果請求體已經被讀完了,該函數會設置讀事件的處理函數為ngx_http_block_reading,這個函數僅僅刪除水平觸發的讀事件,防止同一事件不斷被觸發。
再來看一下讀事件的處理函數ngx_http_discarded_request_body_handler,這個函數每次讀事件來時會被調用,先看一下它的源碼:

void ngx_http_discarded_request_body_handler(ngx_http_request_t *r) {   ...    c = r->connection;   rev = c->read;    if (rev->timedout) {     c->timedout = 1;     c->error = 1;     ngx_http_finalize_request(r, NGX_ERROR);     return;   }    if (r->lingering_time) {     timer = (ngx_msec_t) (r->lingering_time - ngx_time());      if (timer <= 0) {       r->discard_body = 0;       r->lingering_close = 0;       ngx_http_finalize_request(r, NGX_ERROR);       return;     }    } else {     timer = 0;   }    rc = ngx_http_read_discarded_request_body(r);    if (rc == NGX_OK) {     r->discard_body = 0;     r->lingering_close = 0;     ngx_http_finalize_request(r, NGX_DONE);     return;   }    /* rc == NGX_AGAIN */    if (ngx_handle_read_event(rev, 0) != NGX_OK) {     c->error = 1;     ngx_http_finalize_request(r, NGX_ERROR);     return;   }    if (timer) {      clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);      timer *= 1000;      if (timer > clcf->lingering_timeout) {       timer = clcf->lingering_timeout;     }      ngx_add_timer(rev, timer);   } } 

函數一開始就處理了讀事件超時的情況,之前說到在ngx_http_discard_request_body()函數中已經刪除了讀事件的定時器,那么什么時候會設置定時器呢?答案就是在nginx已經處理完該請求,但是又沒有完全將該請求的請求體丟棄的時候(客戶端可能還沒有發送過來),在ngx_http_finalize_connection()函數中,如果檢查到還有未丟棄的請求體時,nginx會添加一個讀事件定時器,它的時長為lingering_timeout指令所指定,默認為5秒,不過這個時間僅僅兩次讀事件之間的超時時間,等待請求體的總時長為lingering_time指令所指定,默認為30秒。這種情況中,該函數如果檢測到超時事件則直接返回并斷開連接。同樣,還需要控制整個丟棄請求體的時長不能超過lingering_time設置的時間,如果超過了最大時長,也會直接返回并斷開連接。
如果讀事件發生在請求處理完之前,則不用處理超時事件,也不用設置定時器,函數只是簡單的調用ngx_http_read_discarded_request_body()來讀取并丟棄數據。



發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩欧美精品中文字幕| 亚洲电影成人av99爱色| 77777亚洲午夜久久多人| 亚洲一区二区三区乱码aⅴ| 热久久这里只有精品| 久久九九精品99国产精品| 91国产视频在线播放| 性亚洲最疯狂xxxx高清| 亚洲成人网久久久| 91av国产在线| 日韩毛片在线观看| 欧美国产精品人人做人人爱| 91福利视频网| 欧美日韩亚洲国产一区| 97精品欧美一区二区三区| 美女福利视频一区| 久久综合伊人77777蜜臀| 亚洲香蕉在线观看| 九九久久久久99精品| 亚洲国产成人久久综合| 97视频在线观看免费| 青草成人免费视频| 久久亚洲精品中文字幕冲田杏梨| 国产成人福利夜色影视| 国产不卡av在线| 成人妇女淫片aaaa视频| 国模极品一区二区三区| 色综合久久天天综线观看| 午夜免费日韩视频| 欧美激情在线一区| 国产精品久久久久久av福利软件| 亚洲国产精品人久久电影| 国产一区二区动漫| 欧美成人精品一区二区| 国产一区二区三区直播精品电影| 日韩精品中文字幕在线观看| 精品成人久久av| 久久精品久久久久久国产 免费| 亚洲国产精品高清久久久| 国产不卡在线观看| 久久躁日日躁aaaaxxxx| 欧美福利在线观看| 69久久夜色精品国产69| 最近更新的2019中文字幕| 91亚洲精品久久久| 精品一区二区电影| 久久人人爽人人| 亚洲影院色在线观看免费| 北条麻妃一区二区三区中文字幕| 国产91av在线| 欧美一级高清免费播放| 国产精品久久久久久久久| 国产精品成人观看视频国产奇米| 国产亚洲精品激情久久| 色老头一区二区三区| 91成人在线观看国产| 亚洲一区二区三区四区视频| 欧美高清电影在线看| 欧美精品久久一区二区| 久久精品国产亚洲一区二区| 91夜夜揉人人捏人人添红杏| 亚洲精品乱码久久久久久金桔影视| 这里只有视频精品| 91成人精品网站| 亚洲成人免费网站| 亚洲激情第一页| 日韩精品在线观看网站| 久久全国免费视频| 5278欧美一区二区三区| 久久成人18免费网站| 国产91精品在线播放| 亚洲乱码一区二区| 精品福利在线视频| 欧美日韩ab片| 91久久久亚洲精品| 性色av一区二区咪爱| 91丨九色丨国产在线| 国产91对白在线播放| 日韩在线播放一区| 中文欧美日本在线资源| 国产精品综合不卡av| 欧美激情精品久久久久久| 美日韩精品视频免费看| 久久99久久久久久久噜噜| 国产精品人成电影在线观看| 亚洲免费av片| 欧美激情一区二区三区成人| 97视频在线观看成人| 精品国产区一区二区三区在线观看| 色黄久久久久久| 亚洲视频在线观看网站| 欧美激情精品久久久久久免费印度| 夜色77av精品影院| 久久精品中文字幕电影| 精品国产区一区二区三区在线观看| 日韩av三级在线观看| 国产成人精品免费视频| 中文字幕亚洲欧美| 亚洲va久久久噜噜噜久久天堂| 国产情人节一区| 一道本无吗dⅴd在线播放一区| 欧美怡春院一区二区三区| 精品欧美激情精品一区| 亚洲欧美在线免费观看| 久久精品成人欧美大片| 久久99精品久久久久久青青91| 亚洲综合色激情五月| 久久九九全国免费精品观看| 亚洲美女动态图120秒| 亚洲国产成人精品女人久久久| 国产suv精品一区二区三区88区| 成人国产在线视频| 伊人久久五月天| 欧美色播在线播放| 日韩成人av在线| 色yeye香蕉凹凸一区二区av| 国产精品福利小视频| 亚洲国产欧美一区二区丝袜黑人| 国产亚洲欧美日韩美女| 色婷婷综合成人| 一区二区日韩精品| 亚洲白拍色综合图区| 亚洲国产精品久久久久秋霞蜜臀| 欧美激情日韩图片| xvideos成人免费中文版| 中文字幕精品视频| 国产欧美精品久久久| 国产一区二区三区四区福利| 国产精品偷伦一区二区| 亚洲伊人久久综合| 欧美午夜www高清视频| 亚洲最新中文字幕| 色妞在线综合亚洲欧美| 国产91ⅴ在线精品免费观看| 日本人成精品视频在线| 色久欧美在线视频观看| 欧美黄色www| 欧美一级淫片丝袜脚交| 亚洲女人天堂av| 国内精品视频久久| 蜜臀久久99精品久久久久久宅男| 在线性视频日韩欧美| 久久久久久久久久久亚洲| 亚洲最大福利视频| 色综合视频一区中文字幕| 国产亚洲精品久久久久久| 中文字幕综合一区| 奇米成人av国产一区二区三区| 国产精品96久久久久久又黄又硬| 国产丝袜一区二区三区| 日韩精品亚洲精品| 韩曰欧美视频免费观看| 久久夜色精品亚洲噜噜国产mv| 97在线视频国产| 日韩中文在线视频| 欧美精品日韩三级| 懂色aⅴ精品一区二区三区蜜月| 北条麻妃99精品青青久久| 国产日本欧美一区| 中文字幕国产亚洲| 国产精品美女在线| 亚洲欧美日韩第一区| 欧美激情亚洲自拍| 国产91精品网站|