void AMFWriter::writeSimpleObject(const AMFSimpleObject& object) { beginObject(); AbstractConfiguration::Keys keys; object.keys(keys); AbstractConfiguration::Keys::const_iterator it; for(it=keys.begin();it!=keys.end();++it) { string name = *it; int type = object.getInt(name+".type",-1); switch(type) { case AMF::Boolean: writeObjectProperty(name,object.getBool(name)); break; case AMF::String: writeObjectProperty(name,object.getString(name)); break; case AMF::Number: writeObjectProperty(name,object.getDouble(name)); break; case AMF::Integer: writeObjectProperty(name,object.getInt(name)); break; case AMF::Date: { Timestamp date((Timestamp::TimeVal)object.getDouble(name)*1000); writeObjectProperty(name,date); break; } case AMF::Null: writeObjectProperty(name); break; default: ERROR("Unknown AMFObject %d type",type); } } endObject(); }
void Middle::packetHandler(PacketReader& packet) { if(!_pMiddleAesEncrypt) { DEBUG("500ms sleeping to wait target handshaking"); Thread::sleep(500); // to wait the target handshake response manage(); } // Middle to target PacketWriter& request = requester(); UInt8 marker = packet.read8(); request << marker; request << packet.read16(); if((marker|0xF0) == 0xFD) request.write16(packet.read16()); // time echo int pos = request.position(); UInt8 type = packet.available()>0 ? packet.read8() : 0xFF; while(type!=0xFF) { UInt16 size = packet.read16(); PacketReader content(packet.current(),size); PacketWriter out(request.begin()+request.position(),request.available()); // 3 for future type and size out.clear(3); if(type==0x10) { out.write8(content.read8()); UInt32 idFlow = content.read7BitValue();out.write7BitValue(idFlow); UInt32 stage = content.read7BitValue();out.write7BitValue(stage); if(idFlow==0x02 && stage==0x01) { if(!_isPeer) { /// Replace NetConnection infos out.writeRaw(content.current(),14);content.next(14); // first string string tmp; content.readString16(tmp);out.writeString16(tmp); AMFWriter writer(out); writer.amf0Preference=true; AMFReader reader(content); writer.writeNumber(reader.readNumber()); // double AMFSimpleObject obj; reader.readSimpleObject(obj); /// Replace tcUrl if(obj.has("tcUrl")) obj.setString("tcUrl",_queryUrl); writer.writeSimpleObject(obj); } else { out.writeRaw(content.current(),3);content.next(3); UInt16 netGroupHeader = content.read16();out.write16(netGroupHeader); if(netGroupHeader==0x4752) { out.writeRaw(content.current(),71);content.next(71); Entities<Group>::Iterator it; for(it = _invoker.groups.begin();it!=_invoker.groups.end();++it) { Group& group = *it->second; Group::Iterator itP; for(itP=group.begin();itP!=group.end();++itP) { if((**itP)==_target.id) { UInt8 result1[AES_KEY_SIZE]; UInt8 result2[AES_KEY_SIZE]; HMAC(EVP_sha256(),_sharedSecret,KEY_SIZE,&_targetNonce[0],_targetNonce.size(),result1,NULL); HMAC(EVP_sha256(),group.id,ID_SIZE,result1,AES_KEY_SIZE,result2,NULL); out.writeRaw(result2,AES_KEY_SIZE);content.next(AES_KEY_SIZE); out.writeRaw(content.current(),4);content.next(4); out.writeRaw(_target.peerId,ID_SIZE);content.next(ID_SIZE); break; } } if(itP!=group.end()) break; } if(it==_invoker.groups.end()) ERROR("Handshake NetGroup packet between peers without corresponding Group"); } } } } else if(type == 0x4C) { kill(); } else if(type == 0x51) { //printf("%s\n",Util::FormatHex(content.current(),content.available()).c_str()); } out.writeRaw(content.current(),content.available()); packet.next(size); if(out.length()>=3) { request<<type; size = out.length()-3; request.write16(size);request.next(size); } type = packet.available()>0 ? packet.read8() : 0xFF; } if(request.length()>pos) sendToTarget(); }
void Middle::packetHandler(PacketReader& packet) { if(!_pMiddleAesEncrypt) manage(); // to wait the target handshake response // Middle to target PacketWriter& request = requester(); UInt8 marker = packet.read8(); request << marker; request << packet.read16(); if((marker|0xF0) == 0xFD) request.write16(packet.read16()); // time echo int pos = request.position(); UInt8 type = packet.available()>0 ? packet.read8() : 0xFF; while(type!=0xFF) { UInt16 size = packet.read16(); PacketReader content(packet.current(),size); PacketWriter out(request.begin()+request.position(),request.available()); // 3 for future type and size out.clear(3); if(type==0x10) { out.write8(content.read8()); UInt64 idFlow = content.read7BitLongValue();out.write7BitLongValue(idFlow); UInt64 stage = content.read7BitLongValue();out.write7BitLongValue(stage); if(idFlow==0x02 && stage==0x01) { if(!_isPeer) { /// Replace NetConnection infos out.writeRaw(content.current(),14);content.next(14); // first string string tmp; content.readString16(tmp);out.writeString16(tmp); AMFWriter writer(out); writer.amf0Preference=true; AMFReader reader(content); writer.writeNumber(reader.readNumber()); // double AMFSimpleObject obj; reader.readSimpleObject(obj); /// Replace tcUrl if(obj.has("tcUrl")) obj.setString("tcUrl",_queryUrl); writer.writeSimpleObject(obj); } else { out.writeRaw(content.current(),3);content.next(3); UInt16 netGroupHeader = content.read16();out.write16(netGroupHeader); if(netGroupHeader==0x4752) { map<string,string>::const_iterator it = peer.properties.find("groupspec"); if(it!=peer.properties.end()) { out.writeRaw(content.current(),71);content.next(71); UInt8 result1[AES_KEY_SIZE]; UInt8 result2[AES_KEY_SIZE]; HMAC(EVP_sha256(),&_sharedSecret[0],_sharedSecret.size(),&_targetNonce[0],_targetNonce.size(),result1,NULL); HMAC(EVP_sha256(),it->second.c_str(),it->second.size(),result1,AES_KEY_SIZE,result2,NULL); out.writeRaw(result2,AES_KEY_SIZE);content.next(AES_KEY_SIZE); out.writeRaw(content.current(),4);content.next(4); out.writeRaw(_target.peerId,ID_SIZE);content.next(ID_SIZE); } else WARN("No groupspec client property indicated to make working the 'man-in-the-middle' mode between peers in a NetGroup case"); } } } } else if(type == 0x4C) { kill(); return; } else if(type == 0x51) { //printf("%s\n",Util::FormatHex(content.current(),content.available()).c_str()); } out.writeRaw(content.current(),content.available()); packet.next(size); if(out.length()>=3) { request<<type; size = out.length()-3; request.write16(size);request.next(size); } type = packet.available()>0 ? packet.read8() : 0xFF; } if(request.length()>pos) sendToTarget(); }
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"); } }