1. librtmp源码之RTMP_SendCtrl
// 发送用戶控制消息
//Ping 是 RTMP 中最神秘的消息,直到现在我们还没有完全解释它。总之,Ping 消息用作客户端和服务器之间交换的特殊命令。此页面旨在记录所有已知的 Ping 消息。预计名单会增长。
//
//Ping 数据包的类型为 0x4,包含两个强制参数和两个可选参数。第一个参数是 Ping 的类型,简称整数。第二个参数是 ping 的目标。由于 Ping 始终在 Channel 2(控制通道)中发送,并且 RTMP 标头中的目标对象始终为 0,这意味着 Connection 对象,因此有必要放置一个额外的参数来指示 Ping 发送到的确切目标对象。第二个参数承担这个责任。该值与 RTMP 头中的目标对象字段含义相同。 (第二个值也可以做其他用途,比如RTT Ping/Pong。它用作时间戳。)第三个和第四个参数是可选的,可以看作是Ping包的参数。以下是 Ping 消息的无穷无尽的列表。
//
// * 类型 0:清除流。没有第三个和第四个参数。第二个参数可以是 0。建立连接后,服务器会向客户端发送 Ping 0,0。该消息还将在 Play 开始时发送给客户端,并响应 Seek 或 Pause/Resume 请求。此 Ping 告诉客户端使用下一个数据包服务器发送的时间戳重新校准时钟。
// * 类型 1:告诉流清除播放缓冲区。
// * 类型 3:客户端的缓冲时间。第三个参数是以毫秒为单位的缓冲时间。
// * 类型 4:重置流。在 VOD 的情况下与类型 0 一起使用。通常在类型 0 之前发送。
// * 类型 6:从服务器 Ping 客户端。第二个参数是当前时间。
// * 类型 7:来自客户的 Pong 回复。第二个参数是服务器发送他的 ping 请求的时间。
// * 类型 26:SWFVerification 请求
// * 类型 27:SWFVerification 响应
int
RTMP_SendCtrl(RTMP *r, short nType, unsigned int nObject, unsigned int nTime)
{
RTMPPacket packet;
char pbuf[256], *pend = pbuf + sizeof(pbuf);
int nSize;
char *buf;
RTMP_Log(RTMP_LOGDEBUG, "sending ctrl. type: 0x%04x", (unsigned short)nType);
packet.m_nChannel = 0x02; /* control channel (ping) */
packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
// #define RTMP_PACKET_TYPE_CONTROL 0x04
packet.m_packetType = RTMP_PACKET_TYPE_CONTROL;
packet.m_nTimeStamp = 0; /* RTMP_GetTime(); */
packet.m_nInfoField2 = 0;
packet.m_hasAbsTimestamp = 0;
packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
switch(nType) {
case 0x03: nSize = 10; break; /* buffer time */
case 0x1A: nSize = 3; break; /* SWF verify request */
case 0x1B: nSize = 44; break; /* SWF verify response */
default: nSize = 6; break;
}
packet.m_nBodySize = nSize;
buf = packet.m_body;
buf = AMF_EncodeInt16(buf, pend, nType);
if (nType == 0x1B)
{
#ifdef CRYPTO
memcpy(buf, r->Link.SWFVerificationResponse, 42);
RTMP_Log(RTMP_LOGDEBUG, "Sending SWFVerification response: ");
RTMP_LogHex(RTMP_LOGDEBUG, (uint8_t *)packet.m_body, packet.m_nBodySize);
#endif
}
else if (nType == 0x1A)
{
*buf = nObject & 0xff;
}
else
{
if (nSize > 2)
buf = AMF_EncodeInt32(buf, pend, nObject);
if (nSize > 6)
buf = AMF_EncodeInt32(buf, pend, nTime);
}
return RTMP_SendPacket(r, &packet, FALSE);
}
参考: