Packet FormatContext::readPacket(OptionalErrorCode ec) { clear_if(ec); if (!m_raw) { throws_if(ec, Errors::Unallocated); return Packet(); } if (!m_streamsInfoFound) { fflog(AV_LOG_ERROR, "Streams does not found. Try call findStreamInfo()\n"); throws_if(ec, Errors::FormatNoStreams); return Packet(); } Packet packet; int sts = 0; int tries = 0; const int retryCount = 5; do { resetSocketAccess(); sts = av_read_frame(m_raw, packet.raw()); ++tries; } while (sts == AVERROR(EAGAIN) && (retryCount < 0 || tries <= retryCount)); // End of file if (sts == AVERROR_EOF /*|| avio_feof(m_raw->pb)*/) { auto ec = std::error_code(sts, ffmpeg_category()); fflog(AV_LOG_DEBUG, "EOF reaches, error=%d, %s, isNull: %d, stream_index: %d, payload: %p\n", sts, ec.message().c_str(), packet.isNull(), packet.streamIndex(), packet.data()); av_pkt_dump_log2(m_raw, AV_LOG_DEBUG, packet.raw(), 0, m_raw->streams[packet.streamIndex()]); if (packet) sts = 0; // not an error else return packet; } if (sts == 0) { auto pberr = m_raw->pb ? m_raw->pb->error : 0; if (pberr) { // TODO: need verification throws_if(ec, pberr, ffmpeg_category()); return packet; } } else { throws_if(ec, sts, ffmpeg_category()); return packet; } if (packet.streamIndex() >= 0) { if ((size_t)packet.streamIndex() > streamsCount()) { throws_if(ec, Errors::FormatInvalidStreamIndex); return packet; } packet.setTimeBase(m_raw->streams[packet.streamIndex()]->time_base); if (m_substractStartTime) { const auto startTs = stream(packet.streamIndex()).startTime(); if (startTs.isValid()) { if (packet.pts().isValid()) packet.setPts(packet.pts() - startTs); if (packet.dts().isValid()) packet.setDts(packet.pts() - startTs); } } } packet.setComplete(true); return packet; }
AckSceneExit(Packet packet) { m_uid = packet.ReadU32(); }
int main(int argc, char* argv[]) { //parse args if (argc != 5) { std::cout << "This program requires 4 arguments in the following format!" << std::endl; std::cout << "sender <host address of emulator> <udp port number of emulator in FWD direction>" << "\n" << "<udp port number of sender to receive acks> <fileName>" << std::endl; std::cout << "Example: sender 192.168.89.78 49998 11234 test.txt" << std::endl; return 1; } const char* ipAddr = argv[1]; if (0 == strcmp(ipAddr, "localhost")) { ipAddr = "127.0.0.1"; } unsigned long remoteIp = inet_addr(ipAddr); int remotePort = atoi(argv[2]); int senderPort = atoi(argv[3]); const char* fileName = argv[4]; int totalPackets = 0; int totalBytes = 0; int sentPackets = 0; int sentBytes = 0; int seqNum = 0; signal(SIGALRM, signal_alarm_handler); bool timer_on = false; list<Packet *> packetsToSend; list<Packet *> packetsSent; //Open the file and prepare the packets for transmission ifstream transferFile(fileName); ofstream seqLog(seqFile); ofstream ackLog(ackFile); if (!(seqLog.is_open() && ackLog.is_open())) { return 1; } if (transferFile.is_open()) { char buffer[Packet::MAX_DATA_LENGTH]; while(false == transferFile.eof()) { transferFile.read(buffer, Packet::MAX_DATA_LENGTH); Packet* packet = Packet::createPacket(seqNum, transferFile.gcount(), buffer); packetsToSend.insert(packetsToSend.end(), packet); LOG("Inserted packet %i in the queue\n", totalPackets); seqNum++; seqNum %= Packet::MAX_SEQ_NUMBER; totalPackets++; totalBytes += packet->getLength(); } } else { LOG("The input file was not found..\n"); return 1; } transferFile.close(); //Add EOT packet Packet *eotPacket = Packet::createEOT(seqNum); packetsToSend.insert(packetsToSend.end(), eotPacket); totalPackets++; LOG("Packets ready for transmission: %i\n", totalPackets); LOG("Total data to be sent: %i\n", totalBytes); //open a udp socket and listen for str UDPSocket udpSocket; int ret = udpSocket.open(senderPort); ASSERT(ret == 0); LOG("Sender is transmitting & receiving on UDP Port %i\n", senderPort); /** * Core Logic * The sender can be in three states * 1. SEND_DATA : Sends a packet as long as data is available and window size is permitted * 2. RECV_ACK : Receives an acknowledgement for a previously sent data * 3. RESEND_DATA: If an ACK is not received for a previously sent data within timer, resend the data */ while ((packetsToSend.size() > 0) || (packetsSent.size() > 0)) { if (udpSocket.hasData()) { g_state = SENDER_RECV_ACK; } switch(g_state) { /** * Within the WINDOW_SIZE, if data is available, send it. * Remove it from packetsToSend, and add it to packetsSent * If timer is off, turn it on. */ case SENDER_SEND_DATA: { if (packetsSent.size() < WINDOW_SIZE && packetsToSend.size() > 0) { list<Packet *>::iterator itr = packetsToSend.begin(); Packet *packet = (*itr); char *packetData = packet->getUDPData(); udpSocket.write(remoteIp, remotePort, packetData, packet->getUDPSize()); sentPackets++; sentBytes += packet->getLength(); seqLog << packet->getSeqNum() << endl; LOG("Sent packet seqnum %i, packet number %i\n", packet->getSeqNum(), sentPackets); LOG("Sent bytes: %i\n", sentBytes); if (false == timer_on) { alarm(TIMER_SECS); timer_on = true; } free(packetData); packetsToSend.remove(packet); packetsSent.insert(packetsSent.end(), packet); } } break; /** * 1. RECV Packet. * 2. Check if the ack number belongs to any packets in packetsSent. * 3. If yes, delete all packets upto and before. * 4. If not, discard packet * 5. If any packets are sent and not recieved ack, start timer again. */ case SENDER_RECV_ACK: { char buffer[Packet::MAX_PACKET_LENGTH]; unsigned long ip; int port; int length = Packet::MAX_PACKET_LENGTH; udpSocket.read(buffer, length, ip, port); Packet *packet = Packet::parseUDPData(buffer); int seqNum = packet->getSeqNum(); ackLog << seqNum << endl; //since it is cumulative keep deleting until seq num is found on packetsSent list<Packet *>::iterator itr = packetsSent.begin(); while (itr != packetsSent.end() && comparePacket((*itr)->getSeqNum(), seqNum) <= 0) { //less than or equal Packet *sentPacket = (*itr); packetsSent.remove(sentPacket); itr = packetsSent.begin(); delete(sentPacket); } delete(packet); if (packetsSent.size() > 0) { alarm(TIMER_SECS); } g_state = SENDER_SEND_DATA; } break; /** * 1. Resend data if timeout. * 2. Send all packets in packetsToSend */ case SENDER_RESEND_DATA: { for (list<Packet *>::iterator itr = packetsSent.begin(); itr != packetsSent.end(); ++itr) { Packet *packet = (*itr); char *packetData = packet->getUDPData(); udpSocket.write(remoteIp, remotePort, packetData, packet->getUDPSize()); seqLog << packet->getSeqNum() << endl; LOG("Resent packet seqnum %i\n", packet->getSeqNum()); if (false == timer_on) { alarm(TIMER_SECS); timer_on = true; } free(packetData); } } break; default: { ASSERT(0); //invalid state } } } LOG("End of Transmission. Exiting \n"); udpSocket.close(); seqLog.close(); ackLog.close(); ASSERT(totalBytes == sentBytes); ASSERT(totalPackets == sentPackets); return 0; }
/** * @param argv[1] receiving port number * argv[2] destination address * argv[3] destination port number * argv[4] filename to save */ int main(int argc, const char * argv[]) { int state = WAITING_STATE; try { ofstream logfile; logfile.open("receiver_log.txt"); logfile << " --- \n"; const char* hname = "localhost"; //configure receiving port Address * my_addr = new Address(hname, (short)(atoi(argv[1]))); LossyReceivingPort *my_port = new LossyReceivingPort(0.2); my_port->setAddress(my_addr); my_port->init(); //configure a sending port to send ACK Address * my_tx_addr = new Address(hname, 3005); Address * dst_addr = new Address(argv[2], (short)(atoi(argv[3]))); mySendingPort *my_tx_port = new mySendingPort(); my_tx_port->setAddress(my_tx_addr); my_tx_port->setRemoteAddress(dst_addr); my_tx_port->init(); Message *m = new Message(); char *filename; char *filename_to_save = (char *) argv[4]; cout << "begin receiving..." <<endl; Packet *p; int ackedSeqNum = 0; while (1) { p = my_port->receivePacket(); if (p !=NULL) { switch(state){ case WAITING_STATE:{ int seqNum = p->accessHeader()->getIntegerInfo(m->SEQNUM_POS); filename = p->getPayload(); Packet * ack_packet = m->make_ack_packet(seqNum); cout << "receiving a packet of seq num " << seqNum << " and filename is " << filename << endl; cout << "Beginning receiving file..." << endl; my_tx_port->sendPacket(ack_packet); remove("out.txt"); state = RECEIVING_STATE; break; } case RECEIVING_STATE:{ // Stop-and-wait scheme int seqNum = p->accessHeader()->getIntegerInfo(m->SEQNUM_POS); cout << "receiving a packet of seq num " << seqNum << endl; logfile << "Receive " << seqNum << "\n"; // special case, if being sent a seqnum = 0, which means the sender does not know // receiver DID receive it, so we send ack again if(seqNum != ackedSeqNum + 1){ Packet * ack_packet = m->make_ack_packet(seqNum); cout << "The sender does not know we DID receive packet! Resend ACK for him... " << endl; my_tx_port->sendPacket(ack_packet); break; } char *payload = p->getPayload(); if(m->append_data_to_file(filename_to_save,payload,p->getPayloadSize())){//only when write to file success... ackedSeqNum = seqNum; Packet *ack_packet = m->make_ack_packet(seqNum); my_tx_port->sendPacket(ack_packet); //... we send ACK } bool isEOF = p->accessHeader()->getShortIntegerInfo(m->EOF_POS) != 0 ? true : false; cout << "isEOF? " << isEOF << endl; if(isEOF){ cout << "Done receive file" <<endl; logfile.close(); } break; } default: break; } } } } catch (const char *reason ) { cerr << "Exception:" << reason << endl; exit(-1); } return 0; }
HRESULT CVideoPin::FillBuffer(IMediaSample* pSample) { try { Packet* buffer = NULL; do { if (m_pFilter->IsStopping() || m_demux.IsMediaChanging() || m_bFlushing || !m_bSeekDone || m_demux.m_bRebuildOngoing) { Sleep(1); return ERROR_NO_DATA; } if (m_demux.EndOfFile()) { LogDebug("vid: set EOF"); return S_FALSE; } if (m_demux.m_bVideoClipSeen || m_demux.m_bAudioRequiresRebuild && !m_demux.m_bVideoClipSeen && !m_demux.m_eAudioClipSeen->Check()) { CheckPlaybackState(); return ERROR_NO_DATA; } if (m_pCachedBuffer) { LogDebug("vid: cached fetch %6.3f clip: %d playlist: %d", m_pCachedBuffer->rtStart / 10000000.0, m_pCachedBuffer->nClipNumber, m_pCachedBuffer->nPlaylist); buffer = m_pCachedBuffer; m_pCachedBuffer = NULL; buffer->bDiscontinuity = true; if (m_bProvidePMT) { CMediaType mt(*buffer->pmt); SetMediaType(&mt); pSample->SetMediaType(&mt); m_bProvidePMT = false; } } else buffer = m_demux.GetVideo(); if (!buffer) { if (m_bFirstSample) Sleep(10); else { if (!m_bClipEndingNotified) { // Deliver end of stream notification to flush the video decoder. // This should only happen when the stream enters into paused state LogDebug("vid: FillBuffer - DeliverEndOfStream"); DeliverEndOfStream(); m_bClipEndingNotified = true; } else Sleep(10); return ERROR_NO_DATA; } } else { bool checkPlaybackState = false; { CAutoLock lock(m_section); if (buffer->nNewSegment > 0) { if ((buffer->nNewSegment & NS_NEW_CLIP) == NS_NEW_CLIP) { LogDebug("vid: Playlist changed to %d - nNewSegment: %d offset: %6.3f rtStart: %6.3f rtPlaylistTime: %6.3f", buffer->nPlaylist, buffer->nNewSegment, buffer->rtOffset / 10000000.0, buffer->rtStart / 10000000.0, buffer->rtPlaylistTime / 10000000.0); m_demux.m_bVideoClipSeen = true; m_bInitDuration = true; checkPlaybackState = true; m_bClipEndingNotified = false; if (buffer->bResuming || buffer->nNewSegment & NS_INTERRUPTED) { m_bDoFakeSeek = true; m_rtStreamOffset = buffer->rtPlaylistTime; m_bZeroTimeStream = true; m_demux.m_bAudioResetStreamPosition = true; } else m_rtStreamOffset = 0; // LAV video decoder requires an end of stream notification to be able to provide complete video frames // to downstream filters in a case where we are waiting for the audio pin to see the clip boundary as // we cannot provide yet the next clip's PMT downstream since audio stream could require a rebuild if (m_currentDecoder == CLSID_LAVVideo && (buffer->nNewSegment & NS_NEW_PLAYLIST)) { LogDebug("DeliverEndOFStream LAV Only for audio pin wait (%d,%d)", buffer->nPlaylist, buffer->nClipNumber); DeliverEndOfStream(); } } if ((buffer->nNewSegment & NS_STREAM_RESET) == NS_STREAM_RESET) m_bInitDuration = true; } if (buffer->pmt) { GUID subtype = subtype = buffer->pmt->subtype; if (buffer->pmt->subtype == FOURCCMap('1CVW') && m_VC1Override != GUID_NULL) { buffer->pmt->subtype = m_VC1Override; LogDebug("vid: FillBuffer - force VC-1 GUID"); } if (!CompareMediaTypes(buffer->pmt, &m_mt)) { LogMediaType(buffer->pmt); HRESULT hrAccept = S_FALSE; m_bProvidePMT = true; if (m_pReceiver && CheckVideoFormat(&buffer->pmt->subtype, &m_currentDecoder)) { // Currently no other video decoders than LAV seems to be compatible with // the dynamic format changes if (m_currentDecoder == CLSID_LAVVideo) hrAccept = m_pReceiver->QueryAccept(buffer->pmt); } if (hrAccept != S_OK) { CMediaType mt(*buffer->pmt); SetMediaType(&mt); LogDebug("vid: graph rebuilding required"); m_demux.m_bVideoRequiresRebuild = true; m_bZeroTimeStream = true; checkPlaybackState = true; //LogDebug("DeliverEndOFStream for rebuild (%d,%d)", buffer->nPlaylist, buffer->nClipNumber); //DeliverEndOfStream(); } else { LogDebug("vid: format change accepted"); CMediaType mt(*buffer->pmt); SetMediaType(&mt); pSample->SetMediaType(&mt); buffer->nNewSegment = 0; m_pCachedBuffer = buffer; //if (m_currentDecoder == CLSID_LAVVideo) //{ // LogDebug("DeliverEndOFStream LAV Only (%d,%d)", buffer->nPlaylist, buffer->nClipNumber); // DeliverEndOfStream(); //} return ERROR_NO_DATA; } } // comparemediatypes } } // lock ends m_rtTitleDuration = buffer->rtTitleDuration; if (checkPlaybackState) { buffer->nNewSegment = 0; m_pCachedBuffer = buffer; CheckPlaybackState(); LogDebug("vid: cached push %6.3f clip: %d playlist: %d", m_pCachedBuffer->rtStart / 10000000.0, m_pCachedBuffer->nClipNumber, m_pCachedBuffer->nPlaylist); return ERROR_NO_DATA; } bool hasTimestamp = buffer->rtStart != Packet::INVALID_TIME; REFERENCE_TIME rtCorrectedStartTime = 0; REFERENCE_TIME rtCorrectedStopTime = 0; if (hasTimestamp) { if (m_bZeroTimeStream) { m_rtStreamTimeOffset = buffer->rtStart - buffer->rtClipStartTime; m_bZeroTimeStream = false; } if (m_bDiscontinuity || buffer->bDiscontinuity) { LogDebug("vid: set discontinuity"); pSample->SetDiscontinuity(true); pSample->SetMediaType(buffer->pmt); m_bDiscontinuity = false; } rtCorrectedStartTime = buffer->rtStart - m_rtStreamTimeOffset; rtCorrectedStopTime = buffer->rtStop - m_rtStreamTimeOffset; pSample->SetTime(&rtCorrectedStartTime, &rtCorrectedStopTime); if (m_bInitDuration) { m_pFilter->SetTitleDuration(m_rtTitleDuration); m_pFilter->ResetPlaybackOffset(buffer->rtPlaylistTime - rtCorrectedStartTime); m_bInitDuration = false; } m_pFilter->OnPlaybackPositionChange(); } else // Buffer has no timestamp pSample->SetTime(NULL, NULL); pSample->SetSyncPoint(buffer->bSyncPoint); { CAutoLock lock(&m_csDeliver); if (!m_bFlushing) { BYTE* pSampleBuffer; pSample->SetActualDataLength(buffer->GetDataSize()); pSample->GetPointer(&pSampleBuffer); memcpy(pSampleBuffer, buffer->GetData(), buffer->GetDataSize()); m_bFirstSample = false; #ifdef LOG_VIDEO_PIN_SAMPLES LogDebug("vid: %6.3f corr %6.3f playlist time %6.3f clip: %d playlist: %d size: %d", buffer->rtStart / 10000000.0, rtCorrectedStartTime / 10000000.0, buffer->rtPlaylistTime / 10000000.0, buffer->nClipNumber, buffer->nPlaylist, buffer->GetCount()); #endif } else { LogDebug("vid: dropped sample as flush is active!"); return ERROR_NO_DATA; } } //static int iFrameNumber = 0; //LogMediaSample(pSample, iFrameNumber++); delete buffer; } } while (!buffer); return NOERROR; } catch(...) { LogDebug("vid: FillBuffer exception"); } return S_OK; }
void Pgw::handle_uplink_udata(Packet pkt, UdpClient &sink_client) { pkt.truncate(); sink_client.set_server(g_sink_ip_addr, g_sink_port); sink_client.snd(pkt); TRACE(cout << "pgw_handleuplinkudata:" << " uplink udata forwarded to sink: " << pkt.len << endl;) }
Packet* CClip::GenerateSparseVideo(REFERENCE_TIME rtStart) { Packet * ret = NULL; if (!SparseVideoAvailable() && m_vecClipVideoPackets.size()==0) return ret; if (m_pSparseVideoPacket != NULL) { if (m_vecClipVideoPackets.size()>0) { Packet * pBDPacket = m_vecClipVideoPackets[0]; if (m_pSparseVideoPacket->rtStart + ONE_SECOND > pBDPacket->rtStart) { ivecVideoBuffers it = m_vecClipVideoPackets.begin(); if ((*it)->rtStart !=Packet::INVALID_TIME) { delete m_pSparseVideoPacket; m_pSparseVideoPacket=*it; it=m_vecClipVideoPackets.erase(it); } else { it=m_vecClipVideoPackets.erase(it); if (!m_vecClipVideoPackets.size()) sparseVideo = false; return *it; } } else { m_pSparseVideoPacket->rtStart += HALF_SECOND/5; m_pSparseVideoPacket->rtStop += HALF_SECOND/5; m_pSparseVideoPacket->bFakeData = true; } } else { m_pSparseVideoPacket->rtStart += HALF_SECOND/5; m_pSparseVideoPacket->rtStop += HALF_SECOND/5; m_pSparseVideoPacket->bFakeData = true; } ret = new Packet(); ret->SetData(m_pSparseVideoPacket->GetData(),m_pSparseVideoPacket->GetDataSize()); ret->CopyProperties(*m_pSparseVideoPacket); } else { if (m_vecClipVideoPackets.size()>0) { ivecVideoBuffers it = m_vecClipVideoPackets.begin(); if ((*it)->rtStart !=Packet::INVALID_TIME) { m_pSparseVideoPacket=*it; it=m_vecClipVideoPackets.erase(it); ret = new Packet(); ret->SetData(m_pSparseVideoPacket->GetData(),m_pSparseVideoPacket->GetDataSize()); ret->CopyProperties(*m_pSparseVideoPacket); } else { it=m_vecClipVideoPackets.erase(it); if (!m_vecClipVideoPackets.size()) sparseVideo = false; return *it; } } } return ret; }
void CReadSendPacket::SendGameServerInfo (SOCKET Socket, SGameServer server) { SPacket SPacket; //CryLog("[CryMasterServer] Send game server info..."); Packet* p = new Packet(); p->create(); /****************************Обязательный блок************************************/ p->writeInt(PACKET_GAME_SERVER); // Тип пакета p->writeString(gClientEnv->clientVersion); // Версия пакета /*******************************Тело пакета****************************************/ p->writeString(server.ip); p->writeInt(server.port); p->writeString(server.serverName); p->writeInt(server.currentPlayers); p->writeInt(server.maxPlayers); p->writeString(server.mapName); p->writeString(server.gameRules); p->writeString(EndBlock); // Завершающий блок p->padPacketTo8ByteLen(); p->encodeBlowfish(gClientEnv->bBlowFish); p->appendChecksum(false); p->appendMore8Bytes(); int size = p->getPacketSize(); char* packet = (char*)p->getBytesPtr(); SPacket.addr = Socket; SPacket.data = packet; SPacket.size = size; gClientEnv->pPacketQueue->InsertPacket(SPacket); if(gClientEnv->bDebugMode) { CryLog("[CryMasterServer] Game Server info packet size = %d",size); CryLog("[CryMasterServer] Game Server ip = %s",server.ip); CryLog("[CryMasterServer] Game Server port = %d",server.port); CryLog("[CryMasterServer] Game Server name = %s",server.serverName); CryLog("[CryMasterServer] Game Server onlain = %d",server.currentPlayers); CryLog("[CryMasterServer] Game Server max players = %d",server.maxPlayers); CryLog("[CryMasterServer] Game Server map name = %s",server.mapName); CryLog("[CryMasterServer] Game Server gamerules = %s",server.gameRules); PacketDebugger::Debug(packet, size, "SendPacketsDebugg.txt"); } }
void CReadSendPacket::SendRequest(SOCKET Socket, SRequestPacket request) { SPacket SPacket; //CryLog("[CryMasterServer] Send request..."); Packet* p = new Packet(); p->create(); /****************************Обязательный блок************************************/ p->writeInt(PACKET_REQUEST); // Тип пакета p->writeString(gClientEnv->clientVersion); // Версия пакета /*******************************Тело пакета****************************************/ p->writeString(request.request); p->writeString(request.sParam); p->writeInt(request.iParam); p->writeString(EndBlock); // Завершающий блок p->padPacketTo8ByteLen(); p->encodeBlowfish(gClientEnv->bBlowFish); p->appendChecksum(false); p->appendMore8Bytes(); int size = p->getPacketSize(); char* packet = (char*)p->getBytesPtr(); SPacket.addr = Socket; SPacket.data = packet; SPacket.size = size; gClientEnv->pPacketQueue->InsertPacket(SPacket); if(gClientEnv->bDebugMode) { CryLog("[CryMasterServer] Request packet size = %d",size); CryLog("[CryMasterServer] Request = %s",request.request); CryLog("[CryMasterServer] Request sParam = %s", request.sParam); CryLog("[CryMasterServer] Request iParam = %d", request.iParam); PacketDebugger::Debug(packet, size, "SendPacketsDebugg.txt"); } }
int Send() { int retVal = 1; if (gIpAddress == NULL) { cout << "Must specify at least a -d \"destination IP Address\"" << endl; cout << "e.g., trapgen -d 244.0.2.43" << endl; return 0; } if (gDump == ' ') { UdpClient udp(gPort, gIpAddress); if (gDoLogging) if (!udp.IsReady()) gOfile << "udp failed to initialize with error " << udp.ErrorCode() << endl; udp.Send(&gPacket); if (gInform) { udp.Timeout(gTimeout); Packet* p = udp.Receive(0); if (p != NULL && (p->RequestId() == gRequestId) && (p->Type() == V1RESPONSE)) retVal = 0; else if (gDoLogging) gOfile << "Sent INFORM but response timed out (timeout = " << gTimeout << ')' << endl; } else retVal = 0; } else { if (gDump == 'a' || gDump == 'b') { cout << "Length: " << gPacket.TotalLength() << endl; int version = gPacket.Version(); cout << "Version: "; if (version == 0) cout << "SNMPv1"; else if (version == 1) cout << "SNMPv2"; cout << endl; cout << "Community: " << gPacket. Community() << endl; if (version == 0) { cout << "Generic: " << gPacket.GenericTrapType() << endl; cout << "Specific: " << gPacket.SpecificTrapType() << endl; //////////////////////////////////////////////////////// int tTime = gPacket.TimeTicks(); tTime /= 100; int days = tTime/(60*60*24); tTime -= days * (60*60*24); int hrs = tTime/(60*60); tTime -= hrs*(60*60); int mins = tTime/(60); tTime -= mins*(60); char newcTime[128]; #ifdef _WIN32 sprintf_s(newcTime, 128, "%d days %02dh:%02dm:%02ds", days, hrs, mins, tTime); #else sprintf(newcTime, "%d days %02dh:%02dm:%02ds", days, hrs, mins, tTime); #endif cout << "TimeStamp: " << newcTime << " (" << gPacket.TimeTicks() << ")" << endl; // cout << "TimeStamp: " << gPacket.TimeTicks() << endl; //////////////////////////////////////////////////////// cout << "SenderIP: " << gPacket.SenderIP() << endl; } if (version == 0) cout << "SenderOID: " << gPacket.SenderOID() << endl; int vblen = gPacket.VbListLength(); for (int x = 1; x <= vblen; x++) { cout << "Varbind Number " << x << ' ' << endl; cout << '\t' << "Oid: " << gPacket.VbOID(x) << endl; cout << '\t' << "Type: " << gPacket.VbType(x) << endl; cout << '\t' << "Data: " << gPacket.VbData(x) << endl; } cout << endl; } if (gDump == 'h' || gDump == 'b') { unsigned int l = gPacket.TotalLength(); unsigned char* pdu = new unsigned char[l]; gPacket.Build(pdu); for (unsigned int asdf = 0; asdf < l; asdf++) { if (asdf && !(asdf % 10)) printf("\n"); printf("%02x ", pdu[asdf]); } printf("\n"); } } return retVal; }
int main(int argc, char** argv) { #ifdef _WIN32 // save the size and other constraints char t[512]; memset(t, 0, 512); GetConsoleTitle(t, 512); HWND h = FindWindow("ConsoleWindowClass", t); // ShowWindow(h, SW_HIDE); #endif int retVal = 0; try { int limCount = min(argc, 4); for (int x = 1; x < limCount; x++) { // check for an input file if (argv[x][0] == '-') { if (argv[x][1] == 'f' || argv[1][1] == 'F') FileOpts(argv[x + 1]); else // see if they need help if (argv[x][1] == 'h') { #ifdef _WIN32 // ShowWindow(h, SW_SHOW); #endif Usage(); exit(0); } } else // this is just for us if (!strcmp(argv[x], "dumpVer")) { cout << "TrapGen from Network Computing Technologies, Inc."; cout << endl << gProgramVersion << endl; return 0; } } // for (int x = 1; x < limCount; x++) // other command line arguments CmdLineOpts(argc, argv); if (gLogFileName != NULL) { gDoLogging = TRUE; gOfile.open(gLogFileName, ios::app); } #ifdef _WIN32 // if (FALSE == gFreeConsole) // { // ShowWindow(h, SW_SHOW); if (TRUE == gFreeConsole) { ShowWindow(h, SW_HIDE); } #endif #ifdef _WIN32 WSADATA wsaData; int err = WSAStartup(0x200, &wsaData); if (err == WSAVERNOTSUPPORTED) err = WSAStartup(0x101, &wsaData); if (gDoLogging) if (err) gOfile << "failed to initialize winsock, error is " << err << endl; #endif /////////////////////////////////////////////////// // new to version 2.7 #ifdef _WIN32 NtSysUpTime sysUpTime; #endif #ifdef _LINUX LinuxSysUpTime sysUpTime; #endif #ifdef _SOLARIS SolarisSysUpTime sysUpTime; #endif #ifdef _IRIX IrixSysUptime sysUpTime; #endif #ifdef _HPUX HpuxSysUpTime sysUpTime; #endif #ifdef _FREEBSD FreeBSDSysUptime sysUpTime; #endif gTimeTicks = sysUpTime.SysUpTime(); /////////////////////////////////////////////////// // figure out the ip address if not specified (V1 only) if (gSenderIP == NULL && gVersion == 0) { char buf[255]; unsigned long len = 255; memset(buf, 0, len); if (gethostname(buf, len)) if (gDoLogging) gOfile << "gethostname failed with error " << WSAGetLastError() << endl; HOSTENT* h = gethostbyname(buf); if (h != NULL) { struct in_addr in; memcpy(&in.s_addr, *(h->h_addr_list), sizeof(in.s_addr)); gSenderIP = inet_ntoa(in); } else { gSenderIP = "240.30.20.10"; if (gDoLogging) gOfile << "gethostbyname failed with error " << WSAGetLastError() << endl; } } // build the packet gPacket.Version(gVersion); gPacket.Community(gCommunity); if (gVersion == 0) { gPacket.Type(V1TRAP); gPacket.SenderOID(gSenderOID); gPacket.SenderIP(gSenderIP); gPacket.TimeTicks(gTimeTicks); gPacket.GenericTrapType(gGenericTrapType); gPacket.SpecificTrapType(gSpecificTrapType); } else { if (!gInform) gPacket.Type(V2TRAP); else gPacket.Type(INFORMPDU); gPacket.RequestId(gRequestId); gPacket.ErrorStatus(0); gPacket.ErrorIndex(0); gPacket.AddV2TrapVarbinds(gTimeTicks, gSenderOID, gGenericTrapType, gSpecificTrapType, gNoSubIds); } // send away retVal = Send(); } catch (SnmpException* se) { retVal = -1; } catch (...) { retVal = -2; } #ifdef _WIN32 WSACleanup(); #endif if (gDoLogging) gOfile.close(); return retVal; }
void InitOption(char opt, char* optionValue, char* secondValue, char* thirdValue) { switch (opt) { #ifdef _WIN32 case 'z': case 'Z': { gFreeConsole = TRUE; break; } #endif case 'x': gNoSubIds = TRUE; break; case 'd': case 'D': { char* colon = strchr(optionValue, ':'); if (colon) { *colon++ = 0; gPort = atoi(colon); } gIpAddress = _strdup(optionValue); break; } case 'c': case 'C': { gCommunity = _strdup(optionValue); break; } case 'o': case 'O': { gSenderOID = _strdup(optionValue); break; } case 'i': case 'I': { gSenderIP = _strdup(optionValue); break; } case 'l': case 'L': { gLogFileName = _strdup(optionValue); break; } case 'm': case 'M': { gTimeout = atoi(optionValue); break; } case 'g': case 'G': { gGenericTrapType = atoi(optionValue); break; } case 'p': case 'P': { gDump = *optionValue; break; } case 'r': case 'R': { gRequestId = atoi(optionValue); break; } case 's': case 'S': { gSpecificTrapType = atoi(optionValue); break; } case 't': case 'T': { gTimeTicks = atoi(optionValue); break; } case 'v': case 'V': { OidVarbind* oid = new OidVarbind(optionValue); Varbind* vb; if (secondValue != NULL && thirdValue != NULL) { switch (secondValue[0]) { case 'S': case 's': { vb = new StringVarbind(thirdValue); break; } case 'A': case 'a': { vb = new IpAddrVarbind(thirdValue); break; } case 'O': case 'o': { vb = new OidVarbind(thirdValue); break; } case 'C': case 'c': { vb = new CounterVarbind(atoi(thirdValue)); break; } case 'G': case 'g': { vb = new GaugeVarbind(atoi(thirdValue)); break; } case 'H': case 'h': { vb = new StringVarbind(thirdValue, 0); break; } case 'I': case 'i': { vb = new IntVarbind(atoi(thirdValue)); break; } case 'T': case 't': { vb = new TimetickVarbind(atoi(thirdValue)); break; } } // switch (argv[x+1]) VbPair* vbp = new VbPair(); vbp->OIDVarbind(oid); vbp->VarBind(vb); // gPacket->Add(vbp); gPacket.Add(vbp); } // if ((x + 1) < argc) break; } } // switch (opt) }
void Packet::WritePacketData(Packet &packet) { if (packet.Length() == 0) return; data.resize(data.size() + packet.Length()); memcpy(&data[data.size() - packet.Length()], packet.Data(), packet.Length()); }
/*! \sa PacketProcessor */ bool PacketProcessor::processFrame(Packet& p_Frame) { //invalidate the packet by default m_Valid = false; //invalidate the destination IP by default m_DestinationIP = ""; //reset the processing buffer resetPacketBuffer(); //get IP packet from the frame p_Frame.getPDU(m_PacketBuffer); //VALIDATE THE PACKET //check the link layer length if((readShort(&m_PacketBuffer[3])) < MIN_LENGTH) { //Report and drop m_Converter.newReportString("Ilegal link layer length for packet: \n"); m_Converter.appendReportString(readIPPacket()); resetPacketBuffer(); SC_REPORT_WARNING(g_ErrorID, m_Converter.getReportString()); return false; } //verify checksum if(!(confirmCheckSum())) { //Report and drop m_Converter.newReportString("Invalid CheckSum for packet: \n"); m_Converter.appendReportString(readIPPacket()); resetPacketBuffer(); SC_REPORT_WARNING(g_ErrorID, m_Converter.getReportString()); return false; } //verify the version if((readSubField(m_PacketBuffer[0], 7, 4) != VERSION)) { //Report and drop m_Converter.newReportString("Invalid protocol version for packet: \n"); m_Converter.appendReportString(readIPPacket()); resetPacketBuffer(); SC_REPORT_WARNING(g_ErrorID, m_Converter.getReportString()); return false; } //verify the IHL if((readSubField(m_PacketBuffer[0], 3, 0) < 5)) { //Report and drop m_Converter.newReportString("Ilegal header length for packet: \n"); m_Converter.appendReportString(readIPPacket()); resetPacketBuffer(); SC_REPORT_WARNING(g_ErrorID, m_Converter.getReportString()); return false; } //verify the maximum length of the packet if((readShort(&m_PacketBuffer[3])) > MAX_LENGTH) { //Report and drop m_Converter.newReportString("The packet length is too long: \n"); m_Converter.appendReportString(readIPPacket()); resetPacketBuffer(); SC_REPORT_WARNING(g_ErrorID, m_Converter.getReportString()); return false; } //store the destination address m_DestinationIP = m_Converter.ipToString(&m_PacketBuffer[16]); //validate the packet m_Valid = true; return true; }
void Handle(Chimera&, const Host&, const Packet& pckt) { std::string message = pckt.GetArg<std::string>(CHIMERA_CHAT_MESSAGE); pf_log[W_INFO] << "CHAT[" << pckt.GetSrc() << "] " << message; }
void CReadSendPacket::SendRegisterPacket(SOCKET Socket, SLoginPacket packet) { //CryLog("[CryMasterServer] Send register packet..."); SPacket SPacket; Packet* p = new Packet(); p->create(); /****************************Обязательный блок************************************/ p->writeInt(PACKET_REGISTER); // Тип пакета p->writeString(gClientEnv->clientVersion); // Версия пакета /*******************************Тело пакета****************************************/ p->writeString(packet.login); p->writeString(packet.password); p->writeString(packet.nickname); p->writeString(EndBlock); // Завершающий блок p->padPacketTo8ByteLen(); p->encodeBlowfish(gClientEnv->bBlowFish); p->appendChecksum(false); p->appendMore8Bytes(); int size = p->getPacketSize(); char* Packet = (char*)p->getBytesPtr(); SPacket.addr = Socket; SPacket.data = Packet; SPacket.size = size; gClientEnv->pPacketQueue->InsertPacket(SPacket); if(gClientEnv->bDebugMode) { CryLog("[CryMasterServer] Register packet size = %d",size); PacketDebugger::Debug(Packet, size, "SendPacketsDebugg.txt"); } }
void Pgw::handle_create_session(struct sockaddr_in src_sock_addr, Packet pkt) { uint64_t imsi; uint8_t eps_bearer_id; uint32_t s5_uteid_ul; uint32_t s5_uteid_dl; uint32_t s5_cteid_ul; uint32_t s5_cteid_dl; uint64_t apn_in_use; uint64_t tai; string ue_ip_addr; pkt.extract_item(s5_cteid_dl); pkt.extract_item(imsi); pkt.extract_item(eps_bearer_id); pkt.extract_item(s5_uteid_dl); pkt.extract_item(apn_in_use); pkt.extract_item(tai); s5_cteid_ul = s5_cteid_dl; s5_uteid_ul = s5_cteid_dl; ue_ip_addr = ip_addrs[imsi]; update_itfid(5, s5_uteid_ul, "", imsi); update_itfid(0, 0, ue_ip_addr, imsi); g_sync.mlock(uectx_mux); ue_ctx[imsi].init(ue_ip_addr, tai, apn_in_use, eps_bearer_id, s5_uteid_ul, s5_uteid_dl, s5_cteid_ul, s5_cteid_dl); g_sync.munlock(uectx_mux); pkt.clear_pkt(); pkt.append_item(s5_cteid_ul); pkt.append_item(eps_bearer_id); pkt.append_item(s5_uteid_ul); pkt.append_item(ue_ip_addr); pkt.prepend_gtp_hdr(2, 1, pkt.len, s5_cteid_dl); s5_server.snd(src_sock_addr, pkt); TRACE(cout << "pgw_handlecreatesession:" << " create session response sent to mme: " << imsi << endl;) }
void CReadSendPacket::SendMsg(SOCKET Socket, SMessage message) { //CryLog("[CryMasterServer] Send message packet..."); SPacket SPacket; Packet* p = new Packet(); p->create(); /****************************Обязательный блок************************************/ p->writeInt(PACKET_MESSAGE); // Тип пакета p->writeString(gClientEnv->clientVersion); // Версия пакета /*******************************Тело пакета****************************************/ p->writeString(message.message); p->writeInt(message.area); p->writeString(EndBlock); // Завершающий блок p->padPacketTo8ByteLen(); p->encodeBlowfish(gClientEnv->bBlowFish); p->appendChecksum(false); p->appendMore8Bytes(); int size = p->getPacketSize(); char* packet = (char*)p->getBytesPtr(); SPacket.addr = Socket; SPacket.data = packet; SPacket.size = size; gClientEnv->pPacketQueue->InsertPacket(SPacket); if(gClientEnv->bDebugMode) { CryLog("[CryMasterServer] Message packet size = %d",size); CryLog("[CryMasterServer] Message packet data = %s",message.message); CryLog("[CryMasterServer] Message packet type = %d",message.area); PacketDebugger::Debug(packet, size, "SendPacketsDebugg.txt"); } }
int main(int argc, char* argv[]) { if (argc != 3) { cout << "Usage: " << argv[0] << " PORT-NUMBER FILE-NAME" << endl; exit(1); } ifstream file(argv[2]); int sockfd = set_up_socket(argv[1]); struct sockaddr_storage recv_addr; socklen_t addr_len = sizeof(recv_addr); int status, n_bytes; uint16_t ack_num, base_num; Packet p; unordered_map<uint16_t, Packet_info> window; Packet_info pkt_info; // select random seq_num srand(time(NULL)); uint16_t seq_num = rand() % MSN; RTO rto; // recv SYN from client do { n_bytes = recvfrom(sockfd, (void *) &p, sizeof(p), 0, (struct sockaddr *) &recv_addr, &addr_len); process_error(n_bytes, "recv SYN"); } while (!p.syn_set()); cout << "Receiving packet " << p.ack_num() << endl; ack_num = (p.seq_num() + 1) % MSN; // sending SYN ACK p = Packet(1, 1, 0, seq_num, ack_num, 0, "", 0); pkt_info = Packet_info(p, n_bytes - HEADER_LEN, rto.get_timeout()); status = sendto(sockfd, (void *) &p, HEADER_LEN, 0, (struct sockaddr *) &recv_addr, addr_len); process_error(status, "sending SYN ACK"); cout << "Sending packet " << seq_num << " " << MSS << " " << INITIAL_SSTHRESH << " SYN" << endl; seq_num = (seq_num + 1) % MSN; base_num = seq_num; // recv ACK do { struct timeval max_time = pkt_info.get_max_time(); struct timeval curr_time; gettimeofday(&curr_time, NULL); struct timeval time_left; timersub(&max_time, &curr_time, &time_left); status = setsockopt(sockfd, SOL_SOCKET,SO_RCVTIMEO, (char *)&time_left, sizeof(time_left)); process_error(status, "setsockopt"); n_bytes = recvfrom(sockfd, (void *) &p, sizeof(p), 0, (struct sockaddr *) &recv_addr, &addr_len); process_recv(n_bytes, "recv ACK after SYN ACK", sockfd, pkt_info, recv_addr, addr_len, rto); } while (p.seq_num() != ack_num); // discard invalid ack uint16_t prev_ack = p.ack_num(); cout << "Receiving packet " << p.ack_num() << endl; ack_num = (p.seq_num() + 1) % MSN; double cwnd = min((double) MSS, MSN / 2.0); uint16_t cwnd_used = 0; uint16_t ssthresh = INITIAL_SSTHRESH; uint16_t cwd_pkts = 0; uint16_t pkts_sent = 0; uint16_t dup_ack = 0; uint16_t recv_window = UINT16_MAX; bool slow_start = true; bool congestion_avoidance = false; bool fast_recovery = false; bool retransmission = false; bool last_retransmit = false; // send file do { if (retransmission) // retransmit missing segment { auto found = window.find(base_num); p = found->second.pkt(); status = sendto(sockfd, (void *) &p, found->second.data_len() + HEADER_LEN, 0, (struct sockaddr *) &recv_addr, addr_len); process_error(status, "sending retransmission"); cout << "Sending packet " << p.seq_num() << " " << cwnd << " " << ssthresh << " Retransmission" << endl; retransmission = false; if (last_retransmit) { // double RTO if retransmission again rto.double_RTO(); } found->second.update_time(rto.get_timeout()); last_retransmit = true; } else // transmit new segment(s), as allowed { last_retransmit = false; while (floor(cwnd) - cwnd_used >= MSS && !file.eof()) { string data; size_t buf_pos = 0; data.resize(MSS); cout << "Sending packet " << seq_num << " " << cwnd << " " << ssthresh << endl; // make sure recv all that we can do { size_t n_to_send = (size_t) min(cwnd - cwnd_used, (double) min(MSS, recv_window)); file.read(&data[buf_pos], n_to_send); n_bytes = file.gcount(); buf_pos += n_bytes; cwnd_used += n_bytes; } while (cwnd_used < floor(cwnd) && !file.eof() && buf_pos != MSS); // send packet p = Packet(0, 0, 0, seq_num, ack_num, 0, data.c_str(), buf_pos); pkt_info = Packet_info(p, buf_pos, rto.get_timeout()); status = sendto(sockfd, (void *) &p, buf_pos + HEADER_LEN, 0, (struct sockaddr *) &recv_addr, addr_len); process_error(status, "sending packet"); window.emplace(seq_num, pkt_info); seq_num = (seq_num + pkt_info.data_len()) % MSN; } } // recv ACK do { struct timeval time_left_tv= time_left(window, base_num); status = setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&time_left_tv, sizeof(time_left_tv)); process_error(status, "setsockopt"); int ack_n_bytes = recvfrom(sockfd, (void *) &p, sizeof(p), 0, (struct sockaddr *) &recv_addr, &addr_len); if (ack_n_bytes == -1) //error { // check if timed out if (errno == EAGAIN || EWOULDBLOCK || EINPROGRESS) { // adjust cwnd and ssthresh ssthresh = cwnd / 2; cwnd = MSS; dup_ack = 0; slow_start = true; congestion_avoidance = false; fast_recovery = false; retransmission = true; break; } else // else another error and process it { process_error(ack_n_bytes, "recv ACK after sending data"); } } } while (!valid_ack(p, base_num)); if (retransmission) continue; cout << "Receiving packet " << p.ack_num() << endl; if (prev_ack == p.ack_num()) // if duplicate { if (fast_recovery) { cwnd += MSS; } else { dup_ack++; } // if retransmit if (dup_ack == 3) { ssthresh = cwnd / 2; cwnd = ssthresh + 3 * MSS; fast_recovery = true; slow_start = false; congestion_avoidance = false; retransmission = true; dup_ack = 0; } } else // new ack { if (slow_start) { cwnd += MSS; dup_ack = 0; if (cwnd >= ssthresh) { slow_start = false; congestion_avoidance = true; cwd_pkts = cwnd / MSS; pkts_sent = 0; } } else if (congestion_avoidance) { if (pkts_sent == cwd_pkts) { cwd_pkts = cwnd / MSS; pkts_sent = 0; } cwnd += MSS / (double) cwd_pkts; pkts_sent++; } else // fast recovery { cwnd = ssthresh; dup_ack = 0; fast_recovery = false; congestion_avoidance = true; } prev_ack = p.ack_num(); cwnd_used -= update_window(p, window, base_num, rto); ack_num = (p.seq_num() + 1) % MSN; } cwnd = min(cwnd, MSN / 2.0); // make sure cwnd is not greater than MSN/2 cwnd = max(cwnd, (double) MSS); // make sure cwnd is not less than MSS ssthresh = max(ssthresh, MSS); // make sure ssthresh is at least MSS recv_window = p.recv_window(); } while (!file.eof() || (window.size() != 0)); // send FIN p = Packet(0, 0, 1, seq_num, ack_num, 0, "", 0); pkt_info = Packet_info(p, 0, rto.get_timeout()); status = sendto(sockfd, (void *) &p, HEADER_LEN, 0, (struct sockaddr *) &recv_addr, addr_len); process_error(status, "sending FIN"); cout << "Sending packet " << seq_num << " FIN" << endl; seq_num = (seq_num + 1) % MSN; // recv FIN ACK do { struct timeval max_time = pkt_info.get_max_time(); struct timeval curr_time; gettimeofday(&curr_time, NULL); struct timeval time_left; timersub(&max_time, &curr_time, &time_left); status = setsockopt(sockfd, SOL_SOCKET,SO_RCVTIMEO, (char *)&time_left, sizeof(time_left)); process_error(status, "setsockopt"); n_bytes = recvfrom(sockfd, (void *) &p, sizeof(p), 0, (struct sockaddr *) &recv_addr, &addr_len); process_recv(n_bytes, "recv FIN ACK", sockfd, pkt_info, recv_addr, addr_len, rto); } while (!p.fin_set() || !p.ack_set()); prev_ack = p.ack_num(); cout << "Receiving packet " << p.ack_num() << endl; ack_num = (p.seq_num() + 1) % MSN; // send ACK after FIN ACK p = Packet(0, 1, 0, seq_num, ack_num, 0, "", 0); pkt_info = Packet_info(p, 0, rto.get_timeout()); status = sendto(sockfd, (void *) &p, HEADER_LEN, 0, (struct sockaddr *) &recv_addr, addr_len); process_error(status, "sending ACK after FIN ACK"); cout << "Sending packet " << seq_num << endl; // make sure client receives ACK after FIN ACK do { struct timeval max_time = pkt_info.get_max_time(); struct timeval curr_time; gettimeofday(&curr_time, NULL); struct timeval time_left; timersub(&max_time, &curr_time, &time_left); time_left.tv_sec *= 2; // 2*RTO time_left.tv_usec *= 2; // 2*RTO status = setsockopt(sockfd, SOL_SOCKET,SO_RCVTIMEO, (char *)&time_left, sizeof(time_left)); process_error(status, "setsockopt"); n_bytes = recvfrom(sockfd, (void *) &p, sizeof(p), 0, (struct sockaddr *) &recv_addr, &addr_len); if (n_bytes == -1) //error { // check if timed out, if so everything is fine close if (errno == EAGAIN || EWOULDBLOCK || EINPROGRESS) { break; } else // else another error and process it { process_error(n_bytes, "checking to see if recv FIN ACK again"); } } else if (p.fin_set() && p.ack_set()) // if client send FIN ACK again, send ACK { pkt_info.update_time(rto.get_timeout()); p = pkt_info.pkt(); status = sendto(sockfd, (void *) &p, sizeof(p), 0, (struct sockaddr *) &recv_addr, addr_len); process_error(status, "sending packet"); } } while (!p.fin_set() || !p.ack_set()); }
/** * @brief Helps to test NetModeUdp objects. * * Client ID used with DealWithData is 10, and operation ID is 5. * * @param [in,out] obj The object. * @param [in,out] packet The packet. * @param str The string stored in @a packet. * @param dealWithDataClientID Client ID to use with DealWithData(). * @param expectedClientID Expected result of destination.GetClientFrom(). * @param operationID Operation ID to use with DealWithData(). * * @return false if the test was failed and a problem was found while testing, true if not. */ bool NetModeUdp::_HelperTestClass(NetModeUdp & obj, Packet & packet, const char * str, size_t dealWithDataClientID, size_t expectedClientID, size_t operationID) { Packet destination; WSABUF buffer; bool problem = false; // Counter: 500 packet.SetCursor(0); packet.AddSizeT(500); packet.PtrIntoWSABUF(buffer); obj.DealWithData(buffer,packet.GetUsedSize(),NULL,dealWithDataClientID,1); if(obj.GetPacketFromStore(&destination,expectedClientID,operationID) != 1 || destination.GetClientFrom() != expectedClientID || destination.GetInstance() != 1|| destination.GetAge() != 500 || (destination.GetOperation() != operationID && destination.GetOperation() != 0)) { cout << "DealWithData is bad (packet 1)\n"; problem = true; } else { destination.Erase(0,destination.GetCursor()); if(destination != str) { cout << "DealWithData is bad due to contents (packet 1)\n"; problem = true; } else { cout << "DealWithData is good (packet 1)\n"; } } // Counter: 499 packet.SetCursor(0); packet.AddSizeT(499); packet.PtrIntoWSABUF(buffer); obj.DealWithData(buffer,packet.GetUsedSize(),NULL,dealWithDataClientID,1); if(obj.GetPacketFromStore(&destination,expectedClientID,operationID) != 0) { cout << "DealWithData is bad (packet 2)\n"; problem = true; } else { cout << "DealWithData is good (packet 2)\n"; } // Counter: 501 packet.SetCursor(0); packet.AddSizeT(501); packet.PtrIntoWSABUF(buffer); obj.DealWithData(buffer,packet.GetUsedSize(),NULL,dealWithDataClientID,3); if(obj.GetPacketFromStore(&destination,expectedClientID,operationID) != 1 || destination.GetClientFrom() != expectedClientID || destination.GetInstance() != 3 || destination.GetAge() != 501 || (destination.GetOperation() != operationID && destination.GetOperation() != 0)) { cout << "DealWithData is bad (packet 3)\n"; problem = true; } else { destination.Erase(0,destination.GetCursor()); if(destination != str) { cout << "DealWithData is bad due to contents (packet 3)\n"; problem = true; } else { cout << "DealWithData is good (packet 3)\n"; } } // Counter: very large (1000 from maximum) packet.SetCursor(0); packet.AddSizeT(-1000); packet.PtrIntoWSABUF(buffer); obj.DealWithData(buffer,packet.GetUsedSize(),NULL,dealWithDataClientID,3); if(obj.GetPacketFromStore(&destination,expectedClientID,operationID) != 1 || destination.GetClientFrom() != expectedClientID || destination.GetInstance() != 3 || destination.GetAge() != -1000 || (destination.GetOperation() != operationID && destination.GetOperation() != 0)) { cout << "DealWithData is bad (packet 4)\n"; problem = true; } else { destination.Erase(0,destination.GetCursor()); if(destination != str) { cout << "DealWithData is bad due to contents (packet 4)\n"; problem = true; } else { cout << "DealWithData is good (packet 4)\n"; } } // Counter: 1 (testing code that an entity can continue running // forever, when the counter reaches maximum it will loop round to 0). packet.SetCursor(0); packet.AddSizeT(1); packet.PtrIntoWSABUF(buffer); obj.DealWithData(buffer,packet.GetUsedSize(),NULL,dealWithDataClientID,3); if(obj.GetPacketFromStore(&destination,expectedClientID,operationID) != 1 || destination.GetClientFrom() != expectedClientID || destination.GetInstance() != 3 || destination.GetAge() != 1 || (destination.GetOperation() != operationID && destination.GetOperation() != 0)) { cout << "DealWithData is bad (packet 5)\n"; problem = true; } else { destination.Erase(0,destination.GetCursor()); if(destination != str) { cout << "DealWithData is bad due to contents (packet 5)\n"; problem = true; } else { cout << "DealWithData is good (packet 5)\n"; } } return !problem; }
HRESULT CStreamParser::ParseH264AnnexB(Packet *pPacket) { if (!m_pPacketBuffer) { m_pPacketBuffer = InitPacket(pPacket); } m_pPacketBuffer->Append(pPacket); BYTE *start = m_pPacketBuffer->GetData(); BYTE *end = start + m_pPacketBuffer->GetDataSize(); MOVE_TO_H264_START_CODE(start, end); while(start <= end-4) { BYTE *next = start + 1; MOVE_TO_H264_START_CODE(next, end); // End of buffer reached if(next >= end-4) { break; } size_t size = next - start; CH264Nalu Nalu; Nalu.SetBuffer(start, (int)size, 0); Packet *p2 = NULL; while (Nalu.ReadNext()) { Packet *p3 = new Packet(); p3->SetDataSize(Nalu.GetDataLength() + 4); // Write size of the NALU (Big Endian) AV_WB32(p3->GetData(), (uint32_t)Nalu.GetDataLength()); memcpy(p3->GetData() + 4, Nalu.GetDataBuffer(), Nalu.GetDataLength()); if (!p2) { p2 = p3; } else { p2->Append(p3); SAFE_DELETE(p3); } } if (!p2) break; p2->StreamId = m_pPacketBuffer->StreamId; p2->bDiscontinuity = m_pPacketBuffer->bDiscontinuity; m_pPacketBuffer->bDiscontinuity = FALSE; p2->bSyncPoint = m_pPacketBuffer->bSyncPoint; m_pPacketBuffer->bSyncPoint = FALSE; p2->rtStart = m_pPacketBuffer->rtStart; m_pPacketBuffer->rtStart = Packet::INVALID_TIME; p2->rtStop = m_pPacketBuffer->rtStop; m_pPacketBuffer->rtStop = Packet::INVALID_TIME; p2->pmt = m_pPacketBuffer->pmt; m_pPacketBuffer->pmt = NULL; m_queue.Queue(p2); if(pPacket->rtStart != Packet::INVALID_TIME) { m_pPacketBuffer->rtStart = pPacket->rtStart; m_pPacketBuffer->rtStop = pPacket->rtStop; pPacket->rtStart = Packet::INVALID_TIME; } if(pPacket->bDiscontinuity) { m_pPacketBuffer->bDiscontinuity = pPacket->bDiscontinuity; pPacket->bDiscontinuity = FALSE; } if(pPacket->bSyncPoint) { m_pPacketBuffer->bSyncPoint = pPacket->bSyncPoint; pPacket->bSyncPoint = FALSE; } if(m_pPacketBuffer->pmt) { DeleteMediaType(m_pPacketBuffer->pmt); } m_pPacketBuffer->pmt = pPacket->pmt; pPacket->pmt = NULL; start = next; } if(start > m_pPacketBuffer->GetData()) { m_pPacketBuffer->RemoveHead(start - m_pPacketBuffer->GetData()); } SAFE_DELETE(pPacket); do { pPacket = NULL; REFERENCE_TIME rtStart = Packet::INVALID_TIME, rtStop = rtStart = Packet::INVALID_TIME; std::deque<Packet *>::iterator it; for (it = m_queue.GetQueue()->begin(); it != m_queue.GetQueue()->end(); ++it) { // Skip the first if (it == m_queue.GetQueue()->begin()) { continue; } Packet *p = *it; BYTE* pData = p->GetData(); if((pData[4]&0x1f) == 0x09) { m_bHasAccessUnitDelimiters = true; } if ((pData[4]&0x1f) == 0x09 || (!m_bHasAccessUnitDelimiters && p->rtStart != Packet::INVALID_TIME)) { pPacket = p; if (p->rtStart == Packet::INVALID_TIME && rtStart != Packet::INVALID_TIME) { p->rtStart = rtStart; p->rtStop = rtStop; } break; } if (rtStart == Packet::INVALID_TIME) { rtStart = p->rtStart; rtStop = p->rtStop; } } if (pPacket) { Packet *p = m_queue.Get(); Packet *p2 = NULL; while ((p2 = m_queue.Get()) != pPacket) { p->Append(p2); SAFE_DELETE(p2); } // Return m_queue.GetQueue()->push_front(pPacket); Queue(p); } } while (pPacket != NULL); return S_OK; }
void CGameSocket::RecvUserInOut(Packet & pkt) { std::string strUserID; uint8 bType; uint16 uid; float fX, fZ; pkt.SByte(); pkt >> bType >> uid >> strUserID >> fX >> fZ; if (fX < 0 || fZ < 0) { TRACE("Error:: RecvUserInOut(),, uid = %d, fX=%.2f, fZ=%.2f\n", uid, fX, fZ); return; } int region_x = 0, region_z=0; int x1 = (int)fX / TILE_SIZE; int z1 = (int)fZ / TILE_SIZE; region_x = (int)fX / VIEW_DIST; region_z = (int)fZ / VIEW_DIST; MAP* pMap = nullptr; CUser* pUser = g_pMain->GetUserPtr(uid); if (pUser == nullptr) return; pMap = pUser->GetMap(); if (pMap == nullptr) { TRACE("#### Fail : pMap == nullptr ####\n"); return; } if (x1 < 0 || z1 < 0 || x1 >= pMap->GetMapSize() || z1 >= pMap->GetMapSize()) { TRACE("#### RecvUserInOut Fail : [name=%s], x1=%d, z1=%d #####\n", pUser->GetName().c_str(), region_x, region_z); return; } //if (pMap->m_pMap[x1][z1].m_sEvent == 0) return; if (region_x > pMap->GetXRegionMax() || region_z > pMap->GetZRegionMax()) { TRACE("#### GameSocket-RecvUserInOut() Fail : [name=%s], nRX=%d, nRZ=%d #####\n", pUser->GetName().c_str(), region_x, region_z); return; } pUser->m_curx = pUser->m_fWill_x = fX; pUser->m_curz = pUser->m_fWill_z = fZ; // leaving a region if (bType == 2) { pMap->RegionUserRemove(region_x, region_z, uid); } // entering a region else if (pUser->m_sRegionX != region_x || pUser->m_sRegionZ != region_z) { pUser->m_sRegionX = region_x; pUser->m_sRegionZ = region_z; pMap->RegionUserAdd(region_x, region_z, uid); } }
int getPlayerNumber(int portal) { Packet response; const int error_check = standard_order_checking(portal, Packet(MsgType::QUERY_PLAYER_NUMBER), &response); if(error_check != Error::success) return error_check; return response.read_int8(); }
bool CGameSocket::HandlePacket(Packet & pkt) { switch (pkt.GetOpcode()) { case AI_SERVER_CONNECT: RecvServerConnect(pkt); break; case AG_USER_INFO: RecvUserInfo(pkt); break; case AG_USER_INOUT: RecvUserInOut(pkt); break; case AG_USER_MOVE: RecvUserMove(pkt); break; case AG_USER_LOG_OUT: RecvUserLogOut(pkt); break; case AG_USER_REGENE: RecvUserRegene(pkt); break; case AG_USER_SET_HP: RecvUserSetHP(pkt); break; case AG_NPC_HP_CHANGE: RecvNpcHpChange(pkt); break; case AG_USER_UPDATE: RecvUserUpdate(pkt); break; case AG_ZONE_CHANGE: RecvZoneChange(pkt); break; case AG_USER_PARTY: m_Party.PartyProcess(pkt); break; case AG_USER_INFO_ALL: RecvUserInfoAllData(pkt); break; case AG_PARTY_INFO_ALL: RecvPartyInfoAllData(pkt); break; case AG_HEAL_MAGIC: RecvHealMagic(pkt); break; case AG_TIME_WEATHER: RecvTimeAndWeather(pkt); break; case AG_BATTLE_EVENT: RecvBattleEvent(pkt); break; case AG_NPC_GATE_OPEN: RecvGateOpen(pkt); break; case AG_USER_VISIBILITY: RecvUserVisibility(pkt); break; case AG_NPC_SPAWN_REQ: RecvNpcSpawnRequest(pkt); break; case AG_MAGIC_ATTACK_REQ: CMagicProcess::MagicPacket(pkt); break; case AG_NPC_UPDATE: RecvNpcUpdate(pkt); break; } return true; }
int main(int argc, char *argv[]) { int debugMode = DEBUGMODE; if(debugMode) { } else { qInstallMessageHandler(myMessageOutputDisable); } QDEBUG() << "number of arguments:" << argc; QStringList args; QDEBUGVAR(RAND_MAX); if(argc > 1) { QCoreApplication a(argc, argv); args = a.arguments(); QDEBUGVAR(args); qRegisterMetaType<Packet>(); QDEBUG() << "Running command line mode."; Packet sendPacket; sendPacket.init(); QString outBuilder; QTextStream o(&outBuilder); QTextStream out(stdout); QDate vDate = QDate::fromString(QString(__DATE__).simplified(), "MMM d yyyy"); QCoreApplication::setApplicationName("Packet Sender"); QCoreApplication::setApplicationVersion("version " + vDate.toString("yyyy-MM-dd")); QCommandLineParser parser; parser.setApplicationDescription("Packet Sender is a Network TCP and UDP Test Utility by Dan Nagle\nSee http://PacketSender.com/ for more information."); parser.addHelpOption(); parser.addVersionOption(); // A boolean option with a single name (-p) QCommandLineOption quietOption(QStringList() << "q" << "quiet", "Quiet mode. Only output received data."); parser.addOption(quietOption); QCommandLineOption hexOption(QStringList() << "x" << "hex", "Parse data as hex (default)."); parser.addOption(hexOption); QCommandLineOption asciiOption(QStringList() << "a" << "ascii", "Parse data as mixed-ascii (like the GUI)."); parser.addOption(asciiOption); QCommandLineOption pureAsciiOption(QStringList() << "A" << "ASCII", "Parse data as pure ascii (no \\xx translation)."); parser.addOption(pureAsciiOption); // An option with a value QCommandLineOption waitOption(QStringList() << "w" << "wait", "Wait up to <milliseconds> for a response after sending. Zero means do not wait (Default).", "milliseconds"); parser.addOption(waitOption); // An option with a value QCommandLineOption fileOption(QStringList() << "f" << "file", "Send contents of specified path. Max 1024 for UDP, 10 MiB for TCP.", "path"); parser.addOption(fileOption); // An option with a value QCommandLineOption bindPortOption(QStringList() << "b" << "bind", "Bind port. Default is 0 (dynamic).", "port"); parser.addOption(bindPortOption); QCommandLineOption tcpOption(QStringList() << "t" << "tcp", "Send TCP (default)."); parser.addOption(tcpOption); // A boolean option with multiple names (-f, --force) QCommandLineOption udpOption(QStringList() << "u" << "udp", "Send UDP."); parser.addOption(udpOption); // An option with a value QCommandLineOption nameOption(QStringList() << "n" << "name", "Send previously saved packet named <name>. Other options overrides saved packet parameters.", "name"); parser.addOption(nameOption); parser.addPositionalArgument("address", "Destination address. Optional for saved packet."); parser.addPositionalArgument("port", "Destination port. Optional for saved packet."); parser.addPositionalArgument("data", "Data to send. Optional for saved packet."); // Process the actual command line arguments given by the user parser.process(a); const QStringList args = parser.positionalArguments(); bool quiet = parser.isSet(quietOption); bool hex = parser.isSet(hexOption); bool mixedascii = parser.isSet(asciiOption); bool ascii = parser.isSet(pureAsciiOption); unsigned int wait = parser.value(waitOption).toUInt(); unsigned int bind = parser.value(bindPortOption).toUInt(); bool tcp = parser.isSet(tcpOption); bool udp = parser.isSet(udpOption); bool ipv6 = false; QString name = parser.value(nameOption); QString filePath = parser.value(fileOption); QString address = ""; unsigned int port = 0; int argssize = args.size(); QString data, dataString; data.clear(); dataString.clear(); if(argssize >= 1) { address = args[0]; } if(argssize >= 2) { port = args[1].toUInt(); } if(argssize >= 3) { data = (args[2]); } //check for invalid options.. if(argssize > 3) { OUTIF() << "Warning: Extra parameters detected. Try surrounding your data with quotes."; } if(hex && mixedascii) { OUTIF() << "Warning: both hex and pure ascii set. Defaulting to hex."; mixedascii = false; } if(hex && ascii) { OUTIF() << "Warning: both hex and pure ascii set. Defaulting to hex."; ascii = false; } if(mixedascii && ascii) { OUTIF() << "Warning: both mixed ascii and pure ascii set. Defaulting to pure ascii."; mixedascii = false; } if(tcp && udp) { OUTIF() << "Warning: both TCP and UDP set. Defaulting to TCP."; udp = false; } if(!filePath.isEmpty() && !QFile::exists(filePath)) { OUTIF() << "Error: specified path "<< filePath <<" does not exist."; filePath.clear(); OUTPUT(); return -1; } //bind is now default 0 if(!bind && parser.isSet(bindPortOption)) { OUTIF() << "Warning: Binding to port zero is dynamic."; } if(!port && name.isEmpty()) { OUTIF() << "Warning: Sending to port zero."; } //set default choices if(!hex && !ascii && !mixedascii) { hex = true; } if(!tcp && !udp) { tcp = true; } //Create the packet to send. if(!name.isEmpty()) { sendPacket = Packet::fetchFromDB(name); if(sendPacket.name.isEmpty()) { OUTIF() << "Error: Saved packet \""<< name <<"\" not found."; OUTPUT(); return -1; } else { if(data.isEmpty()) { data = sendPacket.hexString; hex = true; ascii = false; mixedascii = false; } if(!port) { port = sendPacket.port; } if(address.isEmpty()) { address = sendPacket.toIP; } if(!parser.isSet(tcpOption) && !parser.isSet(udpOption)) { if(sendPacket.tcpOrUdp.toUpper() == "TCP") { tcp=true; udp = false; } else { tcp=false; udp = true; } } } } if(!parser.isSet(bindPortOption)) { bind = 0; } if(!filePath.isEmpty() && QFile::exists(filePath)) { QFile dataFile(filePath); if(dataFile.open(QFile::ReadOnly)) { if(tcp) { QByteArray dataArray = dataFile.read(1024*1024*10);; dataString = Packet::byteArrayToHex(dataArray); } else { QByteArray dataArray = dataFile.read(1024); dataString = Packet::byteArrayToHex(dataArray); } //data format is raw. ascii = 0; hex = 0; mixedascii = 0; } } QDEBUGVAR(argssize); QDEBUGVAR(quiet); QDEBUGVAR(hex); QDEBUGVAR(mixedascii); QDEBUGVAR(ascii); QDEBUGVAR(address); QDEBUGVAR(port); QDEBUGVAR(wait); QDEBUGVAR(bind); QDEBUGVAR(tcp); QDEBUGVAR(udp); QDEBUGVAR(name); QDEBUGVAR(data); QDEBUGVAR(filePath); //NOW LETS DO THIS! if(ascii) { //pure ascii dataString = Packet::byteArrayToHex(data.toLatin1()); } if(hex) { //hex dataString = Packet::byteArrayToHex(Packet::HEXtoByteArray(data)); } if(mixedascii) { //mixed ascii dataString = Packet::ASCIITohex(data); } if(dataString.isEmpty()) { OUTIF() << "Warning: No data to send. Is your formatting correct?"; } QHostAddress addy; if(!addy.setAddress(address)) { QHostInfo info = QHostInfo::fromName(address); if (info.error() != QHostInfo::NoError) { OUTIF() << "Error: Could not resolve address:" + address; OUTPUT(); return -1; } else { addy = info.addresses().at(0); address = addy.toString(); } } QHostAddress theAddress(address); if (QAbstractSocket::IPv6Protocol == theAddress.protocol()) { QDEBUG() << "Valid IPv6 address."; ipv6 = true; } QByteArray sendData = sendPacket.HEXtoByteArray(dataString); QByteArray recvData; recvData.clear(); int bytesWriten = 0; int bytesRead = 0; if(tcp) { QTcpSocket sock; if(ipv6) { sock.bind(QHostAddress::AnyIPv6, bind); } else { sock.bind(QHostAddress::AnyIPv4, bind); } sock.connectToHost(addy, port); sock.waitForConnected(1000); if(sock.state() == QAbstractSocket::ConnectedState) { OUTIF() << "TCP (" <<sock.localPort() <<")://" << address << ":" << port << " " << dataString; bytesWriten = sock.write(sendData); sock.waitForBytesWritten(1000); //OUTIF() << "Sent:" << Packet::byteArrayToHex(sendData); if(wait) { sock.waitForReadyRead(wait); recvData = sock.readAll(); bytesRead = recvData.size(); QString hexString = Packet::byteArrayToHex(recvData); if(quiet) { o << "\n" << hexString; } else { o << "\nResponse Time:" << QDateTime::currentDateTime().toString(DATETIMEFORMAT); o << "\nResponse HEX:" << hexString; o << "\nResponse ASCII:" << Packet::hexToASCII(hexString); } } sock.disconnectFromHost(); sock.waitForDisconnected(1000); sock.close(); OUTPUT(); return bytesWriten; } else { OUTIF() << "Error: Failed to connect to " << address; OUTPUT(); return -1; } } else { QUdpSocket sock; if(ipv6) { if(!sock.bind(QHostAddress::AnyIPv6, bind)) { OUTIF() << "Error: Could not bind to " << bind; OUTPUT(); return -1; } } else { if(!sock.bind(QHostAddress::AnyIPv4, bind)) { OUTIF() << "Error: Could not bind to " << bind; OUTPUT(); return -1; } } OUTIF() << "UDP (" <<sock.localPort() <<")://" << address << ":" << port << " " << dataString; bytesWriten = sock.writeDatagram(sendData, addy, port); //OUTIF() << "Wrote " << bytesWriten << " bytes"; sock.waitForBytesWritten(1000); if(wait) { sock.waitForReadyRead(wait); if(sock.hasPendingDatagrams()) { QHostAddress sender; quint16 senderPort; recvData.resize(sock.pendingDatagramSize()); sock.readDatagram(recvData.data(), recvData.size(), &sender, &senderPort); QString hexString = Packet::byteArrayToHex(recvData); if(quiet) { o << "\n" << hexString; } else { o << "\nResponse Time:" << QDateTime::currentDateTime().toString(DATETIMEFORMAT); o << "\nResponse HEX:" << hexString; o << "\nResponse ASCII:" << Packet::hexToASCII(hexString); } } } sock.close(); OUTPUT(); return bytesWriten; } OUTPUT(); } else { QApplication a(argc, argv); QDEBUGVAR(args); qRegisterMetaType<Packet>(); QFile file(":/packetsender.css"); if(file.open(QFile::ReadOnly)) { QString StyleSheet = QLatin1String(file.readAll()); // qDebug() << "stylesheet: " << StyleSheet; a.setStyleSheet(StyleSheet); } MainWindow w; w.show(); return a.exec(); } return 0; }
void Play::HandleReceivePacket() { if (client->taskQueue.buffers.size() > 0 && client->taskQueue.buffers.front().length() > 0) { string tekst = client->taskQueue.buffers.front(); client->taskQueue.buffers.erase(client->taskQueue.buffers.begin()); std::istringstream iss(tekst); string playerName; iss >> playerName; tekst = tekst.substr(playerName.length() + 1, tekst.length()); Packet packet = Packet::stringToPacket(tekst); if (packet.getPacketType() == "YourName") Tplayers[0].setString(packet.getData().substr(0, packet.getData().length() - 2)); else if (packet.getPacketType() == "PlayerRound") HandlePacketPlayRound(packet); else if (packet.getPacketType() == "PlayerJoin") HandlePacketPlayerJoin(packet); else if (packet.getPacketType() == "Letter") HandlePacketLetter(packet); else if (packet.getPacketType() == "WordCheck") HandlePacketWordCheck(packet); else if (packet.getPacketType() == "LetterRequest") HandlePacketLetterRequest(packet); else if (packet.getPacketType() == "Conversation") HandlePacketConversation(packet, playerName); else if (packet.getPacketType() == "PlayerLeave") HandlePacketPlayerLeave(packet); else if (packet.getPacketType() == "GameRound") round = atoi(packet.getData().c_str()); }
/* *TODO: * if output is null or dummy, the use duration to wait */ void AudioThread::run() { DPTR_D(AudioThread); //No decoder or output. No audio output is ok, just display picture if (!d.dec || !d.dec->isAvailable()) return; resetState(); Q_ASSERT(d.clock != 0); AudioDecoder *dec = static_cast<AudioDecoder*>(d.dec); AudioOutput *ao = static_cast<AudioOutput*>(d.writer); static const double max_len = 0.02; //TODO: how to choose? d.init(); //TODO: bool need_sync in private class bool is_external_clock = d.clock->clockType() == AVClock::ExternalClock; Packet pkt; while (!d.stop) { processNextTask(); //TODO: why put it at the end of loop then playNextFrame() not work? if (tryPause()) { //DO NOT continue, or playNextFrame() will fail if (d.stop) break; //the queue is empty and may block. should setBlocking(false) wake up cond empty? } else { if (isPaused()) continue; } QMutexLocker locker(&d.mutex); Q_UNUSED(locker); if (d.packets.isEmpty() && !d.stop) { d.stop = d.demux_end; if (d.stop) { qDebug("audio queue empty and demux end. break audio thread"); break; } } if (!pkt.isValid()) { pkt = d.packets.take(); //wait to dequeue } if (!pkt.isValid()) { qDebug("Invalid packet! flush audio codec context!!!!!!!! audio queue size=%d", d.packets.size()); dec->flush(); continue; } if (is_external_clock) { d.delay = pkt.pts - d.clock->value(); /* *after seeking forward, a packet may be the old, v packet may be *the new packet, then the d.delay is very large, omit it. *TODO: 1. how to choose the value * 2. use last delay when seeking */ if (qAbs(d.delay) < 2.718) { if (d.delay > kSyncThreshold) { //Slow down //d.delay_cond.wait(&d.mutex, d.delay*1000); //replay may fail. why? //qDebug("~~~~~wating for %f msecs", d.delay*1000); usleep(d.delay * 1000000); } else if (d.delay < -kSyncThreshold) { //Speed up. drop frame? //continue; } } else { //when to drop off? qDebug("delay %f/%f", d.delay, d.clock->value()); if (d.delay > 0) { msleep(64); } else { //audio packet not cleaned up? continue; } } } else { d.clock->updateValue(pkt.pts); } //DO NOT decode and convert if ao is not available or mute! bool has_ao = ao && ao->isAvailable(); //if (!has_ao) {//do not decode? if (has_ao && dec->resampler()) { if (dec->resampler()->speed() != ao->speed() || dec->resampler()->outAudioFormat() != ao->audioFormat()) { //resample later to ensure thread safe. TODO: test if (d.resample) { qDebug("decoder set speed: %.2f", ao->speed()); dec->resampler()->setOutAudioFormat(ao->audioFormat()); dec->resampler()->setSpeed(ao->speed()); dec->resampler()->prepare(); d.resample = false; } else { d.resample = true; } } } if (dec->decode(pkt.data)) { QByteArray decoded(dec->data()); int decodedSize = decoded.size(); int decodedPos = 0; qreal delay =0; //AudioFormat.durationForBytes() calculates int type internally. not accurate AudioFormat &af = dec->resampler()->inAudioFormat(); qreal byte_rate = af.bytesPerSecond(); while (decodedSize > 0) { int chunk = qMin(decodedSize, int(max_len*byte_rate)); qreal chunk_delay = (qreal)chunk/(qreal)byte_rate; pkt.pts += chunk_delay; d.clock->updateDelay(delay += chunk_delay); QByteArray decodedChunk(chunk, 0); //volume == 0 || mute if (has_ao) { //TODO: volume filter and other filters!!! if (!ao->isMute()) { decodedChunk = QByteArray::fromRawData(decoded.constData() + decodedPos, chunk); qreal vol = ao->volume(); if (vol != 1.0) { int len = decodedChunk.size()/ao->audioFormat().bytesPerSample(); switch (ao->audioFormat().sampleFormat()) { case AudioFormat::SampleFormat_Unsigned8: case AudioFormat::SampleFormat_Unsigned8Planar: { quint8 *data = (quint8*)decodedChunk.data(); //TODO: other format? for (int i = 0; i < len; data[i++] *= vol) {} } break; case AudioFormat::SampleFormat_Signed16: case AudioFormat::SampleFormat_Signed16Planar: { qint16 *data = (qint16*)decodedChunk.data(); //TODO: other format? for (int i = 0; i < len; data[i++] *= vol) {} } break; case AudioFormat::SampleFormat_Signed32: case AudioFormat::SampleFormat_Signed32Planar: { qint32 *data = (qint32*)decodedChunk.data(); //TODO: other format? for (int i = 0; i < len; data[i++] *= vol) {} } break; case AudioFormat::SampleFormat_Float: case AudioFormat::SampleFormat_FloatPlanar: { float *data = (float*)decodedChunk.data(); //TODO: other format? for (int i = 0; i < len; data[i++] *= vol) {} } break; case AudioFormat::SampleFormat_Double: case AudioFormat::SampleFormat_DoublePlanar: { double *data = (double*)decodedChunk.data(); //TODO: other format? for (int i = 0; i < len; data[i++] *= vol) {} } break; default: break; } } } ao->writeData(decodedChunk); } else { /* * why need this even if we add delay? and usleep sounds weird * the advantage is if no audio device, the play speed is ok too * So is portaudio blocking the thread when playing? */ static bool sWarn_no_ao = true; //FIXME: no warning when replay. warn only once if (sWarn_no_ao) { qDebug("Audio output not available! msleep(%lu)", (unsigned long)((qreal)chunk/(qreal)byte_rate * 1000)); sWarn_no_ao = false; } //TODO: avoid acummulative error. External clock? msleep((unsigned long)(chunk_delay * 1000.0)); } decodedPos += chunk; decodedSize -= chunk; } int undecoded = dec->undecodedSize(); if (undecoded > 0) { pkt.data.remove(0, pkt.data.size() - undecoded); } else { pkt = Packet(); } } else { //??? qWarning("Decode audio failed"); qreal dt = pkt.pts - d.last_pts; if (abs(dt) > 0.618 || dt < 0) { dt = 0; } //qDebug("sleep %f", dt); //TODO: avoid acummulative error. External clock? msleep((unsigned long)(dt*1000.0)); pkt = Packet(); } d.last_pts = d.clock->value(); //not pkt.pts! the delay is updated! } qDebug("Audio thread stops running..."); }
STDMETHODIMP CBDDemuxer::FillMVCExtensionQueue(REFERENCE_TIME rtBase) { if (!m_MVCFormatContext) return E_FAIL; int ret, count = 0; bool found = (rtBase == Packet::INVALID_TIME); AVPacket mvcPacket = { 0 }; av_init_packet(&mvcPacket); while (count < MVC_DEMUX_COUNT) { ret = av_read_frame(m_MVCFormatContext, &mvcPacket); if (ret == AVERROR(EINTR) || ret == AVERROR(EAGAIN)) { continue; } else if (ret == AVERROR_EOF) { DbgLog((LOG_TRACE, 10, L"EOF reading MVC extension data")); break; } else if (mvcPacket.size <= 0 || mvcPacket.stream_index != m_MVCStreamIndex) { av_packet_unref(&mvcPacket); continue; } else { AVStream *stream = m_MVCFormatContext->streams[mvcPacket.stream_index]; REFERENCE_TIME rtDTS = m_lavfDemuxer->ConvertTimestampToRT(mvcPacket.dts, stream->time_base.num, stream->time_base.den); REFERENCE_TIME rtPTS = m_lavfDemuxer->ConvertTimestampToRT(mvcPacket.pts, stream->time_base.num, stream->time_base.den); if (rtBase == Packet::INVALID_TIME || rtDTS == Packet::INVALID_TIME) { // do nothing, can't compare timestamps when they are not set } else if (rtDTS < rtBase) { DbgLog((LOG_TRACE, 10, L"CBDDemuxer::FillMVCExtensionQueue(): Dropping MVC extension at %I64d, base is %I64d", rtDTS, rtBase)); av_packet_unref(&mvcPacket); continue; } else if (rtDTS == rtBase) { found = true; } Packet *pPacket = new Packet(); if (!pPacket) { av_packet_unref(&mvcPacket); return E_OUTOFMEMORY; } pPacket->SetPacket(&mvcPacket); pPacket->rtDTS = rtDTS; pPacket->rtPTS = rtPTS; m_lavfDemuxer->QueueMVCExtension(pPacket); av_packet_unref(&mvcPacket); count++; } }; if (found) return S_OK; else if (count > 0) return S_FALSE; else return E_FAIL; }
void ShadowChicken::update(VM& vm, ExecState* exec) { if (verbose) { dataLog("Running update on: ", *this, "\n"); WTFReportBacktrace(); } const unsigned logCursorIndex = m_logCursor - m_log; // We need to figure out how to reconcile the current machine stack with our shadow stack. We do // that by figuring out how much of the shadow stack to pop. We apply three different rules. The // precise rule relies on the log. The log contains caller frames, which means that we know // where we bottomed out after making any call. If we bottomed out but made no calls then 'exec' // will tell us. That's why "highestPointSinceLastTime" will go no lower than exec. The third // rule, based on comparing to the current real stack, is executed in a later loop. CallFrame* highestPointSinceLastTime = exec; for (unsigned i = logCursorIndex; i--;) { Packet packet = m_log[i]; if (packet.isPrologue()) { CallFrame* watermark; if (i && m_log[i - 1].isTail()) watermark = packet.frame; else watermark = packet.callerFrame; highestPointSinceLastTime = std::max(highestPointSinceLastTime, watermark); } } if (verbose) dataLog("Highest point since last time: ", RawPointer(highestPointSinceLastTime), "\n"); while (!m_stack.isEmpty() && (m_stack.last().frame < highestPointSinceLastTime || m_stack.last().isTailDeleted)) m_stack.removeLast(); if (verbose) dataLog(" Revised stack: ", listDump(m_stack), "\n"); // It's possible that the top of stack is now tail-deleted. The stack no longer contains any // frames below the log's high watermark. That means that we just need to look for the first // occurence of a tail packet for the current stack top. if (!m_stack.isEmpty()) { ASSERT(!m_stack.last().isTailDeleted); for (unsigned i = 0; i < logCursorIndex; ++i) { Packet& packet = m_log[i]; if (packet.isTail() && packet.frame == m_stack.last().frame) { Frame& frame = m_stack.last(); frame.thisValue = packet.thisValue; frame.scope = packet.scope; frame.codeBlock = packet.codeBlock; frame.callSiteIndex = packet.callSiteIndex; frame.isTailDeleted = true; break; } } } if (verbose) dataLog(" Revised stack: ", listDump(m_stack), "\n"); // The log-based and exec-based rules require that ShadowChicken was enabled. The point of // ShadowChicken is to give sensible-looking results even if we had not logged. This means that // we need to reconcile the shadow stack and the real stack by actually looking at the real // stack. This reconciliation allows the shadow stack to have extra tail-deleted frames, but it // forbids it from diverging from the real stack on normal frames. if (!m_stack.isEmpty()) { Vector<Frame> stackRightNow; StackVisitor::visit( exec, [&] (StackVisitor& visitor) -> StackVisitor::Status { if (visitor->isInlinedFrame()) return StackVisitor::Continue; if (visitor->isWasmFrame()) { // FIXME: Make shadow chicken work with Wasm. // https://bugs.webkit.org/show_bug.cgi?id=165441 return StackVisitor::Continue; } bool isTailDeleted = false; // FIXME: Make shadow chicken work with Wasm. // https://bugs.webkit.org/show_bug.cgi?id=165441 stackRightNow.append(Frame(jsCast<JSObject*>(visitor->callee()), visitor->callFrame(), isTailDeleted)); return StackVisitor::Continue; }); stackRightNow.reverse(); if (verbose) dataLog(" Stack right now: ", listDump(stackRightNow), "\n"); unsigned shadowIndex = 0; unsigned rightNowIndex = 0; while (shadowIndex < m_stack.size() && rightNowIndex < stackRightNow.size()) { if (m_stack[shadowIndex].isTailDeleted) { shadowIndex++; continue; } // We specifically don't use operator== here because we are using a less // strict filter on equality of frames. For example, the scope pointer // could change, but we wouldn't want to consider the frames different entities // because of that because it's natural for the program to change scopes. if (m_stack[shadowIndex].frame == stackRightNow[rightNowIndex].frame && m_stack[shadowIndex].callee == stackRightNow[rightNowIndex].callee) { shadowIndex++; rightNowIndex++; continue; } break; } m_stack.resize(shadowIndex); if (verbose) dataLog(" Revised stack: ", listDump(m_stack), "\n"); } // It's possible that the top stack frame is actually lower than highestPointSinceLastTime. // Account for that here. highestPointSinceLastTime = nullptr; for (unsigned i = m_stack.size(); i--;) { if (!m_stack[i].isTailDeleted) { highestPointSinceLastTime = m_stack[i].frame; break; } } if (verbose) dataLog(" Highest point since last time: ", RawPointer(highestPointSinceLastTime), "\n"); // Set everything up so that we know where the top frame is in the log. unsigned indexInLog = logCursorIndex; auto advanceIndexInLogTo = [&] (CallFrame* frame, JSObject* callee, CallFrame* callerFrame) -> bool { if (verbose) dataLog(" Advancing to frame = ", RawPointer(frame), " from indexInLog = ", indexInLog, "\n"); if (indexInLog > logCursorIndex) { if (verbose) dataLog(" Bailing.\n"); return false; } unsigned oldIndexInLog = indexInLog; while (indexInLog--) { Packet packet = m_log[indexInLog]; // If all callees opt into ShadowChicken, then this search will rapidly terminate when // we find our frame. But if our frame's callee didn't emit a prologue packet because it // didn't opt in, then we will keep looking backwards until we *might* find a different // frame. If we've been given the callee and callerFrame as a filter, then it's unlikely // that we will hit the wrong frame. But we don't always have that information. // // This means it's worth adding other filters. For example, we could track changes in // stack size. Once we've seen a frame at some height, we're no longer interested in // frames below that height. Also, we can break as soon as we see a frame higher than // the one we're looking for. // FIXME: Add more filters. // https://bugs.webkit.org/show_bug.cgi?id=155685 if (packet.isPrologue() && packet.frame == frame && (!callee || packet.callee == callee) && (!callerFrame || packet.callerFrame == callerFrame)) { if (verbose) dataLog(" Found at indexInLog = ", indexInLog, "\n"); return true; } } // This is an interesting eventuality. We will see this if ShadowChicken was not // consistently enabled. We have a choice between: // // - Leaving the log index at -1, which will prevent the log from being considered. This is // the most conservative. It means that we will not be able to recover tail-deleted frames // from anything that sits above a frame that didn't log a prologue packet. This means // that everyone who creates prologues must log prologue packets. // // - Restoring the log index to what it was before. This prevents us from considering // whether this frame has tail-deleted frames behind it, but that's about it. The problem // with this approach is that it might recover tail-deleted frames that aren't relevant. // I haven't thought about this too deeply, though. // // It seems like the latter option is less harmful, so that's what we do. indexInLog = oldIndexInLog; if (verbose) dataLog(" Didn't find it.\n"); return false; }; Vector<Frame> toPush; StackVisitor::visit( exec, [&] (StackVisitor& visitor) -> StackVisitor::Status { if (visitor->isInlinedFrame()) { // FIXME: Handle inlining. // https://bugs.webkit.org/show_bug.cgi?id=155686 return StackVisitor::Continue; } if (visitor->isWasmFrame()) { // FIXME: Make shadow chicken work with Wasm. return StackVisitor::Continue; } CallFrame* callFrame = visitor->callFrame(); if (verbose) dataLog(" Examining ", RawPointer(callFrame), "\n"); if (callFrame == highestPointSinceLastTime) { if (verbose) dataLog(" Bailing at ", RawPointer(callFrame), " because it's the highest point since last time.\n"); return StackVisitor::Done; } bool foundFrame = advanceIndexInLogTo(callFrame, callFrame->jsCallee(), callFrame->callerFrame()); bool isTailDeleted = false; JSScope* scope = nullptr; CodeBlock* codeBlock = callFrame->codeBlock(); if (codeBlock && codeBlock->wasCompiledWithDebuggingOpcodes() && codeBlock->scopeRegister().isValid()) { scope = callFrame->scope(codeBlock->scopeRegister().offset()); RELEASE_ASSERT(scope->inherits(vm, JSScope::info())); } else if (foundFrame) { scope = m_log[indexInLog].scope; if (scope) RELEASE_ASSERT(scope->inherits(vm, JSScope::info())); } toPush.append(Frame(jsCast<JSObject*>(visitor->callee()), callFrame, isTailDeleted, callFrame->thisValue(), scope, codeBlock, callFrame->callSiteIndex())); if (indexInLog < logCursorIndex // This condition protects us from the case where advanceIndexInLogTo didn't find // anything. && m_log[indexInLog].frame == toPush.last().frame) { if (verbose) dataLog(" Going to loop through to find tail deleted frames with indexInLog = ", indexInLog, " and push-stack top = ", toPush.last(), "\n"); for (;;) { ASSERT(m_log[indexInLog].frame == toPush.last().frame); // Right now the index is pointing at a prologue packet of the last frame that // we pushed. Peek behind that packet to see if there is a tail packet. If there // is one then we know that there is a corresponding prologue packet that will // tell us about a tail-deleted frame. if (!indexInLog) break; Packet tailPacket = m_log[indexInLog - 1]; if (!tailPacket.isTail()) { // Last frame that we recorded was not the outcome of a tail call. So, there // will not be any more deleted frames. // FIXME: We might want to have a filter here. Consider that this was a tail // marker for a tail call to something that didn't log anything. It should // be sufficient to give the tail marker a copy of the caller frame. // https://bugs.webkit.org/show_bug.cgi?id=155687 break; } indexInLog--; // Skip over the tail packet. if (!advanceIndexInLogTo(tailPacket.frame, nullptr, nullptr)) { if (verbose) dataLog("Can't find prologue packet for tail: ", RawPointer(tailPacket.frame), "\n"); // We were unable to locate the prologue packet for this tail packet. // This is rare but can happen in a situation like: // function foo() { // ... call some deeply tail-recursive function, causing a random number of log processings. // return bar(); // tail call // } break; } Packet packet = m_log[indexInLog]; bool isTailDeleted = true; RELEASE_ASSERT(tailPacket.scope->inherits(vm, JSScope::info())); toPush.append(Frame(packet.callee, packet.frame, isTailDeleted, tailPacket.thisValue, tailPacket.scope, tailPacket.codeBlock, tailPacket.callSiteIndex)); } } return StackVisitor::Continue; }); if (verbose) dataLog(" Pushing: ", listDump(toPush), "\n"); for (unsigned i = toPush.size(); i--;) m_stack.append(toPush[i]); // We want to reset the log. There is a fun corner-case: there could be a tail marker at the end // of this log. We could make that work by setting isTailDeleted on the top of stack, but that // would require more corner cases in the complicated reconciliation code above. That code // already knows how to handle a tail packet at the beginning, so we just leverage that here. if (logCursorIndex && m_log[logCursorIndex - 1].isTail()) { m_log[0] = m_log[logCursorIndex - 1]; m_logCursor = m_log + 1; } else m_logCursor = m_log; if (verbose) dataLog(" After pushing: ", *this, "\n"); // Remove tail frames until the number of tail deleted frames is small enough. const unsigned maxTailDeletedFrames = Options::shadowChickenMaxTailDeletedFramesSize(); if (m_stack.size() > maxTailDeletedFrames) { unsigned numberOfTailDeletedFrames = 0; for (const Frame& frame : m_stack) { if (frame.isTailDeleted) numberOfTailDeletedFrames++; } if (numberOfTailDeletedFrames > maxTailDeletedFrames) { unsigned dstIndex = 0; unsigned srcIndex = 0; while (srcIndex < m_stack.size()) { Frame frame = m_stack[srcIndex++]; if (numberOfTailDeletedFrames > maxTailDeletedFrames && frame.isTailDeleted) { numberOfTailDeletedFrames--; continue; } m_stack[dstIndex++] = frame; } m_stack.resize(dstIndex); } } if (verbose) dataLog(" After clean-up: ", *this, "\n"); }
int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); qDebug() << QLatin1String("usage: ") << a.applicationFilePath().split(QLatin1String("/")).last().append(QLatin1String(" url")); if (a.arguments().size() < 2) return 0; QScopedPointer<AudioOutput> ao(new AudioOutput()); AVDemuxer demuxer; demuxer.setMedia(a.arguments().last()); if (!demuxer.load()) { qWarning() << "Failed to load file " << demuxer.fileName(); return 1; } QScopedPointer<AudioDecoder> dec(AudioDecoder::create()); // delete by user dec->setCodecContext(demuxer.audioCodecContext()); //dec->prepare(); if (!dec->open()) qFatal("open decoder error"); int astream = demuxer.audioStream(); Packet pkt; while (!demuxer.atEnd()) { if (!pkt.isValid()) { // continue to decode previous undecoded data if (!demuxer.readFrame() || demuxer.stream() != astream) continue; pkt = demuxer.packet(); } if (!dec->decode(pkt)) { pkt = Packet(); // set invalid to read from demuxer continue; } // decode the rest data in the next loop. read from demuxer if no data remains pkt.data = QByteArray::fromRawData(pkt.data.constData() + pkt.data.size() - dec->undecodedSize(), dec->undecodedSize()); AudioFrame frame(dec->frame()); // why is faster to call frame() for hwdec? no frame() is very slow for VDA if (!frame) continue; //frame.setAudioResampler(dec->resampler()); // if not set, always create a resampler in AudioFrame.to() AudioFormat af(frame.format()); if (ao->isOpen()) { af = ao->audioFormat(); } else { dec->resampler()->setOutAudioFormat(af); // if decoded format is not supported by audio renderer, change decoder output format if (!ao->isSupported(af)) { af.setSampleFormat(ao->preferredSampleFormat()); af.setChannelLayout(ao->preferredChannelLayout()); dec->resampler()->setOutAudioFormat(af); dec->resampler()->prepare(); } // now af is supported by audio renderer. it's safe to open ao->setAudioFormat(af); if (!ao->open()) qFatal("Open audio output error"); #if 0 // always resample ONCE due to QtAV bug // the first format unsupported frame still need to be converted to a supported format if (!ao->isSupported(frame.format())) frame = frame.to(af); #endif qDebug() << "Input: " << frame.format(); qDebug() << "Output: " << af; } printf("playing: %.3f...\r", frame.timestamp()); fflush(0); // always resample ONCE. otherwise data are all 0x0. QtAV bug frame = frame.to(af); QByteArray data(frame.data()); // plane data. currently only packet sample formats are supported. while (!data.isEmpty()) { ao->play(QByteArray::fromRawData(data.constData(), qMin(data.size(), ao->bufferSize()))); data.remove(0, qMin(data.size(), ao->bufferSize())); } } // dec, ao will be closed in dtor. demuxer will call unload in dtor return 0; }