static Handle reuse_existing_handle(uintptr_t key, H_Type type, size_t flags) { if(flags & RES_NO_CACHE) return 0; // object of specified key and type doesn't exist yet Handle h = h_find(type, key); if(h <= 0) return 0; HDATA* hd; RETURN_STATUS_IF_ERR(h_data_tag_type(h, type, hd)); // h_find means this won't fail hd->refs += 1; // we are reactivating a closed but cached handle. // need to generate a new tag so that copies of the // previous handle can no longer access the resource. // (we don't need to reset the tag in h_free, because // use before this fails due to refs > 0 check in h_user_data). if(hd->refs == 1) { const Tag tag = gen_tag(); h = handle(h_idx(h), tag); // can't fail hd->h = h; } return h; }
static Handle alloc_new_handle(H_Type type, const PIVFS& vfs, const VfsPath& pathname, uintptr_t key, size_t flags, va_list* init_args) { HDATA* hd = (HDATA*)pool_alloc(&hpool, 0); if(!hd) WARN_RETURN(ERR::NO_MEM); new(&hd->pathname) VfsPath; ssize_t idx = h_idx_from_data(hd); RETURN_STATUS_IF_ERR(idx); // (don't want to do this before the add-reference exit, // so as not to waste tags for often allocated handles.) const Tag tag = gen_tag(); Handle h = handle(idx, tag); // can't fail. hd->h = h; hd->key = key; hd->type = type; hd->refs = 1; if(!(flags & RES_NO_CACHE)) hd->keep_open = 1; if(flags & RES_DISALLOW_RELOAD) hd->disallow_reload = 1; hd->unique = (flags & RES_UNIQUE) != 0; hd->pathname = pathname; if(key && !hd->unique) key_add(key, h); Status err = call_init_and_reload(h, type, hd, vfs, pathname, init_args); if(err < 0) goto fail; return h; fail: // reload failed; free the handle hd->keep_open = 0; // disallow caching (since contents are invalid) (void)h_free(h, type); // (h_free already does WARN_IF_ERR) // note: since some uses will always fail (e.g. loading sounds if // g_Quickstart), do not complain here. return (Handle)err; }
//========================================================================================================== // Get the value for a variable that appear in the script in brackets (like [call_id]). Some are static to // the test (received from MServer), some generated, some stored from previous messages. //========================================================================================================== string ScriptReader::get_value(string var, int call_number, bool try_as_last) { smatch match; if(!regex_match(var, match, var_regex)) { throw string("Wrong format for var in ScriptReader::get_value(): " + var); } // var_regex: "(last_)?(((cseq)\\+(\\d+))|([-\\w]+))(:value)?" // submatches: 1 234 5 6 7 bool is_last = (match[1].length() > 0); bool just_value = (match[7].length() > 0); int add_to_cseq = 0; string name = match[2]; if(match[3].length() > 0) { name = match[4]; add_to_cseq = stoi(match[5]); } if(is_last || (try_as_last && (SipMessage::is_message_var(name) || SipParser::inst().match(HEADER_NAME, name)))) { string result = get_last_value(name, call_number, just_value); if(name == CSEQ) { return to_string(stoi(result) + add_to_cseq); } return result; } if(name == BRANCH) { return gen_branch(); } CallIDKind cid_kind = string_to_call_id_kind(name); if(cid_kind != NONE) { return gen_call_id(cid_kind); } if(name == TAG) { return gen_tag(); } if(vars.count(name) != 0) { return vars[name]; } if(static_vars.count(name) != 0) { return static_vars.at(name); } return MServer::inst.get_value(name); }