Example #1
0
UInt32 RTMFP::Unpack(PacketReader& packet) {
	packet.reset();
	UInt32 id=0;
	for(int i=0;i<3;++i)
		id ^= packet.read32();
	packet.reset(4);
	return id;
}
Example #2
0
bool WSSession::buildPacket(PacketReader& packet) {
	if (packet.available()<2)
		return false;
	UInt8 type = packet.read8() & 0x0F;
	UInt8 lengthByte = packet.read8();

	UInt32 size=lengthByte&0x7f;
	if (size==127) {
		if (packet.available()<8)
			return false;
		size = (UInt32)packet.read64();
	} else if (size==126) {
		if (packet.available()<2)
			return false;
		size = packet.read16();
	}

	if(lengthByte&0x80)
		size += 4;

	if (packet.available()<size)
		return false;

	packet.shrink(size);

	if (lengthByte & 0x80) {
		shared_ptr<WSUnmasking> pWSUnmasking(new WSUnmasking(invoker, packet.current(),packet.available(), type));
		decode<WSUnmasking>(pWSUnmasking);
	} else {
		packet.reset(packet.position()-1);
		*(UInt8*)packet.current() = type;
	}
	return true;
}
Example #3
0
void Publication::pushRawPacket(UInt8 type,PacketReader& packet) {
	list<Listener*>::const_iterator it;
	int pos = packet.position();
	for(it=_listeners.begin();it!=_listeners.end();++it) {
		(*it)->pushRawPacket(type,packet);
		packet.reset(pos);
	}
}
Example #4
0
void Publication::pushVideoPacket(PacketReader& packet) {
	UInt32 time = packet.read32(); // TODO?
	list<Listener*>::const_iterator it;
	int pos = packet.position();
	for(it=_listeners.begin();it!=_listeners.end();++it) {
		(*it)->pushVideoPacket(packet);
		packet.reset(pos);
	}
}
Example #5
0
bool RTMFP::Decode(AESEngine& aesDecrypt,PacketReader& packet) {
	// Decrypt
	aesDecrypt.process(packet.current(),packet.current(),packet.available());

	// Check the first 2 CRC bytes 
	packet.reset(4);
	UInt16 sum = packet.read16();
	return (sum == CheckSum(packet));
}
Example #6
0
void ServerConnection::packetHandler(PacketReader& packet) {

	UInt8 marker = packet.read8();
	if(marker!=0x0b) {
		ERROR("ServerConnection with an unknown %u marker, it should be 0x0b",marker);
		return;
	}

	packet.next(2);
	UInt8 id = packet.read8();
	switch(id) {
		case 0x71: {
			packet.next(2);
			string tag;
			packet.readString8(tag);
			map<string,P2PHandshakerAddress>::iterator it = _p2pHandshakers.find(tag);
			if(it==_p2pHandshakers.end()) {
				ERROR("Unknown ServerConnection tag %s on P2P handshake",tag.c_str());
				break;
			}

			(SocketAddress&)_handshake.peer.address = it->second;
			packet.reset(0);
			PacketWriter writer(packet.current(),packet.available()+16); // +16 for futur 0xFFFF padding
			writer.clear(packet.available());
			_handshake.send(writer);
			_p2pHandshakers.erase(it);

			break;
		}
		case 0x40: {
			if(!_connected) {
				// Edge hello response
				_connected=true;
				return;
			}
			// Edge keepalive
			PacketWriter& packet(writer());
			packet.write8(0x41);
			packet.write16(0);
			flush();
			INFO("Keepalive RTMFP server");
			break;
		}
		case 0x45: {
			// Server is death!
			(bool&)died=true;
			break;
		}
		default:
			ERROR("Unkown ServerConnection packet id %u",id);
	}


}
Example #7
0
void Listener::pushDataPacket(const string& name,PacketReader& packet) {
	// TODO create _dataWriter ??
	if(_unbuffered) {
		UInt16 offset = name.size()+9;
		if(packet.position()>=offset) {
			packet.reset(packet.position()-offset);
			_writer.writeUnbufferedMessage(packet.current(),packet.available());
			return;
		}
		WARN("Written unbuffered impossible, it requires %u head bytes available on PacketReader given",offset);
	}
	StreamCopier::copyStream(packet.stream(),_writer.writeAMFPacket(name).writer.stream());
}
Example #8
0
	void write(UInt32 time,PacketReader& data,bool unbuffered) {
	//	if(_type==0x08)
	//		time=0;
	/*	if(_type==0x09)
			TRACE("Video timestamp : %u",_time)
		else
			TRACE("Audio timestamp : %u",_time);*/
		if(unbuffered) {
			if(data.position()>=5) {
				data.reset(data.position()-5);
				PacketWriter writer(data.current(),5);
				writer.write8(_type);
				writer.write32(time);
				writeUnbufferedMessage(data.current(),data.available(),data.current(),5);
				return;
			}
			WARN("Written unbuffered impossible, it requires 5 head bytes available on PacketReader given");
		}
		BinaryWriter& out = writeRawMessage(true);
		out.write8(_type);
		out.write32(time);
		StreamCopier::copyStream(data.stream(),out.stream());

	}
Example #9
0
void RTMFPWriter::acknowledgment(PacketReader& packet) {

	UInt64 bufferSize = packet.read7BitLongValue(); // TODO use this value in reliability mechanism?
	
	if(bufferSize==0) {
		// In fact here, we should send a 0x18 message (with id flow),
		// but it can create a loop... We prefer the following behavior
		fail("Negative acknowledgment");
		return;
	}

	UInt64 stageAckPrec = _stageAck;
	UInt64 stageReaden = packet.read7BitLongValue();
	UInt64 stage = _stageAck+1;

	if(stageReaden>_stage) {
		ERROR("Acknowledgment received ",stageReaden," superior than the current sending stage ",_stage," on writer ",id);
		_stageAck = _stage;
	} else if(stageReaden<=_stageAck) {
		// already acked
		if(packet.available()==0)
			DEBUG("Acknowledgment ",stageReaden," obsolete on writer ",id);
	} else
		_stageAck = stageReaden;

	UInt64 maxStageRecv = stageReaden;
	UInt32 pos=packet.position();

	while(packet.available()>0)
		maxStageRecv += packet.read7BitLongValue()+packet.read7BitLongValue()+2;
	if(pos != packet.position()) {
		// TRACE(stageReaden,"..x"Util::FormatHex(reader.current(),reader.available()));
		packet.reset(pos);
	}

	UInt64 lostCount = 0;
	UInt64 lostStage = 0;
	bool repeated = false;
	bool header = true;
	bool stop=false;

	auto it=_messagesSent.begin();
	while(!stop && it!=_messagesSent.end()) {
		RTMFPMessage& message(**it);

		if(message.fragments.empty()) {
			CRITIC("RTMFPMessage ",(stage+1)," is bad formatted on fowWriter ",id);
			++it;
			continue;
		}

		map<UInt32,UInt64>::iterator itFrag=message.fragments.begin();
		while(message.fragments.end()!=itFrag) {
			
			// ACK
			if(_stageAck>=stage) {
				message.fragments.erase(message.fragments.begin());
				itFrag=message.fragments.begin();
				++_ackCount;
				++stage;
				continue;
			}

			// Read lost informations
			while(!stop) {
				if(lostCount==0) {
					if(packet.available()>0) {
						lostCount = packet.read7BitLongValue()+1;
						lostStage = stageReaden+1;
						stageReaden = lostStage+lostCount+packet.read7BitLongValue();
					} else {
						stop=true;
						break;
					}
				}
				// check the range
				if(lostStage>_stage) {
					// Not yet sent
					ERROR("Lost information received ",lostStage," have not been yet sent on writer ",id);
					stop=true;
				} else if(lostStage<=_stageAck) {
					// already acked
					--lostCount;
					++lostStage;
					continue;
				}
				break;
			}
			if(stop)
				break;
			
			// lostStage > 0 and lostCount > 0

			if(lostStage!=stage) {
				if(repeated) {
					++stage;
					++itFrag;
					header=true;
				} else // No repeated, it means that past lost packet was not repeatable, we can ack this intermediate received sequence
					_stageAck = stage;
				continue;
			}

			/// Repeat message asked!
			if(!message.repeatable) {
				if(repeated) {
					++itFrag;
					++stage;
					header=true;
				} else {
					INFO("RTMFPWriter ",id," : message ",stage," lost");
					--_ackCount;
					++_lostCount;
					_stageAck = stage;
				}
				--lostCount;
				++lostStage;
				continue;
			}

			repeated = true;
			// Don't repeate before that the receiver receives the itFrag->second sending stage
			if(itFrag->second >= maxStageRecv) {
				++stage;
				header=true;
				--lostCount;
				++lostStage;
				++itFrag;
				continue;
			}

			// Repeat message

			DEBUG("RTMFPWriter ",id," : stage ",stage," repeated");
			UInt32 fragment(itFrag->first);
			itFrag->second = _stage; // Save actual stage sending to wait that the receiver gets it before to retry
			UInt32 contentSize = message.size() - fragment; // available
			++itFrag;

			// Compute flags
			UInt8 flags = 0;
			if(fragment>0)
				flags |= MESSAGE_WITH_BEFOREPART; // fragmented
			if(itFrag!=message.fragments.end()) {
				flags |= MESSAGE_WITH_AFTERPART;
				contentSize = itFrag->first - fragment;
			}

			UInt32 size = contentSize+4;
			UInt32 availableToWrite(_band.availableToWrite());
			if(!header && size>availableToWrite) {
				_band.flush();
				header=true;
			}

			if(header)
				size+=headerSize(stage);

			if(size>availableToWrite)
				_band.flush();

			// Write packet
			size-=3;  // type + timestamp removed, before the "writeMessage"
			flush(_band.writeMessage(header ? 0x10 : 0x11,(UInt16)size)
				,stage,flags,header,message,fragment,contentSize);
			header=false;
			--lostCount;
			++lostStage;
			++stage;
		}

		if(message.fragments.empty()) {
			if(message.repeatable)
				--_repeatable;
			if(_ackCount || _lostCount) {
				_qos.add(_lostCount / (_lostCount + _ackCount));
				_ackCount=_lostCount=0;
			}
			
			delete *it;
			it=_messagesSent.erase(it);
		} else
			++it;
	
	}

	if(lostCount>0 && packet.available()>0)
		ERROR("Some lost information received have not been yet sent on writer ",id);


	// rest messages repeatable?
	if(_repeatable==0)
		_trigger.stop();
	else if(_stageAck>stageAckPrec || repeated)
		_trigger.reset();
}
Example #10
0
bool RTMFP::ReadCRC(PacketReader& packet) {
	// Check the first 2 CRC bytes 
	packet.reset(4);
	UInt16 sum = packet.read16();
	return (sum == CheckSum(packet));
}
Example #11
0
void MobHandler::monsterControl(Player *player, PacketReader &packet) {
	int32_t mobid = packet.get<int32_t>();

	Mob *mob = Maps::getMap(player->getMap())->getMob(mobid);

	if (mob == nullptr || mob->getControlStatus() == Mobs::ControlStatus::ControlNone) {
		return;
	}

	int16_t moveid = packet.get<int16_t>();
	bool useskill = packet.getBool();
	int8_t skill = packet.get<int8_t>();
	uint8_t realskill = 0;
	uint8_t level = 0;
	Pos projectiletarget = packet.getPos();
	packet.skipBytes(5); // 1 byte of always 0?, 4 bytes of always 1 or always 0?
	Pos spot = packet.getPos();

	MovementHandler::parseMovement(mob, packet);

	if (useskill && (skill == -1 || skill == 0)) {
		if (!(mob->hasStatus(StatusEffects::Mob::Freeze) || mob->hasStatus(StatusEffects::Mob::Stun) || mob->hasStatus(StatusEffects::Mob::ShadowWeb))) {
			uint8_t size = mob->getSkillCount();
			bool used = false;
			if (size) {
				bool stop = false;
				uint8_t rand = Randomizer::Instance()->randChar(size - 1);
				MobSkillInfo *info = MobDataProvider::Instance()->getMobSkill(mob->getMobId(), rand);
				realskill = info->skillId;
 				level = info->level;
				MobSkillLevelInfo *mobskill = SkillDataProvider::Instance()->getMobSkill(realskill, level);
				switch (realskill) {
					case MobSkills::WeaponAttackUp:
					case MobSkills::WeaponAttackUpAoe:
						stop = mob->hasStatus(StatusEffects::Mob::Watk);
						break;
					case MobSkills::MagicAttackUp:
					case MobSkills::MagicAttackUpAoe:
						stop = mob->hasStatus(StatusEffects::Mob::Matk);
						break;
					case MobSkills::WeaponDefenseUp:
					case MobSkills::WeaponDefenseUpAoe:
						stop = mob->hasStatus(StatusEffects::Mob::Wdef);
						break;
					case MobSkills::MagicDefenseUp:
					case MobSkills::MagicDefenseUpAoe:
						stop = mob->hasStatus(StatusEffects::Mob::Mdef);
						break;
					case MobSkills::WeaponImmunity:
					case MobSkills::MagicImmunity:
					case MobSkills::WeaponDamageReflect:
					case MobSkills::MagicDamageReflect:
						stop = mob->hasImmunity();
						break;
					case MobSkills::McSpeedUp:
						stop = mob->hasStatus(StatusEffects::Mob::Speed);
						break;
					case MobSkills::Summon: {
						int16_t limit = mobskill->limit;
						if (limit == 5000) // Custom limit based on number of players on map
							limit = 30 + Maps::getMap(mob->getMapId())->getNumPlayers() * 2;
						if (mob->getSpawnCount() >= limit)
							stop = true;
						break;
					}
				}
				if (!stop) {
					time_t now = time(0);
					time_t ls = mob->getLastSkillUse(realskill);
					if (ls == 0 || ((int32_t)(now - ls) > mobskill->interval)) {
						mob->setLastSkillUse(realskill, now);
						int64_t reqhp = mob->getHp() * 100;
						reqhp /= mob->getMaxHp();
						if ((uint8_t)(reqhp) <= mobskill->hp) {
							if (info->effectAfter == 0) {
								handleMobSkill(mob, realskill, level, mobskill);
							}
							else {
								new Timer::Timer(bind(&MobHandler::handleMobSkill, mob, realskill, level, mobskill),
									Timer::Id(Timer::Types::MobSkillTimer, mob->getMobId(), mob->getCounter()),
									mob->getTimers(), Timer::Time::fromNow(info->effectAfter));
							}
							used = true;
						}
					}
				}
			}
			if (!used) {
				realskill = 0;
				level = 0;
			}
		}
	}
	MobsPacket::moveMobResponse(player, mobid, moveid, useskill, mob->getMp(), realskill, level);
	packet.reset(19);
	MobsPacket::moveMob(player, mobid, useskill, skill, projectiletarget, packet.getBuffer(), packet.getBufferLength());
}
Example #12
0
void InventoryHandler::useCashItem(Player *player, PacketReader &packet) {
	packet.get<int8_t>(); // Type
	packet.skipBytes(1);
	int32_t itemid = packet.get<int32_t>();

	if (!player->getInventory()->getItemAmount(itemid)) {
		// Hacking
		return;
	}

	bool used = false;
	if (GameLogicUtilities::getItemType(itemid) == Items::Types::WeatherCash) {
		string message = packet.getString();
		if (!player->updateTickCount(packet.get<int32_t>())) {
			// Tickcount was the same or less than 100 of the difference.
			return;
		}
		if (message.length() <= 35) {
			Map *map = Maps::getMap(player->getMap());
			message = player->getName() + " 's message : " + message;
			used = map->createWeather(player, false, Items::WeatherTime, itemid, message);
		}
	}
	else if (GameLogicUtilities::getItemType(itemid) == Items::Types::CashPetFood) {
		// Pet food.
		Pet *pet = player->getPets()->getSummoned(0);
		if (pet != nullptr) {
			if (pet->getFullness() < Stats::MaxFullness) {
				PetsPacket::showAnimation(player, pet, 1);
				pet->modifyFullness(Stats::MaxFullness, false);
				pet->addCloseness(100); // All cash pet food gives 100 closeness.
				used = true;
			}
		}
	}
	else {
		switch (itemid) {
			case Items::TeleportRock:
			case Items::TeleportCoke:
			case Items::VipRock: // Only occurs when you actually try to move somewhere
				used = handleRockTeleport(player, itemid, packet);
				break;
			case Items::FirstJobSpReset:
			case Items::SecondJobSpReset:
			case Items::ThirdJobSpReset:
			case Items::FourthJobSpReset: {
				int32_t toskill = packet.get<int32_t>();
				int32_t fromskill = packet.get<int32_t>();
				if (!player->getSkills()->addSkillLevel(fromskill, -1, true)) {
					// Hacking
					return;
				}
				if (!player->getSkills()->addSkillLevel(toskill, 1, true)) {
					// Hacking
					return;
				}
				used = true;
				break;
			}
			case Items::ApReset: {
				int32_t tostat = packet.get<int32_t>();
				int32_t fromstat = packet.get<int32_t>();
				player->getStats()->addStat(tostat, 1, true);
				player->getStats()->addStat(fromstat, -1, true);
				used = true;
				break;
			}
			case Items::Megaphone: {
				string msg = player->getMedalName() + " : " + packet.getString();
				InventoryPacket::showMegaphone(player, msg);
				used = true;
				break;
			}
			case Items::SuperMegaphone: {
				string msg = player->getMedalName() + " : " + packet.getString();
				bool whisper = packet.getBool();
				InventoryPacket::showSuperMegaphone(player, msg, whisper);
				used = true;
				break;
			}
			case Items::DiabloMessenger:
			case Items::Cloud9Messenger:
			case Items::LoveholicMessenger: {
				string msg = packet.getString();
				string msg2 = packet.getString();
				string msg3 = packet.getString();
				string msg4 = packet.getString();

				InventoryPacket::showMessenger(player, msg, msg2, msg3, msg4, packet.getBuffer(), packet.getBufferLength(), itemid);
				used = true;
				break;
			}
			case Items::ItemMegaphone: {
				string msg = player->getMedalName() + " : " + packet.getString();
				bool whisper = packet.getBool();
				Item *item = nullptr;
				if (packet.getBool()) {
					int8_t inv = (int8_t) packet.get<int32_t>();
					int16_t slot = (int16_t) packet.get<int32_t>();
					item = player->getInventory()->getItem(inv, slot);
					if (item == nullptr) {
						// Hacking
						return;
					}
				}
				InventoryPacket::showItemMegaphone(player, msg, whisper, item);
				used = true;
				break;
			}
			case Items::ArtMegaphone: {
				int8_t lines = packet.get<int8_t>();
				if (lines < 1 || lines > 3) {
					// Hacking
					return;
				}
				string text[3];
				for (int8_t i = 0; i < lines; i++) {
					text[i] = player->getMedalName() + " : " + packet.getString();
				}
				bool whisper = packet.getBool();
				InventoryPacket::showTripleMegaphone(player, lines, text[0], text[1], text[2], whisper);
				used = true;
				break;
			}
			case Items::PetNameTag: {
				string name = packet.getString();
				PetHandler::changeName(player, name);
				used = true;
				break;
			}
			case Items::ItemNameTag: {
				int16_t slot = packet.get<int16_t>();
				if (slot != 0) {
					Item *item = player->getInventory()->getItem(Inventories::EquipInventory, slot);
					if (item == nullptr) {
						// Hacking or failure, dunno
						return;
					}
					item->setName(player->getName());
					InventoryPacket::addNewItem(player, Inventories::EquipInventory, slot, item, true);
					used = true;
				}
				break;
			}
			case Items::ItemLock: 
			case Items::ScissorsOfKarma: {
				int8_t inventory = (int8_t) packet.get<int32_t>();
				int16_t slot = (int16_t) packet.get<int32_t>();
				if (slot != 0) {
					Item *item = player->getInventory()->getItem(inventory, slot);
					if (item == nullptr || (itemid == Items::ItemLock && item->hasLock()) || item->hasTradeBlock() || (itemid == Items::ScissorsOfKarma && item->hasKarma())) {
						// Hacking or failure, dunno
						return;
					}
					ItemInfo *info = ItemDataProvider::Instance()->getItemInfo(item->getId());
					if (itemid == Items::ScissorsOfKarma && info->karmascissors) {
						// Hacking
						return;
					}

					switch (itemid) {
						case Items::ItemLock: item->setLock(true); break;
						case Items::ScissorsOfKarma: item->setKarma(true); break;
					}

					InventoryPacket::addNewItem(player, inventory, slot, item, true);
					used = true;
				}
				break;
			}
			case Items::MapleTvMessenger: 
			case Items::Megassenger: {
				bool hasreceiver = (packet.get<int8_t>() == 3);
				bool show_whisper = (itemid == Items::Megassenger ? packet.getBool() : false);
				Player *receiver = PlayerDataProvider::Instance()->getPlayer(packet.getString());
				int32_t time = 15;

				if ((hasreceiver && receiver != nullptr) || (!hasreceiver && receiver == nullptr)) {
					string msg = packet.getString();
					string msg2 = packet.getString();
					string msg3 = packet.getString();
					string msg4 = packet.getString();
					string msg5 = packet.getString();
					if (!player->updateTickCount(packet.get<int32_t>())) {
						// Tickcount was the same or less than 100 of the difference.
						return;
					}
					MapleTvs::Instance()->addMessage(player, receiver, msg, msg2, msg3, msg4, msg5, itemid - (itemid == Items::Megassenger ? 3 : 0), time);

					if (itemid == Items::Megassenger) {
						InventoryPacket::showSuperMegaphone(player, player->getMedalName() + " : " + msg + msg2 + msg3 + msg4 + msg5, show_whisper);
					}
					used = true;
				}
				break;
			}
			case Items::MapleTvStarMessenger: 
			case Items::StarMegassenger: {
				int32_t time = 30;
				bool show_whisper = (itemid == Items::StarMegassenger ? packet.getBool() : false);
				string msg = packet.getString();
				string msg2 = packet.getString();
				string msg3 = packet.getString();
				string msg4 = packet.getString();
				string msg5 = packet.getString();
				if (!player->updateTickCount(packet.get<int32_t>())) {
					// Tickcount was the same or less than 100 of the difference.
					return;
				}
				MapleTvs::Instance()->addMessage(player, nullptr, msg, msg2, msg3, msg4, msg5, itemid - (itemid == Items::StarMegassenger ? 3 : 0), time);

				if (itemid == Items::StarMegassenger) {
					InventoryPacket::showSuperMegaphone(player, player->getMedalName() + " : " + msg + msg2 + msg3 + msg4 + msg5, show_whisper);
				}
				used = true;
				break;
			}
			case Items::MapleTvHeartMessenger:
			case Items::HeartMegassenger: {
				bool show_whisper = (itemid == Items::HeartMegassenger ? packet.getBool() : false);
				string name = packet.getString();
				Player *receiver = PlayerDataProvider::Instance()->getPlayer(name);
				int32_t time = 60;

				if (receiver != nullptr) {
					string msg = packet.getString();
					string msg2 = packet.getString();
					string msg3 = packet.getString();
					string msg4 = packet.getString();
					string msg5 = packet.getString();
					if (!player->updateTickCount(packet.get<int32_t>())) {
						// Tickcount was the same or less than 100 of the difference.
						return;
					}
					MapleTvs::Instance()->addMessage(player, receiver, msg, msg2, msg3, msg4, msg5, itemid - (itemid == Items::HeartMegassenger ? 3 : 0), time);
					if (itemid == Items::HeartMegassenger) {
						InventoryPacket::showSuperMegaphone(player, player->getMedalName() + " : " + msg + msg2 + msg3 + msg4 + msg5, show_whisper);
					}
					used = true;
				}
				break;
			}
			case Items::BronzeSackOfMesos:
			case Items::SilverSackOfMesos:
			case Items::GoldSackOfMesos: {
				int32_t mesos = ItemDataProvider::Instance()->getMesoBonus(itemid);
				if (!player->getInventory()->modifyMesos(mesos)) {
					InventoryPacket::sendMesobagFailed(player);
				}
				else {
					InventoryPacket::sendMesobagSucceed(player, mesos);
					used = true;
				}
				break;
			}
			case Items::Chalkboard:
			case Items::Chalkboard2: {
				string msg = packet.getString();
				player->setChalkboard(msg);
				InventoryPacket::sendChalkboardUpdate(player, msg);
				break;
			}
			case Items::FungusScroll:
			case Items::OinkerDelight:
			case Items::ZetaNightmare:
				Inventory::useItem(player, itemid);
				used = true;
				break;
			case Items::ViciousHammer: {
				int8_t inventory = (int8_t) packet.get<int32_t>(); // How pointless...
				int16_t slot = (int16_t) packet.get<int32_t>();
				Item *f = player->getInventory()->getItem(inventory, slot);
				if (f == nullptr || f->getHammers() == Items::MaxHammers) {
					// Hacking, probably
					return;
				}
				f->incHammers();
				f->incSlots();
				InventoryPacket::sendHammerSlots(player, f->getHammers());
				player->getInventory()->setHammerSlot(slot);
				used = true;
				break;
			}
			case Items::CongratulatorySong:
				if (!player->updateTickCount(packet.get<int32_t>())) {
					// Tickcount was the same or less than 100 of the difference.
					return;
				}
				used = Maps::getMap(player->getMap())->playJukebox(player, itemid, 60 * 5); // 5 minutes is enough!
				break;
			case Items::KoreanKite:
			case Items::HeartBalloon:
			case Items::GraduationBanner:
			case Items::AdmissionBanner: {
				string message = packet.getString();
				if (!player->updateTickCount(packet.get<int32_t>())) {
					// Tickcount was the same or less than 100 of the difference.
					return;
				}

				used = Maps::getMap(player->getMap())->createKite(player, itemid, message);
				if (!used) {
					InventoryPacket::sendCannotFlyHere(player);
				}

				break;
			}
			default: {
				packet.reset();
				std::stringstream x;
				x << "Unknown cash item! ItemID: " << itemid << "; Player ID: " << player->getId() << "; Packet: " << packet;
				ChannelServer::Instance()->log(LogTypes::Info, x.str());
				break;
			}
		}
	}
	if (used) {
		Inventory::takeItem(player, itemid, 1);
	}
	else {
		InventoryPacket::blankUpdate(player);
	}
}
Example #13
0
UInt8 Handshake::handshakeHandler(UInt8 id,PacketReader& request,PacketWriter& response) {

	switch(id){
		case 0x30: {
			
			request.read8(); // passer un caractere (boite dans boite)
			UInt8 epdLen = request.read8()-1;

			UInt8 type = request.read8();

			string epd;
			request.readRaw(epdLen,epd);

			string tag;
			request.readRaw(16,tag);
			response.writeString8(tag);
			
			if(type == 0x0f)
				return _gateway.p2pHandshake(tag,response,peer.address,(const UInt8*)epd.c_str());

			if(type == 0x0a){
				/// Handshake
				HelloAttempt& attempt = helloAttempt<HelloAttempt>(tag);
				if(edges().size()>0 && (_invoker.edgesAttemptsBeforeFallback==0 || attempt.count <_invoker.edgesAttemptsBeforeFallback)) {
					
					if(_invoker.edgesAttemptsBeforeFallback>0) {
						try {
							URI uri(epd);
							response.writeAddress(SocketAddress(uri.getHost(),uri.getPort()),false); // TODO check with true!
						} catch(Exception& ex) {
							ERROR("Parsing %s URL problem in hello attempt : %s",epd.c_str(),ex.displayText().c_str());
						}
					}

					map<int,list<Edge*> > edgesSortedByCount;
					map<string,Edge*>::const_iterator it;
					for(it=edges().begin();it!=edges().end();++it)
						edgesSortedByCount[it->second->count].push_back(it->second);

					UInt8 count=0;
					map<int,list<Edge*> >::const_iterator it2;
					for(it2=edgesSortedByCount.begin();it2!=edgesSortedByCount.end();++it2) {
						list<Edge*>::const_iterator it3;
						for(it3=it2->second.begin();it3!=it2->second.end();++it3) {
							response.writeAddress((*it3)->address,false);
							if((++count)==6) // 6 redirections maximum
								break;
						}
						if(it3!=it2->second.end())
							break;
					}
					return 0x71;

				}

				if(edges().size()>0)
					WARN("After %u hello attempts, impossible to connect to edges. Edges are busy? or unreachable?",_invoker.edgesAttemptsBeforeFallback);
	
				// New Cookie
				createCookie(response,attempt,tag,epd);
				 
				// instance id (certificat in the middle)
				response.writeRaw(_certificat,sizeof(_certificat));
				
				return 0x70;
			} else
				ERROR("Unkown handshake first way with '%02x' type",type);
			break;
		}
		case 0x39:
		case 0x38: {
			(UInt32&)farId = request.read32();

			if(request.read7BitLongValue()!=COOKIE_SIZE) {
				ERROR("Bad handshake cookie '%s': its size should be 64 bytes",Util::FormatHex(request.current(),COOKIE_SIZE).c_str());
				return 0;
			}
	
			map<const UInt8*,Cookie*,CompareCookies>::iterator itCookie = _cookies.find(request.current());
			if(itCookie==_cookies.end()) {
				if(id!=0x39) {
					ERROR("Handshake cookie '%s' unknown",Util::FormatHex(request.current(),COOKIE_SIZE).c_str());
					return 0;
				}
				Cookie* pCookie = new Cookie();
				UInt32 pos = request.position();
				request.readRaw((UInt8*)pCookie->value,COOKIE_SIZE);
				request >> (string&)pCookie->queryUrl;
				request.reset(pos);
				itCookie = _cookies.insert(pair<const UInt8*,Cookie*>(pCookie->value,pCookie)).first;
			}

			Cookie& cookie(*itCookie->second);

			if(cookie.id==0) {

				UInt8 decryptKey[AES_KEY_SIZE];UInt8* pDecryptKey=&decryptKey[0];
				UInt8 encryptKey[AES_KEY_SIZE];UInt8* pEncryptKey=&encryptKey[0];

				if(id==0x38) {
					request.next(COOKIE_SIZE);
					size_t size = (size_t)request.read7BitLongValue();
					// peerId = SHA256(farPubKey)
					EVP_Digest(request.current(),size,(UInt8*)peer.id,NULL,EVP_sha256(),NULL);

					vector<UInt8> publicKey(request.read7BitValue()-2);
					request.next(2); // unknown
					request.readRaw(&publicKey[0],publicKey.size());

					size = request.read7BitValue();

					cookie.computeKeys(&publicKey[0],publicKey.size(),request.current(),(UInt16)size,decryptKey,encryptKey);
				} else {
					// edge
					pDecryptKey=NULL;
					pEncryptKey=NULL;
					memcpy((UInt8*)peer.id,request.current(),ID_SIZE);
					request.next(COOKIE_SIZE);
					request.next(request.read7BitEncoded());
				}

				// Fill peer infos
				Util::UnpackUrl(cookie.queryUrl,(string&)peer.path,(map<string,string>&)peer.properties);

				// RESPONSE
				Session& session = _gateway.createSession(farId,peer,pDecryptKey,pEncryptKey,cookie);
				(UInt32&)cookie.id = session.id;

				string address;
				if(id==0x39) {
					// Session by edge 
					session.flags |= SESSION_BY_EDGE;
					Edge* pEdge = _invoker.edges(peer.address);
					if(!pEdge)
						ERROR("Edge session creation by an unknown server edge %s",peer.address.toString().c_str())
					else
						pEdge->addSession(session);
					request >> address;
				} else // Session direct
					address = session.peer.address.toString();

				session.peer.addresses.clear();
				session.peer.addresses.push_back(address);

				cookie.write();
			} else