日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

NGINX-RTMP复杂度分析

發布時間:2024/2/28 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 NGINX-RTMP复杂度分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
很好奇nginx如何處理異步請求,我看nginx-rtmp在處理異步時狀態也還行,所以調試下看看。
純異步做rtmp協議,真是非常復雜,特別是需要做回源。無數的回調和處理邏輯。NGINX-RTMP幾個簡化問題的方法:
1. RTMP-CHUNK協議解析直接在一個函數里做,避免添加狀態。
2. CHUNK的長度可以計算得出,所以收到要求的長度的數據后,才開始協議解析。
3. 收發數據,協議解析,包邏輯處理,三部分分離。
4. 包收到后通過各種handler回調,包發送時只是發送到chain,異步的發送和包發送分離。
5. 使用ATM模型來收發數據。
6. 使用chain作為收發數據的緩存。收取時,chain達到長度才開始處理;發送包時,緩存到chain,然后啟動異步發送即可。
整個機制雖然有所簡化,比起同步的調用,要復雜至少10倍。


首先,下載和解壓nginx:
? ? ?tar xf nginx-1.5.0.tar.gz && tar xf nginx-rtmp-module-1.0.4.tar.gz
? ? ?cd nginx-1.5.0 && ./configure --add-module=/home/winlin/nginx-rtmp-module-1.0.4 --with-http_ssl_module --prefix=`pwd`/release
修改編譯參數,將優化去掉:
? ? ?sed -i "s/-O /-O0 /g" objs/Makefile
編譯:
? ? ?make && make install
配置RTMP:
? ? ?vi conf/nginx.conf
添加如下:
? ? daemon off;
? ? master_process off;
? ? rtmp {
? ? ? ? server {
? ? ? ? ? ? listen 19352;
? ? ? ? ? ? application live {
? ? ? ? ? ? ? ? live on;
? ? ? ? ? ? ? ? allow publish all;
? ? ? ? ? ? ? ? allow play all;
? ? ? ? ? ? }
? ? ? ? }
? ? }
配置可以在nginx.c中看到:
? ? { ngx_string("daemon"),
? ? ? NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
? ? ? ngx_conf_set_flag_slot,
? ? ? 0,
? ? ? offsetof(ngx_core_conf_t, daemon),
? ? ? NULL },
跳到函數:ngx_conf_set_flag_slot,可以看到應該配置為on或off。
開始調試。


ultimate IDE的project如附件:


目錄結構如下:
E:\Chnvideo\research\nginx
main
nginx-1.5.0
nginx-rtmp-module-1.0.4
只要將nginx和rtmp模塊解壓到這個目錄,然后將當前目錄(E:\Chnvideo\research\nginx)在IDE打開即可。
IDE=>New assembly => package nests 輸入:E:\Chnvideo\research\nginx


Rtmp模塊初始化
rtmp模塊初始化函數調用如下:
(gdb) bt
#0 ?ngx_rtmp_optimize_servers (cf=0x7fffffffe1d0, ports=0x7fffffffddb0) at /home/winlin/nginx-rtmp-module-1.0.4/ngx_rtmp.c:605
#1 ?0x00000000004ae362 in ngx_rtmp_block (cf=0x7fffffffe1d0, cmd=0x711680, conf=0xa4da78) at /home/winlin/nginx-rtmp-module-1.0.4/ngx_rtmp.c:312
#2 ?0x000000000041f173 in ngx_conf_handler (cf=0x7fffffffe1d0, last=1) at src/core/ngx_conf_file.c:387
#3 ?0x000000000041ed1e in ngx_conf_parse (cf=0x7fffffffe1d0, filename=0xa4ce00) at src/core/ngx_conf_file.c:243
#4 ?0x000000000041b9cc in ngx_init_cycle (old_cycle=0x7fffffffe310) at src/core/ngx_cycle.c:268
#5 ?0x0000000000406230 in main (argc=1, argv=0x7fffffffe5d8) at src/core/nginx.c:333
(gdb) f
#0 ?ngx_rtmp_optimize_servers (cf=0x7fffffffe1d0, ports=0x7fffffffddb0) at /home/winlin/nginx-rtmp-module-1.0.4/ngx_rtmp.c:605
605 ? ? ? ? ? ? ? ? ls->handler = ngx_rtmp_init_connection;
默認將accept之后的處理函數設置為了ngx_rtmp_init_connection。


Nginx的回調函數
在ngx_rtmp_init_connection(ngx_rtmp_init.c:132)中設置斷點,可以看到接受連接和處理handshake的過程。
#0 ?ngx_rtmp_init_connection (c=0x7ffff7fad190) at /home/winlin/nginx-rtmp-module-1.0.4/ngx_rtmp_init.c:31
#1 ?0x000000000042befe in ngx_event_accept (ev=0xa7b370) at src/event/ngx_event_accept.c:357
#2 ?0x0000000000435d26 in ngx_epoll_process_events (cycle=0xa4cca0, timer=18446744073709551615, flags=1) at src/event/modules/ngx_epoll_module.c:683
#3 ?0x0000000000428f02 in ngx_process_events_and_timers (cycle=0xa4cca0) at src/event/ngx_event.c:249
#4 ?0x0000000000433181 in ngx_single_process_cycle (cycle=0xa4cca0) at src/os/unix/ngx_process_cycle.c:315
#5 ?0x00000000004064c8 in main (argc=1, argv=0x7fffffffe5d8) at src/core/nginx.c:409
在ngx_event_accept(ngx_event_accept.c:206)中,接受到連接后進行處理,其中設置了recvchain:
? ? ? ? c->recv_chain = ngx_recv_chain;
? ? ? ? c->send_chain = ngx_send_chain;
這兩個值是宏定義,在ngx_event.h:458:
extern ngx_os_io_t ?ngx_io;
#define ngx_recv_chain ? ? ? ngx_io.recv_chain
#define ngx_send_chain ? ? ? ngx_io.send_chain
這個ngx_io是個extern的變量,grep搜索,發現定義在:
[winlin@dev6 nginx-1.5.0]$ find src -name "*.c"|xargs grep -in "ngx_io\;"
src/core/ngx_connection.c:13:ngx_os_io_t ?ngx_io;
[winlin@dev6 nginx-1.5.0]$ find src -name "*.c"|xargs grep -in "ngx_io ="|grep epoll
src/event/modules/ngx_epoll_module.c:329: ? ?ngx_io = ngx_os_io;
所以會在epoll這個模塊被重置,可以設置斷點。
b ngx_epoll_module.c:329
Breakpoint 6, ngx_epoll_init (cycle=0xa4cca0, timer=0) at src/event/modules/ngx_epoll_module.c:329
329 ? ? ? ? ngx_io = ngx_os_io;
(gdb) p &ngx_io
$32 = (ngx_os_io_t *) 0xa222a0
(gdb) p &ngx_os_io
$33 = (ngx_os_io_t *) 0x703440
(gdb) p ngx_os_io
$34 = {recv = 0x42f8b0 <ngx_unix_recv>, recv_chain = 0x42f9c8 <ngx_readv_chain>, udp_recv = 0x42fc74 <ngx_udp_unix_recv>, send = 0x42fd34 <ngx_unix_send>, send_chain = 0x435ee4 <ngx_linux_sendfile_chain>, flags = 1}
(gdb) p ngx_io
$35 = {recv = 0, recv_chain = 0, udp_recv = 0, send = 0, send_chain = 0, flags = 0}
在connection.c中的初始化只是默認初始化為0,只有在ngx_os_io這個里面才是真正用到的。
這個ngx_os_io是在這里定義的:
[winlin@dev6 nginx-1.5.0]$ find src -name "*.c"|xargs grep -in "ngx_os_io \="|grep linux
src/os/unix/ngx_linux_init.c:75: ? ?ngx_os_io = ngx_linux_io;
這個結構體定義為:
static ngx_os_io_t ngx_linux_io = {
? ? ngx_unix_recv,
? ? ngx_readv_chain,
? ? ngx_unix_send,
? ? ngx_linux_sendfile_chain,
};
函數定義在ngx_readv_chain.c:19和ngx_linux_sendfile_chain.c:38(對于rtmp還是用的writev,不是用的sendfile)。


處理函數的改變
ngx_rtmp_init_connection里面調用了ngx_rtmp_init_session和ngx_rtmp_handshake。
ngx_rtmp_init_session先調用ngx_rtmp_set_chunk_size,然后調用 ngx_rtmp_fire_event激發了事件NGX_RTMP_CONNECT。
ngx_rtmp_set_chunk_size,第一次將chunk-size設為128(NGX_RTMP_DEFAULT_CHUNK_SIZE),不需要發包。
ngx_rtmp_fire_event的handler可以搜索:NGX_RTMP_CONNECT,定義在:ngx_rtmp_limit_postconfiguration
h = ngx_array_push(&cmcf->events[NGX_RTMP_CONNECT]);
*h = ngx_rtmp_limit_connect;
所以NGX_RTMP_CONNECT的handler應該是ngx_rtmp_limit_connect,這個函數檢查一個共享的變量,然后判斷是否超過連接數,返回錯誤或者OK:
? ? ? rc = n > (ngx_uint_t) lmcf->max_conn ? NGX_ERROR : NGX_OK;
若可以接受這個連接,則開始握手,調用函數ngx_rtmp_handshake如下:
#0 ?ngx_rtmp_handshake (s=0xa665b0) at /home/winlin/nginx-rtmp-module-1.0.4/ngx_rtmp_handshake.c:576
#1 ?0x00000000004af3ab in ngx_rtmp_init_connection (c=0x7ffff7fad190) at /home/winlin/nginx-rtmp-module-1.0.4/ngx_rtmp_init.c:132
#2 ?0x000000000042befe in ngx_event_accept (ev=0xa7b370) at src/event/ngx_event_accept.c:357
#3 ?0x0000000000435d26 in ngx_epoll_process_events (cycle=0xa4cca0, timer=18446744073709551615, flags=1) at src/event/modules/ngx_epoll_module.c:683
#4 ?0x0000000000428f02 in ngx_process_events_and_timers (cycle=0xa4cca0) at src/event/ngx_event.c:249
#5 ?0x0000000000433181 in ngx_single_process_cycle (cycle=0xa4cca0) at src/os/unix/ngx_process_cycle.c:315
#6 ?0x00000000004064c8 in main (argc=1, argv=0x7fffffffe5d8) at src/core/nginx.c:409
在ngx_rtmp_handshake中,初始化rtmp的讀寫函數為:
c->read->handler = ?ngx_rtmp_handshake_recv;
c->write->handler = ngx_rtmp_handshake_send;
然后,設置狀態機:
? ? ? s->hs_stage = NGX_RTMP_HANDSHAKE_SERVER_RECV_CHALLENGE;
并直接進入下一個狀態:
? ? ? ngx_rtmp_handshake_recv(c->read);
可見,還是使用了狀態機,只是將狀態組合成了幾個大的階段,通過設置不同的c->read/write->hander來處理。
在handshake完畢的函數ngx_rtmp_cycle(s)里面,將handler設置成了ngx_rtmp_recv/ngx_rtmp_send。


HandshakeBuffer
設置斷點,看狀態如何改變:
(gdb) b ngx_rtmp_handshake_recv
Breakpoint 15 at 0x4b0526: file /home/winlin/nginx-rtmp-module-1.0.4/ngx_rtmp_handshake.c, line 375.
(gdb) b ngx_rtmp_handshake_send
Breakpoint 16 at 0x4b09a6: file /home/winlin/nginx-rtmp-module-1.0.4/ngx_rtmp_handshake.c, line 490.
ngx_rtmp_handshake_recv,接受消息,處理時,先接受指定長度的數據,然后再處理。
b = s->hs_buf;
while (b->last != b->end) {
? ? n = c->recv(c, b->last, b->end - b->last);
? ? if (n == NGX_AGAIN) {
? ? ? ? ngx_add_timer(rev, s->timeout);
? ? ? ? if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
? ? ? ? ? ? ngx_rtmp_finalize_session(s);
? ? ? ? }
? ? ? ? return;
? ? }
? ? b->last += n;
}
第一次時,會收1537字節然后處理,:
? ? ?(gdb) p b->end-b->last
? ? ? $76 = 1537
所以這個s->hs_buf應該初始化為1537字節,即handshake的字節。在調用handshake時初始化為NGX_RTMP_HANDSHAKE_BUFSIZE長度。


獲取時間:
ngx_time_update這個函數會更新全局變量 ngx_current_msec ,調用的是ngx_gettimeofday,如果過多頻繁的調用會有性能問題。
所以應該不會隨意調用它,很多時候只是直接用,相當于cache了這個時間。


timer的處理,超時:
假設收取失敗,返回的是NGX_AGAIN(-2),則會使用定時器:ngx_add_timer設置超時,然后調用ngx_handle_read_event偵聽READ事件。
ngx_add_timer會添加到rbtree里面去:
? ? ? timer = {key = 1380262079704, left = 0x719700, right = 0x719700, parent = 0x0, color = 0 '\000', data = 0 '\000'}
NGX_EAGAIN返回后,會調用ngx_event_expire_timers函數,這個會取全局的rbtree的root:ngx_event_timer_rbtree
? ? ? (gdb) p ngx_event_timer_rbtree?
? ? ? $98 = {root = 0xa7b468, sentinel = 0x719700, insert = 0x414ded <ngx_rbtree_insert_timer_value>}
? ? ?(gdb) p *ngx_event_timer_rbtree.root
? ? ? $101 = {key = 1380262079704, left = 0x719700, right = 0x719700, parent = 0x0, color = 0 '\000', data = 0 '\000'}
這個root就是ngx_add_timer添加的那個選項,rev就是handshake的那個結構。
rbtree的key是超時時間,所以最小的超時時間會放在前面,ngx_event_add_timer函數里面:
? ? ? key = ngx_current_msec + timer;
rbtree的節點是直接指向evt對象的,所以ngx_event_expire_timers可以直接從rbtree的node獲取evt:
? ? ? ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer));
然后設置為timeout后,直接就調用handler:
? ? ?ev->timedout = 1;
? ? ?ev->handler(ev); // ngx_rtmp_handshake_recv
因為timeout,所以就關掉連接了。


EAGAIN的處理:
假若沒有timeout,則進入到EAGAIN的處理。
ngx_event_find_timer會返回一個timeout,共epoll_wait來處理超時事件。
? ? ?timer = ngx_event_find_timer(); //60000,handshake的超時為60秒。
? ? ?events = epoll_wait(ep, event_list, (int) nevents, timer);
若fd可讀,則調用read的handler:
? ? ?if ((revents & EPOLLIN) && rev->active) {
? ? ? ? ? rev = c->read;
? ? ? ? ? rev->handler(rev);
? ? ?(gdb) p *c->read->handler
? ? ? $125 = {void (ngx_event_t *)} 0x4b0519 <ngx_rtmp_handshake_recv>
所以直接就調用到了這個處理函數ngx_rtmp_handshake_recv,先清除timer,然后讀取到handshake需要的長度的數據。
? ? ?(gdb) p b->end-b->last
? ? ? $126 = 1437
還需要讀取這些數據。若EAGAIN,還是在可讀時調用這個函數。
可見nginx來設置不同的handler,相當于將大狀態機切割成小狀態機,小狀態機里面直接switch。
若c++用類表示大狀態機,用switch表示小狀態機,是可以簡化的。設置不同的handler,就設置不同的狀態子類表示。


ATM模型:
ATM就是讀-寫-讀這種分離的模型 ,避免又讀又寫。即同一時刻,只能讀或者寫,做完了才能做下一個。
ngx_rtmp_handshake_recv中,會先讀取,若EAGAIN則偵聽讀事件,若讀取完畢則刪除讀事件。
? ? ?// start read, if not completed, focus read event.
? ? ?n = c->recv(c, b->last, b->end - b->last);
? ? ?if (n == NGX_AGAIN) {
? ? ? ? ? ngx_handle_read_event(c->read, 0);
? ? ? ? ? return;
? ? ?}
? ? ?// read completed, donot focus read event.
? ? ?if (rev->active) {
? ? ? ? ? ngx_del_event(rev, NGX_READ_EVENT, 0);
? ? ?}
若讀取C0C1成功,則發送S0S1S2。調用的是:
? ? ?ngx_rtmp_handshake_send(c->write);
這個函數會嘗試發送,也是ATM模型:
? ? ?// start write, if not completed, focus write event.
? ? ?n = c->send(c, b->pos, b->last - b->pos);
? ? ?if (n == NGX_AGAIN || n == 0) {
? ? ? ? ? ngx_handle_write_event(c->write, 0)
? ? ? ? ? return;
? ? ?}
? ? ?// write completed, donot focus write event.
? ? ?if (wev->active) {
? ? ? ? ? ngx_del_event(wev, NGX_WRITE_EVENT, 0);
? ? ?}
發送S0S1完畢,還是要收C2.等C0C1C2和S0S1S2都處理完畢,則進入ngx_rtmp_handshake_done,調用ngx_rtmp_cycle函數,進入包處理邏輯。


RTMP收包
這個應該是狀態巨多的一個場景,每個包都是一個大狀態。
首先把handler設置成收發的函數。
? ? ?c->read->handler = ?ngx_rtmp_recv;
? ? ?c->write->handler = ngx_rtmp_send;
并先開始收數據并處理:
? ? ?ngx_rtmp_recv(c->read);
ngx_rtmp_recv的 主要邏輯就是解析chunk為RTMP包,并調用處理包的函數。
ngx_rtmp_session_t* s中有個成員是 ngx_rtmp_stream_t* in_streams,這個就是chunk streams
? ? ?st = &s->in_streams[s->in_csid]; // 獲取或創建一個chunk_stream,直接將數組轉換為map,即預先開辟in_streams的空間。
其中:
typedef struct {
? ? ngx_rtmp_header_t ? ? ? hdr;
? ? uint32_t ? ? ? ? ? ? ? ?dtime;
? ? uint32_t ? ? ? ? ? ? ? ?len; ? ? ? ?/* current fragment length */
? ? uint8_t ? ? ? ? ? ? ? ? ext;
? ? ngx_chain_t ? ? ? ? ? ?*in;
} ngx_rtmp_stream_t;
每個ngx_rtmp_stream_t中都定義了一個chain:in。每個chain其實就是一個緩存 ,就是說給每個chunk_stream新建了一個可以寫的buffer。
? ? ?n = c->recv(c, b->last, b->end - b->last); // 先收146字節的數據。調試時可以改為10,看如何解析。
b的初始化在ngx_rtmp_init_session,設置了in_streams里面:
? ? ?s->in_streams = ngx_pcalloc(c->pool, sizeof(ngx_rtmp_stream_t) * cscf->max_streams);
收到數據后,開始解析chunk。若只讀取了10字節,那么basic_header當fmt為0時需要12字節,會在這個地方再讀取:
? ? ?if (fmt == 0) {
? ? ? ? ? if (b->last - p < 4)
? ? ? ? ? ? ? ?continue;
? ? (gdb) p b->last - p
? ? $173 = 2
再次循環調用recv和解析:
? ? ?n = c->recv(c, b->last, b->end - b->last); // b->end - b->last=136,讀取了10字節。
解析時,還是會重頭開始解析一遍。 除非header解析完了,才會改變pos位置
? ? ?/* header done */
? ? ?b->pos = p; // p-b->start=12, fmt為0時的12字節basic header.
解析完的頭如下:
? ? ?(gdb) p st->hdr
? ? ? $189 = {csid = 3, timestamp = 0, mlen = 161, type = 20 '\024', msid = 0}
有個地方驗證了消息的最大長度,不能超過這個: cscf->max_message,默認1048576即1M,這個對大碼率視頻可能需要配置
解析完頭,就得看body是否足夠了:
? ? ?size = b->last - b->pos; // buffer的數據,134
? ? ?fsize = h->mlen - st->len; // 消息還沒有下載的長度。
這個時候,還需要更多的數據:
? ? ?if (fsize > s->in_chunk_size) {
? ? ? ? ? st->len += s->in_chunk_size;
? ? ? ? ? b->last = b->pos + s->in_chunk_size;
這樣就算出了還需要收多少數據:
? ? ?(gdb) p b->end-b->last
? ? ? $198 = 6
然后會接著收,一直收完為止。


RTMP處理包
ngx_rtmp_recv收到一個包后 ,調用ngx_rtmp_receive_message處理, 這個函數根據消息的類型來找到對應的handler:
? ? ? evhs = &cmcf->events[h->type];
? ? ?evh = evhs->elts;
? ? ?(*evh)(s, h, in)
消息處理的鉤子函數的初始化是在ngx_rtmp_init_event_handlers,譬如AMF0的消息處理在:
? ? static size_t ? ? ? ? ? ? ? amf_events[] = {
? ? ? ? NGX_RTMP_MSG_AMF_CMD,
? ? ? ? NGX_RTMP_MSG_AMF_META,
? ? ? ? NGX_RTMP_MSG_AMF_SHARED,
? ? ? ? NGX_RTMP_MSG_AMF3_CMD,
? ? ? ? NGX_RTMP_MSG_AMF3_META,
? ? ? ? NGX_RTMP_MSG_AMF3_SHARED
? ? };
? ? /* init amf events */
? ? for(n = 0; n < sizeof(amf_events) / sizeof(amf_events[0]); ++n) {
? ? ? ? eh = ngx_array_push(&cmcf->events[amf_events[n]]);
? ? ? ? *eh = ngx_rtmp_amf_message_handler;
? ? }
在amf的處理函數中,還得解析body內容后再調用其他鉤子,來處理特定的amf0函數:
? ? ?ph = ch->elts;
? ? ?(*ph)(s, h, in) // ngx_rtmp_cmd_connect_init
也就是說,這個處理實際上是最難的,雖然一個消息能被一個處理函數處理,可是這個函數不知道很多狀態信息。
不過nginx-rtmp這樣還是處理的很漂亮,非常Nice。
其實同步的邏輯是這樣寫:
? ? ? ? ? MessagePacket* packet = NULL;
? ? ? ? ? if((ret = ctx_core->rtmp->RecvMessage(&packet)) != ErrorCode::Success){
? ? ? ? ? ? ? ?return ret;
? ? ? ? ? }
? ? ? ? ? if(packet is play){
? ? ? ? ? ? ? ?return process_play();
? ? ? ? ? }
? ? ? ? ? if(packet is publish){
? ? ? ? ? ? ? ?return process_publish();
? ? ? ? ? }
純異步的方式是超級復雜,特別是加上了回源pull和push兩種方式后。
能簡化純異步的技術有:
1. 將收包和解析處理分開,確認消息收到了才開始解析。
2. 異步的ATM模型,讀寫分開,讀完才寫,寫完才讀。
3. 處理時使用handler,譬如handshake有handler,amf0有handler,amf0-connect有handler。
同步方式是要簡單很多。


Edge-relay-pull模式
nginx-rtmp的邊緣叫做relay,即中繼模式。有pull和push,即上行推流和下行播放。
實際上FMS是不區分這兩個的,中繼時只需要指定上游服務器地址即可。
收到請求前的調用:
ngx_rtmp_relay_create_app_conf,初始化app的配置。
ngx_rtmp_relay_push_pull,解析pull的命令和參數。
ngx_rtmp_relay_merge_app_conf
ngx_rtmp_relay_postconfiguration
ngx_rtmp_relay_init_process
連接上游的調用:
ngx_rtmp_relay_pull
ngx_rtmp_relay_create_local_ctx
ngx_rtmp_relay_create_remote_ctx
ngx_rtmp_relay_create_connection
ngx_event_connect_peer(堆棧如下)
#0 ?ngx_event_connect_peer (pc=0xa53ed8) at src/event/ngx_event_connect.c:25
#1 ?0x00000000004cb815 in ngx_rtmp_relay_create_connection (cctx=0x7fffffffdd60, name=0x7fffffffde80, target=0xa4fef0) at /home/winlin/nginx-rtmp-module-1.0.4/ngx_rtmp_relay_module.c:468
#2 ?0x00000000004cba2a in ngx_rtmp_relay_create_remote_ctx (s=0xa665b0, name=0x7fffffffde80, target=0xa4fef0) at /home/winlin/nginx-rtmp-module-1.0.4/ngx_rtmp_relay_module.c:527
#3 ?0x00000000004cbce3 in ngx_rtmp_relay_create (s=0xa665b0, name=0x7fffffffde80, target=0xa4fef0, create_publish_ctx=0x4cb9d5 <ngx_rtmp_relay_create_remote_ctx>, create_play_ctx=0x4cba2c <ngx_rtmp_relay_create_local_ctx>)
? ? at /home/winlin/nginx-rtmp-module-1.0.4/ngx_rtmp_relay_module.c:607
#4 ?0x00000000004cbde9 in ngx_rtmp_relay_pull (s=0xa665b0, name=0x7fffffffde80, target=0xa4fef0) at /home/winlin/nginx-rtmp-module-1.0.4/ngx_rtmp_relay_module.c:630
#5 ?0x00000000004cc226 in ngx_rtmp_relay_play (s=0xa665b0, v=0x719da0) at /home/winlin/nginx-rtmp-module-1.0.4/ngx_rtmp_relay_module.c:738
#6 ?0x00000000004d0df5 in ngx_rtmp_enotify_play (s=0xa665b0, v=0x719da0) at /home/winlin/nginx-rtmp-module-1.0.4/ngx_rtmp_enotify_module.c:412
#7 ?0x00000000004d4045 in ngx_rtmp_notify_play (s=0xa665b0, v=0x719da0) at /home/winlin/nginx-rtmp-module-1.0.4/ngx_rtmp_notify_module.c:1407
#8 ?0x00000000004d5b6d in ngx_rtmp_log_play (s=0xa665b0, v=0x719da0) at /home/winlin/nginx-rtmp-module-1.0.4/ngx_rtmp_log_module.c:844
#9 ?0x00000000004b8f7c in ngx_rtmp_cmd_play_init (s=0xa665b0, h=0xa50dc0, in=0xa51cc0) at /home/winlin/nginx-rtmp-module-1.0.4/ngx_rtmp_cmd_module.c:569
#10 0x00000000004b6d2b in ngx_rtmp_amf_message_handler (s=0xa665b0, h=0xa50dc0, in=0xa51cc0) at /home/winlin/nginx-rtmp-module-1.0.4/ngx_rtmp_receive.c:436
#11 0x00000000004b28f3 in ngx_rtmp_receive_message (s=0xa665b0, h=0xa50dc0, in=0xa51cc0) at /home/winlin/nginx-rtmp-module-1.0.4/ngx_rtmp_handler.c:791
#12 0x00000000004b1d19 in ngx_rtmp_recv (rev=0xa7b440) at /home/winlin/nginx-rtmp-module-1.0.4/ngx_rtmp_handler.c:456
#13 0x0000000000435d26 in ngx_epoll_process_events (cycle=0xa4cca0, timer=59762, flags=1) at src/event/modules/ngx_epoll_module.c:683
#14 0x0000000000428f02 in ngx_process_events_and_timers (cycle=0xa4cca0) at src/event/ngx_event.c:249
#15 0x0000000000433181 in ngx_single_process_cycle (cycle=0xa4cca0) at src/os/unix/ngx_process_cycle.c:315
#16 0x00000000004064c8 in main (argc=1, argv=0x7fffffffe5d8) at src/core/nginx.c:409
連接后,進行握手:
? ? ?ngx_rtmp_relay_create_connection
? ? ?ngx_event_connect_peer
? ? ?ngx_rtmp_init_session
? ? ?ngx_rtmp_client_handshake
握手完成時,回調relay的函數:
? ? ?ngx_epoll_process_events
? ? ?ngx_rtmp_handshake_recv
? ? ?ngx_rtmp_handshake_recv
? ? ?ngx_rtmp_handshake_send
? ? ?ngx_rtmp_handshake_done
? ? ?ngx_rtmp_fire_event
? ? ?ngx_rtmp_relay_handshake_done
? ? ?ngx_rtmp_relay_send_connect
正常的握手是沒有回調的,就進入了ngx_rtmp_cycle,相當于relay在這個地方進行了hook:
ngx_rtmp_handshake_done(ngx_rtmp_session_t *s)
? ? ?ngx_rtmp_fire_event(s, NGX_RTMP_HANDSHAKE_DONE)
? ? ?ngx_rtmp_cycle(s);


異步發送多個包
回源連接connect時,連續發送了幾個包,對于異步的socket,如何做到的呢?
ngx_rtmp_relay_send_connect
? ? return ngx_rtmp_send_chunk_size(s, cscf->chunk_size) != NGX_OK
? ? ? ? || ngx_rtmp_send_ack_size(s, cscf->ack_window) != NGX_OK
? ? ? ? || ngx_rtmp_send_amf(s, &h, out_elts,
? ? ? ? ? ? sizeof(out_elts) / sizeof(out_elts[0])) != NGX_OK
? ? ? ? ? NGX_ERROR
? ? ? ? : NGX_OK;
分析一個:ngx_rtmp_send_chunk_size
? ? ?ngx_rtmp_relay_send_connect
? ? ?ngx_rtmp_send_chunk_size
? ? ?ngx_rtmp_send_shared_packet
? ? ?ngx_rtmp_send_message
? ? ?ngx_rtmp_send
這個函數是先將包寫到buffer:
ngx_int_t
ngx_rtmp_send_chunk_size(ngx_rtmp_session_t *s, uint32_t chunk_size)
{
? ? return ngx_rtmp_send_shared_packet(s,
? ? ? ? ? ?ngx_rtmp_create_chunk_size(s, chunk_size));
}
ngx_chain_t *
ngx_rtmp_create_chunk_size(ngx_rtmp_session_t *s, uint32_t chunk_size)?
其中,ngx_rtmp_create_chunk_size就是將包寫到ngx_chain_t*,調用ngx_rtmp_prepare_message。
發送多包的邏輯是:
? ? ?if (!s->connection->write->active) {
? ? ? ? ? ngx_rtmp_send(s->connection->write);
? ? ?}
其中,ngx_rtmp_send就是一個沒有返回值的函數,它主要是啟動ATM到寫模式,若寫不完,在可寫時會自動回調這個函數。
所以發送多包,實際上就是把包發送到ngx_rtmp_send(ngx_event_t *wev)的wev的chain里面,相當于緩沖區,它會保證將它發送完。
至于ngx_rtmp_send_message,根本就不會處理這個發送錯誤,它打交道的是緩沖區。
不過這樣比起同步來,也足夠麻煩了。
簡化的地方:將發送和組包分離,組包到chain,可以將多個包進入隊列,發送只負責發就好了。
同樣,發送成功后,需要調用特殊的回調函數。
譬如處理amf的_result消息時:
ngx_rtmp_relay_postconfiguration
? ? ch = ngx_array_push(&cmcf->amf);
? ? ngx_str_set(&ch->name, "_result");
? ? ch->handler = ngx_rtmp_relay_on_result;
這樣可以回調:
? ? ?ngx_rtmp_recv
? ? ?ngx_rtmp_receive_message
? ? ?ngx_rtmp_amf_message_handler
? ? ?ngx_rtmp_relay_on_result
? ? ?ngx_rtmp_relay_send_create_stream
整個異步的狀態,無處不在。


邊緣數據
邊緣處理數據包的調用是:
? ? ?ngx_epoll_process_events
? ? ?ngx_rtmp_recv
? ? ?ngx_rtmp_receive_message
? ? ?ngx_rtmp_codec_av
回調是在ngx_rtmp_codec_postconfiguration中設置:
? ? ?h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_AUDIO]);
? ? ?*h = ngx_rtmp_codec_av;
? ? ?h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_VIDEO]);
? ? ?*h = ngx_rtmp_codec_av;
其中,回源連接的ngx_rtmp_receive_message會調用的handler包括:
? ? ?ngx_rtmp_codec_av //解碼av。
? ? ?ngx_rtmp_live_av // 轉發給所有客戶端
ngx_rtmp_live_av的調用是:
#0 ?ngx_rtmp_send (wev=0xa95450) at /home/winlin/nginx-rtmp-module-1.0.4/ngx_rtmp_handler.c:492
#1 ?0x00000000004b283f in ngx_rtmp_send_message (s=0xa665b0, out=0xab33e4, priority=0) at /home/winlin/nginx-rtmp-module-1.0.4/ngx_rtmp_handler.c:736
#2 ?0x00000000004bef33 in ngx_rtmp_live_av (s=0xa53f88, h=0xaaf4a0, in=0xab1400) at /home/winlin/nginx-rtmp-module-1.0.4/ngx_rtmp_live_module.c:957
#3 ?0x00000000004b28f3 in ngx_rtmp_receive_message (s=0xa53f88, h=0xaaf4a0, in=0xab1400) at /home/winlin/nginx-rtmp-module-1.0.4/ngx_rtmp_handler.c:791
#4 ?0x00000000004b1d19 in ngx_rtmp_recv (rev=0xa7b4a8) at /home/winlin/nginx-rtmp-module-1.0.4/ngx_rtmp_handler.c:456
#5 ?0x0000000000435d26 in ngx_epoll_process_events (cycle=0xa4cca0, timer=49151, flags=1) at src/event/modules/ngx_epoll_module.c:683
#6 ?0x0000000000428f02 in ngx_process_events_and_timers (cycle=0xa4cca0) at src/event/ngx_event.c:249
#7 ?0x0000000000433181 in ngx_single_process_cycle (cycle=0xa4cca0) at src/os/unix/ngx_process_cycle.c:315
#8 ?0x00000000004064c8 in main (argc=1, argv=0x7fffffffe5d8) at src/core/nginx.c:409
其中ngx_rtmp_live_av,也是調用ngx_rtmp_send_message,發送到緩沖區,然后發起發送請求而已,不必等到所有數據都發出去了。
? ? ?ngx_rtmp_live_av
? ? ?/* broadcast to all subscribers */
是在live模塊中實現的這個轉發,即subscribe模式。
也就是說,這個回源連接收到數據后,同時轉發給了其他socket(準確講是轉發給了各個客戶端的chain,然后異步發送)。

總結

以上是生活随笔為你收集整理的NGINX-RTMP复杂度分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

av免费播放 | 综合在线色 | 最新av在线网站 | 中文字幕第一页在线vr | 国产视频一区在线 | 黄色毛片视频免费观看中文 | 国产裸体视频网站 | 亚洲成a人片综合在线 | 久久久久久久久久久久久久免费看 | 亚洲成人黄色 | 91桃色免费观看 | 韩国av电影在线观看 | 亚洲综合一区二区精品导航 | 久久精品精品电影网 | 国产亚洲精品久久久久久移动网络 | 欧美综合久久 | 日b视频在线观看网址 | 国产成人av电影在线 | 狠狠久久伊人 | 国内一级片在线观看 | 国产小视频在线免费观看 | 国产亚洲精品福利 | 五月天亚洲综合小说网 | 日日夜夜狠狠干 | 国产精品久久久久三级 | 国产成人三级一区二区在线观看一 | 国产精品mm| 国产午夜精品一区 | 中文字幕日本在线 | 久久精品男人的天堂 | 国产视频精选在线 | av中文字幕在线看 | 色综合天天爱 | 日韩在线激情 | 免费观看v片在线观看 | 亚洲精品在线视频 | 免费看黄视频 | 92精品国产成人观看免费 | 在线视频观看成人 | 91高清完整版在线观看 | 国产午夜精品免费一区二区三区视频 | 国产精品电影在线 | 手机av电影在线 | 黄色免费观看视频 | 亚洲成人av一区二区 | 国产免费又爽又刺激在线观看 | 精品久久久精品 | 天天射天天做 | 亚洲国产综合在线 | 涩涩色亚洲一区 | 一区二区视频免费在线观看 | 五月天堂色 | 玖玖在线免费视频 | 久久99在线观看 | 成人亚洲精品久久久久 | 国产日韩视频在线播放 | 国产在线色站 | 精品在线免费观看 | 中文字幕在线观看网 | 色九九影院 | 中文字幕一区二区三区久久蜜桃 | 天天操夜夜操天天射 | 日本丶国产丶欧美色综合 | 国产一区二区精品在线 | 亚洲第一香蕉视频 | 国产系列在线观看 | 免费黄色网止 | 在线观看中文字幕dvd播放 | 久在线 | 日本女人b| 久久久精品久久 | 成人午夜电影在线观看 | 日韩网站中文字幕 | 国产一级免费视频 | 草久中文字幕 | 九九九热精品免费视频观看网站 | 美女中文字幕 | 久久久久伊人 | 91精品在线视频观看 | 久久97久久97精品免视看 | 国产美女久久久 | 欧美影院久久 | 中文字幕黄色网 | 日韩av片无码一区二区不卡电影 | 狠狠综合久久av | 99精品国产在热久久 | 在线不卡视频 | 日韩精品一区二区在线观看视频 | 国产精品免费视频一区二区 | 日韩一区二区三区免费电影 | 天天干,狠狠干 | 丰满少妇在线观看 | 精产嫩模国品一二三区 | 中文乱码视频在线观看 | 午夜av在线播放 | 91亚洲精品久久久蜜桃网站 | 日本黄色免费看 | 中文字幕免费成人 | 日韩精选在线观看 | 日韩91精品 | 91在线九色 | 国产精品男女啪啪 | 日本久久中文 | 超碰在线成人 | 激情五月综合 | 色综合久久中文字幕综合网 | 亚洲精品字幕在线 | 久久久影院一区二区三区 | 天堂入口网站 | 东方av在线免费观看 | 在线国产不卡 | 亚洲精品日韩一区二区电影 | 一区二区三区在线免费观看 | 久久精品视频在线观看免费 | 亚洲狠狠丁香婷婷综合久久久 | av免费网站 | 人人干网 | av免费观看在线 | 国产精品久久在线观看 | 亚洲日本成人网 | 亚洲免费小视频 | 精品在线视频一区二区三区 | 爱爱av在线| 国产成人亚洲在线电影 | 久久麻豆精品 | 久久不射影院 | 99国产精品 | 国产91亚洲精品 | 狠狠干天天色 | 五月婷婷六月丁香 | 夜夜操天天 | 国产亚洲精品久久久久久电影 | 国产午夜精品一区二区三区欧美 | 99色免费 | 在线观看av中文字幕 | 久久精品韩国 | 亚洲伊人色 | 精品国产乱码久久久久久天美 | 91理论片午午伦夜理片久久 | 国产精品免费久久久久久久久久中文 | 欧美性生活久久 | 成人黄色在线看 | 在线观看va | 2019av在线视频 | 97在线视频免费观看 | 久久久国产精品人人片99精片欧美一 | 日韩欧美在线不卡 | 国产黄在线播放 | 亚洲视频在线播放 | 精品视频在线免费 | 91亚洲精品国偷拍自产在线观看 | 国产在线观看免费观看 | 黄色的网站免费看 | 国产精品九九久久久久久久 | 亚洲无吗视频在线 | 国内外成人免费在线视频 | 日本三级香港三级人妇99 | 一区二区三区免费网站 | 亚洲一区天堂 | 99久久这里有精品 | 国产综合视频在线观看 | 亚洲一区二区黄色 | 伊人五月 | 日韩高清久久 | 免费看国产黄色 | 国产精品日韩 | 亚洲 综合 专区 | 免费一级日韩欧美性大片 | 五月天电影免费在线观看一区 | 久久久久久福利 | 欧美精选一区二区三区 | 免费观看国产成人 | 国产精品久久久久久久久久久久午夜 | 午夜精品影院 | 久久蜜臀av | 日韩a在线| av中文字幕亚洲 | 日韩黄色一级电影 | 欧美亚洲三级 | 久久中文字幕导航 | 国产精品日韩久久久久 | 国产精品午夜久久 | 欧美aa在线 | 丁香在线视频 | 国产丝袜制服在线 | 亚洲区精品视频 | 中午字幕在线 | 久久精品香蕉视频 | 国产精品一区二区久久 | 久草在线在线精品观看 | 成年人在线 | 高清免费av在线 | 韩日电影在线观看 | 国产精品久久片 | 国产综合小视频 | 日韩国产欧美在线视频 | 中文字幕av影院 | 欧美日韩一区二区三区在线观看视频 | 91插插视频 | 欧美日韩三级在线观看 | 国产日韩欧美在线播放 | 麻豆91在线播放 | 日韩r级电影在线观看 | 中文字幕三区 | 午夜三级影院 | 91成版人在线观看入口 | 午夜精品一区二区三区在线 | av超碰在线观看 | 亚洲 欧美 91 | 国产精品毛片一区二区在线 | 亚洲欧美日韩一级 | 日韩美女免费线视频 | av先锋影音少妇 | 久久综合偷偷噜噜噜色 | 天天操综 | 日韩乱码在线 | 婷婷综合国产 | 国产日韩一区在线 | 久久久久久国产精品 | 欧美成人黄色片 | 日本 在线 视频 中文 有码 | 亚州天堂 | 国产精品ssss在线亚洲 | 色美女在线| 黄色免费高清视频 | 丁香色婷 | 久久视频6| 人人干网 | 不卡国产视频 | 亚洲精品免费在线观看 | 久久国产剧场电影 | 精品网站999www| 欧美有色 | 久久成电影 | 一级一片免费观看 | av先锋影音少妇 | 久久免费a | 黄色在线看网站 | 国产日韩精品一区二区 | 亚洲综合色视频 | 人人爽久久涩噜噜噜网站 | 日本精品视频一区二区 | 国产在线久久久 | 黄色影院在线免费观看 | 亚洲一区 av | 激情五月在线 | 伊人天堂久久 | 夜夜操天天干 | av中文天堂在线 | 91中文字幕在线 | 久久久精品小视频 | aa一级片 | 超碰伊人网 | 日韩一区正在播放 | 首页av在线| 国产精品久久久久久久久久久免费 | 中文字幕免费高清在线观看 | 国产精品黄色影片导航在线观看 | 国产精品美女网站 | 国产一区二区三区 在线 | 成人资源在线播放 | 成人午夜影院在线观看 | 精品免费视频123区 午夜久久成人 | 色综合色综合久久综合频道88 | 日本韩国精品一区二区在线观看 | 欧美日一级片 | 久久夜色精品国产欧美乱极品 | 国产视频一区在线免费观看 | 69精品视频在线观看 | 成人h在线播放 | 视频一区二区在线观看 | 国产中文视频 | 日本久久影视 | 人人玩人人添人人澡超碰 | 在线看污网站 | 午夜视频播放 | 亚洲综合国产精品 | 国产精品手机在线观看 | 夜夜爽www| 亚洲精品午夜一区人人爽 | 免费高清在线观看电视网站 | 97视频在线观看视频免费视频 | 激情欧美一区二区三区免费看 | 日韩成人免费在线 | 欧美激情片在线观看 | 爱干视频 | 狠狠干我 | 国产精品嫩草影视久久久 | 国产一区在线视频播放 | 国产日韩中文字幕在线 | 中文字幕在线影视资源 | 国产黄色一级大片 | 五月婷影院 | 色欧美视频 | 一区二区三区四区影院 | 欧美精品中文 | 一本一本久久aa综合精品 | 香蕉97视频观看在线观看 | 日韩中文字幕免费看 | 五月天激情视频 | 天天摸天天干天天操天天射 | 在线日韩中文字幕 | 欧美日韩中文国产一区发布 | 日韩精品观看 | 欧美 另类 交 | 中文网丁香综合网 | 毛片网站免费 | 色先锋资源网 | 国产美女视频免费观看的网站 | 麻豆视频在线免费观看 | 久久亚洲区 | 国产精品乱码一区二三区 | 国产最顶级的黄色片在线免费观看 | 亚洲欧美婷婷六月色综合 | 日韩亚洲在线视频 | 九九九九精品九九九九 | 丁香婷婷激情五月 | 日韩精品一区二区三区中文字幕 | 人人澡人人爽欧一区 | 成人永久视频 | 久久成电影 | 久久国产精品视频 | 激情欧美丁香 | 国产精品 日本 | 久久99亚洲热视 | 国产高清在线免费视频 | 狠狠干狠狠艹 | 久久久久成 | 精品国产一区二区三区久久久蜜月 | 探花视频网站 | 久久高清国产视频 | 丁香九月婷婷综合 | 亚洲精品黄 | 黄色软件在线看 | 国产黄色精品 | 美女免费视频一区 | av看片在线| 激情五月婷婷丁香 | 精品久久久免费视频 | 午夜 久久 tv| 亚洲国产人午在线一二区 | 日韩成人精品一区二区 | 91福利视频免费观看 | 日本爱爱免费 | 97人人超| 天天爱综合 | 欧美一区二区三区免费看 | 成人久久精品视频 | 国产色中涩 | 日韩美在线观看 | 在线看片成人 | 欧美一级xxxx| 日韩大片在线免费观看 | 欧美久久久久久久久久久久 | 日女人免费视频 | 伊人丁香 | 免费成人在线网站 | 国产综合视频在线观看 | 成人性生活大片 | 久久久人 | 久久6精品 | 亚洲成人精品国产 | 久久久久亚洲天堂 | 精品国产美女在线 | 国产精品久久久久久久久久白浆 | 深夜国产在线 | 精品国产一区二区三区久久久久久 | 最近日本字幕mv免费观看在线 | 伊人久在线 | 久久精品中文视频 | 日本 在线 视频 中文 有码 | 亚洲mv大片欧洲mv大片免费 | 亚洲综合干 | 伊人久操 | 久草| 91av中文字幕 | 婷婷综合伊人 | 国产人成免费视频 | 亚洲最新视频在线 | 五月婷婷激情网 | 亚洲精品午夜国产va久久成人 | 天天操天天操天天 | 免费看片网页 | 日本精品视频在线观看 | 国产乱对白刺激视频不卡 | 久久亚洲综合国产精品99麻豆的功能介绍 | 日韩欧美电影在线 | 操夜夜操 | 成人av免费在线播放 | 日韩小视频 | 国产精品白丝jk白祙 | 三级视频片 | 天天天操天天天干 | 日韩一区二区三免费高清在线观看 | 国产成人久久av免费高清密臂 | 在线观看黄色国产 | 国产精品字幕 | 国产三级香港三韩国三级 | 看片的网址 | 亚州av网站大全 | 91激情| 成人在线免费观看视视频 | 成人精品国产免费网站 | 这里只有精彩视频 | av网站免费看 | 久久综合精品国产一区二区三区 | 成人av影视观看 | 91中文字幕在线 | 久久这里只有精品9 | 97在线免费观看视频 | 国产精品久久久久永久免费看 | 93久久精品日日躁夜夜躁欧美 | 99热在线国产 | 在线看成人片 | 91免费网址 | 色91av| 国产精品乱看 | 国产精品一区二区久久国产 | 伊甸园永久入口www 99热 精品在线 | 免费视频成人 | 综合久色| www狠狠操| 干天天 | 麻豆首页 | 伊人成人久久 | 国产在线精 | 亚洲免费视频在线观看 | 日韩理论片在线观看 | 欧美伦理一区 | 午夜精品一区二区三区在线视频 | www五月天com | 国产探花 | 国产精品1区2区在线观看 | 青草草在线视频 | 天天综合在线观看 | 2019天天干天天色 | 国产精品va在线观看入 | 国产欧美精品在线观看 | 四虎永久精品在线 | 丁香高清视频在线看看 | 成年人在线观看视频免费 | 午夜视频在线观看一区二区三区 | 成人一区在线观看 | 在线观看日韩av | 欧美极品裸体 | 91麻豆精品国产自产在线游戏 | 久久伊人精品一区二区三区 | 成人播放器| 国产精品久久久久久久久久新婚 | 91九色蝌蚪在线 | 欧美精品久久久久久久久老牛影院 | 亚洲日韩欧美视频 | 国产剧情一区二区 | 久草在线免费电影 | 久久精品96 | 成人作爱视频 | 日三级在线 | 欧美精品午夜 | 国际av在线 | 四虎成人精品永久免费av | 日韩精品高清视频 | 国产h片在线观看 | 蜜桃视频精品 | 欧美日韩亚洲国产一区 | 精品人妖videos欧美人妖 | 黄色tv视频 | 在线看岛国av | 久久网站av | 久久久久亚洲国产 | 永久免费精品视频 | 久产久精国产品 | 99视频精品免费观看, | 天天插日日操 | 丁香婷婷综合色啪 | 日韩二区在线观看 | 日韩字幕 | 亚洲国产无 | 国产精品久久一卡二卡 | 久久国产免| 国产黄色片免费在线观看 | 六月丁香久久 | 免费看国产黄色 | 久久99中文字幕 | 91福利小视频 | 久久久视频在线 | 久久久国产精品网站 | 97理论片 | 91成年视频 | www.天天射.com | 97在线看| 久草网在线视频 | 色婷婷成人 | 欧美夫妻生活视频 | 日本久久综合网 | 四虎成人精品在永久免费 | 在线免费观看av网站 | 毛片3 | 久久成人人人人精品欧 | 国产一区二区在线免费播放 | 婷婷丁香在线观看 | 最近中文字幕大全中文字幕免费 | 91手机视频| 国产日本亚洲高清 | 日韩理论片在线观看 | 99热在线国产 | 成人免费在线观看电影 | 在线成人免费电影 | 日韩网站一区 | 久久国产香蕉视频 | 国产精品久久久久永久免费观看 | 日韩91在线 | 亚洲高清在线精品 | 久久综合九色综合网站 | 日本最新高清不卡中文字幕 | 五月婷婷亚洲 | 麻豆久久久 | 手机在线观看国产精品 | 337p日本大胆噜噜噜噜 | avv天堂| www.色婷婷| 久久免费激情视频 | 久久精品国产99国产 | 国产在线精品观看 | 欧美日韩国产三级 | 婷色| 免费h视频| 精品影院一区二区久久久 | 国产精品福利在线 | 久久亚洲美女 | 亚洲永久在线 | 精品91视频 | 成人av观看| 天堂在线一区二区 | 久久成人一区二区 | 久久免费精品 | 国产精品免费在线 | 国产涩涩在线观看 | www蜜桃视频 | 久久精品视频播放 | 99亚洲精品在线 | 久久激情五月婷婷 | 成人在线小视频 | 亚洲aⅴ一区二区三区 | 亚洲一区视频免费观看 | 中文字幕在线视频一区二区三区 | 福利区在线观看 | 久久91久久久久麻豆精品 | 亚洲国产日韩精品 | 日韩经典一区二区三区 | 狠狠色丁香婷婷综合 | 91麻豆网站 | 国产破处在线播放 | 久久免费一 | 亚洲第一av在线播放 | 国产一二三区av | 亚洲人成免费网站 | 亚洲激情六月 | 精品毛片一区二区免费看 | 久久一区国产 | 九九九国产 | 亚洲精品一区二区三区新线路 | 国产精品 日韩精品 | 亚洲波多野结衣 | 在线中文字幕网站 | 99热这里只有精品1 av中文字幕日韩 | 亚洲国产精品传媒在线观看 | 欧美日韩不卡在线观看 | 超碰99人人 | 黄色在线观看www | 天天综合色 | 欧美一级xxxx | 午夜性生活片 | 在线成人欧美 | a√天堂资源| 99久久夜色精品国产亚洲96 | 日韩精品资源 | 国产无吗一区二区三区在线欢 | 国产区精品视频 | 黄色小说免费在线观看 | 91成人亚洲| 午夜在线国产 | 国产超碰在线 | 久草网视频在线观看 | 天天色.com | 久久视频在线免费观看 | 成年人在线免费看 | www.日本色| 久久视频免费看 | 国产精品久久久久久妇 | 天天摸天天干天天操天天射 | 国产午夜精品久久 | 久久综合九色 | 黄色三级免费网址 | 中文字幕在线播放av | 欧美精品视 | 黄色aaaaa| 一区三区视频 | 成人av电影免费在线播放 | 婷婷色影院 | 日韩精品视频久久 | 麻豆传媒一区二区 | 国产在线不卡视频 | 99久久电影| 亚洲精品资源在线观看 | 欧美精品一区二区在线播放 | 日本高清免费中文字幕 | 国产精品亚洲视频 | 国产成人精品一区二区三区在线 | 欧美日韩高清国产 | 2019精品手机国产品在线 | 亚洲国产成人在线观看 | 欧美激情综合色综合啪啪五月 | 亚洲成av人片在线观看无 | 国产精品一区二区白浆 | 国产精品理论片在线播放 | 天天躁天天操 | 91热视频| 一区 在线 影院 | 美腿丝袜一区二区三区 | 精品国产伦一区二区三区观看方式 | 国产视频在线观看免费 | 叶爱av在线 | 国产一区二区成人 | av电影免费看 | 久要激情网 | 深夜免费网站 | 日韩精品视频在线免费观看 | 国产在线观看a | 免费在线观看黄 | 国产精品一区二区三区久久久 | 男女免费视频观看 | 四虎在线视频 | 午夜少妇一区二区三区 | 超碰激情在线 | 国产最新在线 | 国产黄色片免费看 | 91在线porny国产在线看 | 精品一二三四在线 | 91传媒在线播放 | 在线视频久 | 激情综合国产 | 中文在线字幕免 | 亚洲成人av电影在线 | 亚洲va天堂va欧美ⅴa在线 | aaa日本高清在线播放免费观看 | 国产精品激情偷乱一区二区∴ | 夜夜夜精品 | 超碰97人人爱 | 天天射天天做 | 91亚洲网站 | 久久久影院 | 亚洲日本成人 | 日日狠狠 | 国产精选在线观看 | 亚洲激情在线观看 | 国产一区高清在线观看 | 中文字幕在线观看第一区 | 最近中文字幕视频完整版 | 国产aa免费视频 | 国语久久 | 欧美999| 九七视频在线观看 | 国产群p视频 | 日日婷婷夜日日天干 | 国产精品高 | 在线视频精品 | 超碰97在线人人 | 日韩精品一区二区久久 | 久久99精品久久久久婷婷 | 精品美女久久久久久免费 | 亚洲乱亚洲乱亚洲 | 久青草影院 | 激情视频一区二区三区 | 在线免费观看av网站 | 国产精品高清在线 | 国产九九热视频 | 成人亚洲欧美 | 天天操天天曰 | 国产成人三级在线 | 蜜臀久久99精品久久久酒店新书 | 国产不卡精品 | 国产在线a不卡 | 中文字幕在线不卡国产视频 | 日本公乱妇视频 | 一区二区久久久久 | 婷婷激情5月天 | av三级av| 国产成人精品综合久久久久99 | 久久99久国产精品黄毛片入口 | 特级黄色一级 | 日韩高清不卡一区二区三区 | 国产精品久久一卡二卡 | 一区二区视频免费在线观看 | 一区二区三区四区五区在线 | 亚洲最大成人免费网站 | 国产精品久久久久影院 | 中文字幕色综合网 | 国产成人香蕉 | 在线观看一 | 欧美激情在线看 | 国内外激情视频 | 手机成人在线电影 | 天天操天天是 | 亚洲国产日韩一区 | 久久免费公开视频 | 国产精品久久久久久久久婷婷 | 欧美午夜a | 碰碰影院| 国产一区免费 | 国产精品com | 久久久久久久久久久免费视频 | 国产手机视频在线 | 在线天堂v| 久久久久久高清 | 亚洲国产wwwccc36天堂 | 亚洲精品国产精品乱码在线观看 | 在线观看亚洲电影 | 午夜视频色 | 日日天天 | 日韩高清精品免费观看 | 亚洲一区二区三区精品在线观看 | 国产精品综合久久久久久 | 丁香激情综合久久伊人久久 | 人人爽人人爽人人爽人人爽 | 国产香蕉视频在线观看 | 狠狠色丁香婷综合久久 | 在线观看免费色 | 日日爽天天操 | 一区二区三区免费在线观看视频 | 久久久精品免费看 | 国产xxxx | 999一区二区三区 | 成人av中文字幕在线观看 | 色噜噜狠狠狠狠色综合 | 欧美va日韩va | 国产99久久久国产精品免费二区 | 美女网站黄免费 | 久久免费在线视频 | 这里有精品在线视频 | 久章草在线 | 国产福利精品一区二区 | 国产在线国偷精品产拍免费yy | 去干成人网 | 国产免费又粗又猛又爽 | 亚洲欧洲久久久 | av最新资源 | 亚洲精品高清视频 | 韩国av一区二区 | 亚洲国产日本 | 黄色免费高清视频 | 9797在线看片亚洲精品 | 三上悠亚在线免费 | 亚洲艳情| 天堂网一区二区三区 | 婷婷久久久| 久久久www免费电影网 | 免费看的黄色录像 | 国产日韩欧美视频在线观看 | 99在线视频观看 | 久久人91精品久久久久久不卡 | 在线观看黄网站 | 欧美日韩一区二区三区免费视频 | 91在线蜜桃臀 | www.超碰 | 久草在线电影网 | 国产精品99久久久久久人免费 | 日韩试看| 美女久久久| 一区二区三区四区五区在线 | 国产一级久久久 | 日本一区二区三区视频在线播放 | 欧美日韩视频一区二区 | 午夜精选视频 | 久草在线播放视频 | 亚洲三级在线播放 | 精品少妇一区二区三区在线 | 西西4444www大胆无视频 | 精品国产一区二区三区久久影院 | 99视频在线免费看 | 国产精品久久久久久久av大片 | 草樱av | 99久久婷婷国产 | 久久成人亚洲欧美电影 | 亚洲激情小视频 | 国产在线91在线电影 | 亚洲一一在线 | 国产亚洲精品久久久久5区 成人h电影在线观看 | 成全在线视频免费观看 | 成人app在线播放 | 在线精品观看国产 | 成年人免费观看国产 | 夜色在线资源 | 97成人在线视频 | 操操操干干干 | 欧美伦理电影一区二区 | 91av在线免费播放 | 欧美激情视频在线观看免费 | 天天操天天干天天操天天干 | 日韩一二三区不卡 | 国产xxxxx在线观看 | 99精品国产一区二区三区麻豆 | 人人狠狠综合久久亚洲婷 | 最新av网址大全 | 久久成人国产精品免费软件 | 久久精品观看 | 天天干天天操天天干 | 超碰人人做 | 久久99久久99精品中文字幕 | 欧美 亚洲 另类 激情 另类 | 国产麻豆精品在线观看 | 超碰伊人网| 成人蜜桃网 | 粉嫩av一区二区三区四区在线观看 | 久色网| 久久久久国产精品午夜一区 | 国产大片黄色 | 91一区二区三区久久久久国产乱 | 有码一区二区三区 | 久久免费电影 | 啪一啪在线 | 草久久精品 | 亚洲aaa毛片| 在线观看成人福利 | 日日干干 | 国产高清 不卡 | 香蕉网在线观看 | 在线观看一级视频 | 天天干天天看 | 日韩免费电影网 | 久久久蜜桃一区二区 | 丁香五月亚洲综合在线 | 欧美一区二区三区四区夜夜大片 | 国产精品2区 | 91麻豆精品 | 天天干,狠狠干 | 91亚瑟视频 | 人人爽人人爱 | 久久亚洲福利视频 | 久热精品国产 | 日韩成人中文字幕 | 久久大香线蕉app | 美女视频久久黄 | 麻豆精品在线视频 | 日韩欧美一区二区三区在线 | 一区二区国产精品 | 久久精品视频3 | 日韩网站一区二区 | 亚洲综合欧美激情 | 日韩视频专区 | 国产福利91精品一区二区三区 | 国产在线视频一区二区三区 | 日本在线观看一区二区三区 | 99久热在线精品视频 | 麻豆影视在线观看 | 国产在线探花 | 国产黄在线看 | 日韩一区视频在线 | 久久综合丁香 | 在线观看黄网站 | 2019中文字幕第一页 | 天天色天天骑天天射 | 伊人久操| 九七人人干 | 久久婷婷久久 | 国产在线看| 丁香网五月天 | 欧美一二区视频 | 免费网站在线观看人 | 欧美日韩三级在线观看 | 免费观看福利视频 | 亚洲精品短视频 | 国产福利精品在线观看 | 亚洲天堂视频在线 | 久久国产精品久久久 | 中文字幕观看视频 | 国产aaa大片| 国产专区精品 | 人人网av| 在线观看91精品国产网站 | 亚洲精品88欧美一区二区 | 99久热| 日韩美av在线 | 欧美福利精品 | 免费在线国产黄色 | 中文一二区 | a久久久久久| 奇米影音四色 | 91亚州| av高清免费| 久久综合干 | 黄色av电影在线 | 黄色网址在线播放 | 国产精品毛片久久蜜 | 精品一区二区三区久久久 | 精品免费视频123区 午夜久久成人 | 天天搞天天干 | av夜夜操 | 精品一区 在线 | 久久日韩精品 | 欧洲av在线 | 狠狠做深爱婷婷综合一区 | 日韩二区在线播放 | 成人在线视频免费观看 | 亚洲在线视频免费观看 | 久久精品免费 | 手机av永久免费 | 成人黄色毛片视频 | 成人一区二区三区在线 | 久久久久久国产精品亚洲78 | 中文字幕乱码电影 | 色综合亚洲精品激情狠狠 | 欧美一级在线观看视频 | 天天干国产 | 国产原创在线观看 | 国产二区电影 | 亚洲国产日韩在线 | 一区二区av | 丁香六月中文字幕 | 黄色一级片视频 | 黄色精品免费 | 免费性网站| av丝袜在线| 国产一级片播放 | 免费高清男女打扑克视频 | 国产亚洲精品久久久久久移动网络 | 国产婷婷vvvv激情久 | 午夜精品久久久久久久99水蜜桃 | 久久精品综合网 | 911香蕉| 欧美国产日韩在线观看 | 久热只有精品 | 国产精品久久久久久久久久不蜜月 | 黄色资源在线观看 | 岛国精品一区二区 | 97香蕉超级碰碰久久免费软件 | 91成人精品视频 | 超碰国产在线 | .国产精品成人自产拍在线观看6 | 深夜免费福利网站 | av免费在线观看网站 | 精品在线观看免费 | 国产探花在线看 | 99色国产| 日本女人的性生活视频 | wwwav视频| a视频在线观看 | 色综合久久久久综合 | 天天操夜夜操夜夜操 | 日韩一区二区三免费高清在线观看 | 一区二区中文字幕在线播放 | 日日夜夜亚洲 | 国产精品日韩欧美 | 亚洲精品影院在线观看 | 久久三级毛片 | 一区二区三区四区在线 | 国产粉嫩在线 | av免费网站 | 狠狠色综合网站久久久久久久 | 美女视频免费一区二区 | 欧美一级片免费在线观看 | av免费在线网站 | 国产精品免费视频一区二区 | 91亚洲狠狠婷婷综合久久久 | 亚洲国产av精品毛片鲁大师 | 天天色.com | 伊人婷婷激情 | 欧美精品久久久久久久久老牛影院 | av超碰在线 | 久久成人国产精品免费软件 | 久久国产精品久久w女人spa | 99久久久国产精品免费观看 | 国产成人三级一区二区在线观看一 | 中文字幕在线看片 | 亚洲一级国产 | 国产精品大片免费观看 | 欧美国产日韩一区二区 | 在线久久| 99国产精品久久久久老师 | 国产福利一区二区三区在线观看 | 97超视频免费观看 | 成人av网站在线观看 | www.日本色| 国产精品99久久免费观看 | 玖草影院 | 欧美国产日韩一区二区三区 | 国产精品一区二区三区久久久 | 蜜臀av性久久久久av蜜臀三区 | 欧美人操人 | 国产精品乱码久久久久久1区2区 | 91视频免费网址 | 五月天婷婷在线播放 | 久要激情网| 午夜国产影院 | 91一区啪爱嗯打偷拍欧美 | 在线 国产 亚洲 欧美 | 99久久精品日本一区二区免费 | 午夜久久久久久久 | 国产伦精品一区二区三区高清 |