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); }
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); }
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); }
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"); } }
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; }
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); }
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"); } }