NamespaceResolver::Ptr GenericNamespaceResolver::defaultXSLTBindings() { Bindings list; list.insert(StandardPrefixes::xml, StandardNamespaces::xml); list.insert(StandardPrefixes::empty, StandardNamespaces::empty); return NamespaceResolver::Ptr(new GenericNamespaceResolver(list)); }
std::vector<std::string> SubscriberManager::subscriptions_to_remove(const Bindings& orig_bindings, const Subscriptions& orig_subscriptions, const Bindings& bindings_to_update, const std::vector<std::string> binding_ids_to_remove) { std::vector<std::string> subscription_ids_to_remove; std::set<std::string> missing_uris; // Store off the contact URIs of bindings to be removed. Any subscriptions // sharing any of these contact URIs will be removed. for (std::string binding_id : binding_ids_to_remove) { Bindings::const_iterator b = orig_bindings.find(binding_id); if (b != orig_bindings.end()) { missing_uris.insert(b->second->_uri); } } // Store off the original contact URI of bindings where the contact is about // to be changed. Any subscriptions that share any of the original contact // URIs will be removed. for (BindingPair bp : bindings_to_update) { Bindings::const_iterator b = orig_bindings.find(bp.first); if ((b != orig_bindings.end()) && (b->second->_uri != bp.second->_uri)) { missing_uris.insert(b->second->_uri); } } // Loop over the subscriptions. If any have the same contact as one of the // missing URIs, the subscription should be removed. for (SubscriptionPair sp : orig_subscriptions) { if (missing_uris.find(sp.second->_req_uri) != missing_uris.end()) { TRC_DEBUG("Subscription %s is being removed because the binding that shares" " its contact URI %s is being removed or changing contact URI", sp.first.c_str(), sp.second->_req_uri.c_str()); subscription_ids_to_remove.push_back(sp.first); } } return subscription_ids_to_remove; }
void Statement::BindParams( const Bindings& bindings ) { if (m_kQueryParts.size()) { FV_ASSERT( bindings.size() == m_kQueryParts.size()-1 ); m_kParams = bindings; } }
void Bindings::construct(const Args& args) { Isolate* isolate(args.GetIsolate()); HandleScope scope(isolate); if (args.IsConstructCall()) { // Invoked as constructor with 'new'. Bindings* obj = new Bindings(); obj->Wrap(args.Holder()); args.GetReturnValue().Set(args.Holder()); } else { // Invoked as a function, turn into construct call. Local<Function> ctor(Local<Function>::New(isolate, constructor)); args.GetReturnValue().Set(ctor->NewInstance()); } }
bool RegDB::getUnexpiredContactsUserContaining(const string& matchIdentity, int timeNow, Bindings& bindings) const { mongo::BSONObj query = BSON("expirationTime" << BSON_GREATER_THAN(timeNow)); mongo::ScopedDbConnection conn(_info.getConnectionString()); auto_ptr<mongo::DBClientCursor> pCursor = conn->query(_info.getNS(), query); if (pCursor.get() && pCursor->more()) { while (pCursor->more()) { RegBinding binding(pCursor->next()); if (binding.getContact().find(matchIdentity) != string::npos) bindings.push_back(binding); } conn.done(); return bindings.size() > 0; } conn.done(); return false; }
NamespaceResolver::Ptr GenericNamespaceResolver::defaultXQueryBindings() { Bindings list; list.insert(StandardPrefixes::xml, StandardNamespaces::xml); list.insert(StandardPrefixes::xs, StandardNamespaces::xs); list.insert(StandardPrefixes::xsi, StandardNamespaces::xsi); list.insert(StandardPrefixes::fn, StandardNamespaces::fn); list.insert(StandardPrefixes::local, StandardNamespaces::local); list.insert(StandardPrefixes::empty, StandardNamespaces::empty); return NamespaceResolver::Ptr(new GenericNamespaceResolver(list)); }
// TODO : Unclear how big this dataset would be, decide if this should be removed bool RegDB::getUnexpiredContactsInstrument(const string& instrument, int timeNow, Bindings& bindings) const { mongo::BSONObj query = BSON( "instrument" << instrument << "expirationTime" << BSON_GREATER_THAN(timeNow)); mongo::ScopedDbConnection conn(_info.getConnectionString()); auto_ptr<mongo::DBClientCursor> pCursor = conn->query(_info.getNS(), query); if (pCursor.get() && pCursor->more()) { while (pCursor->more()) { bindings.push_back(RegBinding(pCursor->next())); } conn.done(); return true; } conn.done(); return false; }
bool RegDB::getUnexpiredContactsUser(const string& identity, int timeNow, Bindings& bindings) const { static string gruuPrefix = GRUU_PREFIX; bool isGruu = identity.substr(0, gruuPrefix.size()) == gruuPrefix; mongo::BSONObj query; if (isGruu) { string searchString(identity); searchString += ";"; searchString += SIP_GRUU_URI_PARAM; query = BSON( "gruu" << searchString << "expirationTime" << BSON_GREATER_THAN(timeNow)); } else { query = BSON( "identity" << identity << "expirationTime" << BSON_GREATER_THAN(timeNow)); } mongo::ScopedDbConnection conn(_info.getConnectionString()); auto_ptr<mongo::DBClientCursor> pCursor = conn->query(_info.getNS(), query); if (pCursor.get() && pCursor->more()) { while (pCursor->more()) { bindings.push_back(RegBinding(pCursor->next())); } conn.done(); return true; } conn.done(); return false; }
HTTPCode SubscriberManager::register_subscriber_internal(const std::string& aor_id, const std::string& server_name, const AssociatedURIs& associated_uris, const Bindings& add_bindings, Bindings& all_bindings, HSSConnection::irs_info& irs_info, bool retry, SAS::TrailId trail) { TRC_DEBUG("Registering AoR %s for the first time", aor_id.c_str()); int now = time(NULL); // We are registering a subscriber for the first time, so there is no stored // AoR. PUT the new bindings to S4. AoR* orig_aor = NULL; AoR* updated_aor = NULL; // We may have been called with no bindings to update. This is the case when // we receive a fetch bindings register from a subscriber that is unregistered. // In that situation, we do not have any data to PUT to S4, but we should // deregister the subscriber with the HSS. if (!add_bindings.empty()) { PatchObject patch_object; build_patch(patch_object, add_bindings, associated_uris); updated_aor = new AoR(aor_id); updated_aor->patch_aor(patch_object); updated_aor->_scscf_uri = server_name; // PUT a new AoR. HTTPCode rc = _s4->handle_put(aor_id, *updated_aor, trail); // If the PUT resulted in precondition failed (which happens if there is // already an AoR in the store), we retry with a reregister. if ((rc == HTTP_PRECONDITION_FAILED) && (retry)) { TRC_DEBUG("Registering AoR %s failed with 412 PRECONDITION FAILED - retry with reregister", aor_id.c_str()); delete updated_aor; updated_aor = NULL; return reregister_subscriber_internal(aor_id, server_name, associated_uris, add_bindings, {}, all_bindings, irs_info, false, trail); } else if (rc != HTTP_OK) { TRC_DEBUG("Registering AoR %s failed with return code %d", aor_id.c_str(), rc); delete updated_aor; updated_aor = NULL; return rc; } log_updated_bindings(*updated_aor, add_bindings, now); // Get all bindings to return to the caller all_bindings = SubscriberDataUtils::copy_active_bindings(updated_aor->bindings(), now, trail); } else { // The was nothing to store for this subscriber so we should deregister the // subscriber with the HSS since they will have previously been registered // incorrectly when the registrar was figuring out the default public ID. if (all_bindings.empty()) { HTTPCode rc = deregister_with_hss(aor_id, HSSConnection::DEREG_USER, server_name, irs_info, trail); if (rc != HTTP_OK) { TRC_DEBUG("Failed to deregister subscriber %s with HSS", aor_id.c_str()); delete orig_aor; orig_aor = NULL; delete updated_aor; updated_aor = NULL; return rc; } } } delete orig_aor; orig_aor = NULL; delete updated_aor; updated_aor = NULL; return HTTP_OK; }
HTTPCode SubscriberManager::remove_bindings(const std::string& public_id, const std::vector<std::string>& binding_ids, const SubscriberDataUtils::EventTrigger& event_trigger, Bindings& bindings, SAS::TrailId trail) { TRC_DEBUG("Removing bindings from IMPU %s", public_id.c_str()); int now = time(NULL); // Get cached subscriber information from the HSS. std::string aor_id; HSSConnection::irs_info irs_info; HTTPCode rc = get_cached_default_id(public_id, aor_id, irs_info, trail); if (rc != HTTP_OK) { return rc; } // Get the original AoR from S4. AoR* orig_aor = NULL; uint64_t unused_version; rc = _s4->handle_get(aor_id, &orig_aor, unused_version, trail); if (rc != HTTP_OK) { delete orig_aor; orig_aor = NULL; if (rc == HTTP_NOT_FOUND) { // If there is no AoR, we still count that as a success. TRC_DEBUG("Removing bindings for AoR %s succeeded because no bindings are present in the store", aor_id.c_str()); return HTTP_OK; } TRC_DEBUG("Removing bindings for AoR %s failed during GET with return code %d", aor_id.c_str(), rc); return rc; } // We log removed bindings before writing to the store so that in the case // that the write fails, our estimate of how many active bindings we have will // be an underestimate, not an overestimate. log_removed_bindings(*orig_aor, binding_ids); // Check if there are any subscriptions that share the same contact as // the removed bindings, and delete them too. std::vector<std::string> subscription_ids_to_remove = subscriptions_to_remove(orig_aor->bindings(), orig_aor->subscriptions(), Bindings(), binding_ids); PatchObject patch_object; build_patch(patch_object, binding_ids, subscription_ids_to_remove, irs_info._associated_uris); // PATCH the existing AoR. AoR* updated_aor = NULL; rc = _s4->handle_patch(aor_id, patch_object, &updated_aor, trail); if (rc != HTTP_OK) { TRC_DEBUG("Removing bindings for AoR %s failed during PATCH with return code %d", aor_id.c_str(), rc); delete orig_aor; orig_aor = NULL; delete updated_aor; updated_aor = NULL; return rc; } log_subscriptions(aor_id, *orig_aor, *updated_aor, subscription_ids_to_remove, now); // Get all bindings to return to the caller bindings = SubscriberDataUtils::copy_active_bindings(updated_aor->bindings(), now, trail); send_notifys(aor_id, orig_aor, updated_aor, event_trigger, now, trail); // Update HSS if all bindings expired. if (bindings.empty()) { // If this action was not triggered by the HSS e.g. because of an RTR, we // should dergister with the HSS. if (event_trigger != SubscriberDataUtils::EventTrigger::HSS) { std::string dereg_reason = (event_trigger == SubscriberDataUtils::EventTrigger::USER) ? HSSConnection::DEREG_USER : HSSConnection::DEREG_ADMIN; rc = deregister_with_hss(aor_id, dereg_reason, updated_aor->_scscf_uri, irs_info, trail); if (rc != HTTP_OK) { TRC_DEBUG("Failed to deregister subscriber %s with HSS", aor_id.c_str()); delete orig_aor; orig_aor = NULL; delete updated_aor; updated_aor = NULL; return rc; } } // Send 3rd party deREGISTERs. _registration_sender->deregister_with_application_servers(public_id, irs_info._service_profiles[public_id], trail); } delete orig_aor; orig_aor = NULL; delete updated_aor; updated_aor = NULL; return HTTP_OK; }
HTTPCode SubscriberManager::reregister_subscriber_internal(const std::string& aor_id, const std::string& server_name, const AssociatedURIs& associated_uris, const Bindings& updated_bindings, const std::vector<std::string>& binding_ids_to_remove, Bindings& all_bindings, HSSConnection::irs_info& irs_info, bool retry, SAS::TrailId trail) { TRC_DEBUG("Reregistering AoR %s", aor_id.c_str()); int now = time(NULL); AoR* orig_aor = NULL; uint64_t unused_version; HTTPCode rc = _s4->handle_get(aor_id, &orig_aor, unused_version, trail); // We are reregistering a subscriber, so there must be an existing AoR in the // store. AoR* updated_aor = NULL; if ((rc == HTTP_NOT_FOUND) && (retry)) { TRC_DEBUG("Reregistering AoR %s failed with 404 NOT FOUND - retry with register", aor_id.c_str()); return register_subscriber_internal(aor_id, server_name, associated_uris, updated_bindings, all_bindings, irs_info, false, trail); } else if (rc != HTTP_OK) { TRC_DEBUG("Reregistering AoR %s failed during GET with return code %d", aor_id.c_str(), rc); delete orig_aor; orig_aor = NULL; return rc; } // Check if there are any subscriptions that share the same contact as // the removed bindings, and delete them too. std::vector<std::string> subscription_ids_to_remove = subscriptions_to_remove(orig_aor->bindings(), orig_aor->subscriptions(), updated_bindings, binding_ids_to_remove); // We log removed bindings before writing to the store so that in the case // that the write fails, our estimate of how many active bindings we have will // be an underestimate, not an overestimate. log_removed_bindings(*orig_aor, binding_ids_to_remove); PatchObject patch_object; build_patch(patch_object, updated_bindings, binding_ids_to_remove, subscription_ids_to_remove, associated_uris); // PATCH the existing AoR. rc = _s4->handle_patch(aor_id, patch_object, &updated_aor, trail); // If we didn't find an existing AoR, that means the subscriber does not // currently exist. We might want to retry by registering the subscriber // afresh. if ((rc == HTTP_NOT_FOUND) && (retry)) { TRC_DEBUG("Reregistering AoR %s failed with 404 NOT FOUND - retry with register", aor_id.c_str()); delete orig_aor; orig_aor = NULL; return register_subscriber_internal(aor_id, server_name, associated_uris, updated_bindings, all_bindings, irs_info, false, trail); } else if (rc != HTTP_OK) { TRC_DEBUG("Reregistering AoR %s failed during PATCH with return code %d", aor_id.c_str(), rc); delete orig_aor; orig_aor = NULL; delete updated_aor; updated_aor = NULL; return rc; } log_updated_bindings(*updated_aor, updated_bindings, now); log_subscriptions(aor_id, *orig_aor, *updated_aor, subscription_ids_to_remove, now); // Get all bindings to return to the caller all_bindings = SubscriberDataUtils::copy_active_bindings(updated_aor->bindings(), now, trail); send_notifys(aor_id, orig_aor, updated_aor, SubscriberDataUtils::EventTrigger::USER, now, trail); // Update HSS if all bindings expired. if (all_bindings.empty()) { rc = deregister_with_hss(aor_id, HSSConnection::DEREG_USER, updated_aor->_scscf_uri, irs_info, trail); if (rc != HTTP_OK) { TRC_DEBUG("Failed to deregister subscriber %s with HSS", aor_id.c_str()); delete orig_aor; orig_aor = NULL; delete updated_aor; updated_aor = NULL; return rc; } } delete orig_aor; orig_aor = NULL; delete updated_aor; updated_aor = NULL; return HTTP_OK; }
Value Interpreter::exec(const InstructionList &instructions, Bindings &bindings) { Stack stack; ClosureValues closureValues; for(InstructionList::const_iterator it = instructions.begin() ; it != instructions.end() ; ++it) { Instruction::Type type = it->type(); const Value &value = it->value(); switch(type) { case Instruction::PUSH: if(settings_.trace) { std::cout << "DEBUG: " << it->sourceLocation() << " push " << value << '\n'; } stack.push_back(value); break; case Instruction::CALL: { if(settings_.trace) { std::cout << "DEBUG: " << it->sourceLocation() << " call " << value << '\n'; } Value result = handleFunction(it->sourceLocation(), value, stack, bindings); stack.push_back(result); if(settings_.trace) { std::cout << "DEBUG: " << it->sourceLocation() << " return value " << result << '\n'; } } break; case Instruction::JUMP: { int instructionsToSkip = getInstructionsToSkip(type, value); int remaining = instructions.end() - it; if(remaining < instructionsToSkip) { throw CompilerBug("insufficient instructions available to skip! (remaining: " + str(remaining) + " < instructionsToSkip: " + str(instructionsToSkip) + ")"); } if(settings_.trace) { std::cout << "DEBUG: " << it->sourceLocation() << " jumping back " << instructionsToSkip << '\n'; } it += instructionsToSkip; } break; case Instruction::LOOP: { int instructionsToSkip = getInstructionsToSkip(type, value); int instructionsAvailable = instructions.size(); // Note: signed type is important! if(instructionsAvailable < instructionsToSkip) { throw CompilerBug("insufficient instructions available to loop! (instructionsToSkip: " + str(instructionsToSkip) + " > instructions.size(): " + str(instructions.size()) + ")"); } if(settings_.trace) { std::cout << "DEBUG: " << it->sourceLocation() << " looping back " << instructionsToSkip << " instructions\n"; } it -= instructionsToSkip; } break; case Instruction::CLOSE: { if(settings_.trace) { std::cout << "DEBUG: " << it->sourceLocation() << " close " << value << '\n'; } Value result = handleClose(value, stack, closureValues, bindings); stack.push_back(result); } break; case Instruction::COND_JUMP: { if(stack.empty()) { throw CompilerBug("empty stack when testing conditional jump"); } int instructionsToSkip = getInstructionsToSkip(type, value); int remaining = instructions.end() - it; if(remaining < instructionsToSkip) { throw CompilerBug("insufficient instructions available to skip! (remaining: " + str(remaining) + " < instructionsToSkip: " + str(instructionsToSkip) + ")"); } Value top = pop(stack); if(settings_.trace) { std::cout << "DEBUG: " << it->sourceLocation() << " jumping back " << instructionsToSkip << " if " << top << '\n'; } if(top.isFalsey()) { it += instructionsToSkip; } } break; case Instruction::REF_LOCAL: handleRef(Bindings::Local, value, stack, bindings); if(settings_.trace) { std::cout << "DEBUG: " << it->sourceLocation() << " local ref '" << value.string() << "' is " << stack.back() << '\n'; } break; case Instruction::INIT_LOCAL: { const Value &intialisedValue = handleInit(Bindings::Local, value, stack, bindings); if(settings_.trace) { std::cout << "DEBUG: " << it->sourceLocation() << " local init '" << value.string() << "' to " << intialisedValue << '\n'; } } break; case Instruction::ASSIGN_LOCAL: { const Value &assignedValue = handleAssign(Bindings::Local, value, stack, bindings); if(settings_.trace) { std::cout << "DEBUG: " << it->sourceLocation() << " local assign '" << value.string() << "' to " << assignedValue << '\n'; } } break; case Instruction::REF_GLOBAL: handleRef(Bindings::Global, value, stack, bindings); if(settings_.trace) { std::cout << "DEBUG: " << it->sourceLocation() << " global ref '" << value.string() << "' is " << stack.back() << '\n'; } break; case Instruction::INIT_GLOBAL: { const Value &intialisedValue = handleInit(Bindings::Global, value, stack, bindings); if(settings_.trace) { std::cout << "DEBUG: " << it->sourceLocation() << " global init '" << value.string() << "' to " << intialisedValue << '\n'; } } break; case Instruction::ASSIGN_GLOBAL: { const Value &assignedValue = handleAssign(Bindings::Global, value, stack, bindings); if(settings_.trace) { std::cout << "DEBUG: " << it->sourceLocation() << " global assign '" << value.string() << "' to " << assignedValue << '\n'; } } break; case Instruction::REF_CLOSURE: handleRef(Bindings::Closure, value, stack, bindings); if(settings_.trace) { std::cout << "DEBUG: " << it->sourceLocation() << " closure ref '" << value.string() << "' is " << stack.back() << '\n'; } break; case Instruction::INIT_CLOSURE: { Identifier identifier = Identifier(value.string()); Bindings::ValuePtr &binding = bindings.getPointer(identifier); closureValues.push_back(ClosedNameAndValue(identifier, binding)); if(settings_.trace) { std::cout << "DEBUG: " << it->sourceLocation() << " closure init '" << value.string() << "' is " << *binding << '\n'; } } break; case Instruction::ASSIGN_CLOSURE: { const Value &assignedValue = handleAssign(Bindings::Closure, value, stack, bindings); if(settings_.trace) { std::cout << "DEBUG: " << it->sourceLocation() << " closure assign '" << value.string() << "' to " << assignedValue << '\n'; } } break; case Instruction::MEMBER_ACCESS: { if(settings_.trace) { std::cout << "DEBUG: " << it->sourceLocation() << " member access " << value << '\n'; } assert(value.isString()); const std::string &memberName = value.string(); Value top = pop(stack); if(!top.isObject()) { throw ExecutionError(it->sourceLocation(), "Member access instruction requires an object but got " + str(top)); } const Value::Object &object = top.object(); Value::Object::const_iterator memberIterator = object.find(memberName); if (memberIterator == object.end()) { throw ExecutionError(it->sourceLocation(), "Unknown member name " + memberName + " for " + str(top)); } if(settings_.trace) { std::cout << "DEBUG: " << it->sourceLocation() << " member access " << value.string() << "." << memberName << " was " << memberIterator->second << '\n'; } stack.push_back(memberIterator->second); } break; default: throw CompilerBug("unhandled instruction type: " + str(type)); } if (settings_.trace) { if (stack.empty()) { std::cout << "Stack is empty\n"; } else { std::cout << "Stack contains " << stack.size() << " entries:\n"; int index = 0; for(Stack::const_iterator it = stack.begin() ; it != stack.end() ; ++it) { ++index; std::cout << index << ": " << *it << '\n'; } } if (closureValues.empty()) { std::cout << "closureValues is empty\n"; } else { std::cout << "closureValues contains " << closureValues.size() << " entries:\n"; int index = 0; for(const ClosedNameAndValue &closedValue: closureValues) { ++index; std::cout << index << ": " << closedValue.first << " -> " << *closedValue.second << " @ " << closedValue.second << '\n'; } } } } return stack.empty() ? Value::nil() : pop(stack); }