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