void FlowConnection::messageHandler(const std::string& name,AMFReader& message) {
	
	if(name=="connect") {
		AMFObject obj;
		message.readObject(obj);
		((URI&)peer.swfUrl) = obj.getString("swfUrl","");
		((URI&)peer.pageUrl) = obj.getString("pageUrl","");

		// Don't support AMF0 forced on NetConnection object because impossible to exchange custome data (ByteArray written impossible)
		// But it's not a pb because NetConnection RTMFP works since flash player 10.0 only (which supports AMF3)
		if(obj.getDouble("objectEncoding")==0)
			throw Exception("ObjectEncoding client must be AMF3 and not AMF0");

		// Check if the client is authorized
		++((UInt32&)handler.count);
		((Peer::PeerState&)peer.state) = Peer::REJECTED;
		if(!handler.onConnection(peer,writer))
			throw Exception("Client rejected");
		
		((Peer::PeerState&)peer.state) = Peer::ACCEPTED;

		AMFObjectWriter response(writer.writeSuccessResponse("Connect.Success","Connection succeeded"));
		response.write("objectEncoding",3);
		response.write("data",peer.data);

	} else if(name == "setPeerInfo") {

		list<Address> address;
		string addr;
		while(message.available()) {
			message.read(addr); // private host
			address.push_back(addr);
		}
		peer.setPrivateAddress(address);
		
		BinaryWriter& response(writer.writeRawMessage());
		response.write16(0x29); // Unknown!
		response.write32(handler.keepAliveServer);
		response.write32(handler.keepAlivePeer);

	} else if(name == "initStream") {
		// TODO?
	} else if(name == "createStream") {

		AMFWriter& response(writer.writeAMFResult());
		response.writeNumber(*_streamIndex.insert(handler.streams.create()).first);

	} else if(name == "deleteStream") {
		UInt32 index = (UInt32)message.readNumber();
		_streamIndex.erase(index);
		handler.streams.destroy(index);
	} else {
		if(!handler.onMessage(peer,name,message,writer))
			writer.writeErrorResponse("Call.Failed","Method '" + name + "' not found");
	}
}
Exemplo n.º 2
0
bool FlowConnection::requestHandler(const std::string& name,AMFReader& request,ResponseWriter& responseWriter) {
	
	if(name=="connect") {

		AMFObject obj;
		request.readObject(obj);
		((URI&)peer.swfUrl) = obj.getString("swfUrl","");
		((URI&)peer.pageUrl) = obj.getString("pageUrl","");

		((Client::ClientState&)peer.state) = Client::REJECTED;

		// Don't support AMF0 forced on NetConnection object because impossible to exchange custome data (ByteArray written impossible)
		// But it's not a pb because NetConnection RTMFP works since flash player 10.0 only (which supports AMF3)
		if(obj.getDouble("objectEncoding")==0)
			return false;

		// Check if the client is authorized
		if(!serverHandler.connection(peer))
			return false;
		
		((Client::ClientState&)peer.state) = Client::ACCEPTED;

		AMFObjectWriter response(responseWriter.writeSuccessResponse("Connection succeeded"));
		response.write("objectEncoding",3);
		response.write("data",peer.data);

	} else if(name == "setPeerInfo") {

		list<Address> address;
		string addr;
		while(request.available()) {
			request.read(addr); // private host
			address.push_back(addr);
		}
		peer.setPrivateAddress(address);
		
		PacketWriter& response(responseWriter.writeRawResponse());
		response.write16(0x29); // Unknown!
		response.write32(serverHandler.keepAliveServer);
		response.write32(serverHandler.keepAlivePeer);

	} else if(name == "createStream") {

		AMFWriter& response(responseWriter.writeAMFResponse());
		response.writeNumber(1); // TODO, id stream!

	} else
		responseWriter.writeErrorResponse("Method not found (" + name + ")");

	return false;
}
Exemplo n.º 3
0
void FlashStream::messageHandler(const string& name,AMFReader& message,FlashWriter& writer) {
	if(name=="play") {
		disengage(&writer);

		string publication;
		message.readString(publication);
		// TODO implements completly NetStream.play method, with possible NetStream.play.failed too!
		Exception ex;
		_pListener = invoker.subscribe(ex,peer,publication,writer);
		if (ex) {
			writer.writeAMFStatus("NetStream.Play.Failed",ex.error());
			return;
		}
		if(message.available())
			_pListener->setNumber("unbuffered",message.readNumber()==-3000);

		if(_bufferTime>0) {
			// To do working the buffertime on receiver side
			BinaryWriter& raw = writer.writeRaw();
			raw.write16(0);
			raw.write32(id);
			_pListener->setNumber("bufferTime",_bufferTime);
		}
		writer.writeAMFStatus("NetStream.Play.Reset","Playing and resetting " + publication); // for entiere playlist
		writer.writeAMFStatus("NetStream.Play.Start","Started playing " + publication); // for item

	} else if(name == "closeStream") {
		disengage(&writer);
	} else if(name=="publish") {

		disengage(&writer);

		string type,publication;
		message.readString(publication);
		size_t query = publication.find('?');
		if (query != string::npos)
			publication = publication.substr(0, query); // TODO use query in Util::UnpackQuery for publication options?
		if(message.available())
			message.readString(type); // TODO support "append" and "appendWithGap"

		Exception ex;
		_pPublication = invoker.publish(ex, peer, publication, type == "record" ? Publication::RECORD : Publication::LIVE);
		if (ex)
			writer.writeAMFStatus("NetStream.Publish.BadName",ex.error());
		else
			writer.writeAMFStatus("NetStream.Publish.Start",publication +" is now published");
	} else if(_pListener && name=="receiveAudio") {
		_pListener->receiveAudio = message.readBoolean();
	} else if(_pListener && name=="receiveVideo") {
		_pListener->receiveVideo = message.readBoolean();
	} else
		ERROR("RTMFPMessage '",name,"' unknown on stream ",id);
}
Exemplo n.º 4
0
void FlowStream::messageHandler(const string& action,AMFReader& message) {
	if(action=="play") {
		disengage();

		message.read((string&)name);
		// TODO implements completly NetStream.play method, with possible NetStream.play.failed too!
		double start = -2000;
		if(message.available())
			start = message.readNumber();

		try {
			_pListener = &invoker._streams.subscribe(peer,_index,name,writer,start);
			_state = PLAYING;
		} catch(...) {}
		
	} else if(action == "closeStream") {
		disengage();
	} else if(action=="publish") {

		disengage();

		string type;
		message.read((string&)name);
		if(message.available())
			message.read(type); // TODO recording publication feature!

		try {
			invoker._streams.publish(peer,_index,name,&writer);
			_state = PUBLISHING;
		} catch(...) {}

	} else if(_state==PUBLISHING) {
		if(!_pPublication) {
			Publications::Iterator it = invoker.publications(name);
			if(it!=invoker.publications.end())
				_pPublication = it->second;
			else
				ERROR("Publication %s unfound, related for the %s message",name.c_str(),action.c_str());
		}
		if(_pPublication)
			_pPublication->pushDataPacket(action,message.reader);
	} else if(_pListener && action=="receiveAudio")
		_pListener->receiveAudio = message.readBoolean();
	else if(_pListener && action=="receiveVideo")
		_pListener->receiveVideo = message.readBoolean();
	else
		Flow::messageHandler(action,message);

}
Exemplo n.º 5
0
void FlowStream::messageHandler(const string& action,AMFReader& message) {

    if(action=="play") {
        disengage();
        _state = PLAYING;

        message.read((string&)name);
        // TODO implements completly NetStream.play method, with possible NetStream.play.failed too!
        double start = -2000;
        if(message.available())
            start = message.readNumber();

        BinaryWriter& data = writer.writeRawMessage(true);
        data.write8(0x0F);
        data.write32(0x00);
        data.write8(0x00);
        AMFWriter amf(data);
        amf.write("|RtmpSampleAccess");
        amf.writeBool(handler.audioSampleAccess);
        amf.writeBool(handler.videoSampleAccess);

        writer.writeStatusResponse("Play.Reset","Playing and resetting " + name);

        writer.writeStatusResponse("Play.Start","Started playing " + name);

        handler.streams.subscribe(peer,_index,name,writer,start);

    } else if(action == "closeStream") {
        disengage();
    } else if(action=="publish") {

        disengage();

        string type;
        message.read((string&)name);
        if(message.available())
            message.read(type); // TODO recording publication feature!

        if(handler.streams.publish(peer,_index,name)) {
            writer.writeStatusResponse("Publish.Start",name +" is now published");
            _state = PUBLISHING;
        } else
            writer.writeStatusResponse("Publish.BadName",name +" is already publishing");

    } else if(_state==PUBLISHING) {
        if(!_pPublication) {
            Publications::Iterator it = handler.streams.publications(name);
            if(it!=handler.streams.publications.end())
                _pPublication = it->second;
            else
                ERROR("Publication %s unfound, related for the %s message",name.c_str(),action.c_str());
        }
        if(_pPublication)
            _pPublication->pushDataPacket(peer,action,message.reader);
    } else
        Flow::messageHandler(action,message);

}
Exemplo n.º 6
0
void FlowStream::messageHandler(const string& action,AMFReader& message) {

	if(action=="play") {
		disengage();

		message.read((string&)name);
		// TODO implements completly NetStream.play method, with possible NetStream.play.failed too!
		double start = -2000;
		if(message.available())
			start = message.readNumber();

		if(invoker._streams.subscribe(peer,_index,name,writer,start))
			_state = PLAYING;

	} else if(action == "closeStream") {
		disengage();
	} else if(action=="publish") {

		disengage();

		string type;
		message.read((string&)name);
		if(message.available())
			message.read(type); // TODO recording publication feature!

		try {
			invoker._streams.publish(peer,_index,name);
			_state = PUBLISHING;
			writer.writeStatusResponse("Publish.Start",name +" is now published");
		} catch(Exception& ex) {
			writer.writeStatusResponse(ex.code() == Publication::BADNAME ? "Publish.BadName" : "Publish.Failed", ex.displayText());
		}

	} else if(_state==PUBLISHING) {
		if(!_pPublication) {
			Publications::Iterator it = invoker.publications(name);
			if(it!=invoker.publications.end())
				_pPublication = it->second;
			else
				ERROR("Publication %s unfound, related for the %s message",name.c_str(),action.c_str());
		}
		if(_pPublication)
			_pPublication->pushDataPacket(action,message.reader);
	} else
		Flow::messageHandler(action,message);

}
Exemplo n.º 7
0
void FlashStream::messageHandler(const string& name, AMFReader& message, FlashWriter& writer) {
	if (name == "play") {
		disengage(&writer);

		string publication;
		message.readString(publication);
		// TODO implements completly NetStream.play method, with possible NetStream.play.failed too!
		Exception ex;
		_pListener = invoker.subscribe(ex, peer, publication, writer); // ex already log displayed
		if (!_pListener) {
			writer.writeAMFStatus("NetStream.Play.Failed", ex.error());
			return;
		}
		
		OnStart::raise(id, writer); // stream begin
		writer.writeAMFStatus("NetStream.Play.Reset", "Playing and resetting " + publication); // for entiere playlist
		writer.writeAMFStatus("NetStream.Play.Start", "Started playing "+publication); // for item
		AMFWriter& amf(writer.writeInfos("|RtmpSampleAccess"));
		amf.writeBoolean(true); // audioSampleAccess
		amf.writeBoolean(true); // videoSampleAccess

		if (_bufferTime > 0)
			_pListener->setNumber("bufferTime", _bufferTime);
	
	} else if (name == "closeStream") {
		disengage(&writer);
	} else if (name == "publish") {

		disengage(&writer);

		string type, publication;
		message.readString(publication);
		size_t query = publication.find('?');
		if (query != string::npos)
			publication = publication.substr(0, query); // TODO use query in Util::UnpackQuery for publication options?
		if (message.available())
			message.readString(type); // TODO support "append" and "appendWithGap"

		Exception ex;
		_pPublication = invoker.publish(ex, peer, publication, type == "record" ? Publication::RECORD : Publication::LIVE);
		if (ex) {
			writer.writeAMFStatus("NetStream.Publish.BadName", ex.error());
			_pPublication = NULL;
		} else
			writer.writeAMFStatus("NetStream.Publish.Start", publication + " is now published");
	} else if (_pListener && name == "receiveAudio") {
		message.readBoolean(_pListener->receiveAudio);
	} else if (_pListener && name == "receiveVideo") {
		message.readBoolean(_pListener->receiveVideo);

	} else if (_pListener && name == "pause") {
		bool paused(true);
		message.readBoolean(paused);
		// TODO support pause for VOD
		
		if (paused) {
			// useless, client knows it when it calls NetStream::pause method
			// writer.writeAMFStatus("NetStream.Pause.Notify", _pListener->publication.name() + " paused");
		} else {
			double position;
			if (message.readNumber(position))
				_pListener->seek((UInt32)position);
			OnStart::raise(id, writer); // stream begin
			// useless, client knows it when it calls NetStream::resume method
			//	writer.writeAMFStatus("NetStream.Unpause.Notify", _pListener->publication.name() + " resumed");
		}

	} else if (_pListener && name == "seek") {
		double position;
		if (message.readNumber(position)) {
			_pListener->seek((UInt32)position);
			 // TODO support seek for VOD
			OnStart::raise(id, writer); // stream begin
			// useless, client knows it when it calls NetStream::seek method, and wait "NetStream.Seek.Complete" rather (raised by client side)
			// writer.writeAMFStatus("NetStream.Seek.Notify", _pListener->publication.name() + " seek operation");
		} else
			writer.writeAMFStatus("NetStream.Seek.InvalidTime", _pListener->publication.name() + " seek operation must pass in argument a milliseconds position time");
	} else if (_pPublication && name == "@setDataFrame") {
		// metadata
		_pPublication->writeProperties(message);
	} else if (_pPublication && name == "@clearDataFrame") {
		_pPublication->clearProperties();
	} else
		ERROR("Message '",name,"' unknown on stream ",id);
}
Exemplo n.º 8
0
void FlowStream::messageHandler(const string& action,AMFReader& message) {

	if(action=="|RtmpSampleAccess") {
		// TODO?
		bool value1 = message.readBool();
		bool value2 = message.readBool();
	} else if(action=="play") {
		// Stop a precedent playing
		if(_state==PLAYING) {
			serverHandler.streams.unsubscribe(name,*_pListener);
			_pListener->close();
		}
		_state = PLAYING;

		// TODO add a failed scenario?
		message.read((string&)name);

		BinaryWriter& writer1 = writer.writeRawMessage(true);
		writer1.write8(0x0F);
		writer1.write32(0x00);
		writer1.write8(0x00);
		AMFWriter amf(writer1);
		amf.write("|RtmpSampleAccess");
		amf.writeBool(false);
		amf.writeBool(false);

	/*	BinaryWriter& writer2 = writeRawMessage();
		writer2.write16(0x00);
		writer2.write32(0x02);*/

		writer.writeStatusResponse("Reset","Playing and resetting '" + name +"'");

		writer.writeStatusResponse("Start","Started playing '" + name +"'");

		/*BinaryWriter& writer3 = writer.writeRawMessage(); TODO added? useful?
		writer3.write16(0x22);
		writer3.write32(0);
		writer3.write32(0x02);*/

		_pListener = &newFlowWriter<Listener>(_signature);
		serverHandler.streams.subscribe(name,*_pListener);


	} else if(action == "closeStream") {
		// Stop the current  job
		if(_state==PUBLISHING) {
			serverHandler.streams.unpublish(_index,name);
			writer.writeSuccessResponse("Stopped publishing '" + name +"'"); // TODO doesn't work! NetStream.Unpublish.Success should be!
		} else if(_state==PLAYING) {
			serverHandler.streams.unsubscribe(name,*_pListener);
			_pListener->close();
			writer.writeStatusResponse("Stop","Stopped playing '" + name +"'"); // TODO doesn't work!
		}
		_state=IDLE;
	} else if(action=="publish") {

		// Stop a precedent publishment
		if(_state==PUBLISHING)
			serverHandler.streams.unpublish(_index,name);
		_state = IDLE;

		string type;
		message.read((string&)name);
		if(message.available())
			message.read(type); // TODO record!

		// TODO add a failed scenario?

		if(serverHandler.streams.publish(_index,name)) {
			writer.writeStatusResponse("Start","'" + name +"' is now published");
			_state = PUBLISHING;
		} else
			writer.writeErrorResponse("'" + name +"' is already publishing","BadName");

	} else
		Flow::messageHandler(action,message);

}
Exemplo n.º 9
0
void FlowConnection::messageHandler(const std::string& name,AMFReader& message) {
	if(name=="connect") {
		message.stopReferencing();
		AMFSimpleObject obj;
		message.readSimpleObject(obj);
		message.startReferencing();
		((URI&)peer.swfUrl) = obj.getString("swfUrl","");
		((URI&)peer.pageUrl) = obj.getString("pageUrl","");
		((string&)peer.flashVersion) = obj.getString("flashVer","");

		// Don't support AMF0 forced on NetConnection object because AMFWriter writes in AMF3 format
		// But it's not a pb because NetConnection RTMFP works since flash player 10.0 only (which supports AMF3)
		if(obj.getNumber("objectEncoding",0)==0) {
			writer.writeErrorResponse("Connect.Rejected","ObjectEncoding client must be in a AMF3 format (not AMF0)");
			return;
		}

		// Check if the client is authorized
		peer.setFlowWriter(&writer);
		writer.beginTransaction();
		bool accept=true;
		{
			AMFObjectWriter response(writer.writeSuccessResponse("Connect.Success","Connection succeeded"));
			response.write("objectEncoding",3.0);
			accept = peer.onConnection(message,response);
		}
		if(!accept) {
			writer.endTransaction(1);
			writer.writeAMFMessage("close");
			writer.close();
		} else
			writer.endTransaction();

	} else if(name == "setPeerInfo") {

		peer.addresses.resize(1);
		string addr;
		while(message.available()) {
			message.read(addr); // private host
			peer.addresses.push_back(addr);
		}
		
		BinaryWriter& response(writer.writeRawMessage());
		response.write16(0x29); // Unknown!
		response.write32(invoker.keepAliveServer);
		response.write32(invoker.keepAlivePeer);

	} else if(name == "initStream") {
		// TODO?
	} else if(name == "createStream") {

		AMFWriter& response(writer.writeAMFResult());
		response.writeInteger(*_streamIndex.insert(invoker._streams.create()).first);

	} else if(name == "deleteStream") {
		UInt32 index = (UInt32)message.readNumber();
		_streamIndex.erase(index);
		invoker._streams.destroy(index);
	} else {
		if(!peer.onMessage(name,message))
			writer.writeErrorResponse("Call.Failed","Method '" + name + "' not found");
	}
}