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;
}
Exemple #2
0
	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;
}
Exemple #5
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;)
}
Exemple #7
0
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;
}
Exemple #8
0
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");

	}
}
Exemple #9
0
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");
	}
}
Exemple #10
0
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;
}
Exemple #11
0
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;
}
Exemple #12
0
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)
}
Exemple #13
0
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;
}
Exemple #15
0
	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;
	}
Exemple #16
0
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;)
}
Exemple #18
0
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");
	}
}
Exemple #19
0
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());
}
Exemple #20
0
/**
 * @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;
}
Exemple #21
0
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;
}
Exemple #22
0
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();
	}
Exemple #24
0
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;

}
Exemple #26
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());
		
	}
Exemple #27
0
/*
 *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...");
}
Exemple #28
0
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;
}
Exemple #29
0
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");
}
Exemple #30
0
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;
}