findModuleByPath("host") returns nullptr in OMNeT++ - c++

In OMNeT++ I'm working on example aloha. I try adding acknowledge message sent from server to the node. So, I have defined cModule *host and added host = findModuleByPath("host"); line to the initialize() method in Server.cc but it returns nullptr and I have seen the getModuleByPath() method also does the same work but throws and exception instead of returning a nullptr.
It cannot find the host module even though I have defined it. I believe I am missing something but I don't know what. Is there a good example of network (with multiple nodes) that also sends acknowledgement message?

There are several issues in using cModule *host = findModuleByPath("host") in initialize() of server.
According to 4.11.4 Finding Modules by Path that command leads to looking for a submodule named host inside the current module, i.e. in server. Of course, server does not contain host, so it results in returning nullptr. To find a sibling module called host one should use
cModule *host = findModuleByPath("^.host").
In Aloha there is no single host module, but a vector of modules. It means, that first host has the name host[0], the second - host[1] etc. Therefore, it would be possible to use:
cModule *host = findModuleByPath("^.host[2]")
Another way is the following command:
cModule *host = getParentModule()->getSubmodule("host", 2)
Be aware that initialize() is called sequentially in modules in the network and the order of choosing the next module is not guaranteed by the simulation environment, e.g. initialize() was called in host[1] but not yet in server.
Multi-Stage Initialization may be used to be sure that one stage of initialize() has been performed in all modules.

Related

(OMNeT++) Where do packets go?

I'm trying to do a project described also here: PacketQueue is 0
I've modified the UdpBasicApp.cc to suit my needs, and in the handleMessage() function I added a piece of code to retrieve the length of the ethernet queue of a router. However the value returned is always 0.
My .ned file regarding the queue of routers is this:
**.router*.eth[*].mac.queue.typename = "DropTailQueue"
**.router*.eth[*].mac.queue.packetCapacity = 51
The code added in the UdpBasicApp.cc file is this:
cModule *mod = getModuleByPath("router3.eth[*].mac.queue.");
queueing::PacketQueue *queue = check_and_cast<queueing::PacketQueue*>(mod);
int c = queue->getNumPackets();
So my question is this: is this the right way to create a queue in a router linked to other nodes with an ethernet link?
My doubt is that maybe packets don't pass through the specified interface, i.e. I've set the ini parameters for the wrong queue.
You are not creating that queue. It was already instantiated by the OMNeT++ kernel. You are just getting a reference to an already existing module with the getModuleByPath() call.
The router3.eth[*].mac.queue. module path is rather suspicious in that call. It is hard-coded in all of your application to get the queue length from router3 even if the app is installed in router1. i.e. you are trying to look at the queue length in a completely different node. Then, the eth[*] is wrong. As a router obviously contains more than one ethernet interface (otherwise it would not be a router), you must explicitly specify which interface you want to sepcify. You must not specify patterns in module path (i.e. eth[0] or something like that, with an exact index must be specified). And at this point, you have to answer the question which ethernet interface I'm interested in, and specify that index. Finally the . end the end is also invalid, so I believe, your code never executes, otherwise the check_and_cast part would have raised an error already.
If you wanted to reach the first enthern interface from an UDP app in the same node, you would use relative path, something like this: ^.eth[0].mac.queue
Finally, if you are unsure whether your model works correctly, why not start the model with Qtenv, and check whether the given module receives any packet? Like,, drill down in the model until the given queue is opened as a simple module (i.e. you see the empty inside of the queue module) and then tap the run/fast run until next event in this module. If the simulation does not stop, then that module indeed did not received any packets and your configuration is wrong.

Cannot build Corda (release/os/4.6) on Ubuntu 20.04 due to failing tests (CryptoUtilsTest & NodeH2SecurityTests)

I am trying to build Corda on Ubuntu 20.04. I have the latest sources from the git repo (release/os/4.6) and I run ./gradlew build in the main folder. However the build fails during two tests (see the detail description below). Is there something that I'm missing? Are there some special flags that I should use for building Corda?
First, the test test default SecureRandom uses platformSecureRandom fails at the last assert, i.e.,
// in file net/corda/core/crypto/CryptoUtilsTest.kt
fun `test default SecureRandom uses platformSecureRandom`() {
// [...]
// Remove Corda Provider again and add it as the first Provider entry.
Security.removeProvider(CordaSecurityProvider.PROVIDER_NAME)
Security.insertProviderAt(CordaSecurityProvider(), 1) // This is base-1.
val secureRandomRegisteredFirstCordaProvider = SecureRandom()
assertEquals(PlatformSecureRandomService.algorithm, secureRandomRegisteredFirstCordaProvider.algorithm)
}
The reason for the failed test is Expected <CordaPRNG>, actual <SHA1PRNG>..
For some reason, the test is successful if before inserting the provider, I call the getServices() method, i.e.,
val provider = CordaSecurityProvider()
provider.getServices()
Security.insertProviderAt(provider, 1) // This is base-1.
I also tried to get the service SecureRandom.CordaPRNG directly from the provider and it works, i.e,
println(provider.getService("SecureRandom", "CordaPRNG"))
prints out Corda: SecureRandom.CordaPRNG -> javaClass
Second, the test h2 server on the host IP requires non-default database password fails since it expects a CouldNotCreateDataSourceException, but it gets a NullPointerException instead, i.e.,
// in file net/corda/node/internal/NodeH2SecurityTests.kt
fun `h2 server on the host IP requires non-default database password`() {
// [...]
address = NetworkHostAndPort(InetAddress.getLocalHost().hostAddress, 1080)
val node = MockNode()
val exception = assertFailsWith(CouldNotCreateDataSourceException::class) {
node.startDb()
}
// [...]
}
The problem is that the address is 127.0.1.1:1080, which means that net/corda/node/internal/Node.kt::startDatabase() does not throw CouldNotCreateDataSourceException since the condition to enter the branch
if (!InetAddress.getByName(effectiveH2Settings.address.host).isLoopbackAddress
&& configuration.dataSourceProperties.getProperty("dataSource.password").isBlank()) {
throw CouldNotCreateDataSourceException()
}
is not satisfied. Instead it calls toString() on the parent of the path given by the DB name; the parent is null, and thus, it throws NullPointerException, i.e.,
val databaseName = databaseUrl.removePrefix(h2Prefix).substringBefore(';')
// databaseName=my_file
val baseDir = Paths.get(databaseName).parent.toString()
Unfortunately there't a LOT of reasons that building Corda from source might not work.
Here are my recommendations:
it could be a java issue, there's a docs page on the specific version of java 8 that you need to use, (latest java support is on the roadmap for corda 5 🔥) Here's the docs page on that https://docs.corda.net/docs/corda-os/4.5/getting-set-up.html
Like Alessandro said, you'll want to be aware that 4.6 isn't generally available yet so there may well be bugs and problems in the code until the release. In addition just take another look at the docs page on building corda (here: https://docs.corda.net/docs/corda-os/4.5/building-corda.html#debianubuntu-linux), it's mentioned to use 18.04 but not the latest linux, as there might be some random clib things that could get in the way there.
Good luck to you.

Is it possible to compile a static library with an external dependancy that is unresolvable at compilation time?

I've created a web server using C and C++, which works in the following way:
First, it initialize the socket for the connection.
Then, when the server receives an HTTP request, it calls a function that will retrieve the data form the request, and create an object which will parse the incoming request. (The object contains the request's parameters and headers).
Then, it calls a function named HandleRequest, and gives him the object created. The object's type is Request, which I wrote myself.
The HandleRequest function will analyze the request, generate an HTML document, and returns the whole document as a string.
Finally, The server takes the string returned by the HandleRequest function and send it back to the client.
Now, if I want to create another site, the only code I will have to changed is the HandleRequest function.
My point is I want to pack the server itself in a static library, and then when I want to make a new website, I only have to write the HandleRequest function and link the static library when compiling to make the server.
Of course, when I try to do so, I have the error
undefined reference to 'HandleRequest'
So is it possible to make the library compile, knowing that a function has its code written outside of the library ?
Edit: I tried to compile the .cpp file with without the -c option, so that the library already have the linking done. I am aware that with the -c option, everything works fine.
Also, I tried to put
extern std::string HandleRequest(Request request);
before the function that calls HandleRequest but it didn't worked.
Quick and easy solution
Make HandleRequest a global variable that’s function pointer:
std::string (*HandleRequest)(Request);
You can move the functionality of the old HandleRequest function into something like DefaultHandleRequest, and you can even initialize the function pointer using the DefaultHandleRequest:
std::string DefaultHandleRequest(Request request)
{
// stuff
}
std::string (*HandleRequest)(Request) = DefaultHandleRequest;
If you do this, you won’t have to change any other code, but you’ll be able to update HandleRequest whenever you like.
More thorough solution
We can make this solution much more general, enabling you to have multiple servers running in the same program.
In order to do this, make a Server class, which acts as the server. An instance of this class will act as your server. Have Server store a std::function<std::string(Request)> that handles incoming requests. You can assign or update this at any time, as necessary.
Design Server so that there can be multiple instances at once, each representing a different server/service with it’s own HandleRequest function.

How to get the module connected to a gate?

Inside a module, I can get a cGate pointer calling the method:
const cGate* cModule::gate ( const char * gatename, int index = -1)
But once obtained the cGate pointer, I don't see a way to get the associate module that is connected (in output) to the gate. I don't see it in the cChannel class either. Is there a way?
Check the cGate::getPathStartGate() and cGate::getPathEndGate() methods. Depending on the direction of the connection those will give you the endpoint gates (it will follow the connections even across module boundaries until it finds a simple module at the other side of the connection chain).
(cGate::getNextGate() and cGate::getPreviousGate() gives only the next/prev gate on the chain)
Once you have the cGate object from the other side, you can get the module using cGate::getOwnerModule()

DNS-SD on Windows using MFC

I have an application built using MFC that I need to add Bonjour/Zeroconf service discovery to. I've had a bit of trouble figuring out how best to do it, but I've settled on using the DLL stub provided in the mDNSresponder source code and linking my application to the static lib generated by that (which in turn uses the system dnssd.dll).
However, I'm still having problems as the callbacks don't always seem to be being called so my device discovery stalls. What confuses me is that it all works absolutely fine under OSX, using the OSX dns-sd terminal service and under Windows using the dns-sd command line service. On that basis, I'm ruling out the client service as being the problem and trying to figure out what's wrong with my Windows code.
I'm basically calling DNSBrowseService(), then in that callback calling DNSServiceResolve(), then finally calling DNSServiceGetAddrInfo() to get the IP address of the device so I can connect to it.
All of these calls are based on using WSAAsyncSelect like this :
DNSServiceErrorType err = DNSServiceResolve(&client,kDNSServiceFlagsWakeOnResolve,
interfaceIndex,
serviceName,
regtype,
replyDomain,
ResolveInstance,
context);
if(err == 0)
{
err = WSAAsyncSelect((SOCKET) DNSServiceRefSockFD(client), p->m_hWnd, MESSAGE_HANDLE_MDNS_EVENT, FD_READ|FD_CLOSE);
}
But sometimes the callback just never gets called even though the service is there and using the command line will confirm that.
I'm totally stumped as to why this isn't 100% reliable, but it is if I use the same DLL from the command line. My only possible explanation is that the DNSServiceResolve function tries to call the callback function before the WSAAsyncSelect has registered the handling message for the socket, but I can't see any way around this.
I've spent ages on this and am now completely out of ideas. Any suggestions would be welcome, even if they're "that's a really dumb way to do it, why aren't you doing X, Y, Z".
I call DNSServiceBrowse, with a "shared connection" (see dns_sd.h for documentation) as in:
DNSServiceCreateConnection(&ServiceRef);
// Need to copy the main ref to another variable.
DNSServiceRef BrowseServiceRef = ServiceRef;
DNSServiceBrowse(&BrowseServiceRef, // Receives reference to Bonjour browser object.
kDNSServiceFlagsShareConnection, // Indicate it's a shared connection.
kDNSServiceInterfaceIndexAny, // Browse on all network interfaces.
"_servicename._tcp", // Browse for service types.
NULL, // Browse on the default domain (e.g. local.).
BrowserCallBack, // Callback function when Bonjour events occur.
this); // Callback context.
This is inside a main run method of a thread class called ServiceDiscovery. ServiceRef is a member of ServiceDiscovery.
Then immediately following the above code, I have a main event loop like the following:
while (true)
{
err = DNSServiceProcessResult(ServiceRef);
if (err != kDNSServiceErr_NoError)
{
DNSServiceRefDeallocate(BrowseServiceRef);
DNSServiceRefDeallocate(ServiceRef);
ServiceRef = nullptr;
}
}
Then, in BrowserCallback you have to setup the resolve request:
void DNSSD_API ServiceDiscovery::BrowserCallBack(DNSServiceRef inServiceRef,
DNSServiceFlags inFlags,
uint32_t inIFI,
DNSServiceErrorType inError,
const char* inName,
const char* inType,
const char* inDomain,
void* inContext)
{
(void) inServiceRef; // Unused
ServiceDiscovery* sd = (ServiceDiscovery*)inContext;
...
// Pass a copy of the main DNSServiceRef (just a pointer). We don't
// hang to the local copy since it's passed in the resolve callback,
// where we deallocate it.
DNSServiceRef resolveServiceRef = sd->ServiceRef;
DNSServiceErrorType err =
DNSServiceResolve(&resolveServiceRef,
kDNSServiceFlagsShareConnection, // Indicate it's a shared connection.
inIFI,
inName,
inType,
inDomain,
ResolveCallBack,
sd);
Then in ResolveCallback you should have everything you need.
// Callback for Bonjour resolve events.
void DNSSD_API ServiceDiscovery::ResolveCallBack(DNSServiceRef inServiceRef,
DNSServiceFlags inFlags,
uint32_t inIFI,
DNSServiceErrorType inError,
const char* fullname,
const char* hosttarget,
uint16_t port, /* In network byte order */
uint16_t txtLen,
const unsigned char* txtRecord,
void* inContext)
{
ServiceDiscovery* sd = (ServiceDiscovery*)inContext;
assert(sd);
// Save off the connection info, get TXT records, etc.
...
// Deallocate the DNSServiceRef.
DNSServiceRefDeallocate(inServiceRef);
}
hosttarget and port contain your connection info, and any text records can be obtained using the DNS-SD API (e.g. TXTRecordGetCount and TXTRecordGetItemAtIndex).
With the shared connection references, you have to deallocate each one based on (or copied from) the parent reference when you are done with them. I think the DNS-SD API does some reference counting (and parent/child relationship) when you pass copies of a shared reference to one of their functions. Again, see the documentation for details.
I tried not using shared connections at first, and I was just passing down ServiceRef, causing it to be overwritten in the callbacks and my main loop to get confused. I imagine if you don't use shared connections, you need to maintain a list of references that need further processing (and process each one), then destroy them when you're done. The shared connection approach seemed much easier.