示例#1
0
文件: sdp.cpp 项目: 9aa5/crtmpserver
bool SDP::ParseSDP(SDP &sdp, string &raw) {
	//FINEST("%s", STR(raw));
	//1. Reset
	sdp.Reset();

	//2. Prepare the sections
	sdp[SDP_SESSION].IsArray(false);
	sdp[SDP_MEDIATRACKS].IsArray(true);

	//3. Split the raw content into lines
	replace(raw, "\r\n", "\n");
	vector<string> lines;
	split(raw, "\n", lines);

	//4. Detect the media tracks indexes
	vector<uint32_t> trackIndexes;
	for (uint32_t i = 0; i < lines.size(); i++) {
		trim(lines[i]);
		if (lines[i].find("m=") == 0) {
			ADD_VECTOR_END(trackIndexes, i);
		}
	}
	if (trackIndexes.size() == 0) {
		FATAL("No tracks found");
		return false;
	}

	//5. Parse the header
	if (!ParseSection(sdp[SDP_SESSION], lines, 0, trackIndexes[0])) {
		FATAL("Unable to parse header");
		return false;
	}

	//6. Parse the media sections
	Variant media;
	for (uint32_t i = 0; i < trackIndexes.size() - 1; i++) {
		media.Reset();
		media.IsArray(false);
		if (!ParseSection(media, lines, trackIndexes[i], trackIndexes[i + 1] - trackIndexes[i])) {
			FATAL("Unable to parse header");
			return false;
		}
		sdp[SDP_MEDIATRACKS].PushToArray(media);
	}

	//7. Parse the last media section
	media.Reset();
	media.IsArray(false);
	if (!ParseSection(media, lines,
			trackIndexes[(uint32_t) trackIndexes.size() - 1],
			(uint32_t) trackIndexes.size() - trackIndexes[(uint32_t) trackIndexes.size() - 1])) {
		FATAL("Unable to parse header");
		return false;
	}
	sdp[SDP_MEDIATRACKS].PushToArray(media);


	return true;
}
示例#2
0
文件: sdp.cpp 项目: Undev/crtmpserver
bool SDP::ParseSDPLineA(string &attributeName, Variant &value, string line) {
	string::size_type pos = line.find(':');
	if ((pos == string::npos)
			|| (pos == 0)
			|| (pos == (line.size() - 1))) {
		attributeName = line;
		value = (bool)true;
		return true;
	}

	attributeName = line.substr(0, pos);
	string rawValue = line.substr(line.find(':') + 1);
	if (attributeName == "control") {
		value = rawValue;
		return true;
	} else if (attributeName == "maxprate") {
		value = (double) strtod(STR(rawValue), NULL);
		return true;
	} else if (attributeName.find("x-") == 0) {
		value = rawValue;
		return true;
	} else if (attributeName == "rtpmap") {
		//rtpmap:<payload type> <encoding name>/<clock rate>[/<encoding parameters>]
		vector<string> parts;
		split(rawValue, " ", parts);
		if (parts.size() != 2)
			return false;
		value["payloadType"] = (uint8_t) atoi(STR(parts[0]));
		split(parts[1], "/", parts);
		if ((parts.size() != 2) && (parts.size() != 3))
			return false;
		value["encodingName"] = parts[0];
		if (lowerCase((string) value["encodingName"]) == "h264") {
			value["encodingName"] = (uint64_t) CODEC_VIDEO_AVC;
		} else if ((string) lowerCase(value["encodingName"]) == "mpeg4-generic") {
			value["encodingName"] = (uint64_t) CODEC_AUDIO_AAC;
		} else {
			WARN("Invalid codec");
			value.Reset();
			return true;
		}
		value["clockRate"] = (uint32_t) atoi(STR(parts[1]));
		if (parts.size() == 3) {
			value["encodingParameters"] = parts[2];
		}

		return true;
	} else if (attributeName == "fmtp") {
		replace(rawValue, "; ", ";");
		vector<string> parts;
		split(rawValue, " ", parts);
		if (parts.size() != 2)
			return false;
		value["payloadType"] = (uint8_t) atoi(STR(parts[0]));
		map<string, string> temp = mapping(parts[1], ";", "=", false);

		FOR_MAP(temp, string, string, i) {
			value[MAP_KEY(i)] = MAP_VAL(i);
		}
示例#3
0
void RTSPProtocol::GetStats(Variant &info, uint32_t namespaceId) {
  BaseProtocol::GetStats(info, namespaceId);
  info["streams"].IsArray(true);
  Variant si;
  if (GetApplication() != NULL) {
    StreamsManager *pStreamsManager = GetApplication()->GetStreamsManager();
    map<uint32_t, BaseStream*> streams = pStreamsManager->FindByProtocolId(GetId());

    FOR_MAP(streams, uint32_t, BaseStream *, i) {
      si.Reset();
      MAP_VAL(i)->GetStats(si, namespaceId);
      info["streams"].PushToArray(si);
    }
示例#4
0
bool PopStack(lua_State *pLuaState, Variant &variant) {
	variant.Reset();
	variant.IsArray(true);
	while (lua_gettop(pLuaState) > 0) {
		Variant temp;
		if (!PopVariant(pLuaState, temp)) {
			FATAL("Unable to pop variant");
			return false;
		}
		variant.PushToArray(temp);
	}
	return true;
}
示例#5
0
文件: sdp.cpp 项目: 9aa5/crtmpserver
bool SDP::ParseTransportLine(string raw, Variant &result) {
	//raw = "MP2T/H2221/UDP;unicast;destination=192.168.1.150;client_port=11112,MP2T/H2221/UDP;multicast,RAW/RAW/UDP;unicast;destination=192.168.1.150;client_port=11112,RAW/RAW/UDP;multicast";
	//raw = "MP2T/H2221/UDP;unicast;destination=192.168.1.150;client_port=11112," + raw;
	result.Reset();
	result["original"] = raw;
	result["alternatives"].IsArray(true);

	vector<string> parts;
	split(raw, ",", parts);
	for (vector<string>::size_type i = 0; i < parts.size(); i++) {
		Variant temp;
		if (!ParseTransportLinePart(parts[i], temp)) {
			WARN("Invalid transport part: %s", STR(parts[i]));
			continue;
		}
		result["alternatives"].PushToArray(temp);
	}
	//FINEST("%s", STR(result.ToString()));
	return result["alternatives"].MapSize() != 0;
}
bool RTMPProtocolSerializer::Deserialize(Header &header, IOBuffer &buffer,
		Variant &message) {
	message.Reset();
	message[RM_HEADER] = header.GetVariant();
	switch (H_MT(header)) {
		case RM_HEADER_MESSAGETYPE_NOTIFY:
		{
			return DeserializeNotify(buffer, message[RM_NOTIFY]);
		}
		case RM_HEADER_MESSAGETYPE_FLEXSTREAMSEND:
		{
			return DeserializeFlexStreamSend(buffer, message[RM_FLEXSTREAMSEND]);
		}
		case RM_HEADER_MESSAGETYPE_INVOKE:
		case RM_HEADER_MESSAGETYPE_FLEX:
		{
			message[RM_INVOKE][RM_INVOKE_IS_FLEX] =
					(bool)(H_MT(header) == RM_HEADER_MESSAGETYPE_FLEX);
			return DeserializeInvoke(buffer, message[RM_INVOKE]);
		}
		case RM_HEADER_MESSAGETYPE_FLEXSHAREDOBJECT:
		{
			//TODO: This is a hack. We store the data on RM_SHAREDOBJECT
			//instead of RM_FLEXSHAREDOBJECT
			//return DeserializeFlexSharedObject(buffer, message[RM_FLEXSHAREDOBJECT]);
			return DeserializeFlexSharedObject(buffer, message[RM_SHAREDOBJECT]);
		}
		case RM_HEADER_MESSAGETYPE_SHAREDOBJECT:
		{
			return DeserializeSharedObject(buffer, message[RM_SHAREDOBJECT]);
		}
		case RM_HEADER_MESSAGETYPE_USRCTRL:
		{
			return DeserializeUsrCtrl(buffer, message[RM_USRCTRL]);
		}
		case RM_HEADER_MESSAGETYPE_CHUNKSIZE:
		{
			return DeserializeChunkSize(buffer, message[RM_CHUNKSIZE]);
		}
		case RM_HEADER_MESSAGETYPE_ACK:
		{
			return DeserializeAck(buffer, message[RM_ACK]);
		}
		case RM_HEADER_MESSAGETYPE_WINACKSIZE:
		{
			return DeserializeWinAckSize(buffer, message[RM_WINACKSIZE]);
		}
		case RM_HEADER_MESSAGETYPE_PEERBW:
		{
			return DeserializePeerBW(buffer, message[RM_PEERBW]);
		}
		case RM_HEADER_MESSAGETYPE_ABORTMESSAGE:
		{
			return DeserializeAbortMessage(buffer, message[RM_ABORTMESSAGE]);
		}
		default:
		{
			FATAL("Invalid message type: %u %s", H_MT(header), STR(buffer));
			return false;
		}
	}
}
示例#7
0
文件: uri.cpp 项目: dista/crtmpserver
bool parseURI(string stringUri, URI &uri) {
	/*
	 * schema://[username[:password]@]host[:port][/[path[?parameters]]]
	 */
	LOG_URI("------------------------");
	LOG_URI("stringUri: `%s`", STR(stringUri));
	string fullUri;
	string fullUriWithAuth = stringUri;
	string scheme;
	string authentication;
	string username;
	string password;
	string hostPort;
	string host;
	string portString;
	uint16_t port;
	bool portSpecified;
	string fullDocumentPathWithParameters;
	string fullDocumentPath;
	string fullParameters;
	string documentPath;
	string document;
	string documentWithFullParameters;
	Variant parameters;

	string::size_type cursor = 0;
	string::size_type pos = 0;

	//1. Reset
	uri.Reset();

	//2. trim
	trim(stringUri);
	if (stringUri == "") {
		FATAL("Empty uri");
		return false;
	}

	//2. Get the scheme and the default port
	pos = stringUri.find("://", cursor);
	if (pos == string::npos) {
		FATAL("Unable to determine scheme");
		return false;
	}
	scheme = lowerCase(stringUri.substr(cursor, pos - cursor));
	cursor = pos + 3;
	if (_schemeToPort.size() == 0) {
		_schemeToPort["http"] = 80;
		_schemeToPort["rtmpt"] = 80;
		_schemeToPort["rtmpte"] = 80;
		_schemeToPort["https"] = 443;
		_schemeToPort["rtmps"] = 443;
		_schemeToPort["rtsp"] = 554;
		_schemeToPort["rtmp"] = 1935;
		_schemeToPort["rtmpe"] = 1935;
		_schemeToPort["mms"] = 1755;
	}
	if (MAP_HAS1(_schemeToPort, scheme)) {
		port = _schemeToPort[scheme];
	}
	//	else {
	//		FATAL("Scheme `%s` not supported", STR(scheme));
	//		return false;
	//	}
	LOG_URI("scheme: %s; default port: %"PRIu16, STR(scheme), port);

	//3. get the authentication portion. the search starts from
	//where the scheme detection left and up to the first / character
	string::size_type limit = stringUri.find("/", cursor);
	bool hasAuthentication = false;
	pos = stringUri.find("@", cursor);
	if (pos != string::npos) {
		if (limit != string::npos) {
			hasAuthentication = pos<limit;
		}
		hasAuthentication = true;
	}
	if (hasAuthentication) {
		authentication = stringUri.substr(cursor, pos - cursor);
		fullUri = stringUri.substr(0, cursor);
		fullUri += stringUri.substr(pos + 1);
		cursor = pos + 1;
	} else {
		fullUri = fullUriWithAuth;
	}
	if (authentication != "") {
		pos = authentication.find(":");
		if (pos != string::npos) {
			username = authentication.substr(0, pos);
			password = authentication.substr(pos + 1);
		} else {
			username = authentication;
			password = "";
		}
	}
	LOG_URI("fullUri: `%s`; fullUriWithAuth: `%s`", STR(fullUri), STR(fullUriWithAuth));
	LOG_URI("username: `%s`; password: `%s`", STR(username), STR(password));

	//4. Get the host:port
	pos = stringUri.find("/", cursor);
	if (pos == string::npos) {
		hostPort = stringUri.substr(cursor);
		cursor = stringUri.size() - 1;
		fullDocumentPathWithParameters = "/";
	} else {
		hostPort = stringUri.substr(cursor, pos - cursor);
		cursor = pos + 1;
		fullDocumentPathWithParameters = "/" + stringUri.substr(cursor);
	}
	trim(hostPort);
	if (hostPort == "") {
		FATAL("Invalid host:port specified");
		return false;
	}
	pos = hostPort.find(":");
	if (pos == string::npos) {
		host = hostPort;
		portSpecified = false;
	} else {
		host = hostPort.substr(0, pos);
		trim(host);
		portString = hostPort.substr(pos + 1);
		portSpecified = true;
		port = (uint16_t) atoi(STR(portString));
		if (format("%"PRIu16, port) != portString) {
			FATAL("Invalid port number specified: `%s`", STR(portString));
			return false;
		}
	}
	LOG_URI("host: %s; port: %"PRIu16"; portSpecified: %d", STR(host), port, portSpecified);

	//5. fullDocumentPathWithParameters
	fullDocumentPath = "/";
	fullParameters = "";
	documentPath = "/";
	document = "";
	documentWithFullParameters = "";
	parameters.Reset();
	parameters.IsArray(false);
	if (fullDocumentPathWithParameters != "/") {
		pos = fullDocumentPathWithParameters.find("?");
		if (pos == string::npos) {
			fullDocumentPath = fullDocumentPathWithParameters;
			fullParameters = "";
		} else {
			fullDocumentPath = fullDocumentPathWithParameters.substr(0, pos);
			fullParameters = fullDocumentPathWithParameters.substr(pos + 1);
		}

		trim(fullParameters);
		if (fullParameters != "") {
			vector<string> elements;
			split(fullParameters, "&", elements);
			for (uint32_t i = 0; i < elements.size(); i++) {
				string kvp = elements[i];
				if (kvp == "")
					continue;
				string k = "";
				string v = "";
				pos = kvp.find("=");
				if (pos == string::npos) {
					k = kvp;
					v = "";
				} else {
					k = kvp.substr(0, pos);
					v = kvp.substr(pos + 1);
				}
				if (k == "")
					continue;
				parameters[k] = v;
			}
		}

		for (string::size_type i = fullDocumentPath.size() - 1; i >= 0; i--) {
			if (fullDocumentPath[i] == '/')
				break;
			document = fullDocumentPath[i] + document;
		}
		documentPath = fullDocumentPath.substr(0, fullDocumentPath.size() - document.size());
		documentWithFullParameters = document;
		if (fullParameters != "")
			documentWithFullParameters += "?" + fullParameters;
	}
	LOG_URI("fullDocumentPathWithParameters: `%s`", STR(fullDocumentPathWithParameters));
	LOG_URI("fullDocumentPath: `%s`", STR(fullDocumentPath));
	LOG_URI("fullParameters: `%s`", STR(fullParameters));
	LOG_URI("documentPath: `%s`", STR(documentPath));
	LOG_URI("document: `%s`", STR(document));
	LOG_URI("documentWithFullParameters: `%s`", STR(documentWithFullParameters));
	LOG_URI("parameters:");
#ifdef DEBUG_URI

	FOR_MAP(parameters, string, Variant, i) {
		LOG_URI("\t`%s`: `%s`", STR(MAP_KEY(i)), STR(MAP_VAL(i)));
	}
示例#8
0
文件: sdp.cpp 项目: 9aa5/crtmpserver
bool SDP::ParseTransportLinePart(string raw, Variant &result) {
	result.Reset();
	result["original"] = raw;

	//1. split after ';'
	vector<string> parts;
	split(raw, ";", parts);

	//2. Construct the result
	for (uint32_t i = 0; i < parts.size(); i++) {
		string part = parts[i];
		trim(part);
		if (part == "")
			continue;
		string::size_type pos = part.find('=');
		if (pos == string::npos) {
			result[lowerCase(part)] = (bool)true;
			continue;
		}
		result[lowerCase(part.substr(0, pos))] = part.substr(pos + 1);
	}

	vector<string> keys;
	ADD_VECTOR_END(keys, "client_port");
	ADD_VECTOR_END(keys, "server_port");
	ADD_VECTOR_END(keys, "interleaved");

	for (uint32_t i = 0; i < keys.size(); i++) {
		string key = keys[i];
		if (!result.HasKey(key))
			continue;
		parts.clear();
		raw = (string) result[key];
		split(raw, "-", parts);
		if ((parts.size() != 2) && (parts.size() != 1)) {
			FATAL("Invalid transport line: %s", STR(raw));
			return false;
		}
		string all = "";
		uint16_t data = 0;
		uint16_t rtcp = 0;
		if (parts.size() == 2) {
			data = (uint16_t) atoi(STR(parts[0]));
			rtcp = (uint16_t) atoi(STR(parts[1]));
			if (((data % 2) != 0) || ((data + 1) != rtcp)) {
				FATAL("Invalid transport line: %s", STR(raw));
				return false;
			}
			all = format("%"PRIu16"-%"PRIu16, data, rtcp);
		} else {
			data = (uint16_t) atoi(STR(parts[0]));
			all = format("%"PRIu16, data);
			rtcp = 0;
		}
		if (all != raw) {
			FATAL("Invalid transport line: %s", STR(raw));
			return false;
		}
		result.RemoveKey(key);
		result[key]["data"] = (uint16_t) data;
		result[key]["rtcp"] = (uint16_t) rtcp;
		result[key]["all"] = all;
	}

	return true;
}
示例#9
0
bool PopVariant(lua_State *pLuaState, Variant &variant, int32_t idx, bool pop) {
	variant.Reset();
	int32_t type = lua_type(pLuaState, idx);
	switch (type) {
		case LUA_TNIL:
		{
			variant.Reset();
			if (pop)
				lua_remove(pLuaState, idx);
			break;
		}
		case LUA_TBOOLEAN:
		{
			variant = (bool)(lua_toboolean(pLuaState, idx) != 0);
			if (pop)
				lua_remove(pLuaState, idx);
			break;
		}
		case LUA_TNUMBER:
		{
			lua_Number luaNumber = lua_tonumber(pLuaState, idx);
			if (pop)
				lua_remove(pLuaState, idx);
			variant = (double) luaNumber;
			variant.Compact();

			break;
		}
		case LUA_TSTRING:
		{
			string nullable = lua_tostring(pLuaState, idx);
			if (pop)
				lua_remove(pLuaState, idx);
			if (nullable == VAR_NULL_VALUE)
				variant = Variant();
			else
				variant = nullable;
			break;
		}
		case LUA_TTABLE:
		{
			bool isArray = true;
			lua_pushnil(pLuaState);
			while (lua_next(pLuaState, idx) != 0) {
				Variant value;
				if (!PopVariant(pLuaState, value, lua_gettop(pLuaState)))
					return false;

				Variant key;
				if (!PopVariant(pLuaState, key, lua_gettop(pLuaState), false))
					return false;

				variant[key] = value;
				isArray &= (key == _V_NUMERIC);
			}

			variant.IsArray(isArray);

			if (variant.HasKey(VAR_MAP_NAME)) {
				variant.SetTypeName(variant[VAR_MAP_NAME]);
				variant.RemoveKey(VAR_MAP_NAME);
			} else {
				variant.ConvertToTimestamp();
			}
			if (pop)
				lua_remove(pLuaState, idx);
			break;
		}
		default:
		{
			WARN("Element type not supported: %d (0x%x)", type, type);
			return false;
			break;
		}
	}
	return true;
}