示例#1
0
void CTrackerMainWindow::pause(bool state) {
  _paused = state;

  if(_paused) 
    QObject::disconnect(_Listener.get(), SIGNAL(gotPosition(FOBData)), this, SLOT(onReceive(FOBData)));
  else 
    QObject::connect(_Listener.get(), SIGNAL(gotPosition(FOBData)), SLOT(onReceive(FOBData)));

  updateControls();
}
示例#2
0
void Gosu::MessageSocket::update()
{
    std::vector<char> buffer(maxMessageSize());

    sockaddr_in addr;
    socklen_t size = sizeof addr;

    for (;;)
    {
        int received = ::recvfrom(pimpl->socket.handle(), &buffer.front(),
            buffer.size(), 0, reinterpret_cast<sockaddr*>(&addr),
            &size);

        if (received != SOCKET_ERROR && onReceive)
        {
            onReceive(ntohl(addr.sin_addr.s_addr),
                ntohs(addr.sin_port), &buffer.front(), received);
        }
        else switch (lastSocketError())
        {
            // Ignore some of the errors.
            case GOSU_SOCK_ERR(EWOULDBLOCK):
            case GOSU_SOCK_ERR(ENETDOWN):
            case GOSU_SOCK_ERR(ENETRESET):
            case GOSU_SOCK_ERR(ETIMEDOUT):
            case GOSU_SOCK_ERR(ECONNRESET):
                return;

            // Everything else is unexpected.
            default:
                throwLastSocketError();
        }
    }
}
示例#3
0
int WebSocketImpl::attachSocket(TcpSocketImpl&& tcp, HttpParserImpl&& parser)
{
    is_server_ = true;
    ws_handler_.setDataCallback([this] (uint8_t* data, uint32_t len) { onWsData(data, len); });
    ws_handler_.setHandshakeCallback([this] (int err) { onWsHandshake(err); });
    tcp_socket_.setReadCallback([this] (int err) { onReceive(err); });
    tcp_socket_.setWriteCallback([this] (int err) { onSend(err); });
    tcp_socket_.setErrorCallback([this] (int err) { onClose(err); });
    setState(STATE_HANDSHAKE);

#ifdef KUMA_HAS_OPENSSL
    SOCKET_FD fd;
    SSL* ssl = nullptr;
    uint32_t flags = tcp.getFlags();
    int ret = tcp.detachFd(fd, ssl);
    ret = tcp_socket_.attachFd(fd, ssl, flags);
#else
    SOCKET_FD fd;
    uint32_t flags = tcp.getFlags();
    int ret = tcp.detachFd(fd);
    ret = tcp_socket_.attachFd(fd, flags);
#endif
    
    ws_handler_.setHttpParser(std::move(parser));
    return ret;
}
示例#4
0
bool EReader::processNonBlockingSelect() {
	fd_set readSet, writeSet, errorSet;
	struct timeval tval;

	tval.tv_usec = 100 * 1000; //100 ms
	tval.tv_sec = 0;

	if( m_pClientSocket->fd() >= 0 ) {

		FD_ZERO( &readSet);
		errorSet = writeSet = readSet;

		FD_SET( m_pClientSocket->fd(), &readSet);

		if (m_needsWriteSelect)
			FD_SET( m_pClientSocket->fd(), &writeSet);

		FD_SET( m_pClientSocket->fd(), &errorSet);

		int ret = select( m_pClientSocket->fd() + 1, &readSet, &writeSet, &errorSet, &tval);

		if( ret == 0) { // timeout
			return false;
		}

		if( ret < 0) {	// error
			m_pClientSocket->eDisconnect();
			return false;
		}

		if( m_pClientSocket->fd() < 0)
			return false;

		if( FD_ISSET( m_pClientSocket->fd(), &errorSet)) {
			// error on socket
			m_pClientSocket->onError();
		}

		if( m_pClientSocket->fd() < 0)
			return false;

		if( FD_ISSET( m_pClientSocket->fd(), &writeSet)) {
			// socket is ready for writing
			onSend();
		}

		if( m_pClientSocket->fd() < 0)
			return false;

		if( FD_ISSET( m_pClientSocket->fd(), &readSet)) {
			// socket is ready for reading
			onReceive();
		}

		return true;
	}

	return false;
}
示例#5
0
void StreamReceiver::run()
{
	while (input.good())
	{
		std::string line;
		std::getline(input, line);
		onReceive(line, sender);
	}
}
void i2c_init(void) {
	I2C_ADDR_DDR  = 0x40;		// All pins input
	I2C_ADDR_PORT = 0x0F;		// PC0 - PC3 enable pullup

	begin(~I2C_ADDR_PIN & 0x0F);
	onReceive(receiveEvent);
	onRequest(requestEvent);
	return;
}
示例#7
0
int AutoHelper::attachFd(SOCKET_FD fd, uint32_t flags)
{
    flags_ = flags;
    http_parser_.setDataCallback([this] (const char* data, uint32_t len) { onHttpData(data, len); });
    http_parser_.setEventCallback([this] (HttpEvent ev) { onHttpEvent(ev); });
    
    tcp_.setReadCallback([this] (int err) { onReceive(err); });
    tcp_.setErrorCallback([this] (int err) { onClose(err); });
    
    return tcp_.attachFd(fd, flags);
}
    void testOneShotAttributeSubscription(const T& expectedValue,
                                          SubscribeTo subscribeTo,
                                          ChangeAttribute setAttribute,
                                          const std::string& attributeName) {
        MockSubscriptionListenerOneType<T>* mockListener =
                new MockSubscriptionListenerOneType<T>();

        // Use a semaphore to count and wait on calls to the mock listener
        ON_CALL(*mockListener, onReceive(Eq(expectedValue)))
                .WillByDefault(ReleaseSemaphore(&semaphore));

        std::shared_ptr<ISubscriptionListener<T>> subscriptionListener(
                        mockListener);

        std::shared_ptr<tests::DefaulttestProvider> testProvider(new tests::DefaulttestProvider());
        runtime1->registerProvider<tests::testProvider>(domainName, testProvider);

        //This wait is necessary, because registerProvider is async, and a lookup could occur
        // before the register has finished.
        std::this_thread::sleep_for(std::chrono::milliseconds(registerProviderWait));

        (*testProvider.*setAttribute)(expectedValue, [](){}, [](const joynr::exceptions::ProviderRuntimeException&) {});
        ProxyBuilder<tests::testProxy>* testProxyBuilder
                = runtime2->createProxyBuilder<tests::testProxy>(domainName);
        DiscoveryQos discoveryQos;
        discoveryQos.setArbitrationStrategy(DiscoveryQos::ArbitrationStrategy::HIGHEST_PRIORITY);
        discoveryQos.setDiscoveryTimeout(1000);
        discoveryQos.setRetryInterval(250);

        std::int64_t qosRoundTripTTL = 500;

        // Send a message and expect to get a result
        tests::testProxy* testProxy = testProxyBuilder
                ->setMessagingQos(MessagingQos(qosRoundTripTTL))
                ->setCached(false)
                ->setDiscoveryQos(discoveryQos)
                ->build();

        std::int64_t minInterval_ms = 50;
        OnChangeSubscriptionQos subscriptionQos(
                    500000,   // validity_ms
                    minInterval_ms);  // minInterval_ms

        subscribeTo(testProxy, subscriptionListener, subscriptionQos);
        waitForAttributeSubscriptionArrivedAtProvider(testProvider, attributeName);

        // Wait for a subscription message to arrive
        ASSERT_TRUE(semaphore.waitFor(std::chrono::seconds(3)));

        delete testProxyBuilder;
        delete testProxy;
    }
void ClientSocket::selectEvent()
{
	WSANETWORKEVENTS netEvent;

	::ZeroMemory( &netEvent, sizeof( netEvent ) );
	::WSAEventSelect( m_SocketValue, m_RecvEvent, FD_READ | FD_CLOSE );
	::WSAEnumNetworkEvents( m_SocketValue, m_RecvEvent, &netEvent );

	if( ( netEvent.lNetworkEvents & FD_READ ) == FD_READ )
		onReceive();
 	else if( ( netEvent.lNetworkEvents & FD_CLOSE ) == FD_CLOSE )
		throw NetworkException("ClientSocket::SelectEvent() : 패킷이 닫혔다네");
}
示例#10
0
void ISend::msg_handler(unsigned char *dat, unsigned char len)
{
	unsigned char ret;
        ret = strncmp(item, (const char *)&dat[4], strlen(item));
	if (ret == 0)
		if (getStatus() == S_S) {
			setStatus(S_A);

			memcpy(strRec, dat, len);
			strRecLen = len;

			onReceive(dat, len);
		}
}
示例#11
0
bool Form1::qt_invoke( int _id, QUObject* _o )
{
    switch ( _id - staticMetaObject()->slotOffset() ) {
    case 0: init_var(); break;
    case 1: btnConnect_clicked(); break;
    case 2: onReceive(); break;
    case 3: btnInit_clicked(); break;
    case 4: btnSave_clicked(); break;
    case 5: languageChange(); break;
    case 6: onTimer(); break;
    default:
	return QDialog::qt_invoke( _id, _o );
    }
    return TRUE;
}
示例#12
0
int WebSocketImpl::attachFd(SOCKET_FD fd, uint32_t flags, const uint8_t* init_data, uint32_t init_len)
{
    is_server_ = true;
    if(init_data && init_len > 0) {
        init_data = new uint8_t(init_len);
        memcpy(init_data_, init_data, init_len);
        init_len_ = init_len;
    }
    ws_handler_.setDataCallback([this] (uint8_t* data, uint32_t len) { onWsData(data, len); });
    ws_handler_.setHandshakeCallback([this] (int err) { onWsHandshake(err); });
    tcp_socket_.setReadCallback([this] (int err) { onReceive(err); });
    tcp_socket_.setWriteCallback([this] (int err) { onSend(err); });
    tcp_socket_.setErrorCallback([this] (int err) { onClose(err); });
    setState(STATE_HANDSHAKE);
    return tcp_socket_.attachFd(fd, flags);
}
示例#13
0
FileConveyor::FileConveyor(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::FileConveyor)
{
    ui->setupUi(this);
    sender = new Sender;
    ui->stackedWidget->addWidget(sender);
    receiver = new Receiver;
    ui->stackedWidget->addWidget(receiver);
    connect(ui->sendPushButton, SIGNAL(clicked()), this, SLOT(onSending()));
    connect(sender, SIGNAL(finished()), this, SLOT(onFinished()));
    connect(sender, SIGNAL(error()), this, SLOT(onError()));
    connect(ui->recvPushButton, SIGNAL(clicked()), this, SLOT(onReceive()));
    connect(receiver, SIGNAL(finished()), this, SLOT(onFinished()));
    connect(receiver, SIGNAL(error()), this, SLOT(onError()));
}
示例#14
0
CTrackerMainWindow::CTrackerMainWindow(QWidget *parent, Qt::WFlags flags): 
  QMainWindow(parent, flags), 
  _paused(false),  
  _muted(false),  
  _UDP(IP, PORT),
  _Listener(new CTrackerFOBListener())
{
	ui.setupUi(this);

  QHBoxLayout *hLayout = new QHBoxLayout(ui.fRotation);
  hLayout->setSpacing(0);
  hLayout->setMargin(0);
  _RotationPreview = new CRotationPreview();
  QPalette palette;
  palette.setColor(_RotationPreview->backgroundRole(), Qt::black);
  _RotationPreview->setAutoFillBackground(true);
  _RotationPreview->setPalette(palette);
  hLayout->addWidget(_RotationPreview);  

  ui.cbHemisphere->clear();
  ui.cbHemisphere->addItem("Front", QVariant(BHC_FRONT));
  ui.cbHemisphere->addItem("Rear", QVariant(BHC_REAR));
  ui.cbHemisphere->addItem("Upper", QVariant(BHC_UPPER));
  ui.cbHemisphere->addItem("Lower", QVariant(BHC_LOWER));
  ui.cbHemisphere->addItem("Left", QVariant(BHC_LEFT));
  ui.cbHemisphere->addItem("Right", QVariant(BHC_RIGHT));
  ui.cbHemisphere->setCurrentIndex(3);
  ui.cbBaudRate->setCurrentIndex(ui.cbBaudRate->count() - 1);

  ui.tRotation->horizontalHeader()->hide();
  ui.tRotation->verticalHeader()->hide();
  ui.tRotation->setColumnWidth(0, 75);
  ui.tRotation->setColumnWidth(1, 75);
  ui.tRotation->setColumnWidth(2, 75);
  ui.tRotation->setRowHeight(0, 20);
  ui.tRotation->setRowHeight(1, 20);
  ui.tRotation->setRowHeight(2, 20);

  for (int i = 0; i < 3; i++)
    for (int j = 0; j < 3; j++)
      ui.tRotation->setItem(i, j, new QTableWidgetItem(QString::number(i == j? 1.0 : 0.0), 0));

  updateControls();

  QObject::connect(_Listener.get(), SIGNAL(gotPosition(FOBData)), SLOT(onReceive(FOBData)));
  QObject::connect(_Listener.get(), SIGNAL(Error(QString)), SLOT(onError(QString)));
}
示例#15
0
bool P2pRpcNetwork::handleMessage(PeerId peerId,
    const ACE_INET_Addr& peerAddr)
{
    const P2pPeerHint hint(peerId, &peerAddr);

    try {
        onReceive(*istream_, &hint);
    }
    catch (const srpc::Exception& e) {
        NSRPC_LOG_DEBUG3(
            ACE_TEXT("P2pRpcNetwork::handleMessage(P%u) FAILED(%s)."),
            peerId, e.what());
        return false;
    }

    istream_->reset(true);
    return true;
}
示例#16
0
void XYTCPSocketLayer::ReadSocket()
{
	while(_IsReadThreadRunning)
	{
		usleep(5000);

		if(!_IsReadThreadRunning)
		{
			break;
		}

		char* pOut = new char[MAX_BYTE_READ_ONCE];
		ssize_t readSize = Readn(_fd, pOut, MAX_BYTE_READ_ONCE);
		if(readSize > 0)
		{
			//dispatch data
			onReceive(pOut, readSize);

			bzero(pOut, MAX_BYTE_READ_ONCE);
			delete [] pOut;
		}
		else if(readSize == 0)
		{
			//dispatch disconnect
            onDisconnect(XYNetworkErrorCode(XYNetworkErrorCode::eXYNetworkErrorCode::SERVER_DISCONNECT));

			bzero(pOut, MAX_BYTE_READ_ONCE);
			delete [] pOut;

			_IsReadThreadRunning = false;
			_stat = States_Disconnected;
			break;
		}
		else
		{
			//dispatch read error
            onError(XYNetworkErrorCode(XYNetworkErrorCode::eXYNetworkErrorCode::READ_ERROR));
			bzero(pOut, MAX_BYTE_READ_ONCE);
			delete [] pOut;
		}
	}
	return;
}
示例#17
0
void ISend::msg_handler(unsigned char *dat, unsigned char len)
{
	unsigned char ret;
//        ret = strncmp((char *)&item[1], (const char *)&dat[4], item_len-1);
	ret = compare_keyword(dat);
	if (ret == 0) {
		if (getStatus() == S_S) {
			setStatus(S_A);
			/*返回结果,打出来*/
			/*处理所有接收回来的应答码*/

			clearAckData();
			strncpy((char *)strAck, (const char *)&dat[4+item_len], len-4-item_len);
			strAckLen = len -4-item_len;

			onReceive(dat, len);
		}
	}
}
示例#18
0
void ClientSocket::handleReceive()
{
	memset(m_packetBuf, 0, m_maxPacketSize);
	int ret = 0;

	ret = recv(m_socket, m_packetBuf, m_maxPacketSize, 0);
	if(ret< 0)
	{
		printf("recv() failed! error:%d\n", WSAGetLastError());
		m_socketState = InvalidState;
		closesocket(m_socket);
		return;
	}

	if(ret == 0)
		return;

	//把数据写入缓存里
	onReceive(m_packetBuf, ret);
}
示例#19
0
	void Server::update()
	{
		if (!mNewSocket)
		{
			mNewSocket = std::make_unique<sf::TcpSocket>();
		}

		if (mListener.accept(*mNewSocket) == sf::TcpListener::Done)
		{
			if (onConnect)
				onConnect(*this, mSocketId);

			mNewSocket->setBlocking(false);
			mSockets[mSocketId++].reset(mNewSocket.release());
		}

		sf::Packet packet;

		for (auto it = mSockets.begin(); it != mSockets.end();)
		{
			auto& socket = *it->second;
			const auto status = socket.receive(packet);

			if (status == sf::TcpSocket::Done)
			{
				if (onReceive)
					onReceive(*this, it->first, packet);
			}
			else if (status == sf::TcpSocket::Disconnected)
			{
				if (onDisonnect)
					onDisonnect(*this, it->first);

				socket.disconnect();
				mSockets.erase(it++);
				continue;
			}

			++it;
		}
	}
示例#20
0
int WebSocketImpl::connect_i(const std::string& ws_url)
{
    if(!uri_.parse(ws_url)) {
        return false;
    }
    tcp_socket_.setReadCallback([this] (int err) { onReceive(err); });
    tcp_socket_.setWriteCallback([this] (int err) { onSend(err); });
    tcp_socket_.setErrorCallback([this] (int err) { onClose(err); });
    setState(STATE_CONNECTING);
    std::string str_port = uri_.getPort();
    uint16_t port = 80;
    uint32_t flag = 0;
    if(is_equal("wss", uri_.getScheme())) {
        port = 443;
        flag = FLAG_HAS_SSL;
    }
    if(!str_port.empty()) {
        port = atoi(str_port.c_str());
    }
    return tcp_socket_.connect(uri_.getHost().c_str(), port, [this] (int err) { onConnect(err); }, flag);
}
示例#21
0
	void ServerClient::tick()
	{
        if(m_server)
		for (RakNet::Packet* p = m_server->Receive(); p; m_server->DeallocatePacket(p), p=m_server->Receive())
		{
			// We got a packet, get the identifier with our handy function
			unsigned char packetIdentifier = GetPacketIdentifierC(p);
			//std::cout << (int)packetIdentifier << std::endl;
			// Check if this is a network message packet
            
            if(m_bgMode)
            {
                m_packets.push_back(ServerPacket());
                m_packets.back().packetID = packetIdentifier;
                for(int i = 0; i < p->length; i++)
                {
                    m_packets.back().message.push_back(p->data[i]);
                }
                continue;
            }
			switch (packetIdentifier)
			{
			case ID_DISCONNECTION_NOTIFICATION:
			case ID_CONNECTION_LOST:
				// Connection lost normally
				printf("ID_DISCONNECTION_NOTIFICATION\n");
					m_connected = false;
					m_connecting = false;
					onDisconnect();
					if(m_needsToConnect)
					{
						connect();
						m_needsToConnect = false;
					}
				break;
			case ID_ALREADY_CONNECTED:
				// Connection lost normally
				printf("ID_ALREADY_CONNECTED with guid %" PRINTF_64_BIT_MODIFIER "u\n", p->guid);
				onFailedToConnect(false);
				break;
			case ID_INCOMPATIBLE_PROTOCOL_VERSION:
				printf("ID_INCOMPATIBLE_PROTOCOL_VERSION\n");
				break;
			case ID_CONNECTION_BANNED: // Banned from this server
				printf("We are banned from this server.\n");
				break;			
			case ID_CONNECTION_ATTEMPT_FAILED:
				printf("Connection attempt failed\n");
				m_connecting = false;
				m_connected = false;
				onFailedToConnect(false);
				break;
			case ID_NO_FREE_INCOMING_CONNECTIONS:
				// Sorry, the server is full.  I don't do anything here but
				// A real app should tell the user
				printf("ID_NO_FREE_INCOMING_CONNECTIONS\n");
				break;

			case ID_INVALID_PASSWORD:
				printf("ID_INVALID_PASSWORD\n");
				break;
			case ID_CONNECTION_REQUEST_ACCEPTED:
				// This tells the client they have connected
				m_connecting = false;
				m_connected = true;
				m_needsToConnect = false;
				m_client.initClient(m_server,p->guid,p->systemAddress);
				onConnect();
				break;
			case ID_CONNECTED_PING:
			case ID_UNCONNECTED_PING:
				printf("Ping from %s\n", p->systemAddress.ToString(true));
				break;
			case ID_USER_PACKET_ENUM:
				{
					RakNet::RakString rs;
					RakNet::BitStream bsIn(p->data,p->length,false);
					bsIn.IgnoreBytes(sizeof(RakNet::MessageID));
					bsIn.Read(rs);
					onReceive(rs.C_String(),rs.GetLength());
				}
				break;
			default:
				break;
			}
		}
	}
示例#22
0
void RTCPInstance::incomingReportHandler1() {
  do {
    Boolean callByeHandler = False;
    int tcpReadStreamSocketNum = fRTCPInterface.nextTCPReadStreamSocketNum();
    unsigned char tcpReadStreamChannelId = fRTCPInterface.nextTCPReadStreamChannelId();
    unsigned packetSize = 0;
    unsigned numBytesRead;
    struct sockaddr_in fromAddress;
    Boolean packetReadWasIncomplete;
    if (fNumBytesAlreadyRead >= maxRTCPPacketSize) {
      envir() << "RTCPInstance error: Hit limit when reading incoming packet over TCP. Increase \"maxRTCPPacketSize\"\n";
      break;
    }
    Boolean readResult
      = fRTCPInterface.handleRead(&fInBuf[fNumBytesAlreadyRead], maxRTCPPacketSize - fNumBytesAlreadyRead,
				  numBytesRead, fromAddress, packetReadWasIncomplete);
    if (packetReadWasIncomplete) {
      fNumBytesAlreadyRead += numBytesRead;
      return; // more reads are needed to get the entire packet
    } else { // normal case: We've read the entire packet 
      packetSize = fNumBytesAlreadyRead + numBytesRead;
      fNumBytesAlreadyRead = 0; // for next time
    }
    if (!readResult) break;

    // Ignore the packet if it was looped-back from ourself:
    Boolean packetWasFromOurHost = False;
    if (RTCPgs()->wasLoopedBackFromUs(envir(), fromAddress)) {
      packetWasFromOurHost = True;
      // However, we still want to handle incoming RTCP packets from
      // *other processes* on the same machine.  To distinguish this
      // case from a true loop-back, check whether we've just sent a
      // packet of the same size.  (This check isn't perfect, but it seems
      // to be the best we can do.)
      if (fHaveJustSentPacket && fLastPacketSentSize == packetSize) {
	// This is a true loop-back:
	fHaveJustSentPacket = False;
	break; // ignore this packet
      }
    }

    unsigned char* pkt = fInBuf;
    if (fIsSSMSource && !packetWasFromOurHost) {
      // This packet is assumed to have been received via unicast (because we're a SSM source, and SSM receivers send back RTCP "RR"
      // packets via unicast).  'Reflect' the packet by resending it to the multicast group, so that any other receivers can also
      // get to see it.

      // NOTE: Denial-of-service attacks are possible here.
      // Users of this software may wish to add their own,
      // application-specific mechanism for 'authenticating' the
      // validity of this packet before reflecting it.

      // NOTE: The test for "!packetWasFromOurHost" means that we won't reflect RTCP packets that come from other processes on
      // the same host as us.  The reason for this is that the 'packet size' test above is not 100% reliable; some packets
      // that were truly looped back from us might not be detected as such, and this might lead to infinite forwarding/receiving
      // of some packets.  To avoid this possibility, we only reflect RTCP packets that we know for sure originated elsewhere.
      // (Note, though, that if we ever re-enable the code in "Groupsock::multicastSendOnly()", then we could remove the test for
      // "!packetWasFromOurHost".)
      fRTCPInterface.sendPacket(pkt, packetSize);
      fHaveJustSentPacket = True;
      fLastPacketSentSize = packetSize;
    }

#ifdef DEBUG
    fprintf(stderr, "[%p]saw incoming RTCP packet", this);
    if (tcpReadStreamSocketNum < 0) {
      // Note that "fromAddress" is valid only if we're receiving over UDP (not over TCP):
      fprintf(stderr, " (from address %s, port %d)", AddressString(fromAddress).val(), ntohs(fromAddress.sin_port));
    }
    fprintf(stderr, "\n");
    for (unsigned i = 0; i < packetSize; ++i) {
      if (i%4 == 0) fprintf(stderr, " ");
      fprintf(stderr, "%02x", pkt[i]);
    }
    fprintf(stderr, "\n");
#endif
    int totPacketSize = IP_UDP_HDR_SIZE + packetSize;

    // Check the RTCP packet for validity:
    // It must at least contain a header (4 bytes), and this header
    // must be version=2, with no padding bit, and a payload type of
    // SR (200) or RR (201):
    if (packetSize < 4) break;
    unsigned rtcpHdr = ntohl(*(u_int32_t*)pkt);
    if ((rtcpHdr & 0xE0FE0000) != (0x80000000 | (RTCP_PT_SR<<16))) {
#ifdef DEBUG
      fprintf(stderr, "rejected bad RTCP packet: header 0x%08x\n", rtcpHdr);
#endif
      break;
    }

    // Process each of the individual RTCP 'subpackets' in (what may be)
    // a compound RTCP packet.
    int typeOfPacket = PACKET_UNKNOWN_TYPE;
    unsigned reportSenderSSRC = 0;
    Boolean packetOK = False;
    while (1) {
      unsigned rc = (rtcpHdr>>24)&0x1F;
      unsigned pt = (rtcpHdr>>16)&0xFF;
      unsigned length = 4*(rtcpHdr&0xFFFF); // doesn't count hdr
      ADVANCE(4); // skip over the header
      if (length > packetSize) break;

      // Assume that each RTCP subpacket begins with a 4-byte SSRC:
      if (length < 4) break; length -= 4;
      reportSenderSSRC = ntohl(*(u_int32_t*)pkt); ADVANCE(4);

      Boolean subPacketOK = False;
      switch (pt) {
        case RTCP_PT_SR: {
#ifdef DEBUG
	  fprintf(stderr, "SR\n");
#endif
	  if (length < 20) break; length -= 20;

	  // Extract the NTP timestamp, and note this:
	  unsigned NTPmsw = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
	  unsigned NTPlsw = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
	  unsigned rtpTimestamp = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
	  if (fSource != NULL) {
	    RTPReceptionStatsDB& receptionStats
	      = fSource->receptionStatsDB();
	    receptionStats.noteIncomingSR(reportSenderSSRC,
					  NTPmsw, NTPlsw, rtpTimestamp);
	  }
	  ADVANCE(8); // skip over packet count, octet count

	  // If a 'SR handler' was set, call it now:
	  if (fSRHandlerTask != NULL) (*fSRHandlerTask)(fSRHandlerClientData);

	  // The rest of the SR is handled like a RR (so, no "break;" here)
	}
        case RTCP_PT_RR: {
#ifdef DEBUG
	  fprintf(stderr, "RR\n");
#endif
	  unsigned reportBlocksSize = rc*(6*4);
	  if (length < reportBlocksSize) break;
	  length -= reportBlocksSize;

          if (fSink != NULL) {
	    // Use this information to update stats about our transmissions:
            RTPTransmissionStatsDB& transmissionStats = fSink->transmissionStatsDB();
            for (unsigned i = 0; i < rc; ++i) {
              unsigned senderSSRC = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
              // We care only about reports about our own transmission, not others'
              if (senderSSRC == fSink->SSRC()) {
                unsigned lossStats = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
                unsigned highestReceived = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
                unsigned jitter = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
                unsigned timeLastSR = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
                unsigned timeSinceLastSR = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
                transmissionStats.noteIncomingRR(reportSenderSSRC, fromAddress,
						 lossStats,
						 highestReceived, jitter,
						 timeLastSR, timeSinceLastSR);
              } else {
                ADVANCE(4*5);
              }
            }
          } else {
            ADVANCE(reportBlocksSize);
          }

	  if (pt == RTCP_PT_RR) { // i.e., we didn't fall through from 'SR'
	    // If a 'RR handler' was set, call it now:

	    // Specific RR handler:
	    if (fSpecificRRHandlerTable != NULL) {
	      netAddressBits fromAddr;
	      portNumBits fromPortNum;
	      if (tcpReadStreamSocketNum < 0) {
		// Normal case: We read the RTCP packet over UDP
		fromAddr = fromAddress.sin_addr.s_addr;
		fromPortNum = ntohs(fromAddress.sin_port);
	      } else {
		// Special case: We read the RTCP packet over TCP (interleaved)
		// Hack: Use the TCP socket and channel id to look up the handler
		fromAddr = tcpReadStreamSocketNum;
		fromPortNum = tcpReadStreamChannelId;
	      }
	      Port fromPort(fromPortNum);
	      RRHandlerRecord* rrHandler
		= (RRHandlerRecord*)(fSpecificRRHandlerTable->Lookup(fromAddr, (~0), fromPort));
	      if (rrHandler != NULL) {
		if (rrHandler->rrHandlerTask != NULL) {
		  (*(rrHandler->rrHandlerTask))(rrHandler->rrHandlerClientData);
		}
	      }
	    }

	    // General RR handler:
	    if (fRRHandlerTask != NULL) (*fRRHandlerTask)(fRRHandlerClientData);
	  }

	  subPacketOK = True;
	  typeOfPacket = PACKET_RTCP_REPORT;
	  break;
	}
        case RTCP_PT_BYE: {
#ifdef DEBUG
	  fprintf(stderr, "BYE\n");
#endif
	  // If a 'BYE handler' was set, arrange for it to be called at the end of this routine.
	  // (Note: We don't call it immediately, in case it happens to cause "this" to be deleted.)
	  if (fByeHandlerTask != NULL
	      && (!fByeHandleActiveParticipantsOnly
		  || (fSource != NULL
		      && fSource->receptionStatsDB().lookup(reportSenderSSRC) != NULL)
		  || (fSink != NULL
		      && fSink->transmissionStatsDB().lookup(reportSenderSSRC) != NULL))) {
	    callByeHandler = True;
	  }

	  // We should really check for & handle >1 SSRCs being present #####

	  subPacketOK = True;
	  typeOfPacket = PACKET_BYE;
	  break;
	}
	// Later handle SDES, APP, and compound RTCP packets #####
        default:
#ifdef DEBUG
	  fprintf(stderr, "UNSUPPORTED TYPE(0x%x)\n", pt);
#endif
	  subPacketOK = True;
	  break;
      }
      if (!subPacketOK) break;

      // need to check for (& handle) SSRC collision! #####

#ifdef DEBUG
      fprintf(stderr, "validated RTCP subpacket (type %d): %d, %d, %d, 0x%08x\n", typeOfPacket, rc, pt, length, reportSenderSSRC);
#endif

      // Skip over any remaining bytes in this subpacket:
      ADVANCE(length);

      // Check whether another RTCP 'subpacket' follows:
      if (packetSize == 0) {
	packetOK = True;
	break;
      } else if (packetSize < 4) {
#ifdef DEBUG
	fprintf(stderr, "extraneous %d bytes at end of RTCP packet!\n", packetSize);
#endif
	break;
      }
      rtcpHdr = ntohl(*(u_int32_t*)pkt);
      if ((rtcpHdr & 0xC0000000) != 0x80000000) {
#ifdef DEBUG
	fprintf(stderr, "bad RTCP subpacket: header 0x%08x\n", rtcpHdr);
#endif
	break;
      }
    }

    if (!packetOK) {
#ifdef DEBUG
      fprintf(stderr, "rejected bad RTCP subpacket: header 0x%08x\n", rtcpHdr);
#endif
      break;
    } else {
#ifdef DEBUG
      fprintf(stderr, "validated entire RTCP packet\n");
#endif
    }

    onReceive(typeOfPacket, totPacketSize, reportSenderSSRC);

    // Finally, if we need to call a "BYE" handler, do so now (in case it causes "this" to get deleted):
    if (callByeHandler && fByeHandlerTask != NULL/*sanity check*/) {
      TaskFunc* byeHandler = fByeHandlerTask;
      fByeHandlerTask = NULL; // because we call the handler only once, by default
      (*byeHandler)(fByeHandlerClientData);
    }
  } while (0);
}
示例#23
0
 void ServerClient::execBG()
 {
     if(m_server)
         for (int i = 0; i < m_packets.size(); ++i)
         {
             // We got a packet, get the identifier with our handy function
             unsigned char packetIdentifier = m_packets[i].packetID;
             //std::cout << (int)packetIdentifier << std::endl;
             // Check if this is a network message packet
             switch (packetIdentifier)
             {
                 case ID_DISCONNECTION_NOTIFICATION:
                 case ID_CONNECTION_LOST:
                     // Connection lost normally
                     printf("ID_DISCONNECTION_NOTIFICATION\n");
                     m_connected = false;
                     m_connecting = false;
                     onDisconnect();
                     if(m_needsToConnect)
                     {
                         connect();
                         m_needsToConnect = false;
                     }
                     break;
                 case ID_ALREADY_CONNECTED:
                     // Connection lost normally
                     onFailedToConnect(false);
                     break;
                 case ID_INCOMPATIBLE_PROTOCOL_VERSION:
                     printf("ID_INCOMPATIBLE_PROTOCOL_VERSION\n");
                     break;
                 case ID_CONNECTION_BANNED: // Banned from this server
                     printf("We are banned from this server.\n");
                     break;
                 case ID_CONNECTION_ATTEMPT_FAILED:
                     printf("Connection attempt failed\n");
                     m_connecting = false;
                     m_connected = false;
                     onFailedToConnect(false);
                     break;
                 case ID_NO_FREE_INCOMING_CONNECTIONS:
                     // Sorry, the server is full.  I don't do anything here but
                     // A real app should tell the user
                     printf("ID_NO_FREE_INCOMING_CONNECTIONS\n");
                     break;
                     
                 case ID_INVALID_PASSWORD:
                     printf("ID_INVALID_PASSWORD\n");
                     break;
                 case ID_CONNECTION_REQUEST_ACCEPTED:
                     // This tells the client they have connected
                    // m_connecting = false;
                    // m_connected = true;
                     //m_needsToConnect = false;
                     //m_client.initClient(m_server,p->guid,p->systemAddress);
                    // onConnect();
                     break;
                 case ID_CONNECTED_PING:
                 case ID_UNCONNECTED_PING:
                    // printf("Ping from %s\n", p->systemAddress.ToString(true));
                     break;
                 case ID_USER_PACKET_ENUM:
                 {
                     RakNet::RakString rs;
                     RakNet::BitStream bsIn(&m_packets[i].message[0],m_packets[i].message.size(),false);
                     bsIn.IgnoreBytes(sizeof(RakNet::MessageID));
                     bsIn.Read(rs);
                     onReceive(rs.C_String(),rs.GetLength());
                 }
                     break;
                 default:
                     break;
             }
         }
     
     m_packets.clear();
     m_bgMode = false;
 }
示例#24
0
void RTCPInstance
::processIncomingReport(unsigned packetSize, struct sockaddr_in const& fromAddress,
			int tcpSocketNum, unsigned char tcpStreamChannelId) {
  do {
    Boolean callByeHandler = False;
    unsigned char* pkt = fInBuf;

#ifdef DEBUG
    fprintf(stderr, "[%p]saw incoming RTCP packet (from ", this);
    if (tcpSocketNum < 0) {
      // Note that "fromAddress" is valid only if we're receiving over UDP (not over TCP):
      fprintf(stderr, "address %s, port %d", AddressString(fromAddress).val(), ntohs(fromAddress.sin_port));
    } else {
      fprintf(stderr, "TCP socket #%d, stream channel id %d", tcpSocketNum, tcpStreamChannelId);
    }
    fprintf(stderr, ")\n");
    for (unsigned i = 0; i < packetSize; ++i) {
      if (i%4 == 0) fprintf(stderr, " ");
      fprintf(stderr, "%02x", pkt[i]);
    }
    fprintf(stderr, "\n");
#endif
    int totPacketSize = IP_UDP_HDR_SIZE + packetSize;

    // Check the RTCP packet for validity:
    // It must at least contain a header (4 bytes), and this header
    // must be version=2, with no padding bit, and a payload type of
    // SR (200) or RR (201):
    if (packetSize < 4) break;
    unsigned rtcpHdr = ntohl(*(u_int32_t*)pkt);
    if ((rtcpHdr & 0xE0FE0000) != (0x80000000 | (RTCP_PT_SR<<16))) {
#ifdef DEBUG
      fprintf(stderr, "rejected bad RTCP packet: header 0x%08x\n", rtcpHdr);
#endif
      break;
    }

    // Process each of the individual RTCP 'subpackets' in (what may be)
    // a compound RTCP packet.
    int typeOfPacket = PACKET_UNKNOWN_TYPE;
    unsigned reportSenderSSRC = 0;
    Boolean packetOK = False;
    while (1) {
      unsigned rc = (rtcpHdr>>24)&0x1F;
      unsigned pt = (rtcpHdr>>16)&0xFF;
      unsigned length = 4*(rtcpHdr&0xFFFF); // doesn't count hdr
      ADVANCE(4); // skip over the header
      if (length > packetSize) break;

      // Assume that each RTCP subpacket begins with a 4-byte SSRC:
      if (length < 4) break; length -= 4;
      reportSenderSSRC = ntohl(*(u_int32_t*)pkt); ADVANCE(4);

      Boolean subPacketOK = False;
      switch (pt) {
        case RTCP_PT_SR: {
#ifdef DEBUG
	  fprintf(stderr, "SR\n");
#endif
	  if (length < 20) break; length -= 20;

	  // Extract the NTP timestamp, and note this:
	  unsigned NTPmsw = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
	  unsigned NTPlsw = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
	  unsigned rtpTimestamp = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
	  if (fSource != NULL) {
	    RTPReceptionStatsDB& receptionStats
	      = fSource->receptionStatsDB();
	    receptionStats.noteIncomingSR(reportSenderSSRC,
					  NTPmsw, NTPlsw, rtpTimestamp);
	  }
	  ADVANCE(8); // skip over packet count, octet count

	  // If a 'SR handler' was set, call it now:
	  if (fSRHandlerTask != NULL) (*fSRHandlerTask)(fSRHandlerClientData);

	  // The rest of the SR is handled like a RR (so, no "break;" here)
	}
        case RTCP_PT_RR: {
#ifdef DEBUG
	  fprintf(stderr, "RR\n");
#endif
	  unsigned reportBlocksSize = rc*(6*4);
	  if (length < reportBlocksSize) break;
	  length -= reportBlocksSize;

          if (fSink != NULL) {
	    // Use this information to update stats about our transmissions:
            RTPTransmissionStatsDB& transmissionStats = fSink->transmissionStatsDB();
            for (unsigned i = 0; i < rc; ++i) {
              unsigned senderSSRC = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
              // We care only about reports about our own transmission, not others'
              if (senderSSRC == fSink->SSRC()) {
                unsigned lossStats = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
                unsigned highestReceived = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
                unsigned jitter = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
                unsigned timeLastSR = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
                unsigned timeSinceLastSR = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
                transmissionStats.noteIncomingRR(reportSenderSSRC, fromAddress,
						 lossStats,
						 highestReceived, jitter,
						 timeLastSR, timeSinceLastSR);
              } else {
                ADVANCE(4*5);
              }
            }
          } else {
            ADVANCE(reportBlocksSize);
          }

	  if (pt == RTCP_PT_RR) { // i.e., we didn't fall through from 'SR'
	    // If a 'RR handler' was set, call it now:

	    // Specific RR handler:
	    if (fSpecificRRHandlerTable != NULL) {
	      netAddressBits fromAddr;
	      portNumBits fromPortNum;
	      if (tcpSocketNum < 0) {
		// Normal case: We read the RTCP packet over UDP
		fromAddr = fromAddress.sin_addr.s_addr;
		fromPortNum = ntohs(fromAddress.sin_port);
	      } else {
		// Special case: We read the RTCP packet over TCP (interleaved)
		// Hack: Use the TCP socket and channel id to look up the handler
		fromAddr = tcpSocketNum;
		fromPortNum = tcpStreamChannelId;
	      }
	      Port fromPort(fromPortNum);
	      RRHandlerRecord* rrHandler
		= (RRHandlerRecord*)(fSpecificRRHandlerTable->Lookup(fromAddr, (~0), fromPort));
	      if (rrHandler != NULL) {
		if (rrHandler->rrHandlerTask != NULL) {
		  (*(rrHandler->rrHandlerTask))(rrHandler->rrHandlerClientData);
		}
	      }
	    }

	    // General RR handler:
	    if (fRRHandlerTask != NULL) (*fRRHandlerTask)(fRRHandlerClientData);
	  }

	  subPacketOK = True;
	  typeOfPacket = PACKET_RTCP_REPORT;
	  break;
	}
        case RTCP_PT_BYE: {
#ifdef DEBUG
	  fprintf(stderr, "BYE\n");
#endif
	  // If a 'BYE handler' was set, arrange for it to be called at the end of this routine.
	  // (Note: We don't call it immediately, in case it happens to cause "this" to be deleted.)
	  if (fByeHandlerTask != NULL
	      && (!fByeHandleActiveParticipantsOnly
		  || (fSource != NULL
		      && fSource->receptionStatsDB().lookup(reportSenderSSRC) != NULL)
		  || (fSink != NULL
		      && fSink->transmissionStatsDB().lookup(reportSenderSSRC) != NULL))) {
	    callByeHandler = True;
	  }

	  // We should really check for & handle >1 SSRCs being present #####

	  subPacketOK = True;
	  typeOfPacket = PACKET_BYE;
	  break;
	}
	// Other RTCP packet types that we don't yet handle:
        case RTCP_PT_SDES: {
#ifdef DEBUG
	  // 'Handle' SDES packets only in debugging code, by printing out the 'SDES items':
	  fprintf(stderr, "SDES\n");

	  // Process each 'chunk':
	  Boolean chunkOK = False;
	  ADVANCE(-4); length += 4; // hack so that we see the first SSRC/CSRC again
	  while (length >= 8) { // A valid chunk must be at least 8 bytes long
	    chunkOK = False; // until we learn otherwise

	    u_int32_t SSRC_CSRC = ntohl(*(u_int32_t*)pkt); ADVANCE(4); length -= 4;
	    fprintf(stderr, "\tSSRC/CSRC: 0x%08x\n", SSRC_CSRC);

	    // Process each 'SDES item' in the chunk:
	    u_int8_t itemType = *pkt; ADVANCE(1); --length;
	    while (itemType != 0) {
	      unsigned itemLen = *pkt; ADVANCE(1); --length;
	      // Make sure "itemLen" allows for at least 1 zero byte at the end of the chunk:
	      if (itemLen + 1 > length || pkt[itemLen] != 0) break;

	      fprintf(stderr, "\t\t%s:%s\n",
		      itemType == 1 ? "CNAME" :
		      itemType == 2 ? "NAME" :
		      itemType == 3 ? "EMAIL" :
		      itemType == 4 ? "PHONE" :
		      itemType == 5 ? "LOC" :
		      itemType == 6 ? "TOOL" :
		      itemType == 7 ? "NOTE" :
		      itemType == 8 ? "PRIV" :
		      "(unknown)",
		      itemType < 8 ? (char*)pkt // hack, because we know it's '\0'-terminated
		      : "???"/* don't try to print out PRIV or unknown items */);
	      ADVANCE(itemLen); length -= itemLen;

	      itemType = *pkt; ADVANCE(1); --length;
	    }
	    if (itemType != 0) break; // bad 'SDES item'

	    // Thus, itemType == 0.  This zero 'type' marks the end of the list of SDES items.
	    // Skip over remaining zero padding bytes, so that this chunk ends on a 4-byte boundary:
	    while (length%4 > 0 && *pkt == 0) { ADVANCE(1); --length; }
	    if (length%4 > 0) break; // Bad (non-zero) padding byte

	    chunkOK = True;
	  }
	  if (!chunkOK || length > 0) break; // bad chunk, or not enough bytes for the last chunk
#endif
	  subPacketOK = True;
	  break;
	}
        case RTCP_PT_APP: {
#ifdef DEBUG
	  fprintf(stderr, "APP(unhandled)\n");
#endif
	  subPacketOK = True;
	  break;
	}
        case RTCP_PT_RTPFB: {
#ifdef DEBUG
	  fprintf(stderr, "RTPFB(unhandled)\n");
#endif
	  subPacketOK = True;
	  break;
	}
        case RTCP_PT_PSFB: {
#ifdef DEBUG
	  fprintf(stderr, "PSFB(unhandled)\n");
	  // Temporary code to show "Receiver Estimated Maximum Bitrate" (REMB) feedback reports:
	  //#####
	  if (length >= 12 && pkt[4] == 'R' && pkt[5] == 'E' && pkt[6] == 'M' && pkt[7] == 'B') {
	    u_int8_t exp = pkt[9]>>2;
	    u_int32_t mantissa = ((pkt[9]&0x03)<<16)|(pkt[10]<<8)|pkt[11];
	    double remb = (double)mantissa;
	    while (exp > 0) {
	      remb *= 2.0;
	      exp /= 2;
	    }
	    fprintf(stderr, "\tReceiver Estimated Max Bitrate (REMB): %g bps\n", remb);
	  }
#endif
	  subPacketOK = True;
	  break;
	}
        case RTCP_PT_XR: {
#ifdef DEBUG
	  fprintf(stderr, "XR(unhandled)\n");
#endif
	  subPacketOK = True;
	  break;
	}
        case RTCP_PT_AVB: {
#ifdef DEBUG
	  fprintf(stderr, "AVB(unhandled)\n");
#endif
	  subPacketOK = True;
	  break;
	}
        case RTCP_PT_RSI: {
#ifdef DEBUG
	  fprintf(stderr, "RSI(unhandled)\n");
#endif
	  subPacketOK = True;
	  break;
	}
        case RTCP_PT_TOKEN: {
#ifdef DEBUG
	  fprintf(stderr, "TOKEN(unhandled)\n");
#endif
	  subPacketOK = True;
	  break;
	}
        case RTCP_PT_IDMS: {
#ifdef DEBUG
	  fprintf(stderr, "IDMS(unhandled)\n");
#endif
	  subPacketOK = True;
	  break;
	}
        default: {
#ifdef DEBUG
	  fprintf(stderr, "UNKNOWN TYPE(0x%x)\n", pt);
#endif
	  subPacketOK = True;
	  break;
	}
      }
      if (!subPacketOK) break;

      // need to check for (& handle) SSRC collision! #####

#ifdef DEBUG
      fprintf(stderr, "validated RTCP subpacket: rc:%d, pt:%d, bytes remaining:%d, report sender SSRC:0x%08x\n", rc, pt, length, reportSenderSSRC);
#endif

      // Skip over any remaining bytes in this subpacket:
      ADVANCE(length);

      // Check whether another RTCP 'subpacket' follows:
      if (packetSize == 0) {
	packetOK = True;
	break;
      } else if (packetSize < 4) {
#ifdef DEBUG
	fprintf(stderr, "extraneous %d bytes at end of RTCP packet!\n", packetSize);
#endif
	break;
      }
      rtcpHdr = ntohl(*(u_int32_t*)pkt);
      if ((rtcpHdr & 0xC0000000) != 0x80000000) {
#ifdef DEBUG
	fprintf(stderr, "bad RTCP subpacket: header 0x%08x\n", rtcpHdr);
#endif
	break;
      }
    }

    if (!packetOK) {
#ifdef DEBUG
      fprintf(stderr, "rejected bad RTCP subpacket: header 0x%08x\n", rtcpHdr);
#endif
      break;
    } else {
#ifdef DEBUG
      fprintf(stderr, "validated entire RTCP packet\n");
#endif
    }

    onReceive(typeOfPacket, totPacketSize, reportSenderSSRC);

    // Finally, if we need to call a "BYE" handler, do so now (in case it causes "this" to get deleted):
    if (callByeHandler && fByeHandlerTask != NULL/*sanity check*/) {
      TaskFunc* byeHandler = fByeHandlerTask;
      fByeHandlerTask = NULL; // because we call the handler only once, by default
      (*byeHandler)(fByeHandlerClientData);
    }
  } while (0);
示例#25
0
void RTCPInstance
::processIncomingReport(unsigned packetSize, struct sockaddr_in const& fromAddress) {
  do {
    Boolean callByeHandler = False;
    int tcpReadStreamSocketNum = fRTCPInterface.nextTCPReadStreamSocketNum();
    unsigned char tcpReadStreamChannelId = fRTCPInterface.nextTCPReadStreamChannelId();
    unsigned char* pkt = fInBuf;

#ifdef DEBUG
    fprintf(stderr, "[%p]saw incoming RTCP packet", this);
    if (tcpReadStreamSocketNum < 0) {
      // Note that "fromAddress" is valid only if we're receiving over UDP (not over TCP):
      fprintf(stderr, " (from address %s, port %d)", AddressString(fromAddress).val(), ntohs(fromAddress.sin_port));
    }
    fprintf(stderr, "\n");
    for (unsigned i = 0; i < packetSize; ++i) {
      if (i%4 == 0) fprintf(stderr, " ");
      fprintf(stderr, "%02x", pkt[i]);
    }
    fprintf(stderr, "\n");
#endif
    int totPacketSize = IP_UDP_HDR_SIZE + packetSize;

    // Check the RTCP packet for validity:
    // It must at least contain a header (4 bytes), and this header
    // must be version=2, with no padding bit, and a payload type of
    // SR (200) or RR (201):
    if (packetSize < 4) break;
    unsigned rtcpHdr = ntohl(*(u_int32_t*)pkt);
    if ((rtcpHdr & 0xE0FE0000) != (0x80000000 | (RTCP_PT_SR<<16))) {
#ifdef DEBUG
      fprintf(stderr, "rejected bad RTCP packet: header 0x%08x\n", rtcpHdr);
#endif
      break;
    }

    // Process each of the individual RTCP 'subpackets' in (what may be)
    // a compound RTCP packet.
    int typeOfPacket = PACKET_UNKNOWN_TYPE;
    unsigned reportSenderSSRC = 0;
    Boolean packetOK = False;
    while (1) {
      unsigned rc = (rtcpHdr>>24)&0x1F;
      unsigned pt = (rtcpHdr>>16)&0xFF;
      unsigned length = 4*(rtcpHdr&0xFFFF); // doesn't count hdr
      ADVANCE(4); // skip over the header
      if (length > packetSize) break;

      // Assume that each RTCP subpacket begins with a 4-byte SSRC:
      if (length < 4) break; length -= 4;
      reportSenderSSRC = ntohl(*(u_int32_t*)pkt); ADVANCE(4);

      Boolean subPacketOK = False;
      switch (pt) {
        case RTCP_PT_SR: {
#ifdef DEBUG
	  fprintf(stderr, "SR\n");
#endif
	  if (length < 20) break; length -= 20;

	  // Extract the NTP timestamp, and note this:
	  unsigned NTPmsw = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
	  unsigned NTPlsw = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
	  unsigned rtpTimestamp = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
	  if (fSource != NULL) {
	    RTPReceptionStatsDB& receptionStats
	      = fSource->receptionStatsDB();
	    receptionStats.noteIncomingSR(reportSenderSSRC,
					  NTPmsw, NTPlsw, rtpTimestamp);
	  }
	  ADVANCE(8); // skip over packet count, octet count

	  // If a 'SR handler' was set, call it now:
	  if (fSRHandlerTask != NULL) (*fSRHandlerTask)(fSRHandlerClientData);

	  // The rest of the SR is handled like a RR (so, no "break;" here)
	}
        case RTCP_PT_RR: {
#ifdef DEBUG
	  fprintf(stderr, "RR\n");
#endif
	  unsigned reportBlocksSize = rc*(6*4);
	  if (length < reportBlocksSize) break;
	  length -= reportBlocksSize;

          if (fSink != NULL) {
	    // Use this information to update stats about our transmissions:
            RTPTransmissionStatsDB& transmissionStats = fSink->transmissionStatsDB();
            for (unsigned i = 0; i < rc; ++i) {
              unsigned senderSSRC = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
              // We care only about reports about our own transmission, not others'
              if (senderSSRC == fSink->SSRC()) {
                unsigned lossStats = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
                unsigned highestReceived = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
                unsigned jitter = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
                unsigned timeLastSR = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
                unsigned timeSinceLastSR = ntohl(*(u_int32_t*)pkt); ADVANCE(4);
                transmissionStats.noteIncomingRR(reportSenderSSRC, fromAddress,
						 lossStats,
						 highestReceived, jitter,
						 timeLastSR, timeSinceLastSR);
              } else {
                ADVANCE(4*5);
              }
            }
          } else {
            ADVANCE(reportBlocksSize);
          }

	  if (pt == RTCP_PT_RR) { // i.e., we didn't fall through from 'SR'
	    // If a 'RR handler' was set, call it now:

	    // Specific RR handler:
	    if (fSpecificRRHandlerTable != NULL) {
	      netAddressBits fromAddr;
	      portNumBits fromPortNum;
	      if (tcpReadStreamSocketNum < 0) {
		// Normal case: We read the RTCP packet over UDP
		fromAddr = fromAddress.sin_addr.s_addr;
		fromPortNum = ntohs(fromAddress.sin_port);
	      } else {
		// Special case: We read the RTCP packet over TCP (interleaved)
		// Hack: Use the TCP socket and channel id to look up the handler
		fromAddr = tcpReadStreamSocketNum;
		fromPortNum = tcpReadStreamChannelId;
	      }
	      Port fromPort(fromPortNum);
	      RRHandlerRecord* rrHandler
		= (RRHandlerRecord*)(fSpecificRRHandlerTable->Lookup(fromAddr, (~0), fromPort));
	      if (rrHandler != NULL) {
		if (rrHandler->rrHandlerTask != NULL) {
		  (*(rrHandler->rrHandlerTask))(rrHandler->rrHandlerClientData);
		}
	      }
	    }

	    // General RR handler:
	    if (fRRHandlerTask != NULL) (*fRRHandlerTask)(fRRHandlerClientData);
	  }

	  subPacketOK = True;
	  typeOfPacket = PACKET_RTCP_REPORT;
	  break;
	}
        case RTCP_PT_BYE: {
#ifdef DEBUG
	  fprintf(stderr, "BYE\n");
#endif
	  // If a 'BYE handler' was set, arrange for it to be called at the end of this routine.
	  // (Note: We don't call it immediately, in case it happens to cause "this" to be deleted.)
	  if (fByeHandlerTask != NULL
	      && (!fByeHandleActiveParticipantsOnly
		  || (fSource != NULL
		      && fSource->receptionStatsDB().lookup(reportSenderSSRC) != NULL)
		  || (fSink != NULL
		      && fSink->transmissionStatsDB().lookup(reportSenderSSRC) != NULL))) {
	    callByeHandler = True;
	  }

	  // We should really check for & handle >1 SSRCs being present #####

	  subPacketOK = True;
	  typeOfPacket = PACKET_BYE;
	  break;
	}
	// Later handle SDES, APP, and compound RTCP packets #####
        default:
#ifdef DEBUG
	  fprintf(stderr, "UNSUPPORTED TYPE(0x%x)\n", pt);
#endif
	  subPacketOK = True;
	  break;
      }
      if (!subPacketOK) break;

      // need to check for (& handle) SSRC collision! #####

#ifdef DEBUG
      fprintf(stderr, "validated RTCP subpacket (type %d): %d, %d, %d, 0x%08x\n", typeOfPacket, rc, pt, length, reportSenderSSRC);
#endif

      // Skip over any remaining bytes in this subpacket:
      ADVANCE(length);

      // Check whether another RTCP 'subpacket' follows:
      if (packetSize == 0) {
	packetOK = True;
	break;
      } else if (packetSize < 4) {
#ifdef DEBUG
	fprintf(stderr, "extraneous %d bytes at end of RTCP packet!\n", packetSize);
#endif
	break;
      }
      rtcpHdr = ntohl(*(u_int32_t*)pkt);
      if ((rtcpHdr & 0xC0000000) != 0x80000000) {
#ifdef DEBUG
	fprintf(stderr, "bad RTCP subpacket: header 0x%08x\n", rtcpHdr);
#endif
	break;
      }
    }

    if (!packetOK) {
#ifdef DEBUG
      fprintf(stderr, "rejected bad RTCP subpacket: header 0x%08x\n", rtcpHdr);
#endif
      break;
    } else {
#ifdef DEBUG
      fprintf(stderr, "validated entire RTCP packet\n");
#endif
    }

    onReceive(typeOfPacket, totPacketSize, reportSenderSSRC);

    // Finally, if we need to call a "BYE" handler, do so now (in case it causes "this" to get deleted):
    if (callByeHandler && fByeHandlerTask != NULL/*sanity check*/) {
      TaskFunc* byeHandler = fByeHandlerTask;
      fByeHandlerTask = NULL; // because we call the handler only once, by default
      (*byeHandler)(fByeHandlerClientData);
    }
  } while (0);
}
示例#26
0
	void ServerHost::doTick()
	{
		// Get a packet from either the server or the client

		for (RakNet::Packet* p = m_server->Receive(); p; m_server->DeallocatePacket(p), p=m_server->Receive())
		{
			// We got a packet, get the identifier with our handy function
			unsigned char packetIdentifier = GetPacketIdentifier(p);

			// Check if this is a network message packet
			switch (packetIdentifier)
			{
			case ID_DISCONNECTION_NOTIFICATION:
				// Connection lost normally
				printf("ID_DISCONNECTION_NOTIFICATION\n");
				m_peer.initServer(m_server,p->guid,p->systemAddress);
				onDisconnect(&m_peer);
				break;
			case ID_ALREADY_CONNECTED:
				// Connection lost normally
				printf("ID_ALREADY_CONNECTED with guid %" PRINTF_64_BIT_MODIFIER "u\n", p->guid);
				break;
			case ID_INCOMPATIBLE_PROTOCOL_VERSION:
				printf("ID_INCOMPATIBLE_PROTOCOL_VERSION\n");
				break;
			case ID_CONNECTION_BANNED: // Banned from this server
				printf("We are banned from this server.\n");
				break;			
			case ID_CONNECTION_ATTEMPT_FAILED:
				printf("Connection attempt failed\n");
				break;
			case ID_NO_FREE_INCOMING_CONNECTIONS:
				// Sorry, the server is full.  I don't do anything here but
				// A real app should tell the user
				printf("ID_NO_FREE_INCOMING_CONNECTIONS\n");
				break;

			case ID_INVALID_PASSWORD:
				printf("ID_INVALID_PASSWORD\n");
				break;

			case ID_CONNECTION_LOST:
				// Couldn't deliver a reliable packet - i.e. the other system was abnormally
				// terminated
				printf("ID_CONNECTION_LOST\n");
				m_peer.initServer(m_server,p->guid,p->systemAddress);
				onDisconnect(&m_peer);
				break;

			case ID_NEW_INCOMING_CONNECTION:
				// This tells the client they have connected
				m_peer.initServer(m_server,p->guid,p->systemAddress);
				onConnect(&m_peer);
				break;
			case ID_CONNECTED_PING:
			case ID_UNCONNECTED_PING:
				printf("Ping from %s\n", p->systemAddress.ToString(true));
				break;
			case ID_USER_PACKET_ENUM:
				{
					RakNet::RakString rs;
					RakNet::BitStream bsIn(p->data,p->length,false);
					bsIn.IgnoreBytes(sizeof(RakNet::MessageID));
					bsIn.Read(rs);
					m_peer.initServer(m_server,p->guid,p->systemAddress);
					onReceive(&m_peer,rs.C_String(),rs.GetLength());
				}
				break;
			default:
				break;
			}
		}
	}
示例#27
0
文件: RTCP.cpp 项目: 499276369/ohbee
void RTCPInstance::incomingReportHandler1() {
  unsigned char* pkt = fInBuf;
  unsigned packetSize;
  struct sockaddr_in fromAddress;
  int typeOfPacket = PACKET_UNKNOWN_TYPE;

  do {
    int tcpReadStreamSocketNum = fRTCPInterface.nextTCPReadStreamSocketNum();
    unsigned char tcpReadStreamChannelId = fRTCPInterface.nextTCPReadStreamChannelId();
    if (!fRTCPInterface.handleRead(pkt, maxPacketSize,
				   packetSize, fromAddress)) {
      break;
    }

    // Ignore the packet if it was looped-back from ourself:
    if (RTCPgs()->wasLoopedBackFromUs(envir(), fromAddress)) {
      // However, we still want to handle incoming RTCP packets from
      // *other processes* on the same machine.  To distinguish this
      // case from a true loop-back, check whether we've just sent a
      // packet of the same size.  (This check isn't perfect, but it seems
      // to be the best we can do.)
      if (fHaveJustSentPacket && fLastPacketSentSize == packetSize) {
	// This is a true loop-back:
	fHaveJustSentPacket = False;
	break; // ignore this packet
      }
    }

    if (fIsSSMSource) {
      // This packet was received via unicast.  'Reflect' it by resending
      // it to the multicast group.
      // NOTE: Denial-of-service attacks are possible here.
      // Users of this software may wish to add their own,
      // application-specific mechanism for 'authenticating' the
      // validity of this packet before reflecting it.
      fRTCPInterface.sendPacket(pkt, packetSize);
      fHaveJustSentPacket = True;
      fLastPacketSentSize = packetSize;
    }

#ifdef DEBUG
    fprintf(stderr, "[%p]saw incoming RTCP packet (from address %s, port %d)\n", this, our_inet_ntoa(fromAddress.sin_addr), ntohs(fromAddress.sin_port));
    unsigned char* p = pkt;
    for (unsigned i = 0; i < packetSize; ++i) {
      if (i%4 == 0) fprintf(stderr, " ");
      fprintf(stderr, "%02x", p[i]);
    }
    fprintf(stderr, "\n");
#endif
    int totPacketSize = IP_UDP_HDR_SIZE + packetSize;

    // Check the RTCP packet for validity:
    // It must at least contain a header (4 bytes), and this header
    // must be version=2, with no padding bit, and a payload type of
    // SR (200) or RR (201):
    if (packetSize < 4) break;
    unsigned rtcpHdr = ntohl(*(unsigned*)pkt);
    if ((rtcpHdr & 0xE0FE0000) != (0x80000000 | (RTCP_PT_SR<<16))) {
#ifdef DEBUG
      fprintf(stderr, "rejected bad RTCP packet: header 0x%08x\n", rtcpHdr);
#endif
      break;
    }

    // Process each of the individual RTCP 'subpackets' in (what may be)
    // a compound RTCP packet.
    unsigned reportSenderSSRC = 0;
    Boolean packetOK = False;
    while (1) {
      unsigned rc = (rtcpHdr>>24)&0x1F;
      unsigned pt = (rtcpHdr>>16)&0xFF;
      unsigned length = 4*(rtcpHdr&0xFFFF); // doesn't count hdr
      ADVANCE(4); // skip over the header
      if (length > packetSize) break;

      // Assume that each RTCP subpacket begins with a 4-byte SSRC:
      if (length < 4) break; length -= 4;
      reportSenderSSRC = ntohl(*(unsigned*)pkt); ADVANCE(4);

      Boolean subPacketOK = False;
      switch (pt) {
        case RTCP_PT_SR: {
#ifdef DEBUG
	  fprintf(stderr, "SR\n");
#endif
	  if (length < 20) break; length -= 20;

	  // Extract the NTP timestamp, and note this:
	  unsigned NTPmsw = ntohl(*(unsigned*)pkt); ADVANCE(4);
	  unsigned NTPlsw = ntohl(*(unsigned*)pkt); ADVANCE(4);
	  unsigned rtpTimestamp = ntohl(*(unsigned*)pkt); ADVANCE(4);
	  if (fSource != NULL) {
	    RTPReceptionStatsDB& receptionStats
	      = fSource->receptionStatsDB();
	    receptionStats.noteIncomingSR(reportSenderSSRC,
					  NTPmsw, NTPlsw, rtpTimestamp);
	  }
	  ADVANCE(8); // skip over packet count, octet count

	  // If a 'SR handler' was set, call it now:
	  if (fSRHandlerTask != NULL) (*fSRHandlerTask)(fSRHandlerClientData);

	  // The rest of the SR is handled like a RR (so, no "break;" here)
	}
        case RTCP_PT_RR: {
#ifdef DEBUG
	  fprintf(stderr, "RR\n");
#endif
	  unsigned reportBlocksSize = rc*(6*4);
	  if (length < reportBlocksSize) break;
	  length -= reportBlocksSize;

          if (fSink != NULL) {
	    // Use this information to update stats about our transmissions:
            RTPTransmissionStatsDB& transmissionStats = fSink->transmissionStatsDB();
            for (unsigned i = 0; i < rc; ++i) {
              unsigned senderSSRC = ntohl(*(unsigned*)pkt); ADVANCE(4);
              // We care only about reports about our own transmission, not others'
              if (senderSSRC == fSink->SSRC()) {
                unsigned lossStats = ntohl(*(unsigned*)pkt); ADVANCE(4);
                unsigned highestReceived = ntohl(*(unsigned*)pkt); ADVANCE(4);
                unsigned jitter = ntohl(*(unsigned*)pkt); ADVANCE(4);
                unsigned timeLastSR = ntohl(*(unsigned*)pkt); ADVANCE(4);
                unsigned timeSinceLastSR = ntohl(*(unsigned*)pkt); ADVANCE(4);
                transmissionStats.noteIncomingRR(reportSenderSSRC, fromAddress,
						 lossStats,
						 highestReceived, jitter,
						 timeLastSR, timeSinceLastSR);
              } else {
                ADVANCE(4*5);
              }
            }
          } else {
            ADVANCE(reportBlocksSize);
          }

	  if (pt == RTCP_PT_RR) { // i.e., we didn't fall through from 'SR'
	    // If a 'RR handler' was set, call it now:

	    // Specific RR handler:
	    if (fSpecificRRHandlerTable != NULL) {
	      netAddressBits fromAddr;
	      portNumBits fromPortNum;
	      if (tcpReadStreamSocketNum < 0) {
		// Normal case: We read the RTCP packet over UDP
		fromAddr = fromAddress.sin_addr.s_addr;
		fromPortNum = ntohs(fromAddress.sin_port);
	      } else {
		// Special case: We read the RTCP packet over TCP (interleaved)
		// Hack: Use the TCP socket and channel id to look up the handler
		fromAddr = tcpReadStreamSocketNum;
		fromPortNum = tcpReadStreamChannelId;
	      }
	      Port fromPort(fromPortNum);
	      RRHandlerRecord* rrHandler
		= (RRHandlerRecord*)(fSpecificRRHandlerTable->Lookup(fromAddr, (~0), fromPort));
	      if (rrHandler != NULL) {
		if (rrHandler->rrHandlerTask != NULL) {
		  (*(rrHandler->rrHandlerTask))(rrHandler->rrHandlerClientData);
		}
	      }
	    }

	    // General RR handler:
	    if (fRRHandlerTask != NULL) (*fRRHandlerTask)(fRRHandlerClientData);
	  }

	  subPacketOK = True;
	  typeOfPacket = PACKET_RTCP_REPORT;
	  break;
	}
        case RTCP_PT_BYE: {
#ifdef DEBUG
	  fprintf(stderr, "BYE\n");
#endif
	  // If a 'BYE handler' was set, call it now:
	  TaskFunc* byeHandler = fByeHandlerTask;
	  if (byeHandler != NULL
	      && (!fByeHandleActiveParticipantsOnly
		  || (fSource != NULL
		      && fSource->receptionStatsDB().lookup(reportSenderSSRC) != NULL)
		  || (fSink != NULL
		      && fSink->transmissionStatsDB().lookup(reportSenderSSRC) != NULL))) {
	    fByeHandlerTask = NULL;
	        // we call this only once by default
	    (*byeHandler)(fByeHandlerClientData);
	  }

	  // We should really check for & handle >1 SSRCs being present #####

	  subPacketOK = True;
	  typeOfPacket = PACKET_BYE;
	  break;
	}
	// Later handle SDES, APP, and compound RTCP packets #####
        default:
#ifdef DEBUG
	  fprintf(stderr, "UNSUPPORTED TYPE(0x%x)\n", pt);
#endif
	  subPacketOK = True;
	  break;
      }
      if (!subPacketOK) break;

      // need to check for (& handle) SSRC collision! #####

#ifdef DEBUG
      fprintf(stderr, "validated RTCP subpacket (type %d): %d, %d, %d, 0x%08x\n", typeOfPacket, rc, pt, length, reportSenderSSRC);
#endif

      // Skip over any remaining bytes in this subpacket:
      ADVANCE(length);

      // Check whether another RTCP 'subpacket' follows:
      if (packetSize == 0) {
	packetOK = True;
	break;
      } else if (packetSize < 4) {
#ifdef DEBUG
	fprintf(stderr, "extraneous %d bytes at end of RTCP packet!\n", packetSize);
#endif
	break;
      }
      rtcpHdr = ntohl(*(unsigned*)pkt);
      if ((rtcpHdr & 0xC0000000) != 0x80000000) {
#ifdef DEBUG
	fprintf(stderr, "bad RTCP subpacket: header 0x%08x\n", rtcpHdr);
#endif
	break;
      }
    }

    if (!packetOK) {
#ifdef DEBUG
      fprintf(stderr, "rejected bad RTCP subpacket: header 0x%08x\n", rtcpHdr);
#endif
      break;
    } else {
#ifdef DEBUG
      fprintf(stderr, "validated entire RTCP packet\n");
#endif
    }

    onReceive(typeOfPacket, totPacketSize, reportSenderSSRC);
  } while (0);
}
示例#28
0
void TcpSocketImpl::ioReady(uint32_t events)
{
    switch(getState())
    {
        case ST_CONNECTING:
        {
            if(events & KUMA_EV_ERROR) {
                KUMA_ERRXTRACE("ioReady, KUMA_EV_ERROR, events="<<events
                              <<", err="<<getLastError()<<", state="<<getState());
                onConnect(KUMA_ERROR_POLLERR);
            } else {
                bool destroyed = false;
                destroy_flag_ptr_ = &destroyed;
                onConnect(KUMA_ERROR_NOERR);
                if(destroyed) {
                    return ;
                }
                destroy_flag_ptr_ = nullptr;
                if((events & KUMA_EV_READ)) {
                    onReceive(0);
                }
            }
            break;
        }
            
        case ST_OPEN:
        {
#ifdef KUMA_HAS_OPENSSL
            if(ssl_handler_ && ssl_handler_->getState() == SslHandler::SslState::SSL_HANDSHAKE) {
                int err = KUMA_ERROR_NOERR;
                if(events & KUMA_EV_ERROR) {
                    err = KUMA_ERROR_POLLERR;
                } else {
                    SslHandler::SslState ssl_state = ssl_handler_->doSslHandshake();
                    if(SslHandler::SslState::SSL_ERROR == ssl_state) {
                        err = KUMA_ERROR_SSL_FAILED;
                    } else if(SslHandler::SslState::SSL_HANDSHAKE == ssl_state) {
                        return;
                    }
                }
                if(cb_connect_) {
                    EventCallback cb_connect = std::move(cb_connect_);
                    cb_connect(err);
                } else if(err != KUMA_ERROR_NOERR) {
                    onClose(err);
                } else {
                    events |= KUMA_EV_WRITE; // notify writable
                }
                if(err != KUMA_ERROR_NOERR) {
                    return;
                }
            }
#endif
            bool destroyed = false;
            destroy_flag_ptr_ = &destroyed;
            if(events & KUMA_EV_READ) {// handle EPOLLIN firstly
                onReceive(0);
            }
            if(destroyed) {
                return;
            }
            destroy_flag_ptr_ = nullptr;
            if((events & KUMA_EV_ERROR) && getState() == ST_OPEN) {
                KUMA_ERRXTRACE("ioReady, KUMA_EV_ERROR, events="<<events
                              <<", err="<<getLastError()<<", state="<<getState());
                onClose(KUMA_ERROR_POLLERR);
                break;
            }
            if((events & KUMA_EV_WRITE) && getState() == ST_OPEN) {
                onSend(0);
            }
            break;
        }
        default:
            //KUMA_WARNXTRACE("ioReady, invalid state="<<getState()
            //	<<", events="<<events);
            break;
    }
}