函数调用结构图
RTMPDump (libRTMP)的整体的函数调用结构图如下图所示。
RTMP_Connect()函数用于建立RTMP中的NetConnection;
- //连接
- int
- RTMP_Connect(RTMP *r, RTMPPacket *cp)
- {
- //Socket结构体
- struct sockaddr_in service;
- if (!r->Link.hostname.av_len)
- return FALSE;
- memset(&service, 0, sizeof(struct sockaddr_in));
- service.sin_family = AF_INET;
- if (r->Link.socksport)
- {
- //加入地址信息
- /* 使用SOCKS连接 */
- if (!add_addr_info(&service, &r->Link.sockshost, r->Link.socksport))
- return FALSE;
- }
- else
- {
- /* 直接连接 */
- if (!add_addr_info(&service, &r->Link.hostname, r->Link.port))
- return FALSE;
- }
- //-----------------
- r->dlg->AppendCInfo("建立连接:第0次连接。开始建立Socket连接");
- //-----------------------------
- if (!RTMP_Connect0(r, (struct sockaddr *)&service)){
- r->dlg->AppendCInfo("建立连接:第0次连接。建立Socket连接失败");
- return FALSE;
- }
- //-----------------
- r->dlg->AppendCInfo("建立连接:第0次连接。建立Socket连接成功");
- //-----------------------------
- r->m_bSendCounter = TRUE;
- return RTMP_Connect1(r, cp);
- }
RTMP_Connect0()
- //sockaddr是Linux网络编程的地址结构体一种,其定义如下:
- //struct sockaddr{
- // unsigned short sa_family;
- // char sa_data[14];
- //};
- //说明:sa_family:是地址家族,也称作,协议族,一般都是“AF_xxx”的形式。通常大多用的是都是AF_INET。
- // sa_data:是14字节协议地址。
- //有时不使用sockaddr,而使用sockaddr_in(多用在windows)(等价)
- //struct sockaddr_in {
- // short int sin_family; /* Address family */
- // unsigned short int sin_port; /* Port number */
- // struct in_addr sin_addr; /* Internet address */
- // unsigned char sin_zero[8]; /* Same size as struct sockaddr */
- //};
- //union {
- // struct{
- // unsigned char s_b1,s_b2,s_b3,s_b4;
- // } S_un_b;
- // struct {
- // unsigned short s_w1,s_w2;
- // } S_un_w;
- // unsigned long S_addr;
- // } S_un;
- //} in_addr;
- //第0次连接,建立Socket连接
- int
- RTMP_Connect0(RTMP *r, struct sockaddr * service)
- {
- int on = 1;
- r->m_sb.sb_timedout = FALSE;
- r->m_pausing = 0;
- r->m_fDuration = 0.0;
- //创建一个Socket,并把Socket序号赋值给相应变量
- //-----------------
- r->dlg->AppendCInfo("建立连接:第0次连接。create一个Socket");
- //-----------------------------
- r->m_sb.sb_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (r->m_sb.sb_socket != -1)
- {
- //定义函数 int connect (int sockfd,struct sockaddr * serv_addr,int addrlen);
- //函数说明 connect()用来将参数sockfd 的Socket(刚刚创建)连至参数serv_addr
- //指定的网络地址。参数addrlen为sockaddr的结构长度。
- //连接
- RTMP_LogPrintf("建立Socket连接!\n");
- //-----------------
- r->dlg->AppendCInfo("建立连接:第0次连接。connect该Socket");
- //-----------------------------
- if (connect(r->m_sb.sb_socket, service, sizeof(struct sockaddr)) < 0)
- {
- //-----------------
- r->dlg->AppendCInfo("建立连接:第0次连接。connect该Socket失败");
- //-----------------------------
- int err = GetSockError();
- RTMP_Log(RTMP_LOGERROR, "%s, failed to connect socket. %d (%s)",
- __FUNCTION__, err, strerror(err));
- RTMP_Close(r);
- return FALSE;
- }
- //-----------------
- r->dlg->AppendCInfo("建立连接:第0次连接。connect该Socket成功");
- //-----------------------------
- //指定了端口号。注:这不是必需的。
- if (r->Link.socksport)
- {
- RTMP_Log(RTMP_LOGDEBUG, "%s ... SOCKS negotiation", __FUNCTION__);
- //谈判?发送数据报以进行谈判?!
- if (!SocksNegotiate(r))
- {
- RTMP_Log(RTMP_LOGERROR, "%s, SOCKS negotiation failed.", __FUNCTION__);
- RTMP_Close(r);
- return FALSE;
- }
- }
- }
- else
- {
- RTMP_Log(RTMP_LOGERROR, "%s, failed to create socket. Error: %d", __FUNCTION__,
- GetSockError());
- return FALSE;
- }
- /* set timeout */
- //超时
- {
- SET_RCVTIMEO(tv, r->Link.timeout);
- if (setsockopt
- (r->m_sb.sb_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)))
- {
- RTMP_Log(RTMP_LOGERROR, "%s, Setting socket timeout to %ds failed!",
- __FUNCTION__, r->Link.timeout);
- }
- }
- setsockopt(r->m_sb.sb_socket, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof(on));
- return TRUE;
- }
再来看看RTMP_Connect1(),这是真正建立RTMP连接的函数:
RTMP_Connect1()
- //第1次连接,从握手开始
- int
- RTMP_Connect1(RTMP *r, RTMPPacket *cp)
- {
- if (r->Link.protocol & RTMP_FEATURE_SSL)
- {
- #if defined(CRYPTO) && !defined(NO_SSL)
- TLS_client(RTMP_TLS_ctx, r->m_sb.sb_ssl);
- TLS_setfd((SSL *)r->m_sb.sb_ssl, r->m_sb.sb_socket);
- if (TLS_connect((SSL *)r->m_sb.sb_ssl) < 0)
- {
- RTMP_Log(RTMP_LOGERROR, "%s, TLS_Connect failed", __FUNCTION__);
- RTMP_Close(r);
- return FALSE;
- }
- #else
- RTMP_Log(RTMP_LOGERROR, "%s, no SSL/TLS support", __FUNCTION__);
- RTMP_Close(r);
- return FALSE;
- #endif
- }
- //使用HTTP
- if (r->Link.protocol & RTMP_FEATURE_HTTP)
- {
- r->m_msgCounter = 1;
- r->m_clientID.av_val = NULL;
- r->m_clientID.av_len = 0;
- HTTP_Post(r, RTMPT_OPEN, "", 1);
- HTTP_read(r, 1);
- r->m_msgCounter = 0;
- }
- RTMP_Log(RTMP_LOGDEBUG, "%s, ... connected, handshaking", __FUNCTION__);
- //握手----------------
- r->dlg->AppendCInfo("建立连接:第1次连接。开始握手(HandShake)");
- //-----------------------------
- RTMP_LogPrintf("开始握手(HandShake)!\n");
- if (!HandShake(r, TRUE))
- {
- //----------------
- r->dlg->AppendCInfo("建立连接:第1次连接。握手(HandShake)失败!");
- //-----------------------------
- RTMP_Log(RTMP_LOGERROR, "%s, handshake failed.", __FUNCTION__);
- RTMP_Close(r);
- return FALSE;
- }
- //----------------
- r->dlg->AppendCInfo("建立连接:第1次连接。握手(HandShake)成功");
- //-----------------------------
- RTMP_LogPrintf("握手(HandShake)完毕!\n");
- RTMP_Log(RTMP_LOGDEBUG, "%s, handshaked", __FUNCTION__);
- //发送“connect”命令--------------
- //----------------
- r->dlg->AppendCInfo("建立连接:第1次连接。开始建立网络连接(NetConnection)");
- //-----------------------------
- RTMP_LogPrintf("开始建立网络连接(NetConnection)!\n");
- //----------------
- r->dlg->AppendCInfo("发送数据。消息 命令 (typeID=20) (Connect)。");
- //-----------------------------
- if (!SendConnectPacket(r, cp))
- {
- //----------------
- r->dlg->AppendCInfo("建立连接:第1次连接。建立网络连接(NetConnection)失败!");
- //-----------------------------
- RTMP_Log(RTMP_LOGERROR, "%s, RTMP connect failed.", __FUNCTION__);
- RTMP_Close(r);
- return FALSE;
- }
- //----------------
- r->dlg->AppendCInfo("建立连接:第1次连接。建立网络连接(NetConnection)成功");
- //-----------------------------
- RTMP_LogPrintf("命令消息“Connect”发送完毕!\n");
- return TRUE;
- }