Esempio n. 1
0
void Session::packetHandler(PacketReader& packet) {

	_recvTimestamp.update();

	// Read packet
	UInt8 marker = packet.read8()|0xF0;
	
	_timeSent = packet.read16();

	// with time echo
	if(marker == 0xFD)
		_peer.setPing(RTMFP::Time(_recvTimestamp.epochMicroseconds())-packet.read16());
	else if(marker != 0xF9)
		WARN("Packet marker unknown : %02x",marker);


	// Variables for request (0x10 and 0x11)
	UInt8 flags;
	Flow* pFlow=NULL;
	UInt32 stage=0;
	UInt32 deltaNAck=0;

	UInt8 type = packet.available()>0 ? packet.read8() : 0xFF;
	bool answer = false;

	// Can have nested queries
	while(type!=0xFF) {

		UInt16 size = packet.read16();

		PacketReader message(packet.current(),size);		

		switch(type) {
			case 0x0c :
				fail("Session failed on the client side");
				break;

			case 0x4c :
				/// Session death!
				kill();
				break;

			/// KeepAlive
			case 0x01 :
				writeMessage(0x41,0);
			case 0x41 :
				_timesKeepalive=0;
				break;

			case 0x5e : {
				// Flow exception!
				UInt32 id = message.read7BitValue();
				
				FlowWriter* pFlowWriter = flowWriter(id);
				if(pFlowWriter)
					pFlowWriter->fail("receiver has rejected the flow");
				else
					WARN("FlowWriter %u unfound for failed signal",id);
				break;

			}
			case 0x18 :
				/// This response is sent when we answer with a Acknowledgment negative
				// It contains the id flow
				// I don't unsertand the usefulness...
				//pFlow = &flow(message.read8());
				//stage = pFlow->stageSnd();
				// For the moment, we considerate it like a exception
				fail("ack negative from server"); // send fail message immediatly
				break;

			case 0x51 : {
				/// Acknowledgment
				UInt32 id = message.read7BitValue();
				FlowWriter* pFlowWriter = flowWriter(id);
				if(pFlowWriter) {
					UInt8 ack = message.read8();
					while(ack==0xFF)
						ack = message.read8();
					if(ack>0)
						pFlowWriter->acknowledgment(message.read7BitValue());
					else {
						// In fact here, we should send a 0x18 message (with id flow),
						// but it can create a loop... We prefer the following behavior
						pFlowWriter->fail("ack negative from client");
					}

				} else
					WARN("FlowWriter %u unfound for acknowledgment",id);
				break;
			}
			/// Request
			// 0x10 normal request
			// 0x11 special request, in repeat case (following stage request)
			case 0x10 : {
				flags = message.read8();
				UInt32 idFlow = message.read7BitValue();
				stage = message.read7BitValue()-1;
				deltaNAck = message.read7BitValue()-1;

				map<UInt32,Flow*>::const_iterator it = _flows.find(idFlow);
				pFlow = it==_flows.end() ? NULL : it->second;

				// Header part if present
				if(flags & MESSAGE_HEADER) {
					string signature;
					message.readString8(signature);

					if(!pFlow)
						pFlow = createFlow(idFlow,signature);

					if(message.read8()>0) {

						// Fullduplex header part
						if(message.read8()!=0x0A)
							WARN("Unknown fullduplex header part for the flow '%u'",idFlow)
						else
							message.read7BitValue(); // Fullduplex useless here! Because we are creating a new Flow!

						// Useless header part 
						UInt8 length=message.read8();
						while(length>0 && message.available()) {
							WARN("Unknown message part on flow '%u'",idFlow);
							message.next(length);
							length=message.read8();
						}
						if(length>0)
							ERROR("Bad header message part, finished before scheduled");
					}

				}
				
				if(!pFlow) {
					WARN("Flow %u unfound",idFlow);
					((UInt32&)_pFlowNull->id) = idFlow;
					pFlow = _pFlowNull;
				}

			}	
			case 0x11 : {
				++stage;
				++deltaNAck;

				// has Header?
				if(type==0x11)
					flags = message.read8();

				// Process request
				pFlow->fragmentHandler(stage,deltaNAck,message,flags);
				if(!pFlow->error().empty())
					fail(pFlow->error()); // send fail message immediatly

				break;
			}
			default :
				ERROR("Message type '%02x' unknown",type);
		}

		// Next
		packet.next(size);
		type = packet.available()>0 ? packet.read8() : 0xFF;

		// Commit Flow
		if(pFlow && stage>0 && type!= 0x11) {
			pFlow->commit();
			if(pFlow->consumed()) {
				_flows.erase(pFlow->id);
				delete pFlow;
			}
			pFlow=NULL;
		}
	}
Esempio n. 2
0
void ServerSession::packetHandler(PacketReader& packet) {
	if(died)
		return;

	_recvTimestamp.update();

	// Read packet
	UInt8 marker = packet.read8()|0xF0;
	
	_timeSent = packet.read16();

	// with time echo
	if(marker == 0xFD) {
		UInt16 time = RTMFP::TimeNow();
		UInt16 timeEcho = packet.read16();
		if(timeEcho>time) {
			if(timeEcho-time<30)
				time=0;
			else
				time += 0xFFFF-timeEcho;
			timeEcho = 0;
		}
		(UInt16&)peer.ping = (time-timeEcho)*RTMFP_TIMESTAMP_SCALE;
	}
	else if(marker != 0xF9)
		WARN("Packet marker unknown : %02x",marker);


	// Variables for request (0x10 and 0x11)
	UInt8 flags;
	Flow* pFlow=NULL;
	UInt64 stage=0;
	UInt64 deltaNAck=0;

	UInt8 type = packet.available()>0 ? packet.read8() : 0xFF;
	bool answer = false;

	// Can have nested queries
	while(type!=0xFF) {

		UInt16 size = packet.read16();

		PacketReader message(packet.current(),size);		

		switch(type) {
			case 0x0c :
				fail("failed on client side");
				break;

			case 0x4c :
				/// Session death!
				_failed=true; // to avoid the fail signal!!
				kill();
				return;

			/// KeepAlive
			case 0x01 :
				if(!peer.connected)
					fail("Timeout connection client");
				else
					writeMessage(0x41,0);
			case 0x41 :
				_timesKeepalive=0;
				break;

			case 0x5e : {
				// Flow exception!
				UInt64 id = message.read7BitLongValue();
				
				FlowWriter* pFlowWriter = flowWriter(id);
				if(pFlowWriter)
					pFlowWriter->fail(format("flowWriter rejected on session %u",this->id));
				else
					WARN("FlowWriter %s unfound for failed signal on session %u",NumberFormatter::format(id).c_str(),this->id);
				break;

			}
			case 0x18 :
				/// This response is sent when we answer with a Acknowledgment negative
				// It contains the id flow
				// I don't unsertand the usefulness...
				//pFlow = &flow(message.read8());
				//stage = pFlow->stageSnd();
				// For the moment, we considerate it like a exception
				fail("ack negative from server"); // send fail message immediatly
				break;

			case 0x51 : {
				/// Acknowledgment
				/*if(this->id>1) {
					vector<UInt8> out;
					Util::Dump(message.current(),message.available(),out);
					cout.write((const char*)&out[0],out.size());
				}*/
				UInt64 id = message.read7BitLongValue();
				FlowWriter* pFlowWriter = flowWriter(id);
				if(pFlowWriter)
					pFlowWriter->acknowledgment(message);
				else
					WARN("FlowWriter %s unfound for acknowledgment on session %u",NumberFormatter::format(id).c_str(),this->id);
				break;
			}
			/// Request
			// 0x10 normal request
			// 0x11 special request, in repeat case (following stage request)
			case 0x10 : {
				flags = message.read8();
				UInt64 idFlow = message.read7BitLongValue();
				stage = message.read7BitLongValue()-1;
				deltaNAck = message.read7BitLongValue()-1;
				
				if(_failed)
					break;

				std::map<UInt64,Flow*>::const_iterator 
it = _flows.find(idFlow);
				pFlow = it==_flows.end() ? NULL : it->second;

				// Header part if present
				if(flags & MESSAGE_HEADER) {
					string signature;
					message.readString8(signature);

					if(!pFlow)
						pFlow = createFlow(idFlow,signature);

					if(message.read8()>0) {

						// Fullduplex header part
						if(message.read8()!=0x0A)
							WARN("Unknown fullduplex header part for the flow %s",NumberFormatter::format(idFlow).c_str())
						else 
							message.read7BitLongValue(); // Fullduplex useless here! Because we are creating a new Flow!

						// Useless header part 
						UInt8 length=message.read8();
						while(length>0 && message.available()) {
							WARN("Unknown message part on flow %s",NumberFormatter::format(idFlow).c_str());
							message.next(length);
							length=message.read8();
						}
						if(length>0)
							ERROR("Bad header message part, finished before scheduled");
					}

				}
				
				if(!pFlow) {
					WARN("Flow %s unfound",NumberFormatter::format(idFlow).c_str());
					((UInt64&)_pFlowNull->id) = idFlow;
					pFlow = _pFlowNull;
				}

			}	
			case 0x11 : {
				++stage;
				++deltaNAck;

				// has Header?
				if(type==0x11)
					flags = message.read8();

				// Process request
				if(pFlow) {
					pFlow->fragmentHandler(stage,deltaNAck,message,flags);
					if(!pFlow->error().empty()) {
						fail(pFlow->error()); // send fail message immediatly
						pFlow = NULL;
					}
				}

				break;
			}
			default :
				ERROR("Message type '%02x' unknown",type);
		}

		// Next
		packet.next(size);
		type = packet.available()>0 ? packet.read8() : 0xFF;

		// Commit Flow
		if(pFlow && type!= 0x11) {
			pFlow->commit();
			if(pFlow->consumed()) {
				_flows.erase(pFlow->id);
				delete pFlow;
			}
			pFlow=NULL;
		}
	}