Ejemplo n.º 1
0
bool FallBackHandler::received(Message &msg)
{
    switch (m_type)
    {	
	case Answered:
	{ 
	    GenObject* route = s_fallbacklist[msg.getValue("targetid")];
	    s_fallbacklist.remove(route);
	    return false;
	}
	break;
	case Hangup:
	{
	    GenObject* route = s_fallbacklist[msg.getValue("id")];
	    s_fallbacklist.remove(route);
	    return false;
	}
	break;
	case Disconnect:
	{	
	    String reason=msg.getValue("reason");	
	    if (m_stoperror && m_stoperror.matches(reason)) {
		//stop fallback on this error
		GenObject* route = s_fallbacklist[msg.getValue("id")];
		s_fallbacklist.remove(route);
		return false;
	    }

	    FallBackRoute* route = static_cast<FallBackRoute*>(s_fallbacklist[msg.getValue("id")]);
	    if (route) {
		Message* r = route->get();
		if (r) {
		    r->userData(msg.userData());
		    Engine::enqueue(r);
		    return true;
		}
		s_fallbacklist.remove(route);
	    }
	    return false;
	}
	break;
    }
    return false;
}
Ejemplo n.º 2
0
bool ExmapTest::run()
{
    SysInfoPtr sysinfo(new LinuxSysInfo);
    Snapshot snap(sysinfo);

    is(snap.num_procs(), 0, "zero procs before load");
    ok(snap.load(), "can load snapshot");
    ok(snap.num_procs() > 0, "some procs after load");

    list<ProcessPtr> allprocs = snap.procs();
    ok(!allprocs.empty(), "can get a list of procs");
    list<ProcessPtr>::iterator proc_it;
    list<ProcessPtr> procs;

    bool failed_to_get_sizes = false;
    SizesPtr sizes;
    for (proc_it = allprocs.begin(); proc_it != allprocs.end(); ++proc_it) {
	string cmdline = (*proc_it)->cmdline();
	if (cmdline== SA_EXE) {
	    procs.push_back(*proc_it);
	}
	sizes = (*proc_it)->sizes();
	if (!sizes) {
	    failed_to_get_sizes = true;
	}
    }
    ok(!failed_to_get_sizes, "can get sizes for every proc");

    is((int) procs.size(), NUM_INSTANCES, "can find all our sharedarray procs");

    ProcessPtr proc = procs.front();
    sizes = proc->sizes();
    ok(sizes->val(Sizes::VM) > NUM_ARRAYS * ARRAY_SIZE, "image is big enough");

    double ps_size = get_pid_size_from_ps(proc->pid());
    is_approx_rel(sizes->val(Sizes::VM),
		  ps_size,
		  0.001,
		  "exmap info matches ps output");

    ok(sizes->val(Sizes::RESIDENT) > 0, "nonzero resident size");
    ok(sizes->val(Sizes::EFFECTIVE_RESIDENT) > 0, "nonzero eff resident size");
    ok(sizes->val(Sizes::EFFECTIVE_RESIDENT) < sizes->val(Sizes::RESIDENT),
       "effective is smaller than eff resident");

    ok(sizes->val(Sizes::MAPPED) > 0, "nonzero mapped size");
    ok(sizes->val(Sizes::EFFECTIVE_MAPPED) > 0, "nonzero eff mapped size");
    ok(sizes->val(Sizes::EFFECTIVE_MAPPED) < sizes->val(Sizes::MAPPED),
       "effective is smaller than eff mapped");

    
    list<FilePtr> files;
    list<FilePtr>::iterator file_it;
    list<FilePtr> all_files = snap.files();
    
    ok(all_files.size() > 0, "can find some files");

    Regexp re;
    re.compile(SA_LIB + "$");
    failed_to_get_sizes = false;
    for (file_it = all_files.begin(); file_it != all_files.end(); ++file_it) {
	string name = (*file_it)->name();
	if (re.matches(name)) {
	    files.push_back(*file_it);
	}
	sizes = (*file_it)->sizes();
	if (!sizes) {
	    failed_to_get_sizes = true;
	}
    }
    ok(!failed_to_get_sizes, "can get sizes for every file");
    is((int) files.size(), 1, "shared lib only listed once");
    FilePtr shlib_file = files.front();
    ok(shlib_file->is_elf(), "shared lib recognised as elf file");

    list<ProcessPtr> procs_per_file = shlib_file->procs();
    is((int) procs_per_file.size(), NUM_INSTANCES,
       "right number of procs mapping the file");
    for (proc_it = procs_per_file.begin();
	 proc_it != procs_per_file.end();
	 ++proc_it) {
	ok(proc->cmdline() == SA_EXE, "each proc has correct cmdline");
    }

    for (proc_it = procs.begin();
	 proc_it != procs.end();
	 ++proc_it) {
	sizes = proc->sizes(shlib_file);
	long arrays_size = NUM_ARRAYS * ARRAY_SIZE;
	float delta = std::abs(arrays_size - (long) sizes->val(Sizes::VM));
	delta /= arrays_size;
	ok(delta < 0.01, "Shared lib has correct size in each proc");
    }
    
    Elf::SectionPtr text = shlib_file->elf()->section(".text");
    ok(text, "can find text section");
    ok(text->size() > 0, "text section has nonzero size");
    sizes = procs.front()->sizes(shlib_file, text->mem_range());
    /// This appears to be compiler and system dependent...
    /*
    is_approx_rel(sizes->val(Sizes::RESIDENT),
		  2.0 * text->size(),
		  0.001,
		  "lib text is resident and mapped twice (!)");
		  */
    
    Elf::SectionPtr bss = shlib_file->elf()->section(".bss");
    ok(bss, "can find bss section");
    ok(bss->size() > 0, "bss section has nonzero size");
    SizesPtr bss_sizes = procs.front()->sizes(shlib_file, bss->mem_range());
    ok(bss_sizes, "can get sizes for bss section");

    Elf::SectionPtr data = shlib_file->elf()->section(".data");
    ok(data, "can find data section");
    ok(data->size() > 0, "data section has nonzero size");
    SizesPtr data_sizes = procs.front()->sizes(shlib_file, data->mem_range());
    ok(data_sizes, "can get sizes for data section");

    is(data->size(), bss->size(), "data and bss sections have same size");

    is_approx(data_sizes->val(Sizes::MAPPED),
	      bss_sizes->val(Sizes::MAPPED),
	      Elf::page_size(),
	      "data and bss mapped within page of each other");
    
    is_approx(data_sizes->val(Sizes::RESIDENT),
	      bss_sizes->val(Sizes::RESIDENT),
	      Elf::page_size(),
	      "data and bss resident within page of each other");

    // Now get the all-proc sizes from the file
    sizes = shlib_file->sizes(bss->mem_range());
    // The totals should be a multiple of the individual
    is(sizes->val(Sizes::RESIDENT),
	    bss_sizes->val(Sizes::RESIDENT) * NUM_INSTANCES,
	    "Total resident for all procs the same as multiplying up one proc");
    is(sizes->val(Sizes::MAPPED),
	    bss_sizes->val(Sizes::MAPPED) * NUM_INSTANCES,
	    "Total mapped for all procs the same as multiplying up one proc");

    double bss_resident_arrays_size = 0;
    double data_resident_arrays_size = 0;
    double bss_writable_arrays_size = 0;
    double data_writable_arrays_size = 0;
    for (int i = 0; i < NUM_ARRAYS; ++i) {
	if (ARRAY_INFO[i].initialised) {
	    data_resident_arrays_size
		+= ARRAY_SIZE * ARRAY_INFO[i].resident_percent / 100;
	    data_writable_arrays_size
		+= ARRAY_SIZE * ARRAY_INFO[i].writable_percent / 100;
	}
	else {
	    bss_resident_arrays_size
		+= ARRAY_SIZE * ARRAY_INFO[i].resident_percent / 100;
	    bss_writable_arrays_size
		+= ARRAY_SIZE * ARRAY_INFO[i].writable_percent / 100;
	}
    }

    for (proc_it = procs.begin();
	 proc_it != procs.end();
	 ++proc_it) {
	
	sizes = proc->sizes(shlib_file, data->mem_range());
	is_approx(sizes->val(Sizes::RESIDENT),
		  data_resident_arrays_size,
		  Elf::page_size(),
		  "resident size for data in proc correct with a page");
	is_approx(sizes->val(Sizes::WRITABLE),
		  data_writable_arrays_size,
		  Elf::page_size(),
		  "writable size for data in proc correct with a page");
	
	sizes = proc->sizes(shlib_file, bss->mem_range());
	is_approx_rel(sizes->val(Sizes::RESIDENT),
		      bss_resident_arrays_size,
		      0.001,
		      "correct resident size for bss in proc");
	is_approx_rel(sizes->val(Sizes::WRITABLE),
		      bss_writable_arrays_size,
		      0.001,
		      "correct writable size for bss in proc");
    }


    for (int i = 0; i < NUM_ARRAYS; ++i) {
	const struct array_info *info = ARRAY_INFO + i;
	string symname = info->name;
	Elf::SymbolPtr sym = shlib_file->elf()->symbol(symname);
	ok(sym, "can find symbol " + symname);
	is(sym->size(), ARRAY_SIZE, symname + " has correct size");
	
	sizes = proc->sizes(shlib_file, sym->range());
	is_approx_rel((int) sizes->val(Sizes::RESIDENT),
		      ARRAY_SIZE * info->resident_percent / 100,
		      0.001,
		      symname + " has correct resident size");

	is_approx_rel(sizes->val(Sizes::WRITABLE),
		      ARRAY_SIZE * info->writable_percent / 100.0,
		      0.001,
		      symname + " has correct writable size");

	// Uninitialised space which is only read appears to be shared
	// amongst every proc in the system (a 'zero page'?). This is
	// good from a low-memusage point of view, but it means that
	// it is shared among nearly all running procs to varying
	// degrees. So we can't really account for it.
	if (symname == "uninit_readme" || symname == "uninit_readhalf") {
	    continue;
	}

	int expected_eff_resident = ARRAY_SIZE * info->resident_percent / 100;
	if (info->shared) {
	    expected_eff_resident /= NUM_INSTANCES;
	}
	// approximate match since the percentage (fixed pt)
	// arithmetic could put us off by a factor of 1/100 (and does...:-)
	is_approx((int) sizes->val(Sizes::EFFECTIVE_RESIDENT),
		  expected_eff_resident,
		  1 + (expected_eff_resident / 100),
		  symname + " has correct effective size");
    }


    // Non-elf maps

    procs.clear();
    for (proc_it = allprocs.begin(); proc_it != allprocs.end(); ++proc_it) {
	string cmdline = (*proc_it)->cmdline();
	if (cmdline == MI_EXE) {
	    procs.push_back(*proc_it);
	}
    }
    is((int) procs.size(), NUM_INSTANCES, "can find all our mapit procs");
    proc = procs.front();

    files.clear();
    re.compile("/" + MI_DAT + "$");
    for (file_it = all_files.begin(); file_it != all_files.end(); ++file_it) {
	string name = (*file_it)->name();
	if (re.matches(name)) {
	    files.push_back(*file_it);
	}
    }
    is((int) files.size(), 1, MI_DAT + " file only listed once");
    FilePtr mapped_file = files.front();

    ok(!mapped_file->is_elf(), MI_DAT + " isn't an elf file");
    off_t fsize = 0;
    double mi_data_size = 0;
    ok(file_size(MI_DAT, fsize), "can get file size");
    mi_data_size = fsize;
    ok(mi_data_size > 0, "file has nonzero size");
    
    for (proc_it = procs.begin();
	 proc_it != procs.end();
	 ++proc_it) {
	sizes = (*proc_it)->sizes(mapped_file);
	is_approx_rel(sizes->val(Sizes::VM),
		      mi_data_size,
		      0.001,
		      "correct data file size");
	is_approx_rel(sizes->val(Sizes::RESIDENT),
		      mi_data_size,
		      0.001,
		      "whole data file is resident");
	is_approx_rel(sizes->val(Sizes::EFFECTIVE_RESIDENT),
		      mi_data_size / NUM_INSTANCES,
		      0.001,
		      "data file is shared between instances correctly");
    }
    
    return true;
}
Ejemplo n.º 3
0
// Decode the message line
// Command: verb transaction endpoint proto_name proto_version ...
// Response: code transaction comment ...
MGCPMessage* MGCPMessage::decodeMessage(const char* line, unsigned int len, unsigned int& trans,
	String& error, MGCPEngine* engine)
{
    String name, ver;
    int code = -1;
    unsigned int trID = 0;
    MGCPEndpointId id;

#ifdef PARSER_DEBUG
    String msgLine(line,len);
    Debug(engine,DebugAll,"Parse message line (len=%u): %s",
	msgLine.length(),msgLine.c_str());
#endif

    for (unsigned int item = 1; true; item++) {
	if (item == 6) {
#ifdef DEBUG
	    if (len) {
		String rest(line,len);
		Debug(engine,DebugAll,"Unparsed data on message line: '%s'",rest.c_str());
	    }
#endif
	    break;
	}

	// Response: the 3rd item is the comment
	bool comment = (item == 3) && (code != -1);

	// Get current item
	if (!(skipBlanks(line,len) || comment)) {
	    error = "Unexpected end of line";
	    return 0;
	}

	unsigned int itemLen = 0;
	if (comment)
	    itemLen = len;
	else
	    for (; itemLen < len && !isBlank(line[itemLen]); itemLen++)
		;
	String tmp(line,itemLen);
	len -= itemLen;
	line += itemLen;

	switch (item) {
	    // 1st item: verb (command or notification) or response code
	    // Verbs must be 4-character long. Responses must be numbers in the interval [0..999]
	    case 1:
		if (tmp.length() == 3) {
		    code = tmp.toInteger(-1,10);
		    if (code < 0 || code > 999)
			error << "Invalid response code " << tmp;
		}
		else if (tmp.length() == 4)
		    name = tmp.toUpper();
		else
		    error << "Invalid first item '" << tmp << "' length " << tmp.length();
		break;

	    // 2nd item: the transaction id
	    // Restriction: must be a number in the interval [1..999999999]
	    case 2:
		trID = tmp.toInteger(-1,10);
		if (!trID || trID > 999999999)
		    error << "Invalid transaction id '" << tmp << "'";
		// Set trans for command messages so they can be responded on error
		else if (code == -1)
		    trans = trID;
		break;

	    // 3rd item: endpoint id (code is -1) or response comment (code != -1)
	    case 3:
		if (code != -1)
		    name = tmp;
		else {
		    id.set(tmp);
		    if (!id.valid())
			error << "Invalid endpoint id '" << tmp << "'";
		}
		break;

	    // 4th item: protocol name if this is a verb (command)
	    case 4:
		ver = tmp.toUpper();
		if (ver != "MGCP")
		    error << "Invalid protocol '" << tmp << "'";
		break;

	    // 5th item: protocol version if this is a verb (command)
	    case 5:
		{
		    static const Regexp r("^[0-9]\\.[0-9]\\+$");
		    if (!r.matches(tmp))
			error << "Invalid protocol version '" << tmp << "'";
		}
		ver << " " << tmp;
		break;
	}
	if (error)
	    return 0;
	// Stop parse the rest if this is a response
	if (comment)
	    break;
    }
    // Check known commands
    if (code == -1 &&
	!(engine && (engine->allowUnkCmd() || engine->knownCommand(name)))) {
	error << "Unknown cmd '" << name << "'";
	return 0;
    }
    return new MGCPMessage(engine,name,code,trID,id.id(),ver);
}