Example #1
0
void FlowConnection::rawHandler(UInt8 type,PacketReader& data) {
	UInt16 flag = data.read16();
	if(flag!=0x03) {
		Flow::rawHandler(type,data);
		return;
	}
	// setBufferTime
	UInt32 streamId = data.read32();
	if(streamId>0) {
		INFO("setBufferTime %u on stream %u",data.read32(),streamId)
		BinaryWriter& raw = writer.writeRawMessage();
		raw.write16(0);
		raw.write32(streamId);
	}
}
Example #2
0
void FlowStream::videoHandler(PacketReader& packet) {
	if(_pPublication && _pPublication->publisherId() == _index) {
		_pPublication->pushVideoPacket(packet.read32(),packet,_numberLostFragments);
		_numberLostFragments=0;
	} else
		WARN("a video packet has been received on a no publisher FlowStream, certainly a publication currently closing");
}
Example #3
0
void FlowStream::videoHandler(PacketReader& packet) {
    if(_pPublication && _pPublication->publisherId() == _index) {
        _pPublication->pushVideoPacket(peer,packet.read32(),packet,_numberLostFragments);
        _numberLostFragments=0;
    } else
        fail("a video packet has been received on a no publisher FlowStream");
}
Example #4
0
AMF::ContentType RTMFPFlow::unpack(PacketReader& packet,UInt32& time) {
	if(packet.available()==0)
		return AMF::EMPTY;
	AMF::ContentType type = (AMF::ContentType)packet.read8();
	switch(type) {
		// amf content
		case AMF::INVOCATION_AMF3:
			packet.next(1);
		case AMF::INVOCATION:
			packet.next(4);
			return AMF::INVOCATION;
		case AMF::AUDIO:
		case AMF::VIDEO:
			time = packet.read32();
			break;
		case AMF::DATA:
			packet.next(1);
		case AMF::RAW:
			packet.next(4);
		case AMF::CHUNKSIZE:
			break;
		default:
			ERROR("Unpacking type '",Format<UInt8>("%02x",(UInt8)type),"' unknown");
			break;
	}
	return type;
}
Example #5
0
UInt32 RTMFP::Unpack(PacketReader& packet) {
	packet.reset();
	UInt32 id=0;
	for(int i=0;i<3;++i)
		id ^= packet.read32();
	packet.reset(4);
	return id;
}
Example #6
0
void Publication::pushVideoPacket(PacketReader& packet) {
	UInt32 time = packet.read32(); // TODO?
	list<Listener*>::const_iterator it;
	int pos = packet.position();
	for(it=_listeners.begin();it!=_listeners.end();++it) {
		(*it)->pushVideoPacket(packet);
		packet.reset(pos);
	}
}
Example #7
0
// TODO make perhaps a FlowHandshake
UInt8 Handshake::handshakeHandler(UInt8 id,PacketReader& request,PacketWriter& response) {

	switch(id){
		case 0x30: {
			
			request.read8(); // passer un caractere (boite dans boite)
			UInt8 epdLen = request.read8()-1;

			
			UInt8 type = request.read8();

			string epd;
			request.readRaw(epdLen,epd);

			string tag;
			request.readRaw(16,tag);
			response.writeString8(tag);

			// UDP hole punching

			if(type == 0x0f)
				return _gateway.p2pHandshake(tag,response,peer().address,(const UInt8*)epd.c_str());

			if(type == 0x0a){
				/// Handshake
	
				// RESPONSE 38

				// New Cookie
				char cookie[65];
				RandomInputStream ris;
				ris.read(cookie,64);
				cookie[64]='\0';
				response.write8(64);
				response.writeRaw(cookie,64);
				_cookies[cookie] = new Cookie(epd);
				 
				// instance id (certificat in the middle)
				response.writeRaw(_certificat,sizeof(_certificat));
				
				return 0x70;
			} else {
				ERROR("Unkown handshake first way with '%02x' type",type);
			}
			break;
		}
		case 0x38: {
			_farId = request.read32();
			string cookie;
			request.readRaw(request.read8(),cookie);

			map<string,Cookie*>::iterator itCookie = _cookies.find(cookie.c_str());
			if(itCookie==_cookies.end()) {
				ERROR("Handshake cookie '%s' unknown",cookie.c_str());
				return 0;
			}

			request.read8(); // why 0x81?

			// signature
			string farSignature;
			request.readString8(farSignature); // 81 02 1D 02 stable

			// farPubKeyPart
			UInt8 farPubKeyPart[128];
			request.readRaw((char*)farPubKeyPart,sizeof(farPubKeyPart));

			string farCertificat;
			request.readString8(farCertificat);
			
			// peerId = SHA256(farSignature+farPubKey)
			string temp(farSignature);
			temp.append((char*)farPubKeyPart,sizeof(farPubKeyPart));
			EVP_Digest(temp.c_str(),temp.size(),(UInt8*)peer().id,NULL,EVP_sha256(),NULL);
			
			// Compute Diffie-Hellman secret
			UInt8 pubKey[128];
			UInt8 sharedSecret[128];
			RTMFP::EndDiffieHellman(RTMFP::BeginDiffieHellman(pubKey),farPubKeyPart,sharedSecret);

			// Compute Keys
			UInt8 requestKey[AES_KEY_SIZE];
			UInt8 responseKey[AES_KEY_SIZE];
			RTMFP::ComputeAsymetricKeys(sharedSecret,pubKey,_signature,farCertificat,requestKey,responseKey);

			// RESPONSE
			Util::UnpackUrl(itCookie->second->queryUrl,(string&)peer().path,(map<string,string>&)peer().parameters);
			response << _gateway.createSession(_farId,peer(),requestKey,responseKey);
			response.write8(0x81);
			response.writeString8(_signature);
			response.writeRaw((char*)pubKey,sizeof(pubKey));
			response.write8(0x58);

			// remove cookie
			_cookies.erase(itCookie);

			// db_add_public(s); // TODO

			return 0x78;
		}
		default:
			ERROR("Unkown handshake packet id '%02x'",id);
	}

	return 0;
}
Example #8
0
UInt8 Handshake::handshakeHandler(UInt8 id,PacketReader& request,PacketWriter& response) {

	switch(id){
		case 0x30: {
			
			request.read8(); // passer un caractere (boite dans boite)
			UInt8 epdLen = request.read8()-1;

			UInt8 type = request.read8();

			string epd;
			request.readRaw(epdLen,epd);

			string tag;
			request.readRaw(16,tag);
			response.writeString8(tag);
			
			if(type == 0x0f)
				return _gateway.p2pHandshake(tag,response,peer.address,(const UInt8*)epd.c_str());

			if(type == 0x0a){
				/// Handshake
				HelloAttempt& attempt = helloAttempt<HelloAttempt>(tag);

				// Fill peer infos
				UInt16 port;
				string host;
				Util::UnpackUrl(epd,host,port,(string&)peer.path,(map<string,string>&)peer.properties);
				set<string> addresses;
				peer.onHandshake(attempt.count+1,addresses);
				if(!addresses.empty()) {
					set<string>::iterator it;
					for(it=addresses.begin();it!=addresses.end();++it) {
						try {
							if((*it)=="again")
								((string&)*it).assign(format("%s:%hu",host,port));
							SocketAddress address(*it);
							response.writeAddress(address,it==addresses.begin());
						} catch(Exception& ex) {
							ERROR("Bad redirection address %s in hello attempt, %s",(*it)=="again" ? epd.c_str() : (*it).c_str(),ex.displayText().c_str());
						}
					}
					return 0x71;
				}

				// New Cookie
				createCookie(response,attempt,tag,epd);

				// instance id (certificat in the middle)
				response.writeRaw(_certificat,sizeof(_certificat));
				return 0x70;
			} else
				ERROR("Unkown handshake first way with '%02x' type",type);
			break;
		}
		case 0x38: {
			(UInt32&)farId = request.read32();

			if(request.read7BitLongValue()!=COOKIE_SIZE) {
				ERROR("Bad handshake cookie '%s': its size should be 64 bytes",Util::FormatHex(request.current(),COOKIE_SIZE).c_str());
				return 0;
			}
	
			map<const UInt8*,Cookie*,CompareCookies>::iterator itCookie = _cookies.find(request.current());
			if(itCookie==_cookies.end()) {
				WARN("Cookie %s unknown, maybe already connected (udpBuffer congested?)",Util::FormatHex(request.current(),COOKIE_SIZE).c_str());
				return 0;
			}

			Cookie& cookie(*itCookie->second);
			(SocketAddress&)cookie.peerAddress = peer.address;

			if(cookie.farId==0) {
				((UInt32&)cookie.farId) = farId;
				request.next(COOKIE_SIZE);

				size_t size = (size_t)request.read7BitLongValue();
				// peerId = SHA256(farPubKey)
				EVP_Digest(request.current(),size,(UInt8*)cookie.peerId,NULL,EVP_sha256(),NULL);

				cookie.initiatorKey().resize(request.read7BitValue()-2);
				request.next(2); // unknown
				request.readRaw(&cookie.initiatorKey()[0],cookie.initiatorKey().size());

				cookie.initiatorNonce().resize(request.read7BitValue());
				request.readRaw(&cookie.initiatorNonce()[0],cookie.initiatorNonce().size());

				cookie.computeKeys();
			} else if(cookie.id>0) {
				// Repeat cookie reponse!
				cookie.read(response);
				return 0x78;
			} // else Keys are computing (multi-thread)

			break;
		}
		default:
			ERROR("Unkown handshake packet id %u",id);
	}

	return 0;
}
Example #9
0
UInt8 Handshake::handshakeHandler(UInt8 id,PacketReader& request,PacketWriter& response) {

	switch(id){
		case 0x30: {
			
			request.read8(); // passer un caractere (boite dans boite)
			UInt8 epdLen = request.read8()-1;

			UInt8 type = request.read8();

			string epd;
			request.readRaw(epdLen,epd);

			string tag;
			request.readRaw(16,tag);
			response.writeString8(tag);
			
			if(type == 0x0f)
				return _gateway.p2pHandshake(tag,response,peer.address,(const UInt8*)epd.c_str());

			if(type == 0x0a){
				/// Handshake
				HelloAttempt& attempt = helloAttempt<HelloAttempt>(tag);
				if(edges().size()>0 && (_invoker.edgesAttemptsBeforeFallback==0 || attempt.count <_invoker.edgesAttemptsBeforeFallback)) {
					
					if(_invoker.edgesAttemptsBeforeFallback>0) {
						try {
							URI uri(epd);
							response.writeAddress(SocketAddress(uri.getHost(),uri.getPort()),false); // TODO check with true!
						} catch(Exception& ex) {
							ERROR("Parsing %s URL problem in hello attempt : %s",epd.c_str(),ex.displayText().c_str());
						}
					}

					map<int,list<Edge*> > edgesSortedByCount;
					map<string,Edge*>::const_iterator it;
					for(it=edges().begin();it!=edges().end();++it)
						edgesSortedByCount[it->second->count].push_back(it->second);

					UInt8 count=0;
					map<int,list<Edge*> >::const_iterator it2;
					for(it2=edgesSortedByCount.begin();it2!=edgesSortedByCount.end();++it2) {
						list<Edge*>::const_iterator it3;
						for(it3=it2->second.begin();it3!=it2->second.end();++it3) {
							response.writeAddress((*it3)->address,false);
							if((++count)==6) // 6 redirections maximum
								break;
						}
						if(it3!=it2->second.end())
							break;
					}
					return 0x71;

				}

				if(edges().size()>0)
					WARN("After %u hello attempts, impossible to connect to edges. Edges are busy? or unreachable?",_invoker.edgesAttemptsBeforeFallback);
	
				// New Cookie
				createCookie(response,attempt,tag,epd);
				 
				// instance id (certificat in the middle)
				response.writeRaw(_certificat,sizeof(_certificat));
				
				return 0x70;
			} else
				ERROR("Unkown handshake first way with '%02x' type",type);
			break;
		}
		case 0x39:
		case 0x38: {
			(UInt32&)farId = request.read32();

			if(request.read7BitLongValue()!=COOKIE_SIZE) {
				ERROR("Bad handshake cookie '%s': its size should be 64 bytes",Util::FormatHex(request.current(),COOKIE_SIZE).c_str());
				return 0;
			}
	
			map<const UInt8*,Cookie*,CompareCookies>::iterator itCookie = _cookies.find(request.current());
			if(itCookie==_cookies.end()) {
				if(id!=0x39) {
					ERROR("Handshake cookie '%s' unknown",Util::FormatHex(request.current(),COOKIE_SIZE).c_str());
					return 0;
				}
				Cookie* pCookie = new Cookie();
				UInt32 pos = request.position();
				request.readRaw((UInt8*)pCookie->value,COOKIE_SIZE);
				request >> (string&)pCookie->queryUrl;
				request.reset(pos);
				itCookie = _cookies.insert(pair<const UInt8*,Cookie*>(pCookie->value,pCookie)).first;
			}

			Cookie& cookie(*itCookie->second);

			if(cookie.id==0) {

				UInt8 decryptKey[AES_KEY_SIZE];UInt8* pDecryptKey=&decryptKey[0];
				UInt8 encryptKey[AES_KEY_SIZE];UInt8* pEncryptKey=&encryptKey[0];

				if(id==0x38) {
					request.next(COOKIE_SIZE);
					size_t size = (size_t)request.read7BitLongValue();
					// peerId = SHA256(farPubKey)
					EVP_Digest(request.current(),size,(UInt8*)peer.id,NULL,EVP_sha256(),NULL);

					vector<UInt8> publicKey(request.read7BitValue()-2);
					request.next(2); // unknown
					request.readRaw(&publicKey[0],publicKey.size());

					size = request.read7BitValue();

					cookie.computeKeys(&publicKey[0],publicKey.size(),request.current(),(UInt16)size,decryptKey,encryptKey);
				} else {
					// edge
					pDecryptKey=NULL;
					pEncryptKey=NULL;
					memcpy((UInt8*)peer.id,request.current(),ID_SIZE);
					request.next(COOKIE_SIZE);
					request.next(request.read7BitEncoded());
				}

				// Fill peer infos
				Util::UnpackUrl(cookie.queryUrl,(string&)peer.path,(map<string,string>&)peer.properties);

				// RESPONSE
				Session& session = _gateway.createSession(farId,peer,pDecryptKey,pEncryptKey,cookie);
				(UInt32&)cookie.id = session.id;

				string address;
				if(id==0x39) {
					// Session by edge 
					session.flags |= SESSION_BY_EDGE;
					Edge* pEdge = _invoker.edges(peer.address);
					if(!pEdge)
						ERROR("Edge session creation by an unknown server edge %s",peer.address.toString().c_str())
					else
						pEdge->addSession(session);
					request >> address;
				} else // Session direct
					address = session.peer.address.toString();

				session.peer.addresses.clear();
				session.peer.addresses.push_back(address);

				cookie.write();
			} else