RTMP学习(八)rtmpdump源码阅读(3)初始化与URL解析

初始化与URL解析


初始化


    初始化实际就是创建rtmp对象实例,然后初始化各个成员。

// 创建rtmp对象,设置rtmp实例的属性
void
RTMP_Init(RTMP *r)
{
#ifdef CRYPTO
  if (!RTMP_TLS_ctx)
    RTMP_TLS_Init();
#endif

  memset(r, 0, sizeof(RTMP));
  r->m_sb.sb_socket = -1;
  r->m_inChunkSize = RTMP_DEFAULT_CHUNKSIZE;
  r->m_outChunkSize = RTMP_DEFAULT_CHUNKSIZE;
  r->m_nBufferMS = 30000;
  r->m_nClientBW = 2500000;
  r->m_nClientBW2 = 2;
  r->m_nServerBW = 2500000;
  r->m_fAudioCodecs = 3191.0;
  r->m_fVideoCodecs = 252.0;
  r->Link.timeout = 30;
  r->Link.swfAge = 30;
  r->Link.CombineConnectPacket = TRUE;
  r->Link.ConnectPacket = FALSE;
}




URL解析


    URL解析的目的是把URL中的各个成分提取出来,为接下来连接的建立做准备。

    以 rtmp://live.hkstv.hk.lxdns.com/live/hks为例子,它经过解析之后,就可以得到下面各个部分:

        协议:rtmp
        host:live.hkstv.hk.lxdns.com/live/hks
        path:hks
        application:live/hks

/*
** 解析rtmp的URL
*/
int RTMP_ParseURL(const char *url, int *protocol, AVal *host, unsigned int *port,
	AVal *playpath, AVal *app)
{
	char *p, *end, *col, *ques, *slash;

	RTMP_Log(RTMP_LOGDEBUG, "Parsing...");

	// 设置默认的协议:rtmp
	*protocol = RTMP_PROTOCOL_RTMP;
	*port = 0;
	playpath->av_len = 0;
	playpath->av_val = NULL;
	app->av_len = 0;
	app->av_val = NULL;

	/* Old School Parsing */

	/* look for usual :// pattern */
	p = strstr(url, "://");
	if (!p) {
		RTMP_Log(RTMP_LOGERROR, "RTMP URL: No :// in url!");
		return FALSE;
	}
	{
		int len = (int)(p - url);

		// 解析协议头 
		/*
		 ** 支持的协议有:
		 ** rtmp
		 ** rtmpe
		 ** rtmpt
		 ** rtmps
		 ** rtmpte
		 ** rtmpts
		 ** rtmfp
		 */
		if (len == 4 && strncasecmp(url, "rtmp", 4) == 0)
			*protocol = RTMP_PROTOCOL_RTMP;
		else if (len == 5 && strncasecmp(url, "rtmpt", 5) == 0)
			*protocol = RTMP_PROTOCOL_RTMPT;
		else if (len == 5 && strncasecmp(url, "rtmps", 5) == 0)
			*protocol = RTMP_PROTOCOL_RTMPS;
		else if (len == 5 && strncasecmp(url, "rtmpe", 5) == 0)
			*protocol = RTMP_PROTOCOL_RTMPE;
		else if (len == 5 && strncasecmp(url, "rtmfp", 5) == 0)
			*protocol = RTMP_PROTOCOL_RTMFP;
		else if (len == 6 && strncasecmp(url, "rtmpte", 6) == 0)
			*protocol = RTMP_PROTOCOL_RTMPTE;
		else if (len == 6 && strncasecmp(url, "rtmpts", 6) == 0)
			*protocol = RTMP_PROTOCOL_RTMPTS;
		else {
			RTMP_Log(RTMP_LOGWARNING, "Unknown protocol!\n");
			goto parsehost;
		}
	}

	RTMP_Log(RTMP_LOGDEBUG, "Parsed protocol: %d", *protocol);

parsehost:
	/* let's get the hostname */
	p += 3;

	/* check for sudden death */
	if (*p == 0) {
		RTMP_Log(RTMP_LOGWARNING, "No hostname in URL!");
		return FALSE;
	}

	end = p + strlen(p);
	col = strchr(p, ':');
	ques = strchr(p, '?');
	slash = strchr(p, '/');

	// 解析主机名
	{
		int hostlen;
		if (slash)
			hostlen = slash - p;
		else
			hostlen = end - p;
		if (col && col - p < hostlen)
			hostlen = col - p;

		if (hostlen < 256) {
			host->av_val = p;
			host->av_len = hostlen;
			RTMP_Log(RTMP_LOGDEBUG, "Parsed host    : %.*s", hostlen, host->av_val);
		}
		else {
			RTMP_Log(RTMP_LOGWARNING, "Hostname exceeds 255 characters!");
		}

		p += hostlen;
	}

	// 解析端口号
	/* get the port number if available */
	if (*p == ':') {
		unsigned int p2;
		p++;
		p2 = atoi(p);
		if (p2 > 65535) {
			RTMP_Log(RTMP_LOGWARNING, "Invalid port number!");
		}
		else {
			*port = p2;
		}
	}

	if (!slash) {
		RTMP_Log(RTMP_LOGWARNING, "No application or playpath in URL!");
		return TRUE;
	}
	p = slash + 1;

	// 解析app
	{
		/* parse application
		 *
		 * rtmp://host[:port]/app[/appinstance][/...]
		 * application = app[/appinstance]
		 */

		char *slash2, *slash3 = NULL;
		int applen, appnamelen;

		slash2 = strchr(p, '/');
		if (slash2)
			slash3 = strchr(slash2 + 1, '/');

		applen = end - p; /* ondemand, pass all parameters as app */
		appnamelen = applen; /* ondemand length */

		if (ques && strstr(p, "slist=")) { /* whatever it is, the '?' and slist= means we need to use everything as app and parse plapath from slist= */
			appnamelen = ques - p;
		}
		else if (strncmp(p, "ondemand/", 9) == 0) {
			/* app = ondemand/foobar, only pass app=ondemand */
			applen = 8;
			appnamelen = 8;
		}
		else { /* app!=ondemand, so app is app[/appinstance] */
			if (slash3)
				appnamelen = slash3 - p;
			else if (slash2)
				appnamelen = slash2 - p;

			applen = appnamelen;
		}

		app->av_val = p;
		app->av_len = applen;
		RTMP_Log(RTMP_LOGDEBUG, "Parsed app     : %.*s", applen, p);

		p += appnamelen;
	}

	if (*p == '/')
		p++;

	// 解析path
	if (end - p) {
		AVal av = { p, end - p };
		RTMP_ParsePlaypath(&av, playpath);
	}

	return TRUE;
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值