void GameHandler::processMessage(NetComputer *comp, MessageIn &message) { GameClient &computer = *static_cast< GameClient * >(comp); MessageOut result; if (computer.status == CLIENT_LOGIN) { if (message.getId() != PGMSG_CONNECT) return; std::string magic_token = message.readString(MAGIC_TOKEN_LENGTH); computer.status = CLIENT_QUEUED; // Before the addPendingClient mTokenCollector.addPendingClient(magic_token, &computer); return; } else if (computer.status != CLIENT_CONNECTED) { return; } switch (message.getId()) { case PGMSG_SAY: { std::string say = message.readString(); if (say.empty()) break; if (say[0] == '@') { CommandHandler::handleCommand(computer.character, say); break; } GameState::sayAround(computer.character, say); std::string msg = computer.character->getName() + " said " + say; accountHandler->sendTransaction(computer.character->getDatabaseID(), TRANS_MSG_PUBLIC, msg); } break; case PGMSG_NPC_TALK: case PGMSG_NPC_TALK_NEXT: case PGMSG_NPC_SELECT: case PGMSG_NPC_NUMBER: case PGMSG_NPC_STRING: { int id = message.readShort(); Actor *o = findActorNear(computer.character, id); if (!o || o->getType() != OBJECT_NPC) { sendError(comp, id, "Not close enough to NPC\n"); break; } NPC *q = static_cast< NPC * >(o); if (message.getId() == PGMSG_NPC_SELECT) { q->select(computer.character, message.readByte()); } else if (message.getId() == PGMSG_NPC_NUMBER) { q->integerReceived(computer.character, message.readLong()); } else if (message.getId() == PGMSG_NPC_STRING) { q->stringReceived(computer.character, message.readString()); } else { q->prompt(computer.character, message.getId() == PGMSG_NPC_TALK); } } break; case PGMSG_PICKUP: { int x = message.readShort(); int y = message.readShort(); Point ppos = computer.character->getPosition(); // TODO: use a less arbitrary value. if (std::abs(x - ppos.x) + std::abs(y - ppos.y) < 48) { MapComposite *map = computer.character->getMap(); Point ipos(x, y); for (FixedActorIterator i(map->getAroundPointIterator(ipos, 0)); i; ++i) { Actor *o = *i; Point opos = o->getPosition(); if (o->getType() == OBJECT_ITEM && opos.x == x && opos.y == y) { Item *item = static_cast< Item * >(o); ItemClass *ic = item->getItemClass(); Inventory(computer.character) .insert(ic->getDatabaseID(), item->getAmount()); GameState::remove(item); // log transaction std::stringstream str; str << "User picked up item " << ic->getDatabaseID() << " at " << opos.x << "x" << opos.y; accountHandler->sendTransaction(computer.character->getDatabaseID(), TRANS_ITEM_PICKUP, str.str()); break; } } } } break; case PGMSG_USE_ITEM: { int slot = message.readByte(); Inventory inv(computer.character); if (ItemClass *ic = ItemManager::getItem(inv.getItem(slot))) { if (ic->use(computer.character)) { inv.removeFromSlot(slot, 1); // log transaction std::stringstream str; str << "User used item " << ic->getDatabaseID() << " from slot " << slot; accountHandler->sendTransaction(computer.character->getDatabaseID(), TRANS_ITEM_USED, str.str()); } } } break; case PGMSG_DROP: { int slot = message.readByte(); int amount = message.readByte(); Inventory inv(computer.character); if (ItemClass *ic = ItemManager::getItem(inv.getItem(slot))) { int nb = inv.removeFromSlot(slot, amount); Item *item = new Item(ic, amount - nb); item->setMap(computer.character->getMap()); item->setPosition(computer.character->getPosition()); if (!GameState::insert(item)) { // The map is full. Put back into inventory. inv.insert(ic->getDatabaseID(), amount - nb); delete item; break; } // log transaction Point pt = computer.character->getPosition(); std::stringstream str; str << "User dropped item " << ic->getDatabaseID() << " at " << pt.x << "x" << pt.y; accountHandler->sendTransaction(computer.character->getDatabaseID(), TRANS_ITEM_DROP, str.str()); } } break; case PGMSG_WALK: { handleWalk(&computer, message); } break; case PGMSG_EQUIP: { int slot = message.readByte(); Inventory(computer.character).equip(slot); } break; case PGMSG_UNEQUIP: { int slot = message.readByte(); if (slot >= 0 && slot < EQUIP_PROJECTILE_SLOT) { Inventory(computer.character).unequip(slot); } } break; case PGMSG_MOVE_ITEM: { int slot1 = message.readByte(); int slot2 = message.readByte(); int amount = message.readByte(); Inventory(computer.character).move(slot1, slot2, amount); // log transaction std::stringstream str; str << "User moved item " << " from slot " << slot1 << " to slot " << slot2; accountHandler->sendTransaction(computer.character->getDatabaseID(), TRANS_ITEM_MOVE, str.str()); } break; case PGMSG_ATTACK: { int id = message.readShort(); LOG_DEBUG("Character " << computer.character->getPublicID() << " attacked being " << id); Actor *o = findActorNear(computer.character, id); if (o && o->getType() != OBJECT_NPC) { Being *being = static_cast<Being*>(o); computer.character->setTarget(being); computer.character->setAction(Being::ATTACK); } } break; case PGMSG_USE_SPECIAL: { int specialID = message.readByte(); LOG_DEBUG("Character " << computer.character->getPublicID() << " tries to use his special attack "<<specialID); computer.character->useSpecial(specialID); } case PGMSG_ACTION_CHANGE: { Being::Action action = (Being::Action)message.readByte(); Being::Action current = (Being::Action)computer.character->getAction(); bool logActionChange = true; switch (action) { case Being::STAND: { if (current == Being::SIT) { computer.character->setAction(Being::STAND); logActionChange = false; } } break; case Being::SIT: { if (current == Being::STAND) { computer.character->setAction(Being::SIT); logActionChange = false; } } break; default: break; } // Log the action change only when this is relevant. if (logActionChange) { // log transaction std::stringstream str; str << "User changed action from " << current << " to " << action; accountHandler->sendTransaction( computer.character->getDatabaseID(), TRANS_ACTION_CHANGE, str.str()); } } break; case PGMSG_DIRECTION_CHANGE: { computer.character->setDirection(message.readByte()); } break; case PGMSG_DISCONNECT: { bool reconnectAccount = (bool) message.readByte(); result.writeShort(GPMSG_DISCONNECT_RESPONSE); result.writeByte(ERRMSG_OK); // It is, when control reaches here if (reconnectAccount) { std::string magic_token(utils::getMagicToken()); result.writeString(magic_token, MAGIC_TOKEN_LENGTH); // No accountserver data, the client should remember that accountHandler->playerReconnectAccount( computer.character->getDatabaseID(), magic_token); } // TODO: implement a delayed remove GameState::remove(computer.character); accountHandler->sendCharacterData(computer.character); // Done with the character computer.character->disconnected(); delete computer.character; computer.character = NULL; computer.status = CLIENT_LOGIN; } break; case PGMSG_TRADE_REQUEST: { int id = message.readShort(); if (Trade *t = computer.character->getTrading()) { if (t->request(computer.character, id)) break; } Character *q = findCharacterNear(computer.character, id); if (!q || q->isBusy()) { result.writeShort(GPMSG_TRADE_CANCEL); break; } new Trade(computer.character, q); // log transaction std::string str; str = "User requested trade with " + q->getName(); accountHandler->sendTransaction(computer.character->getDatabaseID(), TRANS_TRADE_REQUEST, str); } break; case PGMSG_TRADE_CANCEL: case PGMSG_TRADE_AGREED: case PGMSG_TRADE_CONFIRM: case PGMSG_TRADE_ADD_ITEM: case PGMSG_TRADE_SET_MONEY: { std::stringstream str; Trade *t = computer.character->getTrading(); if (!t) break; switch (message.getId()) { case PGMSG_TRADE_CANCEL: t->cancel(); break; case PGMSG_TRADE_CONFIRM: t->confirm(computer.character); break; case PGMSG_TRADE_AGREED: t->agree(computer.character); // log transaction accountHandler->sendTransaction(computer.character->getDatabaseID(), TRANS_TRADE_END, "User finished trading"); break; case PGMSG_TRADE_SET_MONEY: { int money = message.readLong(); t->setMoney(computer.character, money); // log transaction str << "User added " << money << " money to trade."; accountHandler->sendTransaction(computer.character->getDatabaseID(), TRANS_TRADE_MONEY, str.str()); } break; case PGMSG_TRADE_ADD_ITEM: { int slot = message.readByte(); t->addItem(computer.character, slot, message.readByte()); // log transaction str << "User add item from slot " << slot; accountHandler->sendTransaction(computer.character->getDatabaseID(), TRANS_TRADE_ITEM, str.str()); } break; } } break; case PGMSG_NPC_BUYSELL: { BuySell *t = computer.character->getBuySell(); if (!t) break; int id = message.readShort(); int amount = message.readShort(); t->perform(id, amount); } break; case PGMSG_RAISE_ATTRIBUTE: { int attribute = message.readByte(); AttribmodResponseCode retCode; retCode = computer.character->useCharacterPoint(attribute); result.writeShort(GPMSG_RAISE_ATTRIBUTE_RESPONSE); result.writeByte(retCode); result.writeByte(attribute); if (retCode == ATTRIBMOD_OK ) { accountHandler->updateCharacterPoints( computer.character->getDatabaseID(), computer.character->getCharacterPoints(), computer.character->getCorrectionPoints(), attribute, computer.character->getAttribute(attribute)); // log transaction std::stringstream str; str << "User increased attribute " << attribute; accountHandler->sendTransaction(computer.character->getDatabaseID(), TRANS_ATTR_INCREASE, str.str()); } } break; case PGMSG_LOWER_ATTRIBUTE: { int attribute = message.readByte(); AttribmodResponseCode retCode; retCode = computer.character->useCorrectionPoint(attribute); result.writeShort(GPMSG_LOWER_ATTRIBUTE_RESPONSE); result.writeByte(retCode); result.writeByte(attribute); if (retCode == ATTRIBMOD_OK ) { accountHandler->updateCharacterPoints( computer.character->getDatabaseID(), computer.character->getCharacterPoints(), computer.character->getCorrectionPoints(), attribute, computer.character->getAttribute(attribute)); // log transaction std::stringstream str; str << "User decreased attribute " << attribute; accountHandler->sendTransaction(computer.character->getDatabaseID(), TRANS_ATTR_DECREASE, str.str()); } } break; case PGMSG_RESPAWN: { computer.character->respawn(); // plausibility check is done by character class } break; case PGMSG_NPC_POST_SEND: { handleSendPost(&computer, message); } break; default: LOG_WARN("Invalid message type"); result.writeShort(XXMSG_INVALID); break; } if (result.getLength() > 0) computer.send(result); }
/* Un-initialize the ssp module and initialize the SPIFI module */ static int lpcspifi_set_hw_mode(struct flash_bank *bank) { struct target *target = bank->target; struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv; uint32_t ssp_base = lpcspifi_info->ssp_base; struct armv7m_algorithm armv7m_info; struct working_area *spifi_init_algorithm; struct reg_param reg_params[2]; int retval = ERROR_OK; LOG_DEBUG("Uninitializing LPC43xx SSP"); /* Turn off the SSP module */ retval = ssp_write_reg(target, ssp_base, SSP_CR1, 0x00000000); if (retval != ERROR_OK) return retval; /* see contrib/loaders/flash/lpcspifi_init.S for src */ static const uint8_t spifi_init_code[] = { 0x4f, 0xea, 0x00, 0x08, 0xa1, 0xb0, 0x00, 0xaf, 0x4f, 0xf4, 0xc0, 0x43, 0xc4, 0xf2, 0x08, 0x03, 0x4f, 0xf0, 0xf3, 0x02, 0xc3, 0xf8, 0x8c, 0x21, 0x4f, 0xf4, 0xc0, 0x43, 0xc4, 0xf2, 0x08, 0x03, 0x4f, 0xf4, 0xc0, 0x42, 0xc4, 0xf2, 0x08, 0x02, 0x4f, 0xf4, 0xc0, 0x41, 0xc4, 0xf2, 0x08, 0x01, 0x4f, 0xf4, 0xc0, 0x40, 0xc4, 0xf2, 0x08, 0x00, 0x4f, 0xf0, 0xd3, 0x04, 0xc0, 0xf8, 0x9c, 0x41, 0x20, 0x46, 0xc1, 0xf8, 0x98, 0x01, 0x01, 0x46, 0xc2, 0xf8, 0x94, 0x11, 0xc3, 0xf8, 0x90, 0x11, 0x4f, 0xf4, 0xc0, 0x43, 0xc4, 0xf2, 0x08, 0x03, 0x4f, 0xf0, 0x13, 0x02, 0xc3, 0xf8, 0xa0, 0x21, 0x40, 0xf2, 0x18, 0x13, 0xc1, 0xf2, 0x40, 0x03, 0x1b, 0x68, 0x1c, 0x68, 0x40, 0xf2, 0xb4, 0x30, 0xc1, 0xf2, 0x00, 0x00, 0x4f, 0xf0, 0x03, 0x01, 0x4f, 0xf0, 0xc0, 0x02, 0x4f, 0xea, 0x08, 0x03, 0xa0, 0x47, 0x00, 0xf0, 0x00, 0xb8, 0x00, 0xbe }; armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; LOG_DEBUG("Allocating working area for SPIFI init algorithm"); /* Get memory for spifi initialization algorithm */ retval = target_alloc_working_area(target, sizeof(spifi_init_code) + SPIFI_INIT_STACK_SIZE, &spifi_init_algorithm); if (retval != ERROR_OK) { LOG_ERROR("Insufficient working area to initialize SPIFI "\ "module. You must allocate at least %zdB of working "\ "area in order to use this driver.", sizeof(spifi_init_code) + SPIFI_INIT_STACK_SIZE ); return retval; } LOG_DEBUG("Writing algorithm to working area at 0x%08" PRIx32, spifi_init_algorithm->address); /* Write algorithm to working area */ retval = target_write_buffer(target, spifi_init_algorithm->address, sizeof(spifi_init_code), spifi_init_code ); if (retval != ERROR_OK) { target_free_working_area(target, spifi_init_algorithm); return retval; } init_reg_param(®_params[0], "r0", 32, PARAM_OUT); /* spifi clk speed */ /* the spifi_init() rom API makes use of the stack */ init_reg_param(®_params[1], "sp", 32, PARAM_OUT); /* For now, the algorithm will set up the SPIFI module * @ the IRC clock speed. In the future, it could be made * a bit smarter to use other clock sources if the user has * already configured them in order to speed up memory- * mapped reads. */ buf_set_u32(reg_params[0].value, 0, 32, 12); /* valid stack pointer */ buf_set_u32(reg_params[1].value, 0, 32, (spifi_init_algorithm->address + sizeof(spifi_init_code) + SPIFI_INIT_STACK_SIZE) & ~7UL); /* Run the algorithm */ LOG_DEBUG("Running SPIFI init algorithm"); retval = target_run_algorithm(target, 0 , NULL, 2, reg_params, spifi_init_algorithm->address, spifi_init_algorithm->address + sizeof(spifi_init_code) - 2, 1000, &armv7m_info); if (retval != ERROR_OK) LOG_ERROR("Error executing SPIFI init algorithm"); target_free_working_area(target, spifi_init_algorithm); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); return retval; }
static int lpcspifi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv; uint32_t page_size, fifo_size; struct working_area *fifo; struct reg_param reg_params[5]; struct armv7m_algorithm armv7m_info; struct working_area *write_algorithm; int sector; int retval = ERROR_OK; LOG_DEBUG("offset=0x%08" PRIx32 " count=0x%08" PRIx32, offset, count); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (offset + count > lpcspifi_info->dev->size_in_bytes) { LOG_WARNING("Writes past end of flash. Extra data discarded."); count = lpcspifi_info->dev->size_in_bytes - offset; } /* Check sector protection */ for (sector = 0; sector < bank->num_sectors; sector++) { /* Start offset in or before this sector? */ /* End offset in or behind this sector? */ if ((offset < (bank->sectors[sector].offset + bank->sectors[sector].size)) && ((offset + count - 1) >= bank->sectors[sector].offset) && bank->sectors[sector].is_protected) { LOG_ERROR("Flash sector %d protected", sector); return ERROR_FAIL; } } page_size = lpcspifi_info->dev->pagesize; retval = lpcspifi_set_hw_mode(bank); if (retval != ERROR_OK) return retval; /* see contrib/loaders/flash/lpcspifi_write.S for src */ static const uint8_t lpcspifi_flash_write_code[] = { 0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x08, 0x0a, 0x4f, 0xf0, 0xea, 0x08, 0xca, 0xf8, 0x8c, 0x81, 0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x90, 0x81, 0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x94, 0x81, 0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x98, 0x81, 0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x9c, 0x81, 0x4f, 0xf0, 0x44, 0x08, 0xca, 0xf8, 0xa0, 0x81, 0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a, 0x4f, 0xf4, 0x00, 0x68, 0xca, 0xf8, 0x14, 0x80, 0x4f, 0xf4, 0x80, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a, 0x4f, 0xf0, 0xff, 0x08, 0xca, 0xf8, 0xab, 0x80, 0x4f, 0xf0, 0x00, 0x0a, 0xc4, 0xf2, 0x05, 0x0a, 0x4f, 0xf0, 0x00, 0x08, 0xc0, 0xf2, 0x00, 0x18, 0xca, 0xf8, 0x94, 0x80, 0x4f, 0xf4, 0x00, 0x5a, 0xc4, 0xf2, 0x05, 0x0a, 0x4f, 0xf0, 0x01, 0x08, 0xca, 0xf8, 0x00, 0x87, 0x4f, 0xf4, 0x40, 0x5a, 0xc4, 0xf2, 0x08, 0x0a, 0x4f, 0xf0, 0x07, 0x08, 0xca, 0xf8, 0x00, 0x80, 0x4f, 0xf0, 0x02, 0x08, 0xca, 0xf8, 0x10, 0x80, 0xca, 0xf8, 0x04, 0x80, 0x4f, 0xf0, 0x00, 0x0b, 0xa3, 0x44, 0x93, 0x45, 0x7f, 0xf6, 0xfc, 0xaf, 0x00, 0xf0, 0x6a, 0xf8, 0x4f, 0xf0, 0x06, 0x09, 0x00, 0xf0, 0x53, 0xf8, 0x00, 0xf0, 0x60, 0xf8, 0x00, 0xf0, 0x62, 0xf8, 0x4f, 0xf0, 0x05, 0x09, 0x00, 0xf0, 0x4b, 0xf8, 0x4f, 0xf0, 0x00, 0x09, 0x00, 0xf0, 0x47, 0xf8, 0x00, 0xf0, 0x54, 0xf8, 0x19, 0xf0, 0x02, 0x0f, 0x00, 0xf0, 0x5d, 0x80, 0x00, 0xf0, 0x52, 0xf8, 0x4f, 0xf0, 0x02, 0x09, 0x00, 0xf0, 0x3b, 0xf8, 0x4f, 0xea, 0x12, 0x49, 0x00, 0xf0, 0x37, 0xf8, 0x4f, 0xea, 0x12, 0x29, 0x00, 0xf0, 0x33, 0xf8, 0x4f, 0xea, 0x02, 0x09, 0x00, 0xf0, 0x2f, 0xf8, 0xd0, 0xf8, 0x00, 0x80, 0xb8, 0xf1, 0x00, 0x0f, 0x00, 0xf0, 0x47, 0x80, 0x47, 0x68, 0x47, 0x45, 0x3f, 0xf4, 0xf6, 0xaf, 0x17, 0xf8, 0x01, 0x9b, 0x00, 0xf0, 0x21, 0xf8, 0x8f, 0x42, 0x28, 0xbf, 0x00, 0xf1, 0x08, 0x07, 0x47, 0x60, 0x01, 0x3b, 0xbb, 0xb3, 0x02, 0xf1, 0x01, 0x02, 0x93, 0x45, 0x7f, 0xf4, 0xe6, 0xaf, 0x00, 0xf0, 0x22, 0xf8, 0xa3, 0x44, 0x00, 0xf0, 0x23, 0xf8, 0x4f, 0xf0, 0x05, 0x09, 0x00, 0xf0, 0x0c, 0xf8, 0x4f, 0xf0, 0x00, 0x09, 0x00, 0xf0, 0x08, 0xf8, 0x00, 0xf0, 0x15, 0xf8, 0x19, 0xf0, 0x01, 0x0f, 0x7f, 0xf4, 0xf0, 0xaf, 0xff, 0xf7, 0xa7, 0xbf, 0x4f, 0xf4, 0x40, 0x5a, 0xc4, 0xf2, 0x08, 0x0a, 0xca, 0xf8, 0x08, 0x90, 0xda, 0xf8, 0x0c, 0x90, 0x19, 0xf0, 0x10, 0x0f, 0x7f, 0xf4, 0xfa, 0xaf, 0xda, 0xf8, 0x08, 0x90, 0x70, 0x47, 0x4f, 0xf0, 0xff, 0x08, 0x00, 0xf0, 0x02, 0xb8, 0x4f, 0xf0, 0x00, 0x08, 0x4f, 0xf4, 0x80, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a, 0xca, 0xf8, 0xab, 0x80, 0x70, 0x47, 0x00, 0x20, 0x50, 0x60, 0xff, 0xf7, 0xef, 0xff, 0x30, 0x46, 0x00, 0xbe, 0xff, 0xff }; if (target_alloc_working_area(target, sizeof(lpcspifi_flash_write_code), &write_algorithm) != ERROR_OK) { LOG_ERROR("Insufficient working area. You must configure"\ " a working area > %zdB in order to write to SPIFI flash.", sizeof(lpcspifi_flash_write_code)); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } retval = target_write_buffer(target, write_algorithm->address, sizeof(lpcspifi_flash_write_code), lpcspifi_flash_write_code); if (retval != ERROR_OK) { target_free_working_area(target, write_algorithm); return retval; } /* FIFO allocation */ fifo_size = target_get_working_area_avail(target); if (fifo_size == 0) { /* if we already allocated the writing code but failed to get fifo * space, free the algorithm */ target_free_working_area(target, write_algorithm); LOG_ERROR("Insufficient working area. Please allocate at least"\ " %zdB of working area to enable flash writes.", sizeof(lpcspifi_flash_write_code) + 1 ); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } else if (fifo_size < page_size) LOG_WARNING("Working area size is limited; flash writes may be"\ " slow. Increase working area size to at least %zdB"\ " to reduce write times.", (size_t)(sizeof(lpcspifi_flash_write_code) + page_size) ); else if (fifo_size > 0x2000) /* Beyond this point, we start to get diminishing returns */ fifo_size = 0x2000; if (target_alloc_working_area(target, fifo_size, &fifo) != ERROR_OK) { target_free_working_area(target, write_algorithm); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); /* buffer start, status (out) */ init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* buffer end */ init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /* target address */ init_reg_param(®_params[3], "r3", 32, PARAM_OUT); /* count (halfword-16bit) */ init_reg_param(®_params[4], "r4", 32, PARAM_OUT); /* page size */ buf_set_u32(reg_params[0].value, 0, 32, fifo->address); buf_set_u32(reg_params[1].value, 0, 32, fifo->address + fifo->size); buf_set_u32(reg_params[2].value, 0, 32, offset); buf_set_u32(reg_params[3].value, 0, 32, count); buf_set_u32(reg_params[4].value, 0, 32, page_size); retval = target_run_flash_async_algorithm(target, buffer, count, 1, 0, NULL, 5, reg_params, fifo->address, fifo->size, write_algorithm->address, 0, &armv7m_info ); if (retval != ERROR_OK) LOG_ERROR("Error executing flash write algorithm"); target_free_working_area(target, fifo); target_free_working_area(target, write_algorithm); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); destroy_reg_param(®_params[3]); destroy_reg_param(®_params[4]); /* Switch to HW mode before return to prompt */ retval = lpcspifi_set_hw_mode(bank); return retval; }
static int stmsmi_probe(struct flash_bank *bank) { struct target *target = bank->target; struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv; uint32_t io_base; struct flash_sector *sectors; uint32_t id = 0; /* silence uninitialized warning */ struct stmsmi_target *target_device; int retval; if (stmsmi_info->probed) free(bank->sectors); stmsmi_info->probed = 0; for (target_device=target_devices ; target_device->name ; ++target_device) if (target_device->tap_idcode == target->tap->idcode) break; if (!target_device->name) { LOG_ERROR("Device ID 0x%" PRIx32 " is not known as SMI capable", target->tap->idcode); return ERROR_FAIL; } switch (bank->base - target_device->smi_base) { case 0: stmsmi_info->bank_num = SMI_SEL_BANK0; break; case SMI_BANK_SIZE: stmsmi_info->bank_num = SMI_SEL_BANK1; break; case 2*SMI_BANK_SIZE: stmsmi_info->bank_num = SMI_SEL_BANK2; break; case 3*SMI_BANK_SIZE: stmsmi_info->bank_num = SMI_SEL_BANK3; break; default: LOG_ERROR("Invalid SMI base address 0x%" PRIx32, bank->base); return ERROR_FAIL; } io_base = target_device->io_base; stmsmi_info->io_base = io_base; LOG_DEBUG("Valid SMI on device %s at address 0x%" PRIx32, target_device->name, bank->base); /* read and decode flash ID; returns in SW mode */ retval = read_flash_id(bank, &id); SMI_SET_HW_MODE(); if (retval != ERROR_OK) return retval; stmsmi_info->dev = NULL; for (struct flash_device *p = flash_devices; p->name ; p++) if (p->device_id == id) { stmsmi_info->dev = p; break; } if (!stmsmi_info->dev) { LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id); return ERROR_FAIL; } LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")", stmsmi_info->dev->name, stmsmi_info->dev->device_id); /* Set correct size value */ bank->size = stmsmi_info->dev->size_in_bytes; /* create and fill sectors array */ bank->num_sectors = stmsmi_info->dev->size_in_bytes / stmsmi_info->dev->sectorsize; sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); if (sectors == NULL) { LOG_ERROR("not enough memory"); return ERROR_FAIL; } for (int sector = 0; sector < bank->num_sectors; sector++) { sectors[sector].offset = sector * stmsmi_info->dev->sectorsize; sectors[sector].size = stmsmi_info->dev->sectorsize; sectors[sector].is_erased = -1; sectors[sector].is_protected = 1; } bank->sectors = sectors; stmsmi_info->probed = 1; return ERROR_OK; }
/** * A thread that actually handles the registration request of the GUI (internal * use only). See rm_register_account() for details. * @param args the account ID is stored here * @return empty */ void *registration_thread(void *args) { int accountId; // current account int pos; // position of account status information int rc; // return code int counter; // counter for registration expire int timeoutCtr; // timeout counter for sipstack events struct account *acc; // account data from account management char *from; // SIP from field char *registrar; // SIP registrar field // accountId is given: accountId = (int) args; LOG_DEBUG(REGISTRAR_MGR_MSG_PREFIX "registration thread entered, " "accountId: %d", accountId); // try to gain lock because we want exclusive responsibility for this // account and we need to use a new position for account status info: rc = pthread_mutex_lock(&accInfoLock); if (rc != 0) { // failed to gain lock, exit (fatal error) LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "mutex lock could not be" "acquired, error: %d", rc); thread_terminated(); return NULL; } LOG_DEBUG(REGISTRAR_MGR_MSG_PREFIX "mutex lock acquired"); // is another thread handling (un-)registration of this account? rc = find_acc_by_id(accountId, NULL); if (rc) { // account is blocked by another thread (impatient GUI user?) LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "account already in use"); rc = go_show_user_event(accountId, "ERROR", "Error registering account", "Account is already in use.", "Either this account is already " "registered or it is currently tried to " "unregister this account."); if (!rc) { LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "failed to inform the GUI"); } // inform GUI and exit: leave_reg_thrd_with_error(-1, accountId, 0); return NULL; } LOG_DEBUG(REGISTRAR_MGR_MSG_PREFIX "account is not in use"); // try to find empty position to save account status information // (there has to be one position for every account of account information) pos = find_empty_acc_info(); if (pos == -1) { // no position found (fatal error): LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "no empty position found"); rc = go_show_user_event(accountId, "ERROR", "Error registering account", "Maximum number of active accounts " "exceeded.", "You have registered more accounts than " "are allowed by the Core configuration."); if (!rc) { LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "failed to inform the GUI"); } // inform GUI and exit: leave_reg_thrd_with_error(-1, accountId, 0); return NULL; } LOG_DEBUG(REGISTRAR_MGR_MSG_PREFIX "position found: %d", pos); // if we set an account ID the array position is marked as used: accInfos[pos].accountId = accountId; accInfos[pos].isRegistered = 0; // get account data from account management: acc = am_get_account(accountId); if (!acc) { LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "account management did not " "return matching account data."); rc = go_show_user_event(accountId, "ERROR", "Error registering account", "No such account available.", "Account management did not return " "matching account data."); if (!rc) { LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "failed to inform the GUI"); } // inform GUI and exit: leave_reg_thrd_with_error(pos, accountId, 0); return NULL; } LOG_DEBUG(REGISTRAR_MGR_MSG_PREFIX "account management found matching " "account data."); // check fields required for registration: if (!acc->domain || !acc->username || !acc->registrar) { LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "domain, username or registrar is missing"); rc = go_show_user_event(accountId, "ERROR", "Error registering account", "Account information is invalid.", "Your account is missing either domain, " "user name or registrar. Please check " "your account information."); if (!rc) { LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "failed to inform the GUI"); } // inform GUI and exit: leave_reg_thrd_with_error(pos, accountId, 0); return NULL; } if (strcmp(acc->domain, "") == 0 || strcmp(acc->username, "") == 0 || strcmp(acc->registrar, "") == 0) { LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "domain, username or registrar is empty"); rc = go_show_user_event(accountId, "ERROR", "Error registering account", "Account information is invalid.", "Your account is missing either domain, " "user name or registrar. Please check " "your account information."); if (!rc) { LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "failed to inform the GUI"); } // inform GUI and exit: leave_reg_thrd_with_error(pos, accountId, 0); return NULL; } // build SIP From and SIP Registrar: from = (char *) malloc(1024 * sizeof(char)); registrar = (char *) malloc(1024 * sizeof(char)); sprintf(from, "sip:%s@%s", acc->username, acc->domain); sprintf(registrar, "sip:%s", acc->registrar); LOG_DEBUG(REGISTRAR_MGR_MSG_PREFIX "from: %s registrar: %s", from, registrar); // now send initial REGISTER to registrar int regId = sipstack_send_register(from, registrar, config.core.sipOutput. registrarManager.expire); if (regId == -1) { // no valid registration ID returned because of an error LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "send register failed"); rc = go_show_user_event(accountId, "ERROR", "Error registering account", "Sending registration message failed.", "Failed to send your registration " "request to the given registrar." "Please check whether your account " "data is correct and whether your " "internet connection is working " "correctly."); if (!rc) { LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "failed to inform the GUI"); } // free strings: free(from); free(registrar); // inform GUI and exit: leave_reg_thrd_with_error(pos, accountId, 0); return NULL; } LOG_DEBUG(REGISTRAR_MGR_MSG_PREFIX "send register succeeded, " "regId: %d", regId); accInfos[pos].regId = regId; accInfos[pos].waitingOnRegOK = 1; // tell dispatcher which OK is expected LOG_DEBUG(REGISTRAR_MGR_MSG_PREFIX "now waiting on OK"); // marked account as "used" rc = pthread_mutex_unlock(&accInfoLock); if (rc != 0) { LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "releasing mutex lock " "failed, error: %d", rc); // free strings: free(from); free(registrar); // inform GUI and exit: leave_reg_thrd_with_error(pos, accountId, 0); return NULL; } // now wait on response: timeoutCtr = 0; while (!accInfos[pos].eventArrived) { sched_yield(); usleep(100000); // 0.1 seconds timeoutCtr++; if (timeoutCtr == config.core.sipOutput.registrarManager.timeout * 10) { break; } } LOG_DEBUG(REGISTRAR_MGR_MSG_PREFIX "done waiting"); // clear event waiting flags: accInfos[pos].eventArrived = 0; accInfos[pos].waitingOnRegOK = 0; // free strings: if (from) { free(from); } if (registrar) { free(registrar); } // test if we did receive an OK (isRegistered is set by dispatcher): if (!accInfos[pos].isRegistered) { LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "registering failed"); rc = go_show_user_event(accountId, "ERROR", "Error registering account", "Sending registration message failed.", "Failed to send your registration " "request to the given registrar." "Please check whether your account " "data is correct and whether your " "internet connection is working " "correctly."); if (!rc) { LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "failed to inform the GUI"); } // inform GUI and exit: leave_reg_thrd_with_error(pos, accountId, 1); return NULL; } // inform GUI that registration succeeded: rc = go_change_reg_status(accountId, 1); if (!rc) { // could not contact GUI (error): LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "GUI registration status update" " failed"); // inform GUI and exit (it is unlikely to succeed but try anyway): leave_reg_thrd_with_error(pos, accountId, 1); return NULL; } LOG_INFO(REGISTRAR_MGR_MSG_PREFIX "registration was successful for " "account: %d", accountId); // ********************************************************************** // now we are responsible for updating registration counter = 0; while (!accInfos[pos].doShutdown) { sleep(1); // test every second for shutdown or imminent expire counter++; if (counter == config.core.sipOutput.registrarManager.expire - config.core.sipOutput.registrarManager.preExpireRange) { // now expire is nearly reached, update registration: counter = 0; // tell dispatcher on which OK we are waiting for: accInfos[pos].waitingOnRefreshOK = 1; // send n-th REGISTER to registrar: rc = sipstack_send_update_register(regId, config.core.sipOutput. registrarManager.expire); if (rc == 0) { // send REGISTER failed LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "send update register" " failed"); rc = go_show_user_event(accountId, "ERROR", "Error refreshing account " "registration", "Sending automated registration " "message failed.", "Failed to send registration " "refresh to the given registrar. " "Please check whether your account " "data is correct and whether your " "internet connection is working " "correctly."); if (!rc) { LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "failed to inform the GUI"); } // inform GUI and exit: leave_reg_thrd_with_error(pos, accountId, 1); return NULL; } LOG_DEBUG(REGISTRAR_MGR_MSG_PREFIX "now waiting on OK"); timeoutCtr = 0; // now wait on response: while (!accInfos[pos].eventArrived) { sched_yield(); usleep(100000); // 0.1 seconds timeoutCtr++; if (timeoutCtr == config.core.sipOutput.registrarManager.timeout * 10) { break; } } LOG_DEBUG(REGISTRAR_MGR_MSG_PREFIX "done waiting"); // test if OK arrived: if (!accInfos[pos].isRefreshed) { LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "updating registration failed"); rc = go_show_user_event(accountId, "ERROR", "Error refreshing account " "registration", "Sending automated registration " "message failed.", "Failed to send registration " "refresh to the given registrar. " "Please check whether your account " "data is correct and whether your " "internet connection is working " "correctly."); if (!rc) { LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "failed to inform the GUI"); } // inform GUI and exit: leave_reg_thrd_with_error(pos, accountId, 1); return NULL; } // clear flags: accInfos[pos].isRefreshed = 0; accInfos[pos].eventArrived = 0; accInfos[pos].waitingOnRefreshOK = 0; LOG_INFO(REGISTRAR_MGR_MSG_PREFIX "registration updated for " "account: %d", accountId); } } // if an unregister-thread requested quitting this thread we tell it that // we are done (no lock required because other thread is only reading): accInfos[pos].doShutdown = 0; accInfos[pos].isShutdown = 1; thread_terminated(); return NULL; }
static decode_state faad_decode(void) { size_t bytes_total; size_t bytes_wrap; NeAACDecFrameInfo info; s32_t *iptr; bool endstream; frames_t frames; LOCK_S; bytes_total = _buf_used(streambuf); bytes_wrap = min(bytes_total, _buf_cont_read(streambuf)); if (stream.state <= DISCONNECT && !bytes_total) { UNLOCK_S; return DECODE_COMPLETE; } if (a->consume) { u32_t consume = min(a->consume, bytes_wrap); LOG_DEBUG("consume: %u of %u", consume, a->consume); _buf_inc_readp(streambuf, consume); a->pos += consume; a->consume -= consume; UNLOCK_S; return DECODE_RUNNING; } if (decode.new_stream) { int found = 0; static unsigned char channels; static unsigned long samplerate; if (a->type == '2') { // adts stream - seek for header while (bytes_wrap >= 2 && (*(streambuf->readp) != 0xFF || (*(streambuf->readp + 1) & 0xF6) != 0xF0)) { _buf_inc_readp(streambuf, 1); bytes_total--; bytes_wrap--; } if (bytes_wrap >= 2) { long n = NEAAC(a, Init, a->hAac, streambuf->readp, bytes_wrap, &samplerate, &channels); if (n < 0) { found = -1; } else { _buf_inc_readp(streambuf, n); found = 1; } } } else { // mp4 - read header found = read_mp4_header(&samplerate, &channels); } if (found == 1) { LOG_INFO("samplerate: %u channels: %u", samplerate, channels); bytes_total = _buf_used(streambuf); bytes_wrap = min(bytes_total, _buf_cont_read(streambuf)); LOCK_O; LOG_INFO("setting track_start"); output.next_sample_rate = decode_newstream(samplerate, output.supported_rates); IF_DSD( output.next_dop = false; )
void SteeringVehicle::update(const float currentTime, const float elapsedTime) { SimpleVehicle::update(currentTime, elapsedTime); Vector3 pos = mCreature->getPosition(); setPosition(pos); OgreNewt::Body* body = mCreature->getActor()->getPhysicalThing()->_getBody(); // Get the velocity vector mCurrentVelocity = body->getVelocity(); // enforce speed limit // newVelocity = newVelocity.truncateLength(maxSpeed()); // update speed setSpeed(mCurrentVelocity.length()); Vector3 newVelocity(mCurrentVelocity); // regenerate local space(by default: align vehicle's forward axis with // new velocity, but this behavior may be overridden by derived classes.) // use future orientation or not?? Quaternion orientation(mController->getYaw(), Ogre::Vector3::UNIT_Y); Vector3 newUnitForward = orientation*Vector3::NEGATIVE_UNIT_Z; regenerateOrthonormalBasisUF(newUnitForward); // only process if mMovingCreature not NULL if (mController == NULL || mCreature->getQueryFlags() & QUERYFLAG_PLAYER) { mCurrentForce = Vector3::ZERO; return; } // calculate the result of the force Vector3 result = mCurrentForce;// + mCurrentVelocity; mDebugSteer = mCurrentForce; // @todo remove this if (mCreature->getAu() <= 6) mCreature->modifyAu(20,true); AbstractMovement* mov_drehen = mController->getMovementFromId(CreatureController::MT_DREHEN); Real vel_drehen(0); Radian max_drehen = Degree(0); if (mov_drehen->calculateBaseVelocity(vel_drehen)) { max_drehen = Degree(vel_drehen * 360 * elapsedTime); } Ogre::Quaternion future_orientation(mController->getYaw(), Ogre::Vector3::UNIT_Y); Ogre::Vector3 creatureDirection = future_orientation * Ogre::Vector3::NEGATIVE_UNIT_Z; Radian yaw(0); creatureDirection.y = result.y = 0; yaw = creatureDirection.getRotationTo(result, Ogre::Vector3::UNIT_Y).getYaw(); if (yaw > Radian(0) && yaw > max_drehen) yaw = max_drehen; if (yaw < Radian(0) && yaw < -max_drehen) yaw = -max_drehen; Ogre::Vector3 direction(Ogre::Vector3::ZERO); Ogre::Vector3 rotation(0,yaw.valueRadians(),0); CreatureController::MovementType movement = CreatureController::MT_STEHEN; if (result != Ogre::Vector3::ZERO) { direction.z = -1; movement = CreatureController::MT_GEHEN; } mController->setMovement(movement, direction, rotation); LOG_DEBUG(Logger::AI, "SteeringVehicle: mController->setMovement " + Ogre::StringConverter::toString(movement) + ", " + Ogre::StringConverter::toString(direction) + ", " + Ogre::StringConverter::toString(rotation)); mCurrentForce = Ogre::Vector3::ZERO; }
int argmax_fs_2i_base::_transformerServiceFunction( std::vector< gr_istream_base * > &istreams , std::vector< gr_ostream_base * > &ostreams ) { typedef std::vector< gr_istream_base * > _IStreamList; typedef std::vector< gr_ostream_base * > _OStreamList; boost::mutex::scoped_lock lock(serviceThreadLock); if ( validGRBlock() == false ) { // create our processing block, and setup property notifiers createBlock(); LOG_DEBUG( argmax_fs_2i_base, " FINISHED BUILDING GNU RADIO BLOCK"); } //process any Stream ID changes this could affect number of io streams processStreamIdChanges(); if ( !validGRBlock() || istreams.size() == 0 || ostreams.size() == 0 ) { LOG_WARN( argmax_fs_2i_base, "NO STREAMS ATTACHED TO BLOCK..." ); return NOOP; } _input_ready.resize( istreams.size() ); _ninput_items_required.resize( istreams.size() ); _ninput_items.resize( istreams.size() ); _input_items.resize( istreams.size() ); _output_items.resize( ostreams.size() ); // // RESOLVE: need to look at forecast strategy, // 1) see how many read items are necessary for N number of outputs // 2) read input data and see how much output we can produce // // // Grab available data from input streams // _OStreamList::iterator ostream; _IStreamList::iterator istream = istreams.begin(); int nitems=0; for ( int idx=0 ; istream != istreams.end() && serviceThread->threadRunning() ; idx++, istream++ ) { // note this a blocking read that can cause deadlocks nitems = (*istream)->read(); if ( (*istream)->overrun() ) { LOG_WARN( argmax_fs_2i_base, " NOT KEEPING UP WITH STREAM ID:" << (*istream)->streamID ); } if ( (*istream)->sriChanged() ) { // RESOLVE - need to look at how SRI changes can affect Gnu Radio BLOCK state LOG_DEBUG( argmax_fs_2i_base, "SRI CHANGED, STREAMD IDX/ID: " << idx << "/" << (*istream)->getPktStreamId() ); setOutputStreamSRI( idx, (*istream)->getPktSri() ); } } LOG_TRACE( argmax_fs_2i_base, "READ NITEMS: " << nitems ); if ( nitems <= 0 && !_istreams[0]->eos() ) { return NOOP; } bool eos = false; int nout = 0; bool workDone = false; while ( nout > -1 && serviceThread->threadRunning() ) { eos = false; nout = _forecastAndProcess( eos, istreams, ostreams ); if ( nout > -1 ) { workDone = true; // we chunked on data so move read pointer.. istream = istreams.begin(); for ( ; istream != istreams.end(); istream++ ) { int idx=std::distance( istreams.begin(), istream ); // if we processed data for this stream if ( _input_ready[idx] ) { size_t nitems = 0; try { nitems = gr_sptr->nitems_read( idx ); } catch(...){} if ( nitems > (*istream)->nitems() ) { LOG_WARN( argmax_fs_2i_base, "WORK CONSUMED MORE DATA THAN AVAILABLE, READ/AVAILABLE " << nitems << "/" << (*istream)->nitems() ); nitems = (*istream)->nitems(); } (*istream)->consume( nitems ); LOG_TRACE( argmax_fs_2i_base, " CONSUME READ DATA ITEMS/REMAIN " << nitems << "/" << (*istream)->nitems()); } } gr_sptr->reset_read_index(); } // check for not enough data return if ( nout == -1 ) { // check for end of stream istream = istreams.begin(); for ( ; istream != istreams.end() ; istream++) { if ( (*istream)->eos() ) { eos=true; } } if ( eos ) { LOG_TRACE( argmax_fs_2i_base, "EOS SEEN, SENDING DOWNSTREAM " ); _forecastAndProcess( eos, istreams, ostreams); } } } if ( eos ) { istream = istreams.begin(); for ( ; istream != istreams.end() ; istream++ ) { int idx=std::distance( istreams.begin(), istream ); LOG_DEBUG( argmax_fs_2i_base, " CLOSING INPUT STREAM IDX:" << idx ); (*istream)->close(); } // close remaining output streams ostream = ostreams.begin(); for ( ; eos && ostream != ostreams.end(); ostream++ ) { int idx=std::distance( ostreams.begin(), ostream ); LOG_DEBUG( argmax_fs_2i_base, " CLOSING OUTPUT STREAM IDX:" << idx ); (*ostream)->close(); } } // // set the read pointers of the GNU Radio Block to start at the beginning of the // supplied buffers // gr_sptr->reset_read_index(); LOG_TRACE( argmax_fs_2i_base, " END OF TRANSFORM SERVICE FUNCTION....." << noutput_items ); if ( nout == -1 && eos == false && !workDone ) { return NOOP; } else { return NORMAL; } }
int argmax_fs_2i_base::_forecastAndProcess( bool &eos, std::vector< gr_istream_base * > &istreams , std::vector< gr_ostream_base * > &ostreams ) { typedef std::vector< gr_istream_base * > _IStreamList; typedef std::vector< gr_ostream_base * > _OStreamList; _OStreamList::iterator ostream; _IStreamList::iterator istream = istreams.begin(); int nout = 0; bool dataReady = false; if ( !eos ) { uint64_t max_items_avail = 0; for ( int idx=0 ; istream != istreams.end() && serviceThread->threadRunning() ; idx++, istream++ ) { LOG_TRACE( argmax_fs_2i_base, "GET MAX ITEMS: STREAM:"<< idx << " NITEMS/SCALARS:" << (*istream)->nitems() << "/" << (*istream)->nelems() ); max_items_avail = std::max( (*istream)->nitems(), max_items_avail ); } if ( max_items_avail == 0 ) { LOG_TRACE( argmax_fs_2i_base, "DATA CHECK - MAX ITEMS NOUTPUT/MAX_ITEMS:" << noutput_items << "/" << max_items_avail); return -1; } // // calc number of output elements based on input items available // noutput_items = 0; if ( !gr_sptr->fixed_rate() ) { noutput_items = round_down((int32_t) (max_items_avail * gr_sptr->relative_rate()), gr_sptr->output_multiple()); LOG_TRACE( argmax_fs_2i_base, " VARIABLE FORECAST NOUTPUT == " << noutput_items ); } else { istream = istreams.begin(); for ( int i=0; istream != istreams.end(); i++, istream++ ) { int t_noutput_items = gr_sptr->fixed_rate_ninput_to_noutput( (*istream)->nitems() ); if ( gr_sptr->output_multiple_set() ) { t_noutput_items = round_up(t_noutput_items, gr_sptr->output_multiple()); } if ( t_noutput_items > 0 ) { if ( noutput_items == 0 ) { noutput_items = t_noutput_items; } if ( t_noutput_items <= noutput_items ) { noutput_items = t_noutput_items; } } } LOG_TRACE( argmax_fs_2i_base, " FIXED FORECAST NOUTPUT/output_multiple == " << noutput_items << "/" << gr_sptr->output_multiple()); } // // ask the block how much input they need to produce noutput_items... // if enough data is available to process then set the dataReady flag // int32_t outMultiple = gr_sptr->output_multiple(); while ( !dataReady && noutput_items >= outMultiple ) { // // ask the block how much input they need to produce noutput_items... // gr_sptr->forecast(noutput_items, _ninput_items_required); LOG_TRACE( argmax_fs_2i_base, "--> FORECAST IN/OUT " << _ninput_items_required[0] << "/" << noutput_items ); istream = istreams.begin(); uint32_t dr_cnt=0; for ( int idx=0 ; noutput_items > 0 && istream != istreams.end(); idx++, istream++ ) { // check if buffer has enough elements _input_ready[idx] = false; if ( (*istream)->nitems() >= (uint64_t)_ninput_items_required[idx] ) { _input_ready[idx] = true; dr_cnt++; } LOG_TRACE( argmax_fs_2i_base, "ISTREAM DATACHECK NELMS/NITEMS/REQ/READY:" << (*istream)->nelems() << "/" << (*istream)->nitems() << "/" << _ninput_items_required[idx] << "/" << _input_ready[idx]); } if ( dr_cnt < istreams.size() ) { if ( outMultiple > 1 ) { noutput_items -= outMultiple; } else { noutput_items /= 2; } } else { dataReady = true; } LOG_TRACE( argmax_fs_2i_base, " TRIM FORECAST NOUTPUT/READY " << noutput_items << "/" << dataReady ); } // check if data is ready... if ( !dataReady ) { LOG_TRACE( argmax_fs_2i_base, "DATA CHECK - NOT ENOUGH DATA AVAIL/REQ:" << _istreams[0]->nitems() << "/" << _ninput_items_required[0] ); return -1; } // reset looping variables int ritems = 0; int nitems = 0; // reset caching vectors _output_items.clear(); _input_items.clear(); _ninput_items.clear(); istream = istreams.begin(); for ( int idx=0 ; istream != istreams.end(); idx++, istream++ ) { // check if the stream is ready if ( !_input_ready[idx] ) { continue; } // get number of items remaining try { ritems = gr_sptr->nitems_read( idx ); } catch(...){ // something bad has happened, we are missing an input stream LOG_ERROR( argmax_fs_2i_base, "MISSING INPUT STREAM FOR GR BLOCK, STREAM ID:" << (*istream)->streamID ); return -2; } nitems = (*istream)->nitems() - ritems; LOG_TRACE( argmax_fs_2i_base, " ISTREAM: IDX:" << idx << " ITEMS AVAIL/READ/REQ " << nitems << "/" << ritems << "/" << _ninput_items_required[idx] ); if ( nitems >= _ninput_items_required[idx] && nitems > 0 ) { //remove eos checks ...if ( nitems < _ninput_items_required[idx] ) nitems=0; _ninput_items.push_back( nitems ); _input_items.push_back( (*istream)->read_pointer(ritems) ); } } // // setup output buffer vector based on noutput.. // ostream = ostreams.begin(); for( ; ostream != ostreams.end(); ostream++ ) { (*ostream)->resize(noutput_items); _output_items.push_back( (*ostream)->write_pointer() ); } nout=0; if ( _input_items.size() != 0 && serviceThread->threadRunning() ) { LOG_TRACE( argmax_fs_2i_base, " CALLING WORK.....N_OUT:" << noutput_items << " N_IN:" << nitems << " ISTREAMS:" << _input_items.size() << " OSTREAMS:" << _output_items.size()); nout = gr_sptr->general_work( noutput_items, _ninput_items, _input_items, _output_items); LOG_TRACE( argmax_fs_2i_base, "RETURN WORK ..... N_OUT:" << nout); } // check for stop condition from work method if ( nout < gr_block::WORK_DONE ) { LOG_WARN( argmax_fs_2i_base, "WORK RETURNED STOP CONDITION..." << nout ); nout=0; eos = true; } } if (nout != 0 or eos ) { noutput_items = nout; LOG_TRACE( argmax_fs_2i_base, " WORK RETURNED: NOUT : " << nout << " EOS:" << eos); ostream = ostreams.begin(); for ( int idx=0 ; ostream != ostreams.end(); idx++, ostream++ ) { bool gotPkt = false; TimeStamp pktTs; int inputIdx = idx; if ( (size_t)(inputIdx) >= istreams.size() ) { for ( inputIdx= istreams.size()-1; inputIdx > -1; inputIdx--) { if ( not istreams[inputIdx]->pktNull() ) { gotPkt = true; pktTs = istreams[inputIdx]->getPktTimeStamp(); break; } } } else { pktTs = istreams[inputIdx]->getPktTimeStamp(); if ( not istreams[inputIdx]->pktNull() ){ gotPkt = true; } } LOG_TRACE( argmax_fs_2i_base, "PUSHING DATA ITEMS/STREAM_ID " << (*ostream)->nitems() << "/" << (*ostream)->streamID ); if ( _maintainTimeStamp ) { // set time stamp for output samples based on input time stamp if ( (*ostream)->nelems() == 0 ) { #ifdef TEST_TIME_STAMP LOG_DEBUG( argmax_fs_2i_base, "SEED - TS SRI: xdelta:" << std::setprecision(12) << ostream->sri.xdelta ); LOG_DEBUG( argmax_fs_2i_base, "OSTREAM WRITE: maint:" << _maintainTimeStamp ); LOG_DEBUG( argmax_fs_2i_base, " mode:" << ostream->tstamp.tcmode ); LOG_DEBUG( argmax_fs_2i_base, " status:" << ostream->tstamp.tcstatus ); LOG_DEBUG( argmax_fs_2i_base, " offset:" << ostream->tstamp.toff ); LOG_DEBUG( argmax_fs_2i_base, " whole:" << std::setprecision(10) << ostream->tstamp.twsec ); LOG_DEBUG( argmax_fs_2i_base, "SEED - TS frac:" << std::setprecision(12) << ostream->tstamp.tfsec ); #endif (*ostream)->setTimeStamp( pktTs, _maintainTimeStamp ); } // write out samples, and set next time stamp based on xdelta and noutput_items (*ostream)->write ( noutput_items, eos ); } else { // use incoming packet's time stamp to forward if ( gotPkt ) { #ifdef TEST_TIME_STAMP LOG_DEBUG( argmax_fs_2i_base, "OSTREAM SRI: items/xdelta:" << noutput_items << "/" << std::setprecision(12) << ostream->sri.xdelta ); LOG_DEBUG( argmax_fs_2i_base, "PKT - TS maint:" << _maintainTimeStamp ); LOG_DEBUG( argmax_fs_2i_base, " mode:" << pktTs.tcmode ); LOG_DEBUG( argmax_fs_2i_base, " status:" << pktTs.tcstatus ); LOG_DEBUG( argmax_fs_2i_base, " offset:" << pktTs.toff ); LOG_DEBUG( argmax_fs_2i_base, " whole:" << std::setprecision(10) << pktTs.twsec ); LOG_DEBUG( argmax_fs_2i_base, "PKT - TS frac:" << std::setprecision(12) << pktTs.tfsec ); #endif (*ostream)->write( noutput_items, eos, pktTs ); } else { #ifdef TEST_TIME_STAMP LOG_DEBUG( argmax_fs_2i_base, "OSTREAM SRI: items/xdelta:" << noutput_items << "/" << std::setprecision(12) << ostream->sri.xdelta ); LOG_DEBUG( argmax_fs_2i_base, "OSTREAM TOD maint:" << _maintainTimeStamp ); LOG_DEBUG( argmax_fs_2i_base, " mode:" << ostream->tstamp.tcmode ); LOG_DEBUG( argmax_fs_2i_base, " status:" << ostream->tstamp.tcstatus ); LOG_DEBUG( argmax_fs_2i_base, " offset:" << ostream->tstamp.toff ); LOG_DEBUG( argmax_fs_2i_base, " whole:" << std::setprecision(10) << ostream->tstamp.twsec ); LOG_DEBUG( argmax_fs_2i_base, "OSTREAM TOD frac:" << std::setprecision(12) << ostream->tstamp.tfsec ); #endif // use time of day as time stamp (*ostream)->write( noutput_items, eos, _maintainTimeStamp ); } } } // for ostreams } return nout; }
static int swddp_transaction_endcheck(struct adiv5_dap *dap) { int retval; uint32_t ctrlstat; /* too expensive to call keep_alive() here */ /* Here be dragons! * * It is easy to be in a JTAG clock range where the target * is not operating in a stable fashion. This happens * for a few reasons: * * - the user may construct a simple test case to try to see * if a higher JTAG clock works to eke out more performance. * This simple case may pass, but more complex situations can * fail. * * - The mostly works JTAG clock rate and the complete failure * JTAG clock rate may be as much as 2-4x apart. This seems * to be especially true on RC oscillator driven parts. * * So: even if calling adi_jtag_scan_inout_check_u32() multiple * times here seems to "make things better here", it is just * hiding problems with too high a JTAG clock. * * Note that even if some parts have RCLK/RTCK, that doesn't * mean that RCLK/RTCK is the *correct* rate to run the JTAG * interface at, i.e. RCLK/RTCK rates can be "too high", especially * before the RC oscillator phase is not yet complete. */ /* Post CTRL/STAT read; discard any previous posted read value * but collect its ACK status. */ retval = adi_swd_scan_inout_check_u32(dap, SWD_DP_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat); if (retval != ERROR_OK) return retval; retval = jtag_execute_queue(); if (retval != ERROR_OK) return retval; dap->ack = dap->ack & 0x7; /* common code path avoids calling timeval_ms() */ if (dap->ack != SWD_ACK_OK) { long long then = timeval_ms(); while (dap->ack != SWD_ACK_OK) { if (dap->ack == SWD_ACK_WAIT) { if ((timeval_ms()-then) > 1000) { /* NOTE: this would be a good spot * to use JTAG_DP_ABORT. */ LOG_WARNING("Timeout (1000ms) waiting " "for ACK=OK/FAULT " "in swd-DP transaction"); return ERROR_JTAG_DEVICE_ERROR; } } else { LOG_WARNING("Invalid ACK %#x " "in swd-DP transaction", dap->ack); return ERROR_JTAG_DEVICE_ERROR; } retval = adi_swd_scan_inout_check_u32(dap, SWD_DP_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat); if (retval != ERROR_OK) return retval; retval = dap_run(dap); if (retval != ERROR_OK) return retval; dap->ack = dap->ack & 0x7; } } /* REVISIT also STICKYCMP, for pushed comparisons (nyet used) */ /* Check for STICKYERR and STICKYORUN */ if (ctrlstat & (SSTICKYORUN | SSTICKYERR)) { LOG_DEBUG("swd-dp: CTRL/STAT error, 0x%" PRIx32, ctrlstat); /* Check power to debug regions */ if ((ctrlstat & 0xf0000000) != 0xf0000000) { retval = ahbap_debugport_init(dap); if (retval != ERROR_OK) return retval; } else { uint32_t mem_ap_csw, mem_ap_tar; /* Maybe print information about last intended * MEM-AP access; but not if autoincrementing. * *Real* CSW and TAR values are always shown. */ if (dap->ap_tar_value != (uint32_t) -1) LOG_DEBUG("MEM-AP Cached values: " "ap_bank 0x%" PRIx32 ", ap_csw 0x%" PRIx32 ", ap_tar 0x%" PRIx32, dap->ap_bank_value, dap->ap_csw_value, dap->ap_tar_value); if (ctrlstat & SSTICKYORUN) LOG_ERROR("SWD-DP OVERRUN - check clock, " "memaccess, or reduce swd speed"); if (ctrlstat & SSTICKYERR) LOG_ERROR("SWD-DP STICKY ERROR"); /* Clear Sticky Error Bits */ // DIFF retval = adi_swd_scan_inout_check_u32(dap, SWD_DP_DPACC, DP_ABORT, DPAP_WRITE, dap->dp_ctrl_stat | ORUNERRCLR | STKERRCLR, NULL); if (retval != ERROR_OK) return retval; retval = adi_swd_scan_inout_check_u32(dap, SWD_DP_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat); if (retval != ERROR_OK) return retval; retval = dap_run(dap); if (retval != ERROR_OK) return retval; LOG_DEBUG("swd-dp: CTRL/STAT 0x%" PRIx32, ctrlstat); retval = dap_queue_ap_read(dap, AP_REG_CSW, &mem_ap_csw); if (retval != ERROR_OK) return retval; retval = dap_queue_ap_read(dap, AP_REG_TAR, &mem_ap_tar); if (retval != ERROR_OK) return retval; retval = dap_run(dap); if (retval != ERROR_OK) return retval; LOG_ERROR("MEM_AP_CSW 0x%" PRIx32 ", MEM_AP_TAR 0x%" PRIx32, mem_ap_csw, mem_ap_tar); } retval = dap_run(dap); if (retval != ERROR_OK) return retval; return ERROR_JTAG_DEVICE_ERROR; } return ERROR_OK; }
void argmax_fs_2i_base::setupIOMappings( ) { int ninput_streams = 0; int noutput_streams = 0; std::string sid(""); int inMode=RealMode; if ( !validGRBlock() ) return; ninput_streams = gr_sptr->get_max_input_streams(); gr_io_signature_sptr g_isig = gr_sptr->input_signature(); noutput_streams = gr_sptr->get_max_output_streams(); gr_io_signature_sptr g_osig = gr_sptr->output_signature(); LOG_DEBUG( argmax_fs_2i_base, "GNUHAWK IO MAPPINGS IN/OUT " << ninput_streams << "/" << noutput_streams ); // // Someone reset the GR Block so we need to clean up old mappings if they exists // we need to reset the io signatures and check the vlens // if ( _istreams.size() > 0 || _ostreams.size() > 0 ) { LOG_DEBUG( argmax_fs_2i_base, "RESET INPUT SIGNATURE SIZE:" << _istreams.size() ); IStreamList::iterator istream; for ( int idx=0 ; istream != _istreams.end(); idx++, istream++ ) { // re-add existing stream definitons LOG_DEBUG( argmax_fs_2i_base, "ADD READ INDEX TO GNU RADIO BLOCK"); if ( ninput_streams == -1 ) gr_sptr->add_read_index(); // setup io signature (*istream)->associate( gr_sptr ); } LOG_DEBUG( argmax_fs_2i_base, "RESET OUTPUT SIGNATURE SIZE:" << _ostreams.size() ); OStreamList::iterator ostream; for ( int idx=0 ; ostream != _ostreams.end(); idx++, ostream++ ) { // need to evaluate new settings...??? (*ostream)->associate( gr_sptr ); } return; } int i = 0; // // Setup mapping of RH port to GNU RADIO Block input streams // For version 1, we are ignoring the GNU Radio input stream -1 case that allows multiple data // streams over a single connection. We are mapping a single RH Port to a single GNU Radio stream. // Stream Identifiers will be pass along as they are received // LOG_TRACE( argmax_fs_2i_base, "setupIOMappings INPUT PORTS: " << inPorts.size() ); RH_ProvidesPortMap::iterator p_in; i = 0; // grab ports based on their order in the scd.xml file p_in = inPorts.find("float_in_1"); if ( p_in != inPorts.end() ) { bulkio::InFloatPort *port = dynamic_cast< bulkio::InFloatPort * >(p_in->second); int mode = inMode; sid = ""; // need to add read index to GNU Radio Block for processing streams when max_input == -1 if ( ninput_streams == -1 ) gr_sptr->add_read_index(); // check if we received SRI during setup BULKIO::StreamSRISequence_var sris = port->activeSRIs(); if ( sris->length() > 0 ) { BULKIO::StreamSRI sri = sris[sris->length()-1]; mode = sri.mode; } std::vector<int> in; io_mapping.push_back( in ); _istreams.push_back( new gr_istream< bulkio::InFloatPort > ( port, gr_sptr, i, mode, sid )); LOG_DEBUG( argmax_fs_2i_base, "ADDING INPUT MAP IDX:" << i << " SID:" << sid ); // increment port counter i++; } // grab ports based on their order in the scd.xml file p_in = inPorts.find("float_in_2"); if ( p_in != inPorts.end() ) { bulkio::InFloatPort *port = dynamic_cast< bulkio::InFloatPort * >(p_in->second); int mode = inMode; sid = ""; // need to add read index to GNU Radio Block for processing streams when max_input == -1 if ( ninput_streams == -1 ) gr_sptr->add_read_index(); // check if we received SRI during setup BULKIO::StreamSRISequence_var sris = port->activeSRIs(); if ( sris->length() > 0 ) { BULKIO::StreamSRI sri = sris[sris->length()-1]; mode = sri.mode; } std::vector<int> in; io_mapping.push_back( in ); _istreams.push_back( new gr_istream< bulkio::InFloatPort > ( port, gr_sptr, i, mode, sid )); LOG_DEBUG( argmax_fs_2i_base, "ADDING INPUT MAP IDX:" << i << " SID:" << sid ); // increment port counter i++; } // // Setup mapping of RH port to GNU RADIO Block input streams // For version 1, we are ignoring the GNU Radio output stream -1 case that allows multiple data // streams over a single connection. We are mapping a single RH Port to a single GNU Radio stream. // LOG_TRACE( argmax_fs_2i_base, "setupIOMappings OutputPorts: " << outPorts.size() ); RH_UsesPortMap::iterator p_out; i = 0; // grab ports based on their order in the scd.xml file p_out = outPorts.find("short_out_1"); if ( p_out != outPorts.end() ) { bulkio::OutShortPort *port = dynamic_cast< bulkio::OutShortPort * >(p_out->second); int idx = -1; BULKIO::StreamSRI sri = createOutputSRI( i, idx ); if (idx == -1) idx = i; if(idx < (int)io_mapping.size()) io_mapping[idx].push_back(i); int mode = sri.mode; sid = sri.streamID; _ostreams.push_back( new gr_ostream< bulkio::OutShortPort > ( port, gr_sptr, i, mode, sid )); LOG_DEBUG( argmax_fs_2i_base, "ADDING OUTPUT MAP IDX:" << i << " SID:" << sid ); _ostreams[i]->setSRI(sri, i ); // increment port counter i++; } // grab ports based on their order in the scd.xml file p_out = outPorts.find("short_out_2"); if ( p_out != outPorts.end() ) { bulkio::OutShortPort *port = dynamic_cast< bulkio::OutShortPort * >(p_out->second); int idx = -1; BULKIO::StreamSRI sri = createOutputSRI( i, idx ); if (idx == -1) idx = i; if(idx < (int)io_mapping.size()) io_mapping[idx].push_back(i); int mode = sri.mode; sid = sri.streamID; _ostreams.push_back( new gr_ostream< bulkio::OutShortPort > ( port, gr_sptr, i, mode, sid )); LOG_DEBUG( argmax_fs_2i_base, "ADDING OUTPUT MAP IDX:" << i << " SID:" << sid ); _ostreams[i]->setSRI(sri, i ); // increment port counter i++; } }
bool CHttpDownloader::download(std::list<IDownload*>& download) { std::list<IDownload*>::iterator it; std::vector <DownloadData*> downloads; CURLM* curlm=curl_multi_init(); for(it=download.begin(); it!=download.end(); ++it) { const int count=std::min(MAX_PARALLEL_DOWNLOADS, std::max(1, std::min((int)(*it)->pieces.size(), (*it)->getMirrorCount()))); //count of parallel downloads if((*it)->getMirrorCount()<=0) { LOG_ERROR("No mirrors found"); return false; } LOG_DEBUG("Using %d parallel downloads", count); CFile* file=new CFile(); if(!file->Open((*it)->name, (*it)->size, (*it)->piecesize)) { delete file; return false; } (*it)->file = file; for(int i=0; i<count; i++) { DownloadData* dlData=new DownloadData(); dlData->download=*it; if (!setupDownload(dlData)) { //no piece found (all pieces already downloaded), skip delete dlData; if ((*it)->state!=IDownload::STATE_FINISHED) { LOG_ERROR("no piece found"); return false; } } else { downloads.push_back(dlData); curl_multi_add_handle(curlm, dlData->easy_handle); } } } bool aborted=false; int running=1, last=-1; while((running>0)&&(!aborted)) { CURLMcode ret = CURLM_CALL_MULTI_PERFORM; while(ret == CURLM_CALL_MULTI_PERFORM) { ret=curl_multi_perform(curlm, &running); } if ( ret == CURLM_OK ) { // showProcess(download, file); if (last!=running) { //count of running downloads changed aborted=processMessages(curlm, downloads); last=running++; } } else { LOG_ERROR("curl_multi_perform_error: %d", ret); aborted=true; } fd_set rSet; fd_set wSet; fd_set eSet; FD_ZERO(&rSet); FD_ZERO(&wSet); FD_ZERO(&eSet); int count=0; struct timeval t; t.tv_sec = 1; t.tv_usec = 0; curl_multi_fdset(curlm, &rSet, &wSet, &eSet, &count); //sleep for one sec / until something happened select(count+1, &rSet, &wSet, &eSet, &t); } if (!aborted) { // if download didn't fail, get file size reported in http-header double size=-1; for (unsigned i=0; i<downloads.size(); i++) { double tmp; curl_easy_getinfo(downloads[i]->easy_handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &tmp); if (tmp>size) { size=tmp; } } //set download size if isn't set and we have a valid number // if ((size>0) && (download->size<0)) { // download->size = size; // } } // showProcess(download, file); LOG("\n"); if (!aborted) { LOG_DEBUG("download complete"); } //close all open files for(it=download.begin(); it!=download.end(); ++it) { if ((*it)->file!=NULL) (*it)->file->Close(); } for (unsigned i=0; i<downloads.size(); i++) { long timestamp; if (curl_easy_getinfo(downloads[i]->easy_handle, CURLINFO_FILETIME, ×tamp) == CURLE_OK) { if (downloads[i]->download->state != IDownload::STATE_FINISHED) //decrease local timestamp if download failed to force redownload next time timestamp--; downloads[i]->download->file->SetTimestamp(timestamp); } delete downloads[i]; } downloads.clear(); curl_multi_cleanup(curlm); return !aborted; }
bool CHttpDownloader::search(std::list<IDownload*>& res, const std::string& name, IDownload::category cat) { LOG_DEBUG("%s", name.c_str() ); const std::string method(XMLRPC_METHOD); //std::string category; XmlRpc::XmlRpcClient client(XMLRPC_HOST,XMLRPC_PORT, XMLRPC_URI); XmlRpc::XmlRpcValue arg; arg["springname"]=name; arg["torrent"]=true; switch(cat) { case IDownload::CAT_MAPS: arg["category"]="map"; break; case IDownload::CAT_GAMES: arg["category"]="game"; break; case IDownload::CAT_ENGINE_LINUX: arg["category"]="engine_linux"; break; case IDownload::CAT_ENGINE_LINUX64: arg["category"]="engine_linux64"; break; case IDownload::CAT_ENGINE_WINDOWS: arg["category"]="engine_windows"; break; case IDownload::CAT_ENGINE_MACOSX: arg["category"]="engine_macosx"; break; default: break; } XmlRpc::XmlRpcValue result; client.execute(method.c_str(),arg, result); if (result.getType()!=XmlRpc::XmlRpcValue::TypeArray) { return false; } for(int i=0; i<result.size(); i++) { XmlRpc::XmlRpcValue resfile = result[i]; if (resfile.getType()!=XmlRpc::XmlRpcValue::TypeStruct) { return false; } if (resfile["category"].getType()!=XmlRpc::XmlRpcValue::TypeString) { LOG_ERROR("No category in result"); return false; } std::string filename=fileSystem->getSpringDir(); std::string category=resfile["category"]; filename+=PATH_DELIMITER; if (category=="map") filename+="maps"; else if (category=="game") filename+="games"; else if (category.find("engine")==0) // engine_windows, engine_linux, engine_macosx filename+="engine"; else LOG_ERROR("Unknown Category %s", category.c_str()); filename+=PATH_DELIMITER; if ((resfile["mirrors"].getType()!=XmlRpc::XmlRpcValue::TypeArray) || (resfile["filename"].getType()!=XmlRpc::XmlRpcValue::TypeString)) { LOG_ERROR("Invalid type in result"); return false; } filename.append(resfile["filename"]); IDownload* dl=new IDownload(filename); XmlRpc::XmlRpcValue mirrors = resfile["mirrors"]; for(int j=0; j<mirrors.size(); j++) { if (mirrors[j].getType()!=XmlRpc::XmlRpcValue::TypeString) { LOG_ERROR("Invalid type in result"); } else { dl->addMirror(mirrors[j]); } } if(resfile["torrent"].getType()==XmlRpc::XmlRpcValue::TypeBase64) { const std::vector<char> torrent = resfile["torrent"]; fileSystem->parseTorrent(&torrent[0], torrent.size(), dl); } if (resfile["version"].getType()==XmlRpc::XmlRpcValue::TypeString) { const std::string& version = resfile["version"]; dl->version = version; } if (resfile["md5"].getType()==XmlRpc::XmlRpcValue::TypeString) { dl->hash=new HashMD5(); dl->hash->Set(resfile["md5"]); } if (resfile["size"].getType()==XmlRpc::XmlRpcValue::TypeInt) { dl->size=resfile["size"]; } if (resfile["depends"].getType() == XmlRpc::XmlRpcValue::TypeArray) { for(int i=0; i<resfile["depends"].size(); i++) { if (resfile["depends"][i].getType() == XmlRpc::XmlRpcValue::TypeString) { const std::string &dep = resfile["depends"][i]; dl->addDepend(dep); } } } res.push_back(dl); } return true; }
bool CHttpDownloader::processMessages(CURLM* curlm, std::vector <DownloadData*>& downloads) { int msgs_left; HashSHA1 sha1; bool aborted=false; while(struct CURLMsg* msg=curl_multi_info_read(curlm, &msgs_left)) { switch(msg->msg) { case CURLMSG_DONE: { //a piece has been downloaded, verify it DownloadData* data=getDataByHandle(downloads, msg->easy_handle); switch(msg->data.result) { case CURLE_OK: break; case CURLE_HTTP_RETURNED_ERROR: //some 4* HTTP-Error (file not found, access denied,...) default: long http_code = 0; curl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE, &http_code); LOG_ERROR("CURL error(%d): %s %d (%s)",msg->msg, curl_easy_strerror(msg->data.result), http_code, data->mirror->url.c_str()); if (data->piece>=0) { data->download->pieces[data->piece].state=IDownload::STATE_NONE; } data->mirror->status=Mirror::STATUS_BROKEN; //FIXME: cleanup curl handle here + process next dl } if (data==NULL) { LOG_ERROR("Couldn't find download in download list"); return false; } if (data->piece<0) { //download without pieces return false; } assert(data->download->file!=NULL); assert(data->piece< (int)data->download->pieces.size()); if (data->download->pieces[data->piece].sha->isSet()) { data->download->file->Hash(sha1, data->piece); if (sha1.compare(data->download->pieces[data->piece].sha)) { //piece valid data->download->pieces[data->piece].state=IDownload::STATE_FINISHED; showProcess(data->download, true); // LOG("piece %d verified!", data->piece); } else { //piece download broken, mark mirror as broken (for this file) data->download->pieces[data->piece].state=IDownload::STATE_NONE; data->mirror->status=Mirror::STATUS_BROKEN; //FIXME: cleanup curl handle here + process next dl } } else { LOG_INFO("sha1 checksum seems to be not set, can't check received piece %d", data->piece); } //get speed at which this piece was downloaded + update mirror info double dlSpeed; curl_easy_getinfo(data->easy_handle, CURLINFO_SPEED_DOWNLOAD, &dlSpeed); data->mirror->UpdateSpeed(dlSpeed); if (data->mirror->status == Mirror::STATUS_UNKNOWN) //set mirror status only when unset data->mirror->status=Mirror::STATUS_OK; //remove easy handle, as its finished curl_multi_remove_handle(curlm, data->easy_handle); curl_easy_cleanup(data->easy_handle); data->easy_handle=NULL; //piece finished / failed, try a new one if (!setupDownload(data)) { LOG_DEBUG("No piece found, all pieces finished / currently downloading"); break; } int ret=curl_multi_add_handle(curlm, data->easy_handle); if (ret!=CURLM_OK) { LOG_ERROR("curl_multi_perform_error: %d %d", ret, CURLM_BAD_EASY_HANDLE); } break; } default: LOG_ERROR("Unhandled message %d", msg->msg); } } return aborted; }
int adaptor_init(zhandle_t *zh) { pthread_mutexattr_t recursive_mx_attr; struct adaptor_threads *adaptor_threads = calloc(1, sizeof(*adaptor_threads)); if (!adaptor_threads) { LOG_ERROR(("Out of memory")); return -1; } /* We use a pipe for interrupting select() in unix/sol and socketpair in windows. */ #ifdef WIN32 if (create_socket_pair(adaptor_threads->self_pipe) == -1){ LOG_ERROR(("Can't make a socket.")); #else if(pipe(adaptor_threads->self_pipe)==-1) { LOG_ERROR(("Can't make a pipe %d",errno)); #endif free(adaptor_threads); return -1; } set_nonblock(adaptor_threads->self_pipe[1]); set_nonblock(adaptor_threads->self_pipe[0]); pthread_mutex_init(&zh->auth_h.lock,0); zh->adaptor_priv = adaptor_threads; pthread_mutex_init(&zh->to_process.lock,0); pthread_mutex_init(&adaptor_threads->zh_lock,0); // to_send must be recursive mutex pthread_mutexattr_init(&recursive_mx_attr); pthread_mutexattr_settype(&recursive_mx_attr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&zh->to_send.lock,&recursive_mx_attr); pthread_mutexattr_destroy(&recursive_mx_attr); pthread_mutex_init(&zh->sent_requests.lock,0); pthread_cond_init(&zh->sent_requests.cond,0); pthread_mutex_init(&zh->completions_to_process.lock,0); pthread_cond_init(&zh->completions_to_process.cond,0); start_threads(zh); return 0; } void adaptor_finish(zhandle_t *zh) { struct adaptor_threads *adaptor_threads; // make sure zh doesn't get destroyed until after we're done here api_prolog(zh); adaptor_threads = zh->adaptor_priv; if(adaptor_threads==0) { api_epilog(zh,0); return; } if(!pthread_equal(adaptor_threads->io,pthread_self())){ wakeup_io_thread(zh); pthread_join(adaptor_threads->io, 0); }else pthread_detach(adaptor_threads->io); if(!pthread_equal(adaptor_threads->completion,pthread_self())){ pthread_mutex_lock(&zh->completions_to_process.lock); pthread_cond_broadcast(&zh->completions_to_process.cond); pthread_mutex_unlock(&zh->completions_to_process.lock); pthread_join(adaptor_threads->completion, 0); }else pthread_detach(adaptor_threads->completion); api_epilog(zh,0); } void adaptor_destroy(zhandle_t *zh) { struct adaptor_threads *adaptor = zh->adaptor_priv; if(adaptor==0) return; pthread_cond_destroy(&adaptor->cond); pthread_mutex_destroy(&adaptor->lock); pthread_mutex_destroy(&zh->to_process.lock); pthread_mutex_destroy(&zh->to_send.lock); pthread_mutex_destroy(&zh->sent_requests.lock); pthread_cond_destroy(&zh->sent_requests.cond); pthread_mutex_destroy(&zh->completions_to_process.lock); pthread_cond_destroy(&zh->completions_to_process.cond); pthread_mutex_destroy(&adaptor->zh_lock); pthread_mutex_destroy(&zh->auth_h.lock); close(adaptor->self_pipe[0]); close(adaptor->self_pipe[1]); free(adaptor); zh->adaptor_priv=0; } int wakeup_io_thread(zhandle_t *zh) { struct adaptor_threads *adaptor_threads = zh->adaptor_priv; char c=0; #ifndef WIN32 return write(adaptor_threads->self_pipe[1],&c,1)==1? ZOK: ZSYSTEMERROR; #else return send(adaptor_threads->self_pipe[1], &c, 1, 0)==1? ZOK: ZSYSTEMERROR; #endif } int adaptor_send_queue(zhandle_t *zh, int timeout) { if(!zh->close_requested) return wakeup_io_thread(zh); // don't rely on the IO thread to send the messages if the app has // requested to close return flush_send_queue(zh, timeout); } /* These two are declared here because we will run the event loop * and not the client */ #ifdef WIN32 int zookeeper_interest(zhandle_t *zh, SOCKET *fd, int *interest, struct timeval *tv); #else int zookeeper_interest(zhandle_t *zh, int *fd, int *interest, struct timeval *tv); #endif int zookeeper_process(zhandle_t *zh, int events); #ifdef WIN32 unsigned __stdcall do_io( void * v) #else void *do_io(void *v) #endif { zhandle_t *zh = (zhandle_t*)v; #ifndef WIN32 struct pollfd fds[2]; struct adaptor_threads *adaptor_threads = zh->adaptor_priv; api_prolog(zh); notify_thread_ready(zh); LOG_DEBUG(("started IO thread")); fds[0].fd=adaptor_threads->self_pipe[0]; fds[0].events=POLLIN; while(!zh->close_requested) { struct timeval tv; int fd; int interest; int timeout; int maxfd=1; int rc; zookeeper_interest(zh, &fd, &interest, &tv); if (fd != -1) { fds[1].fd=fd; fds[1].events=(interest&ZOOKEEPER_READ)?POLLIN:0; fds[1].events|=(interest&ZOOKEEPER_WRITE)?POLLOUT:0; maxfd=2; } timeout=tv.tv_sec * 1000 + (tv.tv_usec/1000); poll(fds,maxfd,timeout); if (fd != -1) { interest=(fds[1].revents&POLLIN)?ZOOKEEPER_READ:0; interest|=((fds[1].revents&POLLOUT)||(fds[1].revents&POLLHUP))?ZOOKEEPER_WRITE:0; } if(fds[0].revents&POLLIN){ // flush the pipe char b[128]; while(read(adaptor_threads->self_pipe[0],b,sizeof(b))==sizeof(b)){} } #else fd_set rfds, wfds, efds; struct adaptor_threads *adaptor_threads = zh->adaptor_priv; api_prolog(zh); notify_thread_ready(zh); LOG_DEBUG(("started IO thread")); FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds); while(!zh->close_requested) { struct timeval tv; SOCKET fd; SOCKET maxfd=adaptor_threads->self_pipe[0]; int interest; int rc; zookeeper_interest(zh, &fd, &interest, &tv); if (fd != -1) { if (interest&ZOOKEEPER_READ) { FD_SET(fd, &rfds); } else { FD_CLR(fd, &rfds); } if (interest&ZOOKEEPER_WRITE) { FD_SET(fd, &wfds); } else { FD_CLR(fd, &wfds); } } FD_SET( adaptor_threads->self_pipe[0] ,&rfds ); rc = select((int)maxfd, &rfds, &wfds, &efds, &tv); if (fd != -1) { interest = (FD_ISSET(fd, &rfds))? ZOOKEEPER_READ:0; interest|= (FD_ISSET(fd, &wfds))? ZOOKEEPER_WRITE:0; } if (FD_ISSET(adaptor_threads->self_pipe[0], &rfds)){ // flush the pipe/socket char b[128]; while(recv(adaptor_threads->self_pipe[0],b,sizeof(b), 0)==sizeof(b)){} } #endif // dispatch zookeeper events rc = zookeeper_process(zh, interest); // check the current state of the zhandle and terminate // if it is_unrecoverable() if(is_unrecoverable(zh)) break; } api_epilog(zh, 0); LOG_DEBUG(("IO thread terminated")); return 0; } #ifdef WIN32 unsigned __stdcall do_completion( void * v) #else void *do_completion(void *v) #endif { zhandle_t *zh = v; api_prolog(zh); notify_thread_ready(zh); LOG_DEBUG(("started completion thread")); while(!zh->close_requested) { pthread_mutex_lock(&zh->completions_to_process.lock); while(!zh->completions_to_process.head && !zh->close_requested) { pthread_cond_wait(&zh->completions_to_process.cond, &zh->completions_to_process.lock); } pthread_mutex_unlock(&zh->completions_to_process.lock); process_completions(zh); } api_epilog(zh, 0); LOG_DEBUG(("completion thread terminated")); return 0; }
/** * Save processor state. This is called after a HALT instruction * succeeds, and on other occasions the processor enters debug mode * (breakpoint, watchpoint, etc). Caller has updated arm11->dscr. */ static int arm11_debug_entry(struct arm11_common *arm11) { int retval; arm11->arm.target->state = TARGET_HALTED; arm_dpm_report_dscr(arm11->arm.dpm, arm11->dscr); /* REVISIT entire cache should already be invalid !!! */ register_cache_invalidate(arm11->arm.core_cache); /* See e.g. ARM1136 TRM, "14.8.4 Entering Debug state" */ /* maybe save wDTR (pending DCC write to debug SW, e.g. libdcc) */ arm11->is_wdtr_saved = !!(arm11->dscr & DSCR_DTR_TX_FULL); if (arm11->is_wdtr_saved) { arm11_add_debug_SCAN_N(arm11, 0x05, ARM11_TAP_DEFAULT); arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT); struct scan_field chain5_fields[3]; arm11_setup_field(arm11, 32, NULL, &arm11->saved_wdtr, chain5_fields + 0); arm11_setup_field(arm11, 1, NULL, NULL, chain5_fields + 1); arm11_setup_field(arm11, 1, NULL, NULL, chain5_fields + 2); arm11_add_dr_scan_vc(ARRAY_SIZE(chain5_fields), chain5_fields, TAP_DRPAUSE); } /* DSCR: set the Execute ARM instruction enable bit. * * ARM1176 spec says this is needed only for wDTR/rDTR's "ITR mode", * but not to issue ITRs(?). The ARMv7 arch spec says it's required * for executing instructions via ITR. */ arm11_write_DSCR(arm11, DSCR_ITR_EN | arm11->dscr); /* From the spec: Before executing any instruction in debug state you have to drain the write buffer. This ensures that no imprecise Data Aborts can return at a later point:*/ /** \todo TODO: Test drain write buffer. */ #if 0 while (1) { /* MRC p14,0,R0,c5,c10,0 */ // arm11_run_instr_no_data1(arm11, /*0xee150e1a*/0xe320f000); /* mcr 15, 0, r0, cr7, cr10, {4} */ arm11_run_instr_no_data1(arm11, 0xee070f9a); uint32_t dscr = arm11_read_DSCR(arm11); LOG_DEBUG("DRAIN, DSCR %08x", dscr); if (dscr & ARM11_DSCR_STICKY_IMPRECISE_DATA_ABORT) { arm11_run_instr_no_data1(arm11, 0xe320f000); dscr = arm11_read_DSCR(arm11); LOG_DEBUG("DRAIN, DSCR %08x (DONE)", dscr); break; } } #endif /* Save registers. * * NOTE: ARM1136 TRM suggests saving just R0 here now, then * CPSR and PC after the rDTR stuff. We do it all at once. */ retval = arm_dpm_read_current_registers(&arm11->dpm); if (retval != ERROR_OK) LOG_ERROR("DPM REG READ -- fail %d", retval); retval = arm11_run_instr_data_prepare(arm11); if (retval != ERROR_OK) return retval; /* maybe save rDTR (pending DCC read from debug SW, e.g. libdcc) */ arm11->is_rdtr_saved = !!(arm11->dscr & DSCR_DTR_RX_FULL); if (arm11->is_rdtr_saved) { /* MRC p14,0,R0,c0,c5,0 (move rDTR -> r0 (-> wDTR -> local var)) */ retval = arm11_run_instr_data_from_core_via_r0(arm11, 0xEE100E15, &arm11->saved_rdtr); if (retval != ERROR_OK) return retval; } /* REVISIT Now that we've saved core state, there's may also * be MMU and cache state to care about ... */ if (arm11->simulate_reset_on_next_halt) { arm11->simulate_reset_on_next_halt = false; LOG_DEBUG("Reset c1 Control Register"); /* Write 0 (reset value) to Control register 0 to disable MMU/Cache etc. */ /* MCR p15,0,R0,c1,c0,0 */ retval = arm11_run_instr_data_to_core_via_r0(arm11, 0xee010f10, 0); if (retval != ERROR_OK) return retval; } if (arm11->arm.target->debug_reason == DBG_REASON_WATCHPOINT) { uint32_t wfar; /* MRC p15, 0, <Rd>, c6, c0, 1 ; Read WFAR */ retval = arm11_run_instr_data_from_core_via_r0(arm11, ARMV4_5_MRC(15, 0, 0, 6, 0, 1), &wfar); if (retval != ERROR_OK) return retval; arm_dpm_report_wfar(arm11->arm.dpm, wfar); } retval = arm11_run_instr_data_finish(arm11); if (retval != ERROR_OK) return retval; return ERROR_OK; }
// read mp4 header to extract config data static int read_mp4_header(unsigned long *samplerate_p, unsigned char *channels_p) { size_t bytes = min(_buf_used(streambuf), _buf_cont_read(streambuf)); char type[5]; u32_t len; while (bytes >= 8) { // count trak to find the first playable one static unsigned trak, play; u32_t consume; len = unpackN((u32_t *)streambuf->readp); memcpy(type, streambuf->readp + 4, 4); type[4] = '\0'; if (!strcmp(type, "moov")) { trak = 0; play = 0; } if (!strcmp(type, "trak")) { trak++; } // extract audio config from within esds and pass to DecInit2 if (!strcmp(type, "esds") && bytes > len) { unsigned config_len; u8_t *ptr = streambuf->readp + 12; if (*ptr++ == 0x03) { mp4_desc_length(&ptr); ptr += 4; } else { ptr += 3; } mp4_desc_length(&ptr); ptr += 13; if (*ptr++ != 0x05) { LOG_WARN("error parsing esds"); return -1; } config_len = mp4_desc_length(&ptr); if (NEAAC(a, Init2, a->hAac, ptr, config_len, samplerate_p, channels_p) == 0) { LOG_DEBUG("playable aac track: %u", trak); play = trak; } } // extract the total number of samples from stts if (!strcmp(type, "stts") && bytes > len) { u32_t i; u8_t *ptr = streambuf->readp + 12; u32_t entries = unpackN((u32_t *)ptr); ptr += 4; for (i = 0; i < entries; ++i) { u32_t count = unpackN((u32_t *)ptr); u32_t size = unpackN((u32_t *)(ptr + 4)); a->sttssamples += count * size; ptr += 8; } LOG_DEBUG("total number of samples contained in stts: " FMT_u64, a->sttssamples); } // stash sample to chunk info, assume it comes before stco if (!strcmp(type, "stsc") && bytes > len && !a->chunkinfo) { a->stsc = malloc(len - 12); if (a->stsc == NULL) { LOG_WARN("malloc fail"); return -1; } memcpy(a->stsc, streambuf->readp + 12, len - 12); } // build offsets table from stco and stored stsc if (!strcmp(type, "stco") && bytes > len && play == trak) { u32_t i; // extract chunk offsets u8_t *ptr = streambuf->readp + 12; u32_t entries = unpackN((u32_t *)ptr); ptr += 4; a->chunkinfo = malloc(sizeof(struct chunk_table) * (entries + 1)); if (a->chunkinfo == NULL) { LOG_WARN("malloc fail"); return -1; } for (i = 0; i < entries; ++i) { a->chunkinfo[i].offset = unpackN((u32_t *)ptr); a->chunkinfo[i].sample = 0; ptr += 4; } a->chunkinfo[i].sample = 0; a->chunkinfo[i].offset = 0; // fill in first sample id for each chunk from stored stsc if (a->stsc) { u32_t stsc_entries = unpackN((u32_t *)a->stsc); u32_t sample = 0; u32_t last = 0, last_samples = 0; u8_t *ptr = (u8_t *)a->stsc + 4; while (stsc_entries--) { u32_t first = unpackN((u32_t *)ptr); u32_t samples = unpackN((u32_t *)(ptr + 4)); if (last) { for (i = last - 1; i < first - 1; ++i) { a->chunkinfo[i].sample = sample; sample += last_samples; } } if (stsc_entries == 0) { for (i = first - 1; i < entries; ++i) { a->chunkinfo[i].sample = sample; sample += samples; } } last = first; last_samples = samples; ptr += 12; } free(a->stsc); a->stsc = NULL; } } // found media data, advance to start of first chunk and return if (!strcmp(type, "mdat")) { _buf_inc_readp(streambuf, 8); a->pos += 8; bytes -= 8; if (play) { LOG_DEBUG("type: mdat len: %u pos: %u", len, a->pos); if (a->chunkinfo && a->chunkinfo[0].offset > a->pos) { u32_t skip = a->chunkinfo[0].offset - a->pos; LOG_DEBUG("skipping: %u", skip); if (skip <= bytes) { _buf_inc_readp(streambuf, skip); a->pos += skip; } else { a->consume = skip; } } a->sample = a->nextchunk = 1; return 1; } else { LOG_DEBUG("type: mdat len: %u, no playable track found", len); return -1; } } // parse key-value atoms within ilst ---- entries to get encoder padding within iTunSMPB entry for gapless if (!strcmp(type, "----") && bytes > len) { u8_t *ptr = streambuf->readp + 8; u32_t remain = len - 8, size; if (!memcmp(ptr + 4, "mean", 4) && (size = unpackN((u32_t *)ptr)) < remain) { ptr += size; remain -= size; } if (!memcmp(ptr + 4, "name", 4) && (size = unpackN((u32_t *)ptr)) < remain && !memcmp(ptr + 12, "iTunSMPB", 8)) { ptr += size; remain -= size; } if (!memcmp(ptr + 4, "data", 4) && remain > 16 + 48) { // data is stored as hex strings: 0 start end samples u32_t b, c; u64_t d; if (sscanf((const char *)(ptr + 16), "%x %x %x " FMT_x64, &b, &b, &c, &d) == 4) { LOG_DEBUG("iTunSMPB start: %u end: %u samples: " FMT_u64, b, c, d); if (a->sttssamples && a->sttssamples < b + c + d) { LOG_DEBUG("reducing samples as stts count is less"); d = a->sttssamples - (b + c); } a->skip = b; a->samples = d; } } } // default to consuming entire box consume = len; // read into these boxes so reduce consume if (!strcmp(type, "moov") || !strcmp(type, "trak") || !strcmp(type, "mdia") || !strcmp(type, "minf") || !strcmp(type, "stbl") || !strcmp(type, "udta") || !strcmp(type, "ilst")) { consume = 8; } // special cases which mix mix data in the enclosing box which we want to read into if (!strcmp(type, "stsd")) consume = 16; if (!strcmp(type, "mp4a")) consume = 36; if (!strcmp(type, "meta")) consume = 12; // consume rest of box if it has been parsed (all in the buffer) or is not one we want to parse if (bytes >= consume) { LOG_DEBUG("type: %s len: %u consume: %u", type, len, consume); _buf_inc_readp(streambuf, consume); a->pos += consume; bytes -= consume; } else if ( !(!strcmp(type, "esds") || !strcmp(type, "stts") || !strcmp(type, "stsc") || !strcmp(type, "stco") || !strcmp(type, "----")) ) { LOG_DEBUG("type: %s len: %u consume: %u - partial consume: %u", type, len, consume, bytes); _buf_inc_readp(streambuf, bytes); a->pos += bytes; a->consume = consume - bytes; break; } else { break; } } return 0; }
/* talk to the target and set things up */ static int arm11_examine(struct target *target) { int retval; char *type; struct arm11_common *arm11 = target_to_arm11(target); uint32_t didr, device_id; uint8_t implementor; /* FIXME split into do-first-time and do-every-time logic ... */ /* check IDCODE */ arm11_add_IR(arm11, ARM11_IDCODE, ARM11_TAP_DEFAULT); struct scan_field idcode_field; arm11_setup_field(arm11, 32, NULL, &device_id, &idcode_field); arm11_add_dr_scan_vc(1, &idcode_field, TAP_DRPAUSE); /* check DIDR */ arm11_add_debug_SCAN_N(arm11, 0x00, ARM11_TAP_DEFAULT); arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT); struct scan_field chain0_fields[2]; arm11_setup_field(arm11, 32, NULL, &didr, chain0_fields + 0); arm11_setup_field(arm11, 8, NULL, &implementor, chain0_fields + 1); arm11_add_dr_scan_vc(ARRAY_SIZE(chain0_fields), chain0_fields, TAP_IDLE); CHECK_RETVAL(jtag_execute_queue()); /* assume the manufacturer id is ok; check the part # */ switch ((device_id >> 12) & 0xFFFF) { case 0x7B36: type = "ARM1136"; break; case 0x7B37: type = "ARM11 MPCore"; break; case 0x7B56: type = "ARM1156"; break; case 0x7B76: arm11->arm.core_type = ARM_MODE_MON; type = "ARM1176"; break; default: LOG_ERROR("unexpected ARM11 ID code"); return ERROR_FAIL; } LOG_INFO("found %s", type); /* unlikely this could ever fail, but ... */ switch ((didr >> 16) & 0x0F) { case ARM11_DEBUG_V6: case ARM11_DEBUG_V61: /* supports security extensions */ break; default: LOG_ERROR("Only ARM v6 and v6.1 debug supported."); return ERROR_FAIL; } arm11->brp = ((didr >> 24) & 0x0F) + 1; /** \todo TODO: reserve one brp slot if we allow breakpoints during step */ arm11->free_brps = arm11->brp; LOG_DEBUG("IDCODE %08" PRIx32 " IMPLEMENTOR %02x DIDR %08" PRIx32, device_id, implementor, didr); /* as a side-effect this reads DSCR and thus * clears the ARM11_DSCR_STICKY_PRECISE_DATA_ABORT / Sticky Precise Data Abort Flag * as suggested by the spec. */ retval = arm11_check_init(arm11); if (retval != ERROR_OK) return retval; /* Build register cache "late", after target_init(), since we * want to know if this core supports Secure Monitor mode. */ if (!target_was_examined(target)) retval = arm11_dpm_init(arm11, didr); /* ETM on ARM11 still uses original scanchain 6 access mode */ if (arm11->arm.etm && !target_was_examined(target)) { *register_get_last_cache_p(&target->reg_cache) = etm_build_reg_cache(target, &arm11->jtag_info, arm11->arm.etm); retval = etm_setup(target); } target_set_examined(target); return ERROR_OK; }
pj_status_t init_stack(const std::string& system_name, const std::string& sas_address, int pcscf_trusted_port, int pcscf_untrusted_port, int scscf_port, int icscf_port, const std::string& local_host, const std::string& public_host, const std::string& home_domain, const std::string& additional_home_domains, const std::string& scscf_uri, const std::string& alias_hosts, SIPResolver* sipresolver, int num_pjsip_threads, int record_routing_model, const int default_session_expires, const int max_session_expires, QuiescingManager *quiescing_mgr_arg, const std::string& cdf_domain) { pj_status_t status; pj_sockaddr pri_addr; pj_sockaddr addr_list[16]; unsigned addr_cnt = PJ_ARRAY_SIZE(addr_list); unsigned i; // Set up the vectors of threads. The threads don't get created until // start_pjsip_threads is called. pjsip_threads.resize(num_pjsip_threads); // Get ports and host names specified on options. If local host was not // specified, use the host name returned by pj_gethostname. char* local_host_cstr = strdup(local_host.c_str()); char* public_host_cstr = strdup(public_host.c_str()); char* home_domain_cstr = strdup(home_domain.c_str()); char* scscf_uri_cstr; if (scscf_uri.empty()) { // Create a default S-CSCF URI using the localhost and S-CSCF port. std::string tmp_scscf_uri = "sip:" + local_host + ":" + std::to_string(scscf_port) + ";transport=TCP"; scscf_uri_cstr = strdup(tmp_scscf_uri.c_str()); } else { // Use the specified URI. scscf_uri_cstr = strdup(scscf_uri.c_str()); } // This is only set on Bono nodes (it's the empty string otherwise) char* cdf_domain_cstr = strdup(cdf_domain.c_str()); // Copy port numbers to stack data. stack_data.pcscf_trusted_port = pcscf_trusted_port; stack_data.pcscf_untrusted_port = pcscf_untrusted_port; stack_data.scscf_port = scscf_port; stack_data.icscf_port = icscf_port; stack_data.sipresolver = sipresolver; // Copy other functional options to stack data. stack_data.default_session_expires = default_session_expires; stack_data.max_session_expires = max_session_expires; // Work out local and public hostnames and cluster domain names. stack_data.local_host = (local_host != "") ? pj_str(local_host_cstr) : *pj_gethostname(); stack_data.public_host = (public_host != "") ? pj_str(public_host_cstr) : stack_data.local_host; stack_data.default_home_domain = (home_domain != "") ? pj_str(home_domain_cstr) : stack_data.local_host; stack_data.scscf_uri = pj_str(scscf_uri_cstr); stack_data.cdf_domain = pj_str(cdf_domain_cstr); // Build a set of home domains stack_data.home_domains = std::unordered_set<std::string>(); stack_data.home_domains.insert(PJUtils::pj_str_to_string(&stack_data.default_home_domain)); if (additional_home_domains != "") { std::list<std::string> domains; Utils::split_string(additional_home_domains, ',', domains, 0, true); stack_data.home_domains.insert(domains.begin(), domains.end()); } // Set up the default address family. This is IPv4 unless our local host is an IPv6 address. stack_data.addr_family = AF_INET; struct in6_addr dummy_addr; if (inet_pton(AF_INET6, local_host_cstr, &dummy_addr) == 1) { LOG_DEBUG("Local host is an IPv6 address - enabling IPv6 mode"); stack_data.addr_family = AF_INET6; } stack_data.record_route_on_every_hop = false; stack_data.record_route_on_initiation_of_originating = false; stack_data.record_route_on_initiation_of_terminating = false; stack_data.record_route_on_completion_of_originating = false; stack_data.record_route_on_completion_of_terminating = false; stack_data.record_route_on_diversion = false; if (scscf_port != 0) { switch (record_routing_model) { case 1: stack_data.record_route_on_initiation_of_originating = true; stack_data.record_route_on_completion_of_terminating = true; break; case 2: stack_data.record_route_on_initiation_of_originating = true; stack_data.record_route_on_initiation_of_terminating = true; stack_data.record_route_on_completion_of_originating = true; stack_data.record_route_on_completion_of_terminating = true; stack_data.record_route_on_diversion = true; break; case 3: stack_data.record_route_on_every_hop = true; stack_data.record_route_on_initiation_of_originating = true; stack_data.record_route_on_initiation_of_terminating = true; stack_data.record_route_on_completion_of_originating = true; stack_data.record_route_on_completion_of_terminating = true; stack_data.record_route_on_diversion = true; break; default: LOG_ERROR("Record-Route setting should be 1, 2, or 3, is %d. Defaulting to Record-Route on every hop.", record_routing_model); stack_data.record_route_on_every_hop = true; } } std::string system_name_sas = system_name; std::string system_type_sas = (pcscf_trusted_port != 0) ? "bono" : "sprout"; // Initialize SAS logging. if (system_name_sas == "") { system_name_sas = std::string(stack_data.local_host.ptr, stack_data.local_host.slen); } SAS::init(system_name, system_type_sas, SASEvent::CURRENT_RESOURCE_BUNDLE, sas_address, sas_write); // Initialise PJSIP and all the associated resources. status = init_pjsip(); // Initialize the PJUtils module. PJUtils::init(); // Create listening transports for the ports whichtrusted and untrusted ports. stack_data.pcscf_trusted_tcp_factory = NULL; if (stack_data.pcscf_trusted_port != 0) { status = start_transports(stack_data.pcscf_trusted_port, stack_data.local_host, &stack_data.pcscf_trusted_tcp_factory); PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); } stack_data.pcscf_untrusted_tcp_factory = NULL; if (stack_data.pcscf_untrusted_port != 0) { status = start_transports(stack_data.pcscf_untrusted_port, stack_data.public_host, &stack_data.pcscf_untrusted_tcp_factory); PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); } stack_data.scscf_tcp_factory = NULL; if (stack_data.scscf_port != 0) { status = start_transports(stack_data.scscf_port, stack_data.public_host, &stack_data.scscf_tcp_factory); if (status == PJ_SUCCESS) { CL_SPROUT_S_CSCF_AVAIL.log(stack_data.scscf_port); } else { CL_SPROUT_S_CSCF_INIT_FAIL2.log(stack_data.scscf_port); } PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); } stack_data.icscf_tcp_factory = NULL; if (stack_data.icscf_port != 0) { status = start_transports(stack_data.icscf_port, stack_data.public_host, &stack_data.icscf_tcp_factory); if (status == PJ_SUCCESS) { CL_SPROUT_I_CSCF_AVAIL.log(stack_data.icscf_port); } else { CL_SPROUT_I_CSCF_INIT_FAIL2.log(stack_data.icscf_port); } PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); } // List all names matching local endpoint. // Note that PJLIB version 0.6 and newer has a function to // enumerate local IP interface (pj_enum_ip_interface()), so // by using it would be possible to list all IP interfaces in // this host. // The first address is important since this would be the one // to be added in Record-Route. stack_data.name[stack_data.name_cnt] = stack_data.local_host; stack_data.name_cnt++; if (strcmp(local_host_cstr, public_host_cstr)) { stack_data.name[stack_data.name_cnt] = stack_data.public_host; stack_data.name_cnt++; } if ((scscf_port != 0) && (!scscf_uri.empty())) { // S-CSCF enabled with a specified URI, so add host name from the URI to hostnames. pjsip_sip_uri* uri = (pjsip_sip_uri*)PJUtils::uri_from_string(scscf_uri, stack_data.pool); if (uri != NULL) { stack_data.name[stack_data.name_cnt] = uri->host; stack_data.name_cnt++; } } if (pj_gethostip(pj_AF_INET(), &pri_addr) == PJ_SUCCESS) { pj_strdup2(stack_data.pool, &stack_data.name[stack_data.name_cnt], pj_inet_ntoa(pri_addr.ipv4.sin_addr)); stack_data.name_cnt++; } // Get the rest of IP interfaces. if (pj_enum_ip_interface(pj_AF_INET(), &addr_cnt, addr_list) == PJ_SUCCESS) { for (i = 0; i < addr_cnt; ++i) { if (addr_list[i].ipv4.sin_addr.s_addr == pri_addr.ipv4.sin_addr.s_addr) { continue; } pj_strdup2(stack_data.pool, &stack_data.name[stack_data.name_cnt], pj_inet_ntoa(addr_list[i].ipv4.sin_addr)); stack_data.name_cnt++; } } // Note that we no longer consider 127.0.0.1 and localhost as aliases. // Parse the list of alias host names. stack_data.aliases = std::unordered_set<std::string>(); if (alias_hosts != "") { std::list<std::string> aliases; Utils::split_string(alias_hosts, ',', aliases, 0, true); stack_data.aliases.insert(aliases.begin(), aliases.end()); for (std::unordered_set<std::string>::iterator it = stack_data.aliases.begin(); it != stack_data.aliases.end(); ++it) { pj_strdup2(stack_data.pool, &stack_data.name[stack_data.name_cnt], it->c_str()); stack_data.name_cnt++; } } LOG_STATUS("Local host aliases:"); for (i = 0; i < stack_data.name_cnt; ++i) { LOG_STATUS(" %.*s", (int)stack_data.name[i].slen, stack_data.name[i].ptr); } // Set up the Last Value Cache, accumulators and counters. std::string process_name; if ((stack_data.pcscf_trusted_port != 0) && (stack_data.pcscf_untrusted_port != 0)) { process_name = "bono"; } else { process_name = "sprout"; } stack_data.stats_aggregator = new LastValueCache(num_known_stats, known_statnames, process_name); if (quiescing_mgr_arg != NULL) { quiescing_mgr = quiescing_mgr_arg; // Create an instance of the stack quiesce handler. This acts as a glue // class between the stack modulem connections tracker, and the quiescing // manager. stack_quiesce_handler = new StackQuiesceHandler(); // Create a new connection tracker, and register the quiesce handler with // it. connection_tracker = new ConnectionTracker(stack_quiesce_handler); // Register the quiesce handler with the quiescing manager (the former // implements the connection handling interface). quiescing_mgr->register_conns_handler(stack_quiesce_handler); pjsip_endpt_register_module(stack_data.endpt, &mod_connection_tracking); } return status; }
static int arm11_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution) { // LOG_DEBUG("current %d address %08x handle_breakpoints %d debug_execution %d", // current, address, handle_breakpoints, debug_execution); struct arm11_common *arm11 = target_to_arm11(target); LOG_DEBUG("target->state: %s", target_state_name(target)); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } address = arm11_nextpc(arm11, current, address); LOG_DEBUG("RESUME PC %08" PRIx32 "%s", address, !current ? "!" : ""); /* clear breakpoints/watchpoints and VCR*/ arm11_sc7_clear_vbw(arm11); if (!debug_execution) target_free_all_working_areas(target); /* Should we skip over breakpoints matching the PC? */ if (handle_breakpoints) { struct breakpoint *bp; for (bp = target->breakpoints; bp; bp = bp->next) { if (bp->address == address) { LOG_DEBUG("must step over %08" PRIx32 "", bp->address); arm11_step(target, 1, 0, 0); break; } } } /* activate all breakpoints */ if (true) { struct breakpoint *bp; unsigned brp_num = 0; for (bp = target->breakpoints; bp; bp = bp->next) { struct arm11_sc7_action brp[2]; brp[0].write = 1; brp[0].address = ARM11_SC7_BVR0 + brp_num; brp[0].value = bp->address; brp[1].write = 1; brp[1].address = ARM11_SC7_BCR0 + brp_num; brp[1].value = 0x1 | (3 << 1) | (0x0F << 5) | (0 << 14) | (0 << 16) | (0 << 20) | (0 << 21); arm11_sc7_run(arm11, brp, ARRAY_SIZE(brp)); LOG_DEBUG("Add BP %d at %08" PRIx32, brp_num, bp->address); brp_num++; } if (arm11_vcr) arm11_sc7_set_vcr(arm11, arm11_vcr); } /* activate all watchpoints and breakpoints */ arm11_leave_debug_state(arm11, true); arm11_add_IR(arm11, ARM11_RESTART, TAP_IDLE); CHECK_RETVAL(jtag_execute_queue()); int i = 0; while (1) { CHECK_RETVAL(arm11_read_DSCR(arm11)); LOG_DEBUG("DSCR %08x", (unsigned) arm11->dscr); if (arm11->dscr & DSCR_CORE_RESTARTED) break; long long then = 0; if (i == 1000) { then = timeval_ms(); } if (i >= 1000) { if ((timeval_ms()-then) > 1000) { LOG_WARNING("Timeout (1000ms) waiting for instructions to complete"); return ERROR_FAIL; } } i++; } target->debug_reason = DBG_REASON_NOTHALTED; if (!debug_execution) target->state = TARGET_RUNNING; else target->state = TARGET_DEBUG_RUNNING; CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_RESUMED)); return ERROR_OK; }
static int stmsmi_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv; uint32_t io_base = stmsmi_info->io_base; uint32_t cur_count, page_size, page_offset; int sector; int retval = ERROR_OK; LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32, __FUNCTION__, offset, count); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (offset + count > stmsmi_info->dev->size_in_bytes) { LOG_WARNING("Write pasts end of flash. Extra data discarded."); count = stmsmi_info->dev->size_in_bytes - offset; } /* Check sector protection */ for (sector = 0; sector < bank->num_sectors; sector++) { /* Start offset in or before this sector? */ /* End offset in or behind this sector? */ if ( (offset < (bank->sectors[sector].offset + bank->sectors[sector].size)) && ((offset + count - 1) >= bank->sectors[sector].offset) && bank->sectors[sector].is_protected ) { LOG_ERROR("Flash sector %d protected", sector); return ERROR_FAIL; } } page_size = stmsmi_info->dev->pagesize; /* unaligned buffer head */ if (count > 0 && (offset & 3) != 0) { cur_count = 4 - (offset & 3); if (cur_count > count) cur_count = count; retval = smi_write_buffer(bank, buffer, bank->base + offset, cur_count); if (retval != ERROR_OK) goto err; offset += cur_count; buffer += cur_count; count -= cur_count; } page_offset = offset % page_size; /* central part, aligned words */ while (count >= 4) { /* clip block at page boundary */ if (page_offset + count > page_size) cur_count = page_size - page_offset; else cur_count = count & ~3; retval = smi_write_buffer(bank, buffer, bank->base + offset, cur_count); if (retval != ERROR_OK) goto err; page_offset = 0; buffer += cur_count; offset += cur_count; count -= cur_count; keep_alive(); } /* buffer tail */ if (count > 0) retval = smi_write_buffer(bank, buffer, bank->base + offset, count); err: /* Switch to HW mode before return to prompt */ SMI_SET_HW_MODE(); return retval; }
static int arm11_step(struct target *target, int current, uint32_t address, int handle_breakpoints) { LOG_DEBUG("target->state: %s", target_state_name(target)); if (target->state != TARGET_HALTED) { LOG_WARNING("target was not halted"); return ERROR_TARGET_NOT_HALTED; } struct arm11_common *arm11 = target_to_arm11(target); address = arm11_nextpc(arm11, current, address); LOG_DEBUG("STEP PC %08" PRIx32 "%s", address, !current ? "!" : ""); /** \todo TODO: Thumb not supported here */ uint32_t next_instruction; CHECK_RETVAL(arm11_read_memory_word(arm11, address, &next_instruction)); /* skip over BKPT */ if ((next_instruction & 0xFFF00070) == 0xe1200070) { address = arm11_nextpc(arm11, 0, address + 4); LOG_DEBUG("Skipping BKPT"); } /* skip over Wait for interrupt / Standby */ /* mcr 15, 0, r?, cr7, cr0, {4} */ else if ((next_instruction & 0xFFFF0FFF) == 0xee070f90) { address = arm11_nextpc(arm11, 0, address + 4); LOG_DEBUG("Skipping WFI"); } /* ignore B to self */ else if ((next_instruction & 0xFEFFFFFF) == 0xeafffffe) { LOG_DEBUG("Not stepping jump to self"); } else { /** \todo TODO: check if break-/watchpoints make any sense at all in combination * with this. */ /** \todo TODO: check if disabling IRQs might be a good idea here. Alternatively * the VCR might be something worth looking into. */ /* Set up breakpoint for stepping */ struct arm11_sc7_action brp[2]; brp[0].write = 1; brp[0].address = ARM11_SC7_BVR0; brp[1].write = 1; brp[1].address = ARM11_SC7_BCR0; if (arm11_config_hardware_step) { /* Hardware single stepping ("instruction address * mismatch") is used if enabled. It's not quite * exactly "run one instruction"; "branch to here" * loops won't break, neither will some other cases, * but it's probably the best default. * * Hardware single stepping isn't supported on v6 * debug modules. ARM1176 and v7 can support it... * * FIXME Thumb stepping likely needs to use 0x03 * or 0xc0 byte masks, not 0x0f. */ brp[0].value = address; brp[1].value = 0x1 | (3 << 1) | (0x0F << 5) | (0 << 14) | (0 << 16) | (0 << 20) | (2 << 21); } else { /* Sets a breakpoint on the next PC, as calculated * by instruction set simulation. * * REVISIT stepping Thumb on ARM1156 requires Thumb2 * support from the simulator. */ uint32_t next_pc; int retval; retval = arm_simulate_step(target, &next_pc); if (retval != ERROR_OK) return retval; brp[0].value = next_pc; brp[1].value = 0x1 | (3 << 1) | (0x0F << 5) | (0 << 14) | (0 << 16) | (0 << 20) | (0 << 21); } CHECK_RETVAL(arm11_sc7_run(arm11, brp, ARRAY_SIZE(brp))); /* resume */ if (arm11_config_step_irq_enable) /* this disable should be redundant ... */ arm11->dscr &= ~DSCR_INT_DIS; else arm11->dscr |= DSCR_INT_DIS; CHECK_RETVAL(arm11_leave_debug_state(arm11, handle_breakpoints)); arm11_add_IR(arm11, ARM11_RESTART, TAP_IDLE); CHECK_RETVAL(jtag_execute_queue()); /* wait for halt */ int i = 0; while (1) { const uint32_t mask = DSCR_CORE_RESTARTED | DSCR_CORE_HALTED; CHECK_RETVAL(arm11_read_DSCR(arm11)); LOG_DEBUG("DSCR %08x e", (unsigned) arm11->dscr); if ((arm11->dscr & mask) == mask) break; long long then = 0; if (i == 1000) { then = timeval_ms(); } if (i >= 1000) { if ((timeval_ms()-then) > 1000) { LOG_WARNING("Timeout (1000ms) waiting for instructions to complete"); return ERROR_FAIL; } } i++; } /* clear breakpoint */ arm11_sc7_clear_vbw(arm11); /* save state */ CHECK_RETVAL(arm11_debug_entry(arm11)); /* restore default state */ arm11->dscr &= ~DSCR_INT_DIS; } target->debug_reason = DBG_REASON_SINGLESTEP; CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_HALTED)); return ERROR_OK; }
OMX_STREAMING_PIPE_API CPresult HttpsPipe_Create(CPhandle *hContent, CPstring szURI) { LOG_DEBUG("%s hContent %p\n", __FUNCTION__, hContent); return HttpsPipe_Open(hContent, szURI, CP_AccessRead); }
/* target memory access * size: 1 = byte (8bit), 2 = half-word (16bit), 4 = word (32bit) * count: number of items of <size> * * arm11_config_memrw_no_increment - in the future we may want to be able * to read/write a range of data to a "port". a "port" is an action on * read memory address for some peripheral. */ static int arm11_read_memory_inner(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer, bool arm11_config_memrw_no_increment) { /** \todo TODO: check if buffer cast to uint32_t* and uint16_t* might cause alignment problems */ int retval; if (target->state != TARGET_HALTED) { LOG_WARNING("target was not halted"); return ERROR_TARGET_NOT_HALTED; } LOG_DEBUG("ADDR %08" PRIx32 " SIZE %08" PRIx32 " COUNT %08" PRIx32 "", address, size, count); struct arm11_common *arm11 = target_to_arm11(target); retval = arm11_run_instr_data_prepare(arm11); if (retval != ERROR_OK) return retval; /* MRC p14,0,r0,c0,c5,0 */ retval = arm11_run_instr_data_to_core1(arm11, 0xee100e15, address); if (retval != ERROR_OK) return retval; switch (size) { case 1: arm11->arm.core_cache->reg_list[1].dirty = true; for (size_t i = 0; i < count; i++) { /* ldrb r1, [r0], #1 */ /* ldrb r1, [r0] */ arm11_run_instr_no_data1(arm11, !arm11_config_memrw_no_increment ? 0xe4d01001 : 0xe5d01000); uint32_t res; /* MCR p14,0,R1,c0,c5,0 */ arm11_run_instr_data_from_core(arm11, 0xEE001E15, &res, 1); *buffer++ = res; } break; case 2: { arm11->arm.core_cache->reg_list[1].dirty = true; for (size_t i = 0; i < count; i++) { /* ldrh r1, [r0], #2 */ arm11_run_instr_no_data1(arm11, !arm11_config_memrw_no_increment ? 0xe0d010b2 : 0xe1d010b0); uint32_t res; /* MCR p14,0,R1,c0,c5,0 */ arm11_run_instr_data_from_core(arm11, 0xEE001E15, &res, 1); uint16_t svalue = res; memcpy(buffer + i * sizeof(uint16_t), &svalue, sizeof(uint16_t)); } break; } case 4: { uint32_t instr = !arm11_config_memrw_no_increment ? 0xecb05e01 : 0xed905e00; /** \todo TODO: buffer cast to uint32_t* causes alignment warnings */ uint32_t *words = (uint32_t *)buffer; /* LDC p14,c5,[R0],#4 */ /* LDC p14,c5,[R0] */ arm11_run_instr_data_from_core(arm11, instr, words, count); break; } } return arm11_run_instr_data_finish(arm11); }
/** * A thread that actually handles the unregistration request of the GUI * (internal use only). See rm_unregister_account() for details. * @param args the account ID is stored here * @return empty */ void *unregistration_thread(void *args) { int accountId; // current account int pos; // position of account status information int rc; // return code int timeoutCtr; // timeout counter for sipstack events // accountId is given: accountId = (int) args; LOG_DEBUG(REGISTRAR_MGR_MSG_PREFIX "unregistration thread entered, " "accountId: %d", accountId); // try to gain lock because we want exclusive responsibility for // unregistering this account - also we want to write data: rc = pthread_mutex_lock(&accInfoLock); if (rc != 0) { // failed to gain lock, exit (fatal error) LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "mutex lock could not be" "acquired, error: %d", rc); thread_terminated(); return NULL; } LOG_DEBUG(REGISTRAR_MGR_MSG_PREFIX "mutex lock acquired"); // a registration/update thread should be active and have saved account // information - find position in array of it: rc = find_acc_by_id(accountId, &pos); if (!rc) { // no registration/update thread active LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "account not in use"); rc = go_show_user_event(accountId, "ERROR", "Error unregistering account", "Account is not in use.", "This account is already unregistered."); if (!rc) { LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "failed to inform the GUI"); } // unlock and exit: pthread_mutex_unlock(&accInfoLock); thread_terminated(); return NULL; } // prevent race conditions because we have to release the lock after // setting doShutdown to 1: if (accInfos[pos].doShutdown || accInfos[pos].isShutdown) { // a second unregister thread was started just when we are trying to // shutdown the active registration thread LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "another thread is already " "unregistering"); rc = go_show_user_event(accountId, "ERROR", "Error unregistering account", "Already unregistering.", "It is currently tried to unregister this " "account."); if (!rc) { LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "failed to inform the GUI"); } // unlock and exit: pthread_mutex_unlock(&accInfoLock); thread_terminated(); return NULL; } LOG_DEBUG(REGISTRAR_MGR_MSG_PREFIX "account is in use"); // shutdown registration/update thread: accInfos[pos].doShutdown = 1; // release lock to enable abnormal termination (otherwise a dead lock // might occur if registration thread is trying to shutdown in case of // an error while updating): rc = pthread_mutex_unlock(&accInfoLock); if (rc != 0) { LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "mutex lock could not be " "released, error %d", rc); thread_terminated(); return NULL; } LOG_DEBUG(REGISTRAR_MGR_MSG_PREFIX "wait for registration thread " "to finish"); // now wait on registration thread: // isShutdown == 1 means regular shutdown // accountId == -1 means the account status info was cleared because // of an error while (!accInfos[pos].isShutdown && accInfos[pos].accountId != -1) { sched_yield(); usleep(100000); // 0.1 seconds } LOG_DEBUG(REGISTRAR_MGR_MSG_PREFIX "done waiting"); // we should not send an unregister if account is not registered if (!accInfos[pos].isRegistered || accInfos[pos].accountId == -1) { LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "unregister failed: account " "is not registered"); rc = go_show_user_event(accountId, "ERROR", "Error unregistering account", "Account is not in use.", "This account is already unregistered."); if (!rc) { LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "failed to inform the GUI"); } // exit: thread_terminated(); return NULL; } // tell dispatcher which OK is expected: accInfos[pos].eventArrived = 0; accInfos[pos].waitingOnUnregOK = 1; // send REGISTER with expire=0 to registrar: rc = sipstack_send_unregister(accInfos[pos].regId); if (!rc) { // sending REGISTER failed LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "send unregister failed"); rc = go_show_user_event(accountId, "ERROR", "Error unregistering account", "Sending unregistration message failed.", "Failed to send your unregistration " "request to the given registrar." "Please check whether your account " "data is correct and whether your " "internet connection is working " "correctly."); if (!rc) { LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "failed to inform the GUI"); } // exit: thread_terminated(); return NULL; } // now wait on response: timeoutCtr = 0; while (!accInfos[pos].eventArrived) { sched_yield(); usleep(100000); // 0.1 seconds timeoutCtr++; if (timeoutCtr == config.core.sipOutput.registrarManager.timeout * 10) { break; } } LOG_DEBUG(REGISTRAR_MGR_MSG_PREFIX "done waiting"); // clear flags: accInfos[pos].eventArrived = 0; accInfos[pos].waitingOnUnregOK = 0; // test if account is really unregistered: if (accInfos[pos].isRegistered) { // account is still in use: LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "unregister failed: account " "is still registered"); if (accInfos[pos].informGui) { rc = go_show_user_event(accountId, "ERROR", "Error unregistering account", "Sending unregistration message failed.", "Failed to send your unregistration " "request to the given registrar." "Please check whether your account " "data is correct and whether your " "internet connection is working " "correctly."); if (!rc) { LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "failed to inform the GUI"); } } // don't terminate because there is no point in believing the account // was still registered with the registrar } if (accInfos[pos].informGui) { // inform GUI that unregister succeeded: rc = go_change_reg_status(accountId, 0); if (!rc) { // failed to contact GUI LOG_ERROR(REGISTRAR_MGR_MSG_PREFIX "GUI registration status " "update failed"); // exit: thread_terminated(); return NULL; } } // mark account as no longer used: clear_account_info(pos); LOG_INFO(REGISTRAR_MGR_MSG_PREFIX "unregister of account %d succeeded", accountId); // we are done: thread_terminated(); return NULL; }
/* * no_increment - in the future we may want to be able * to read/write a range of data to a "port". a "port" is an action on * read memory address for some peripheral. */ static int arm11_write_memory_inner(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer, bool no_increment) { int retval; if (target->state != TARGET_HALTED) { LOG_WARNING("target was not halted"); return ERROR_TARGET_NOT_HALTED; } LOG_DEBUG("ADDR %08" PRIx32 " SIZE %08" PRIx32 " COUNT %08" PRIx32 "", address, size, count); struct arm11_common *arm11 = target_to_arm11(target); retval = arm11_run_instr_data_prepare(arm11); if (retval != ERROR_OK) return retval; /* load r0 with buffer address */ /* MRC p14,0,r0,c0,c5,0 */ retval = arm11_run_instr_data_to_core1(arm11, 0xee100e15, address); if (retval != ERROR_OK) return retval; /* burst writes are not used for single words as those may well be * reset init script writes. * * The other advantage is that as burst writes are default, we'll * now exercise both burst and non-burst code paths with the * default settings, increasing code coverage. */ bool burst = arm11_config_memwrite_burst && (count > 1); switch (size) { case 1: { arm11->arm.core_cache->reg_list[1].dirty = true; for (size_t i = 0; i < count; i++) { /* load r1 from DCC with byte data */ /* MRC p14,0,r1,c0,c5,0 */ retval = arm11_run_instr_data_to_core1(arm11, 0xee101e15, *buffer++); if (retval != ERROR_OK) return retval; /* write r1 to memory */ /* strb r1, [r0], #1 */ /* strb r1, [r0] */ retval = arm11_run_instr_no_data1(arm11, !no_increment ? 0xe4c01001 : 0xe5c01000); if (retval != ERROR_OK) return retval; } break; } case 2: { arm11->arm.core_cache->reg_list[1].dirty = true; for (size_t i = 0; i < count; i++) { uint16_t value; memcpy(&value, buffer + i * sizeof(uint16_t), sizeof(uint16_t)); /* load r1 from DCC with halfword data */ /* MRC p14,0,r1,c0,c5,0 */ retval = arm11_run_instr_data_to_core1(arm11, 0xee101e15, value); if (retval != ERROR_OK) return retval; /* write r1 to memory */ /* strh r1, [r0], #2 */ /* strh r1, [r0] */ retval = arm11_run_instr_no_data1(arm11, !no_increment ? 0xe0c010b2 : 0xe1c010b0); if (retval != ERROR_OK) return retval; } break; } case 4: { /* stream word data through DCC directly to memory */ /* increment: STC p14,c5,[R0],#4 */ /* no increment: STC p14,c5,[R0]*/ uint32_t instr = !no_increment ? 0xeca05e01 : 0xed805e00; /** \todo TODO: buffer cast to uint32_t* causes alignment warnings */ uint32_t *words = (uint32_t*)buffer; /* "burst" here just means trusting each instruction executes * fully before we run the next one: per-word roundtrips, to * check the Ready flag, are not used. */ if (!burst) retval = arm11_run_instr_data_to_core(arm11, instr, words, count); else retval = arm11_run_instr_data_to_core_noack(arm11, instr, words, count); if (retval != ERROR_OK) return retval; break; } } /* r0 verification */ if (!no_increment) { uint32_t r0; /* MCR p14,0,R0,c0,c5,0 */ retval = arm11_run_instr_data_from_core(arm11, 0xEE000E15, &r0, 1); if (retval != ERROR_OK) return retval; if (address + size * count != r0) { LOG_ERROR("Data transfer failed. Expected end " "address 0x%08x, got 0x%08x", (unsigned) (address + size * count), (unsigned) r0); if (burst) LOG_ERROR("use 'arm11 memwrite burst disable' to disable fast burst mode"); if (arm11_config_memwrite_error_fatal) return ERROR_FAIL; } } return arm11_run_instr_data_finish(arm11); }
static int lpcspifi_erase(struct flash_bank *bank, int first, int last) { struct target *target = bank->target; struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv; struct reg_param reg_params[4]; struct armv7m_algorithm armv7m_info; struct working_area *erase_algorithm; int retval = ERROR_OK; int sector; LOG_DEBUG("erase from sector %d to sector %d", first, last); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if ((first < 0) || (last < first) || (last >= bank->num_sectors)) { LOG_ERROR("Flash sector invalid"); return ERROR_FLASH_SECTOR_INVALID; } if (!(lpcspifi_info->probed)) { LOG_ERROR("Flash bank not probed"); return ERROR_FLASH_BANK_NOT_PROBED; } for (sector = first; sector <= last; sector++) { if (bank->sectors[sector].is_protected) { LOG_ERROR("Flash sector %d protected", sector); return ERROR_FAIL; } } /* If we're erasing the entire chip and the flash supports * it, use a bulk erase instead of going sector-by-sector. */ if (first == 0 && last == (bank->num_sectors - 1) && lpcspifi_info->dev->chip_erase_cmd != lpcspifi_info->dev->erase_cmd) { LOG_DEBUG("Chip supports the bulk erase command."\ " Will use bulk erase instead of sector-by-sector erase."); retval = lpcspifi_bulk_erase(bank); if (retval == ERROR_OK) { retval = lpcspifi_set_hw_mode(bank); return retval; } else LOG_WARNING("Bulk flash erase failed. Falling back to sector-by-sector erase."); } retval = lpcspifi_set_hw_mode(bank); if (retval != ERROR_OK) return retval; /* see contrib/loaders/flash/lpcspifi_erase.S for src */ static const uint8_t lpcspifi_flash_erase_code[] = { 0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x08, 0x0a, 0x4f, 0xf0, 0xea, 0x08, 0xca, 0xf8, 0x8c, 0x81, 0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x90, 0x81, 0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x94, 0x81, 0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x98, 0x81, 0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x9c, 0x81, 0x4f, 0xf0, 0x44, 0x08, 0xca, 0xf8, 0xa0, 0x81, 0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a, 0x4f, 0xf4, 0x00, 0x68, 0xca, 0xf8, 0x14, 0x80, 0x4f, 0xf4, 0x80, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a, 0x4f, 0xf0, 0xff, 0x08, 0xca, 0xf8, 0xab, 0x80, 0x4f, 0xf0, 0x00, 0x0a, 0xc4, 0xf2, 0x05, 0x0a, 0x4f, 0xf0, 0x00, 0x08, 0xc0, 0xf2, 0x00, 0x18, 0xca, 0xf8, 0x94, 0x80, 0x4f, 0xf4, 0x00, 0x5a, 0xc4, 0xf2, 0x05, 0x0a, 0x4f, 0xf0, 0x01, 0x08, 0xca, 0xf8, 0x00, 0x87, 0x4f, 0xf4, 0x40, 0x5a, 0xc4, 0xf2, 0x08, 0x0a, 0x4f, 0xf0, 0x07, 0x08, 0xca, 0xf8, 0x00, 0x80, 0x4f, 0xf0, 0x02, 0x08, 0xca, 0xf8, 0x10, 0x80, 0xca, 0xf8, 0x04, 0x80, 0x00, 0xf0, 0x52, 0xf8, 0x4f, 0xf0, 0x06, 0x09, 0x00, 0xf0, 0x3b, 0xf8, 0x00, 0xf0, 0x48, 0xf8, 0x00, 0xf0, 0x4a, 0xf8, 0x4f, 0xf0, 0x05, 0x09, 0x00, 0xf0, 0x33, 0xf8, 0x4f, 0xf0, 0x00, 0x09, 0x00, 0xf0, 0x2f, 0xf8, 0x00, 0xf0, 0x3c, 0xf8, 0x19, 0xf0, 0x02, 0x0f, 0x00, 0xf0, 0x45, 0x80, 0x00, 0xf0, 0x3a, 0xf8, 0x4f, 0xea, 0x02, 0x09, 0x00, 0xf0, 0x23, 0xf8, 0x4f, 0xea, 0x10, 0x49, 0x00, 0xf0, 0x1f, 0xf8, 0x4f, 0xea, 0x10, 0x29, 0x00, 0xf0, 0x1b, 0xf8, 0x4f, 0xea, 0x00, 0x09, 0x00, 0xf0, 0x17, 0xf8, 0x00, 0xf0, 0x24, 0xf8, 0x00, 0xf0, 0x26, 0xf8, 0x4f, 0xf0, 0x05, 0x09, 0x00, 0xf0, 0x0f, 0xf8, 0x4f, 0xf0, 0x00, 0x09, 0x00, 0xf0, 0x0b, 0xf8, 0x00, 0xf0, 0x18, 0xf8, 0x19, 0xf0, 0x01, 0x0f, 0x7f, 0xf4, 0xf0, 0xaf, 0x01, 0x39, 0xf9, 0xb1, 0x18, 0x44, 0xff, 0xf7, 0xbf, 0xbf, 0x4f, 0xf4, 0x40, 0x5a, 0xc4, 0xf2, 0x08, 0x0a, 0xca, 0xf8, 0x08, 0x90, 0xda, 0xf8, 0x0c, 0x90, 0x19, 0xf0, 0x10, 0x0f, 0x7f, 0xf4, 0xfa, 0xaf, 0xda, 0xf8, 0x08, 0x90, 0x70, 0x47, 0x4f, 0xf0, 0xff, 0x08, 0x00, 0xf0, 0x02, 0xb8, 0x4f, 0xf0, 0x00, 0x08, 0x4f, 0xf4, 0x80, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a, 0xca, 0xf8, 0xab, 0x80, 0x70, 0x47, 0x00, 0x20, 0x00, 0xbe, 0xff, 0xff }; armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; /* Get memory for spifi initialization algorithm */ retval = target_alloc_working_area(target, sizeof(lpcspifi_flash_erase_code), &erase_algorithm); if (retval != ERROR_OK) { LOG_ERROR("Insufficient working area. You must configure a working"\ " area of at least %zdB in order to erase SPIFI flash.", sizeof(lpcspifi_flash_erase_code)); return retval; } /* Write algorithm to working area */ retval = target_write_buffer(target, erase_algorithm->address, sizeof(lpcspifi_flash_erase_code), lpcspifi_flash_erase_code); if (retval != ERROR_OK) { target_free_working_area(target, erase_algorithm); return retval; } init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); /* Start address */ init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* Sector count */ init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /* Erase command */ init_reg_param(®_params[3], "r3", 32, PARAM_OUT); /* Sector size */ buf_set_u32(reg_params[0].value, 0, 32, bank->sectors[first].offset); buf_set_u32(reg_params[1].value, 0, 32, last - first + 1); buf_set_u32(reg_params[2].value, 0, 32, lpcspifi_info->dev->erase_cmd); buf_set_u32(reg_params[3].value, 0, 32, bank->sectors[first].size); /* Run the algorithm */ retval = target_run_algorithm(target, 0 , NULL, 4, reg_params, erase_algorithm->address, erase_algorithm->address + sizeof(lpcspifi_flash_erase_code) - 4, 3000*(last - first + 1), &armv7m_info); if (retval != ERROR_OK) LOG_ERROR("Error executing flash erase algorithm"); target_free_working_area(target, erase_algorithm); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); destroy_reg_param(®_params[3]); retval = lpcspifi_set_hw_mode(bank); return retval; }
void tools_snag_brush_handler ( int mouse_event, int mouse_buttons, int keyhit, int x, int y ) { static int startx; static int starty; switch (mouse_event) { case (TOOL_EVENT_INIT): CURSOR_CROSSHAIRS(); Page_Negative(page_rubberband); LOG_DEBUG("brush"); startx = x; starty = y; jsui_dialog_tell_message( toolbar_dialog, TOOLBAR_SNAGBRUSH, JSUI_MSG_TRIGGER_L ); break; case (TOOL_EVENT_DEINIT): Page_Negative(page_rubberband); break; case (TOOL_EVENT_STARTDOWN): startx = x; starty = y; break; case (TOOL_EVENT_DRAGGING): case (TOOL_EVENT_DRAG_STAT): Page_Negative(page_rubberband); if (mouse_buttons == 1) { primitive_rectangle_hollow(page_rubberband, pen_cycle, primitive_pixel, startx, starty, x, y); } else if (mouse_buttons == 3) { primitive_rectangle_hollow(page_rubberband, pen_cycle, primitive_pixel, startx, starty, x, y); } break; case (TOOL_EVENT_RELEASE): Page_Negative(page_rubberband); /* printf ("Snag brush: (%d,%d) - (%d,%d) %d %d\n", x, y, startx, starty, ABS(x-startx), ABS(y-starty)); */ LOG_DEBUG( "snag brush" ); if (brush_custom) Page_Destroy(brush_custom); brush_custom = Page_Cutout_Brush( page_active, startx, starty, x, y, excl_brush, (mouse_buttons == 3)?page_active->bgpen:NULL); brush_active = brush_custom; jsui_dialog_broadcast(PAINT_MSG_DOTTEDDRAW, 0); jsui_dialog_broadcast(PAINT_MSG_MODEMATTE, 0); drawing_mode = DRAW_STYLE_MATTE; break; case (TOOL_EVENT_IDLE): Page_Negative(page_rubberband); primitive_crosshairs(page_rubberband, x, y); break; case (TOOL_EVENT_NONE): default: break; } }
/* On exit, SW mode is kept */ static int lpcspifi_read_flash_id(struct flash_bank *bank, uint32_t *id) { struct target *target = bank->target; struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv; uint32_t ssp_base = lpcspifi_info->ssp_base; uint32_t io_base = lpcspifi_info->io_base; uint32_t value; uint8_t id_buf[3] = {0, 0, 0}; int retval; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } LOG_DEBUG("Getting ID"); retval = lpcspifi_set_sw_mode(bank); if (retval != ERROR_OK) return retval; /* poll WIP */ if (retval == ERROR_OK) retval = wait_till_ready(bank, SSP_PROBE_TIMEOUT); /* Send SPI command "read ID" */ if (retval == ERROR_OK) retval = ssp_setcs(target, io_base, 0); if (retval == ERROR_OK) retval = ssp_write_reg(target, ssp_base, SSP_DATA, SPIFLASH_READ_ID); if (retval == ERROR_OK) retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT); if (retval == ERROR_OK) retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value); /* Dummy write to clock in data */ if (retval == ERROR_OK) retval = ssp_write_reg(target, ssp_base, SSP_DATA, 0x00); if (retval == ERROR_OK) retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT); if (retval == ERROR_OK) retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value); if (retval == ERROR_OK) id_buf[0] = value; /* Dummy write to clock in data */ if (retval == ERROR_OK) retval = ssp_write_reg(target, ssp_base, SSP_DATA, 0x00); if (retval == ERROR_OK) retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT); if (retval == ERROR_OK) retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value); if (retval == ERROR_OK) id_buf[1] = value; /* Dummy write to clock in data */ if (retval == ERROR_OK) retval = ssp_write_reg(target, ssp_base, SSP_DATA, 0x00); if (retval == ERROR_OK) retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT); if (retval == ERROR_OK) retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value); if (retval == ERROR_OK) id_buf[2] = value; if (retval == ERROR_OK) retval = ssp_setcs(target, io_base, 1); if (retval == ERROR_OK) *id = id_buf[2] << 16 | id_buf[1] << 8 | id_buf[0]; return retval; }
HTTPCode AuthTimeoutTask::handle_response(std::string body) { Json::Value json_body; std::string json_str = body; Json::Reader reader; bool parsingSuccessful = reader.parse(json_str.c_str(), json_body); if (!parsingSuccessful) { LOG_ERROR("Failed to read opaque data, %s", reader.getFormattedErrorMessages().c_str()); return HTTP_BAD_REQUEST; } if ((json_body.isMember("impu")) && ((json_body)["impu"].isString())) { _impu = json_body.get("impu", "").asString(); report_sip_all_register_marker(trail(), _impu); } else { LOG_ERROR("IMPU not available in JSON"); return HTTP_BAD_REQUEST; } if ((json_body.isMember("impi")) && ((json_body)["impi"].isString())) { _impi = json_body.get("impi", "").asString(); } else { LOG_ERROR("IMPI not available in JSON"); return HTTP_BAD_REQUEST; } if ((json_body.isMember("nonce")) && ((json_body)["nonce"].isString())) { _nonce = json_body.get("nonce", "").asString(); } else { LOG_ERROR("Nonce not available in JSON"); return HTTP_BAD_REQUEST; } bool success = false; uint64_t cas; Json::Value* av = _cfg->_avstore->get_av(_impi, _nonce, cas, trail()); if (av != NULL) { // Use the original REGISTER's branch parameter for SAS // correlation correlate_branch_from_av(av, trail()); // If authentication completed, we'll have written a marker to // indicate that. Look for it. if (!av->isMember("tombstone")) { LOG_DEBUG("AV for %s:%s has timed out", _impi.c_str(), _nonce.c_str()); // The AUTHENTICATION_TIMEOUT SAR is idempotent, so there's no // problem if Chronos' timer pops twice (e.g. if we have high // latency and these operations take more than 2 seconds). // If either of these operations fail, we return a 500 Internal // Server Error - this will trigger Chronos to try a different // Sprout, which may have better connectivity to Homestead or Memcached. HTTPCode hss_query = _cfg->_hss->update_registration_state(_impu, _impi, HSSConnection::AUTH_TIMEOUT, trail()); if (hss_query == HTTP_OK) { success = true; } } else { SAS::Event event(trail(), SASEvent::AUTHENTICATION_TIMER_POP_IGNORED, 0); SAS::report_event(event); LOG_DEBUG("Tombstone record indicates Authentication Vector has been used successfully - ignoring timer pop"); success = true; } } else { LOG_WARNING("Could not find AV for %s:%s when checking authentication timeout", _impi.c_str(), _nonce.c_str()); // LCOV_EXCL_LINE } delete av; return success ? HTTP_OK : HTTP_SERVER_ERROR; }