亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊(cè) 查看新帖 |

Chinaunix

  平臺(tái) 論壇 博客 文庫(kù)
最近訪問(wèn)板塊 發(fā)新帖
查看: 2082 | 回復(fù): 0
打印 上一主題 下一主題

Doubango ims 框架 分析之 多媒體部分 [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報(bào)告]
發(fā)表于 2011-12-23 01:03 |只看該作者 |倒序?yàn)g覽
序言
RTP提供帶有實(shí)時(shí)特性的端對(duì)端數(shù)據(jù)傳輸服務(wù),傳輸?shù)臄?shù)據(jù)如:交互式的音頻和視頻。那些服務(wù)包括有效載荷類型定義,序列號(hào),時(shí)間戳和傳輸監(jiān)測(cè)控制。應(yīng)用程序在UDP上運(yùn)行RTP來(lái)使用它的多路技術(shù)和checksum服務(wù)。2種協(xié)議都提供傳輸協(xié)議的部分功能。
RTP本身沒(méi)有提供任何的機(jī)制來(lái)確保實(shí)時(shí)的傳輸或其他的服務(wù)質(zhì)量保證,而是由低層的服務(wù)來(lái)完成。它不保證傳輸或防止亂序傳輸,它不假定下層網(wǎng)絡(luò)是否可靠,是否按順序傳送數(shù)據(jù)包。RTP包含的序列號(hào)允許接受方重構(gòu)發(fā)送方的數(shù)據(jù)包順序,但序列號(hào)也用來(lái)確定一個(gè)數(shù)據(jù)包的正確位置,例如,在視頻解碼的時(shí)候不用按順序的對(duì)數(shù)據(jù)包進(jìn)行解碼。
 
  1. 介紹

doubango框架中tinyRTP文件夾實(shí)現(xiàn)RTP/RTCP/RTSP協(xié)議棧,目前只實(shí)現(xiàn)了
RTPRTCP;RTSP還沒(méi)實(shí)現(xiàn)。Rtp用來(lái)在網(wǎng)絡(luò)上傳輸音頻視頻,協(xié)議棧實(shí)現(xiàn)時(shí)主要在音視頻包的封裝,拆包。
 

  1. rtp包由消息頭及消息體組成,消息頭的結(jié)構(gòu)封裝

typedefstruct trtp_rtp_header_s文件trtp_rtp_header.h
 
{
 
TSK_DECLARE_OBJECT;
 
/*RFC 3550 section 5.1 - RTP Fixed Header Fields
 
0 1 2 3
 
01 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
|V=2|P|X| CC |M| PT | sequence number |
 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
| timestamp |
 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
| synchronization source (SSRC) identifier |
 
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
 
| contributing source (CSRC) identifiers |
 
| .... |
 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
*/
 
unsignedversion:2;
 
//版本(V)2比特 此域定義了RTP的版本。此協(xié)議定義的版本是2。(1RTP草案版本使用,值0用在最初"vat"語(yǔ)音工具使用的協(xié)議中。
 
unsignedpadding:1;
 
//填充(P)1比特 若填料比特被設(shè)置,則此包包含一到多個(gè)附加在末端的填充比特,填充比特不算作負(fù)載的一部分。填充的最后一個(gè)字節(jié)指明可以忽略多少個(gè)填充比特。填充可能用于某些具有固定長(zhǎng)度的加密算法,或者用于在底層數(shù)據(jù)單元中傳輸多個(gè)RTP包。
 
unsignedextension:1;
//擴(kuò)展
//擴(kuò)展(X)1比特 若設(shè)置擴(kuò)展比特,固定頭()后面跟隨一個(gè)頭擴(kuò)展。 
unsignedcsrc_count:4;
 
 
unsignedmarker:1;
//標(biāo)志位
unsignedpayload_type:7;
//負(fù)載類型,即承載的語(yǔ)音編碼類型
//負(fù)載類型(PT)7比特 此域定義了負(fù)載的格式,由具體應(yīng)用決定其解釋。協(xié)議可以規(guī)定負(fù)載類型碼和負(fù)載格式之間一個(gè)默認(rèn)的匹配。其他的負(fù)載類型碼可以通過(guò)非RTP方法動(dòng)態(tài)定義。RTP發(fā)送端在任意給定時(shí)間發(fā)出一個(gè)單獨(dú)的RTP負(fù)載類型;此域不用來(lái)復(fù)用不同的媒體流。
uint16_tseq_num;
//序列號(hào),重新組包
//序列號(hào)(sequencenumber):16比特 每發(fā)送一個(gè)RTP數(shù)據(jù)包,序列號(hào)加1,接收端可以據(jù)此檢測(cè)丟包和重建包序列。序列號(hào)的初始值是隨機(jī)的(不可預(yù)測(cè)),以使即便在源本身不加密時(shí)(有時(shí)包要通過(guò)翻譯器,它會(huì)這樣做),對(duì)加密算法泛知的普通文本攻擊也會(huì)更加困難。 
uint32_ttimestamp;
//時(shí)間戳,負(fù)責(zé)流同步
uint32_tssrc;
//同步源標(biāo)識(shí),32比特 用以識(shí)別同步源。標(biāo)識(shí)符被隨機(jī)生成,以使在同一個(gè)RTP會(huì)話期中沒(méi)有任何兩個(gè)同步源有相同的SSRC識(shí)別符。盡管多個(gè)源選擇同一個(gè)SSRC識(shí)別符的概率很低,所有RTP實(shí)現(xiàn)工具都必須準(zhǔn)備檢測(cè)和解決沖突。若一個(gè)源改變本身的源傳輸?shù)刂,必須選擇新的SSRC識(shí)別符,以避免被當(dāng)作一個(gè)環(huán)路源。
uint32_tcsrc[15];
//貢獻(xiàn)源標(biāo)識(shí)
}
trtp_rtp_header_t;
 
 

  1. rtp包結(jié)構(gòu),文件trtp_rtp_packet.h

typedefstruct trtp_rtp_packet_s

  1. {

  2. TSK_DECLARE_OBJECT;

  3.  

  4. trtp_rtp_header_t*header; //包頭

  5.  

  6. struct{

  7. void*data;

  8. constvoid* data_const;

  9. tsk_size_tsize;

  10. }payload; //負(fù)載,即承載內(nèi)容


  11. /*extension header as per RFC 3550 section 5.3.1 */

  12. struct{

  13. void*data;

  14. tsk_size_tsize; /* contains the first two 16-bit fields */

  15. }extension;

  16. }

  17. trtp_rtp_packet_t;

 

  1. rtp包的控制

 
上面兩個(gè)結(jié)構(gòu)用來(lái)標(biāo)示一個(gè)rtp包,同時(shí)提供了包的解析,創(chuàng)建等函數(shù)。
結(jié)構(gòu)trtp_manager_s負(fù)責(zé)rtp.rtcp包的管理,是更高層的抽象,上層應(yīng)用直接通過(guò)trtp_manager_s提供的api控制
rtp包,比如在網(wǎng)絡(luò)上發(fā)送音頻數(shù)據(jù),在音頻session結(jié)構(gòu)中包含trtp_manager_s用來(lái)管理經(jīng)過(guò)封裝的rtp包。
/**RTP/RTCP manager */
typedefstruct trtp_manager_s
{
TSK_DECLARE_OBJECT;
 
struct{
uint16_tseq_num;
uint32_ttimestamp;
uint32_tssrc;
uint8_tpayload_type;
 
char*remote_ip;
tnet_port_tremote_port;
structsockaddr_storage remote_addr;
 
char*public_ip;
tnet_port_tpublic_port;
 
constvoid* callback_data;
trtp_manager_rtp_cb_fcallback;
}rtp;
 
struct{
char*remote_ip;
tnet_port_tremote_port;
structsockaddr_storage remote_addr;
tnet_socket_t*local_socket;
 
char*public_ip;
tnet_port_tpublic_port;
 
constvoid* callback_data;
trtp_manager_rtcp_cb_fcallback;
}rtcp;

char*local_ip;
tsk_bool_tipv6;
tsk_bool_tstarted;
tsk_bool_tenable_rtcp;
tsk_bool_tsocket_disabled;
tnet_transport_t*transport;
}
trtp_manager_t;
 

  1. tdav是音視頻會(huì)話的抽象層,負(fù)責(zé)傳輸層的啟動(dòng),音頻會(huì)話,視頻會(huì)話,各種編碼的注冊(cè)。

 
 
 
 
對(duì)于音頻/視頻會(huì)話(session)tmedia_session_mgr_t管理,而tmedia_session_mgr_t則具體由sip信令控制會(huì)話的狀態(tài)。比如sip客戶端請(qǐng)求時(shí)通過(guò)tmedia_session_mgr_t構(gòu)造自己的sdp信息要借助此結(jié)構(gòu),當(dāng)客戶端對(duì)inviteACK應(yīng)答時(shí)同樣要指定自己的媒體信息。整個(gè)rtp流的啟動(dòng)入口都由tmedia_session_mgr_t控制。
各種媒體會(huì)話以插件的形式注冊(cè),如音頻會(huì)話在啟動(dòng)時(shí)注冊(cè)到tmedia_session_mgr_t的插件鏈表,并綁定start,stop,prepare回調(diào)。tmedia_session_mgr_tsip信令控制媒體流的接口。
 
tmedia_session_plugin_def_t為音頻視頻抽象接口,指定回調(diào)。如音頻會(huì)話,內(nèi)部會(huì)實(shí)現(xiàn)相應(yīng)的回調(diào)函數(shù)。
/**Virtual table used to define a session plugin */
typedefstruct tmedia_session_plugin_def_s
{
//!object definition used to create an instance of the session
consttsk_object_def_t* objdef;
 
//!the type of the session
tmedia_type_ttype;
//!the media name. e.g. "audio", "video", "message","image" etc.
constchar* media;

int(*set) (tmedia_session_t* , const tmedia_param_t*);
int(* prepare) (tmedia_session_t* );
int(* start) (tmedia_session_t* );
int(* pause) (tmedia_session_t* );
int(* stop) (tmedia_session_t* );
 
struct{/* Special case */
int(* send_dtmf) (tmedia_session_t*, uint8_t );
}audio;
 
consttsdp_header_M_t* (* get_local_offer) (tmedia_session_t* );
/*return zero if can handle the ro and non-zero otherwise */
int(* set_remote_offer) (tmedia_session_t* , const tsdp_header_M_t* );
}
tmedia_session_plugin_def_t;
 
tmedia_session_t為會(huì)話的抽象層,包含tmedia_session_plugin_def_t,
/**Base objct used for all media sessions */
typedefstruct tmedia_session_s
{
TSK_DECLARE_OBJECT;

//!unique id. If you want to modifiy this field then you must use @reftmedia_session_get_unique_id()
uint64_tid;
//!session type
tmedia_type_ttype;
//!list of codecs managed by this session
tmedia_codecs_L_t*codecs;
//!negociated codec
tmedia_codecs_L_t*neg_codecs;
//!whether the ro have been prepared (up to the manager to update thevalue)
tsk_bool_tro_changed;
//!whether the session have been initialized (up to the manager toupdate the value)
tsk_bool_tinitialized;
//!whether the session have been prepared (up to the manager to updatethe value)
tsk_bool_tprepared;
//!QoS
tmedia_qos_tline_t*qos;
//!bandwidth level
tmedia_bandwidth_level_tbl;
 
struct{
tsdp_header_M_t*lo;
tsdp_header_M_t*ro;
}M;
 
//!plugin used to create the session
conststruct tmedia_session_plugin_def_s* plugin;
}
tmedia_session_t;
 
 
 
 
sipsession
 
 
 
 
trtp_manager_t
 
 
 
tmedia_session_t tmedia_session_plugin_def_s
 
 
 
 
 
 
 
 
使用過(guò)程:
tdav_init注冊(cè)音頻,視頻,多媒體session;注冊(cè)支持的編碼類型,注冊(cè)支持的媒體信息承載類型(文本,流等)。
tdav_init-> register sessions, codecs.

 
tmedia_session_mgr_create-> tmedia_session_mgr_ctor,sessions,qos,sdp.
 
_tmedia_session_mgr_load_sessions,創(chuàng)建音視頻會(huì)話。
 
tmedia_session_create,創(chuàng)建具體會(huì)話插件類型,tdav_session_video/audio_ctor
 
tmedia_session_init,初始化
 
tmedia_session_load_codecs,此會(huì)話支持的編碼類型
 
tmedia_codec_create,穿件具體編碼類型。
 
創(chuàng)建過(guò)程
 
 
 
 
 
 
 
準(zhǔn)備階段
trtp_manager_prepare,指定傳輸層接收數(shù)據(jù)回調(diào)trtp_transport_layer_cb
tdav_session_audio_prepare,trtp_manager_createtrtp_manager_set_rtp_callback
tnet_transport_create
tnet_transport_set_callback
 
啟動(dòng)
 
tmedia_session_mgr_start(),啟動(dòng)所有上面創(chuàng)建的會(huì)話類型,啟動(dòng)之前一定要設(shè)置sdp信息
Startsthe session manager by
startingall underlying sessions.You should set
bothremote and local offers before calling this
session->plugin->start(),如視頻會(huì)話啟動(dòng) ,tdav_session_video/audio.c
 
trtp_manager_set_rtp_remote,設(shè)置對(duì)端ip,port,后續(xù)發(fā)送rtp包時(shí)構(gòu)造包頭用
 
trtp_manager_set_payload_type,設(shè)置此次會(huì)話用什么編碼類型,編碼類型通過(guò)協(xié)商后選擇最佳
trtp_manager_start,啟動(dòng)rtp,rtcp包管理,
tnet_transport_start,啟動(dòng)傳輸層線程,綁定socket地址,開(kāi)始接收udp數(shù)據(jù),tnet_transport_mainthread
 
 
 
 
請(qǐng)求或響應(yīng)中sdpcodec匹配過(guò)程
tmedia_session_match_codec->tmedia_codec_match_fmtp->tdav_codec_h264_fmtp_match->
tdav_codec_h264_get_profile(根據(jù)fmt獲取對(duì)方的profile版本),
 
當(dāng)發(fā)起外乎請(qǐng)求時(shí)codecsdp處理關(guān)系,
發(fā)起invite或?qū)Ψ礁拿襟w信息時(shí)要把codec信息加載到sdp消息體中,
對(duì)于video,audio過(guò)程是一樣的。
 
(videosession from codecs to sdp)
tdav_session_video_get_lo
|
tsdp_header_M_create(創(chuàng)建sdp媒體頭)
 
|
tmedia_session_match_codec(此函數(shù)最終會(huì)返回一個(gè)協(xié)商成功的編碼類型)
 
對(duì)于h264編碼格式,此函數(shù)內(nèi)部調(diào)用過(guò)程,遍歷協(xié)議棧初始化時(shí)指定的編碼鏈表,用此次請(qǐng)求的sdp消息體中的編碼與自己的編碼鏈表比較。->tmedia_codec_match_fmtp->tdav_codec_h264_fmtp_match->
tdav_codec_h264_get_profile
 
tmedia_session_match_codec返回協(xié)商成功的編碼列表(即雙方都支持的編碼類型列表)后復(fù)制給協(xié)議棧,
self->neg_codecs=tmedia_session_match_codec
然后調(diào)用tmedia_codec_video_set_callback設(shè)置此編碼類型對(duì)應(yīng)的回調(diào)函數(shù),當(dāng)想發(fā)送rtp包時(shí)直接觸發(fā)此回調(diào)函數(shù)即可完成發(fā)送rtp包的任務(wù)。
tmedia_codec_video_set_callback((tmedia_codec_video_t*)TSK_LIST_FIRST_DATA(self->neg_codecs),tdav_session_video_raw_cb, self);
 
tdav_session_video_raw_cb為具體的毀掉函數(shù),內(nèi)部為調(diào)用trtp_manager_send_rtp,發(fā)送rtp包。
 
值得注意的是傳給函數(shù)的tdav_session_video_raw_cb數(shù)據(jù)只是未經(jīng)過(guò)加工成rtp包的裸數(shù)據(jù),tdav_session_video_raw_cb內(nèi)部調(diào)用trtp_manager_send_rt,由trtp_manager_send_rt來(lái)把數(shù)據(jù)加工成rtp包,
然后調(diào)用傳輸層發(fā)送到網(wǎng)絡(luò)上。
 
/*Encapsulate raw data into RTP packet and send it over the network
*Very IMPORTANT: For voice packets, the marker bits indicates thebeginning of a talkspurt */
inttrtp_manager_send_rtp(trtp_manager_t* self, const void* data,tsk_size_t size, uint32_t duration, tsk_bool_t marker, tsk_bool_tlast_packet)
 
trtp_manager_send_rtp內(nèi)部又具體調(diào)用trtp_rtp_packet_create,創(chuàng)建rtp格式的數(shù)據(jù)包,包括rtp消息頭的創(chuàng)建,初始化默認(rèn)參數(shù)(version,marker,payload_type,seq_num)。然后調(diào)用trtp_rtp_packet_serializertp包序列化到一個(gè)buffer中。
trtp_manager_send_rtp最后調(diào)用tnet_sockfd_sendto傳輸層函數(shù)完成實(shí)際發(fā)送到網(wǎng)絡(luò)上。
 
 
 
回到設(shè)置tmedia_codec_video_set_callback完畢后,tdav_session_video_get_lo調(diào)用tmedia_codec_to_sdp
把協(xié)商后的編碼類型的信息轉(zhuǎn)換成sdp格式的信息。
tmedia_codec_to_sdp(self->neg_codecs,self->M.lo);保存到M.lo屬性,即本地的媒體信息。
tmedia_codec_to_sdp分析:
此函數(shù)的功能即把協(xié)商后的編碼鏈表放到協(xié)議棧的sdp屬性中,這樣以后發(fā)送invite請(qǐng)求時(shí)就可以直接用。
/**@ingrouptmedia_codec_group
*Serialize a list of codecs to sdp (m=line) message.

*Will add: fmt, rtpmap and fmtp.
*@param codecs The list of codecs to convert
*@param m The destination
*@retval Zero if succeed and non-zero error code otherwise
*/
inttmedia_codec_to_sdp(const tmedia_codecs_L_t* codecs, tsdp_header_M_t*m)
 
TSK_DEBUG_INFO("Serializea list of codecs to sdp (m=line) message/n");
tsk_list_foreach(item,codecs){
遍歷每個(gè)編碼類型,添加fmt,rtpmap屬性,fmtp屬性(tmedia_codec_get_fmtp,對(duì)于h264格式即調(diào)用tmedia_codec_h264_get_fmtp
 
最后,tdav_session_video_get_lo內(nèi)部在屬性M.ro(即已經(jīng)有請(qǐng)求的sdp信息)非空時(shí)考慮此請(qǐng)求是否為
保持還是接回,通過(guò)設(shè)置spd屬性,sendrecv,sendonly來(lái)提示類型。最后,設(shè)置Qos信息。
 
 
流程tdav_session_video_get_lo
|
tsdp_header_M_create(創(chuàng)建sdp媒體頭)
 
|
tmedia_session_match_codec
|
tmedia_codec_video_set_callback
|
tmedia_codec_to_sdp
 
 
但是
tdav_session_video_get_lo又是由誰(shuí)觸發(fā)的呢?tdav_session_video_get_lo為某一具體session的回調(diào),
比如視頻的session回調(diào),音頻的回調(diào),視頻,音頻的sessionplugin的方式掛在到session中。
 
/**Virtual table used to define a session plugin */
typedefstruct tmedia_session_plugin_def_s
{
//!object definition used to create an instance of the session
consttsk_object_def_t* objdef;
 
//!the type of the session
tmedia_type_ttype;
//!the media name. e.g. "audio", "video", "message","image" etc.
constchar* media;

int(*set) (tmedia_session_t* , const tmedia_param_t*);
int(* prepare) (tmedia_session_t* );
int(* start) (tmedia_session_t* );
int(* pause) (tmedia_session_t* );
int(* stop) (tmedia_session_t* );
 
struct{/* Special case */
int(* send_dtmf) (tmedia_session_t*, uint8_t );
}audio;
 
consttsdp_header_M_t* (* get_local_offer) (tmedia_session_t* );
/*return zero if can handle the ro and non-zero otherwise */
int(* set_remote_offer) (tmedia_session_t* , const tsdp_header_M_t* );
}
tmedia_session_plugin_def_t;
 
 
tdav_session_video_get_lo即為get_local_offer的具體回調(diào)。
get_local_offertmedia_session_get_lo調(diào)用。tmedia_session_get_lo又被tmedia_session_mgr_get_lo
調(diào)用,正是上面提到的tmedia_session_mgr為管理session的抽象接口,用來(lái)與sip信令交互。
整個(gè)流程為:
tmedia_session_mgr
|
tmedia_session_get_lo
|
tdav_session_video_get_lo
|
tsdp_header_M_create(創(chuàng)建sdp媒體頭)
|
tmedia_session_match_codec
|
tmedia_codec_video_set_callback
|
tmedia_codec_to_sdp
 
 
 
tmedia_session_mgr_get_lo又被誰(shuí)觸發(fā)呢?
 
剛才說(shuō)了,是由sip協(xié)議棧調(diào)用的,具體有這樣幾個(gè)與sdp協(xié)商有關(guān)的sip點(diǎn),我們知道,invite請(qǐng)求以及200ok應(yīng)答,183響應(yīng),100響應(yīng)的確認(rèn)(prack)中有sdp信息:
 
 
1)發(fā)送或者更新請(qǐng)求(invite)
 
send_INVITEorUPDATE
//send INVITE/UPDATE request
intsend_INVITEorUPDATE(tsip_dialog_invite_t *self, tsk_bool_t is_INVITE,tsk_bool_t force_sdp)

  1. prack響應(yīng)

//Send PRACK
intsend_PRACK(tsip_dialog_invite_t *self, const tsip_response_t* r1xx)

  1. //Send ACK

intsend_ACK(tsip_dialog_invite_t *self, const tsip_response_t*r2xxINVITE)
初始請(qǐng)求中沒(méi)有sdp信息,在ack中需要攜帶sdp信息
 
4)發(fā)送響應(yīng)時(shí)
/Send any response
intsend_RESPONSE(tsip_dialog_invite_t *self, const tsip_request_t*request, short code, const char* phrase, tsk_bool_t force_sdp)
 
 
2.處理請(qǐng)求中的sdp信息過(guò)程
tsip_dialog_invite_process_ro
|
tmedia_session_mgr_set_ro
 
tsip_dialog_invite_process_rosip信令中處理sdp信息的入口,在狀態(tài)機(jī)的回調(diào)中適時(shí)調(diào)用
。比如在保持狀態(tài)轉(zhuǎn)到接回狀態(tài)。
 
tsip_dialog_invite_process_ro會(huì)初始化mgr,啟動(dòng),
tmedia_session_mgr_create,tmedia_session_mgr_set_rotmedia_session_mgr_set_natt_ctx,
tmedia_session_mgr_start
 
 
您需要登錄后才可以回帖 登錄 | 注冊(cè)

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號(hào)-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號(hào):11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報(bào)專區(qū)
中國(guó)互聯(lián)網(wǎng)協(xié)會(huì)會(huì)員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過(guò)ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請(qǐng)注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP