예제 #1
0
파일: room.cpp 프로젝트: namkazt/citra
void Room::RoomImpl::HandleJoinRequest(const ENetEvent* event) {
    Packet packet;
    packet.Append(event->packet->data, event->packet->dataLength);
    packet.IgnoreBytes(sizeof(u8)); // Ignore the message type
    std::string nickname;
    packet >> nickname;

    MacAddress preferred_mac;
    packet >> preferred_mac;

    u32 client_version;
    packet >> client_version;

    std::string pass;
    packet >> pass;

    if (pass != password) {
        SendWrongPassword(event->peer);
        return;
    }

    if (!IsValidNickname(nickname)) {
        SendNameCollision(event->peer);
        return;
    }

    if (preferred_mac != NoPreferredMac) {
        // Verify if the preferred mac is available
        if (!IsValidMacAddress(preferred_mac)) {
            SendMacCollision(event->peer);
            return;
        }
    } else {
        // Assign a MAC address of this client automatically
        preferred_mac = GenerateMacAddress();
    }

    if (client_version != network_version) {
        SendVersionMismatch(event->peer);
        return;
    }

    // At this point the client is ready to be added to the room.
    Member member{};
    member.mac_address = preferred_mac;
    member.nickname = nickname;
    member.peer = event->peer;

    {
        std::lock_guard<std::mutex> lock(member_mutex);
        members.push_back(std::move(member));
    }

    // Notify everyone that the room information has changed.
    BroadcastRoomInformation();
    SendJoinSuccess(event->peer, preferred_mac);
}
예제 #2
0
파일: room.cpp 프로젝트: citra-emu/citra
void Room::RoomImpl::HandleModKickPacket(const ENetEvent* event) {
    if (!HasModPermission(event->peer)) {
        SendModPermissionDenied(event->peer);
        return;
    }

    Packet packet;
    packet.Append(event->packet->data, event->packet->dataLength);
    packet.IgnoreBytes(sizeof(u8)); // Ignore the message type

    std::string nickname;
    packet >> nickname;

    std::string username;
    {
        std::lock_guard lock(member_mutex);
        const auto target_member =
            std::find_if(members.begin(), members.end(),
                         [&nickname](const auto& member) { return member.nickname == nickname; });
        if (target_member == members.end()) {
            SendModNoSuchUser(event->peer);
            return;
        }

        // Notify the kicked member
        SendUserKicked(target_member->peer);

        username = target_member->user_data.username;

        enet_peer_disconnect(target_member->peer, 0);
        members.erase(target_member);
    }

    // Announce the change to all clients.
    SendStatusMessage(IdMemberKicked, nickname, username);
    BroadcastRoomInformation();
}
예제 #3
0
파일: room.cpp 프로젝트: citra-emu/citra
void Room::RoomImpl::HandleModUnbanPacket(const ENetEvent* event) {
    if (!HasModPermission(event->peer)) {
        SendModPermissionDenied(event->peer);
        return;
    }

    Packet packet;
    packet.Append(event->packet->data, event->packet->dataLength);
    packet.IgnoreBytes(sizeof(u8)); // Ignore the message type

    std::string address;
    packet >> address;

    bool unbanned = false;
    {
        std::lock_guard lock(ban_list_mutex);

        auto it = std::find(username_ban_list.begin(), username_ban_list.end(), address);
        if (it != username_ban_list.end()) {
            unbanned = true;
            username_ban_list.erase(it);
        }

        it = std::find(ip_ban_list.begin(), ip_ban_list.end(), address);
        if (it != ip_ban_list.end()) {
            unbanned = true;
            ip_ban_list.erase(it);
        }
    }

    if (unbanned) {
        SendStatusMessage(IdAddressUnbanned, address, "");
    } else {
        SendModNoSuchUser(event->peer);
    }
}
예제 #4
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;
}
예제 #5
0
void SceneryManager::SendPageRequest(const SceneryPageRequest& request, std::list<PacketManager::PACKET_PAIR>& outgoingPackets)
{
	TimeObject to("SceneryManager::SendPageRequest");

	STRINGLIST queryRows;
	Packet data;
	int wpos = 0;
	char idBuf[32];

	GetThread("SceneryManager::HandlePageRequests[page]");

	SceneryPage *page = GetOrCreatePage(request.zone, request.x, request.y);

	if(page == NULL)
	{
		g_Log.AddMessageFormat("[ERROR] SendPageRequest retrieved NULL page");
		
		wpos = PrepExt_QueryResponseNull(prepBuf, request.queryID);
		data.Assign(prepBuf, wpos);
		outgoingPackets.push_back(PacketManager::PACKET_PAIR(request.socket, data));

		ReleaseThread();
		return;
	}

	SceneryPage::SCENERY_IT it;
	for(it = page->mSceneryList.begin(); it != page->mSceneryList.end(); ++it)
	{
		//Build the list of scenery ID strings to form the response to the scenery.list query.
		//No need to save row data unless the query is required.
		if(request.skipQuery == false)
		{
			sprintf(idBuf, "%d", it->second.ID);
			queryRows.push_back(idBuf);
		}
		
		wpos += PrepExt_UpdateScenery(&prepBuf[wpos], &it->second);
		if(wpos > Global::MAX_SEND_CHUNK_SIZE)
		{
			data.Assign(prepBuf, wpos);
			outgoingPackets.push_back(PacketManager::PACKET_PAIR(request.socket, data));
			wpos = 0;
		}
	}
	if(wpos > 0)
	{
		data.Assign(prepBuf, wpos);
		outgoingPackets.push_back(PacketManager::PACKET_PAIR(request.socket, data));
	}

	//Done accessing the scenery data itself, no need to hold the thread any longer.
	//All the remaining stuff is using a resident list of query IDs to form into a response
	//packet.
	ReleaseThread();

	//Now build the query response if the client has requested it.
	if(request.skipQuery == true)
		return;

	//Reset the packet buffer and data.
	wpos = 0;
	data.Clear();

	//Get the size of the response
	int sizeReq = 6;  //Query ID (4 bytes) + row count (2 bytes)
	for(size_t s = 0; s < queryRows.size(); s++)
	{
		sizeReq++;  //1 string per row
		sizeReq += PutStringReq(queryRows[s].c_str());
	}

	wpos += PutByte(&prepBuf[wpos], 1);         //_handleQueryResultMsg
	wpos += PutShort(&prepBuf[wpos], sizeReq);  //Message size

	wpos += PutInteger(&prepBuf[wpos], request.queryID);
	wpos += PutShort(&prepBuf[wpos], queryRows.size());
	for(size_t s = 0; s < queryRows.size(); s++)
	{
		wpos += PutByte(&prepBuf[wpos], 1);
		wpos += PutStringUTF(&prepBuf[wpos], queryRows[s].c_str());
		if(wpos > Global::MAX_SEND_CHUNK_SIZE)
		{
			data.Append(prepBuf, wpos);
			wpos = 0;
		}
	}
	if(wpos > 0)
		data.Append(prepBuf, wpos);

	outgoingPackets.push_back(PacketManager::PACKET_PAIR(request.socket, data));
}
예제 #6
0
파일: room.cpp 프로젝트: citra-emu/citra
void Room::RoomImpl::HandleModBanPacket(const ENetEvent* event) {
    if (!HasModPermission(event->peer)) {
        SendModPermissionDenied(event->peer);
        return;
    }

    Packet packet;
    packet.Append(event->packet->data, event->packet->dataLength);
    packet.IgnoreBytes(sizeof(u8)); // Ignore the message type

    std::string nickname;
    packet >> nickname;

    std::string username;
    std::string ip;

    {
        std::lock_guard lock(member_mutex);
        const auto target_member =
            std::find_if(members.begin(), members.end(),
                         [&nickname](const auto& member) { return member.nickname == nickname; });
        if (target_member == members.end()) {
            SendModNoSuchUser(event->peer);
            return;
        }

        // Notify the banned member
        SendUserBanned(target_member->peer);

        nickname = target_member->nickname;
        username = target_member->user_data.username;

        char ip_raw[256];
        enet_address_get_host_ip(&target_member->peer->address, ip_raw, sizeof(ip_raw) - 1);
        ip = ip_raw;

        enet_peer_disconnect(target_member->peer, 0);
        members.erase(target_member);
    }

    {
        std::lock_guard lock(ban_list_mutex);

        if (!username.empty()) {
            // Ban the forum username
            if (std::find(username_ban_list.begin(), username_ban_list.end(), username) ==
                username_ban_list.end()) {

                username_ban_list.emplace_back(username);
            }
        }

        // Ban the member's IP as well
        if (std::find(ip_ban_list.begin(), ip_ban_list.end(), ip) == ip_ban_list.end()) {
            ip_ban_list.emplace_back(ip);
        }
    }

    // Announce the change to all clients.
    SendStatusMessage(IdMemberBanned, nickname, username);
    BroadcastRoomInformation();
}
예제 #7
0
파일: room.cpp 프로젝트: citra-emu/citra
void Room::RoomImpl::HandleJoinRequest(const ENetEvent* event) {
    {
        std::lock_guard lock(member_mutex);
        if (members.size() >= room_information.member_slots) {
            SendRoomIsFull(event->peer);
            return;
        }
    }
    Packet packet;
    packet.Append(event->packet->data, event->packet->dataLength);
    packet.IgnoreBytes(sizeof(u8)); // Ignore the message type
    std::string nickname;
    packet >> nickname;

    std::string console_id_hash;
    packet >> console_id_hash;

    MacAddress preferred_mac;
    packet >> preferred_mac;

    u32 client_version;
    packet >> client_version;

    std::string pass;
    packet >> pass;

    std::string token;
    packet >> token;

    if (pass != password) {
        SendWrongPassword(event->peer);
        return;
    }

    if (!IsValidNickname(nickname)) {
        SendNameCollision(event->peer);
        return;
    }

    if (preferred_mac != NoPreferredMac) {
        // Verify if the preferred mac is available
        if (!IsValidMacAddress(preferred_mac)) {
            SendMacCollision(event->peer);
            return;
        }
    } else {
        // Assign a MAC address of this client automatically
        preferred_mac = GenerateMacAddress();
    }

    if (!IsValidConsoleId(console_id_hash)) {
        SendConsoleIdCollision(event->peer);
        return;
    }

    if (client_version != network_version) {
        SendVersionMismatch(event->peer);
        return;
    }

    // At this point the client is ready to be added to the room.
    Member member{};
    member.mac_address = preferred_mac;
    member.console_id_hash = console_id_hash;
    member.nickname = nickname;
    member.peer = event->peer;

    std::string uid;
    {
        std::lock_guard lock(verify_UID_mutex);
        uid = verify_UID;
    }
    member.user_data = verify_backend->LoadUserData(uid, token);

    {
        std::lock_guard lock(ban_list_mutex);

        // Check username ban
        if (!member.user_data.username.empty() &&
            std::find(username_ban_list.begin(), username_ban_list.end(),
                      member.user_data.username) != username_ban_list.end()) {

            SendUserBanned(event->peer);
            return;
        }

        // Check IP ban
        char ip_raw[256];
        enet_address_get_host_ip(&event->peer->address, ip_raw, sizeof(ip_raw) - 1);
        std::string ip = ip_raw;

        if (std::find(ip_ban_list.begin(), ip_ban_list.end(), ip) != ip_ban_list.end()) {
            SendUserBanned(event->peer);
            return;
        }
    }

    // Notify everyone that the user has joined.
    SendStatusMessage(IdMemberJoin, member.nickname, member.user_data.username);

    {
        std::lock_guard lock(member_mutex);
        members.push_back(std::move(member));
    }

    // Notify everyone that the room information has changed.
    BroadcastRoomInformation();
    if (HasModPermission(event->peer)) {
        SendJoinSuccessAsMod(event->peer, preferred_mac);
    } else {
        SendJoinSuccess(event->peer, preferred_mac);
    }
}