Indy's SNMP Trap send nothing - c++builder

I tried to send SNMP Trap using Indy's component TIdSnmp.
(Code was copied from Implementing SNMP SendTrap using Indy components)
void __fastcall TMainForm::btSendTrapClick(TObject *Sender)
{
String myEnterprise = _D("1.5.5.5.5.5.5.5");
String eventType = myEnterprise + _D(".1");
String eventDistance = myEnterprise + _D(".2");
TIdSNMP * idSnmp = 0;
idSnmp = new TIdSNMP(NULL);
idSnmp->Trap->Host = edHost->Text;
idSnmp->Trap->Community = _D("public");
idSnmp->Trap->Enterprise = myEnterprise;
idSnmp->Trap->GenTrap = 6; // I've met such values
idSnmp->Trap->SpecTrap = 1; // somewhere in inet
idSnmp->Trap->MIBAdd(eventType,_D("ftCritical"));
idSnmp->Trap->MIBAdd(eventDistance,_D("2.357"));
idSnmp->SendTrap();
delete idSnmp;
}
But wireshark doesn't registar any network activity. I tried variant with QuickSendTrap with the same result.
In despair I decided to try Indy's UDP component for sending something.
void __fastcall TForm1::btFireClick(TObject *Sender)
{
TIdUDPClient* udpClient = 0;
TIdBytes sendData;
myClass* packet = new myClass();
packet->a = 10;
packet->b = 77;
packet->c = "Test";
int size = sizeof(*packet);
sendData = RawToBytes(packet, size);
udpClient = new TIdUDPClient(NULL);
udpClient->Host = "192.168.100.19";
udpClient->Port = 162;
udpClient->SendBuffer(sendData);
delete udpClient;
}
Surely it's not a real SNMP Trap but wireshark see this:
192.168.100.21 192.168.100.19 UDP 54 Source port: 49873 Destination port: snmptrap
Wireshark filter is "udp portrange 161-162"
And in data section I can find my values. By the way SNMP component works properly for getting values by simple idSnmp->SendQuery() and this is registered by wireshark as well.
So, are there some additinal conditionals in order to SendTrap() works properly?
I have Windows7, administative rights. Firewall is turned off.
Code compiled by Embarcadero RAD Studio 2010, desktop application.
Should SNMP Trap receiver wait my SendTrap() just in order to SendTrap() could work? (unfortunately, I haven't got another computer for experiments at the moment)
Should be OID "1.5.5.5.5.5.5.5" be registered somewhere in my computer just in order to SendTrap() could work?
Maybe some other requirements?

But wireshark doesn't registar any network activity
That is not what you said in the other discussion. You said it was working.
So, are there some additinal conditionals in order to SendTrap() works properly?
No. The code I gave you is all you need.
Should SNMP Trap receiver wait my SendTrap() just in order to SendTrap() could work?
No. UDP is connection-less. A receiver is not required in order to send. If there is no receiver, an ICMP error will be sent back to the sender.
Should be OID "1.5.5.5.5.5.5.5" be registered somewhere in my computer just in order to SendTrap() could work?
No.

Related

How dynamically assign correct message to decode protocol buffer message?

Hi I have a data stream pipeline that works over "events". Those events are simple protocol buffer messages, say:
message OrderCoffee {
int32 id = 1;
}
message CancelOrder {
int32 id = 1;
}
A client then serialize/encode those messages and push them into a message broker (say Google Pub/Sub). A subscriber consumes one message and tries to decode/deserialize (pseudocode):
decoded_message = OrderCoffe.decode(encoded_message)
decoded_message = CancelOrder.decode(encoded_message)
Which of those lines work? Both, at least in my Ruby code. I don't know if I have a conceptual misunderstanding about how to use protocol buffers or that is a ruby bug.
If that is the expected bahaviour, how can I know at runtime which message should I decode the received message?
EDIT:
Ok, the solution seems to be https://developers.google.com/protocol-buffers/docs/techniques?csw=1#self-description .
I couldn't understand though. Could someone provide an example of how to implement that in ruby?
Basically, you can't from there. Protobuf messages are not self-describing. If it was me, I'd add a wrapper:
message SomeType {
oneof the_thing {
OrderCoffee order = 1;
CancelOrder cancel = 2;
}
}
When you deserialize a the_thing, you can test which inner object is assigned.

Receive messages only from a specific DDS topic instance?

I'm using OpenDDS v3.6, and trying to send a message to a specific DDS peer, one of many. In the IDL, the message structure looks like the following:
module Test
{
#pragma DCPS_DATA_TYPE "Test::MyMessage"
#pragma DCPS_DATA_KEY "Test::MyMessage dest_id"
struct MyMessage {
short dest_id;
string txt;
};
};
My understanding is that because the data key is unique, this is a new instance of the topic being written to, and any further msgs written w/ the same data key send to this specific instance of the topic. My send code is as follows:
DDS::ReturnCode_t ret;
Test::MyMessage msg;
// populate msg
msg.dest_id = n;
DDS::InstanceHandle_t handle;
handle = msg_writer->register_instance(msg);
ret = msg_writer->write(msg, handle);
So now I need to figure out how to get the receiving peer to read only from this topic instance and not receive all the other messages being sent to other peers. I started with the following, but not sure how to properly select a specific topic instance.
DDS::InstanceHandle_t instance;
status = msg_dr->take_next_instance(spec, si, 1, DDS::ANY_SAMPLE_STATE,
DDS::ANY_VIEW_STATE, DDS::ANY_INSTANCE_STATE);
Any help much appreciated.
The easiest way to achieve what you are looking for is by using a ContentFilteredTopic. This class is a specialization of the TopicDescription class and allows you to specify an expression (like a SQL WHERE-clause) of the samples that you are interested in.
Suppose you want your DataReader to only receive samples with dest_id equal to 42, then the corresponding code for creating the ContentFilteredTopic would look something like
DDS::ContentFilteredTopic_var cft =
participant->create_contentfilteredtopic("MyTopic-Filtered",
topic,
"dest_id = 42",
StringSeq());
From there on, you create your DataReader using cft as the parameter for the TopicDescription. The resulting reader will look like a regular DataReader, except that it only receives the desired samples and nothing else. Since the field dest_id happens to be the field that identifies the instance, the end result is that you will only have one instance in your DataReader.
You can check out the DDS specification (section 7.1.2.3.3) or OpenDDS Developer's Guide (section 5.2) for more details.

NSNetService Resolve ipv6 that can not make an http request on it

Recently, i was facing a problem while resolving NSNetService.
I was published an NSNetService with type _http._tcp., to be just like an http server.
Other wise, on another device, i was start searching for this service, and it will find it.
After finding it, i was apply resolveWithTimeout on it.
While resolving, sometimes i was get only ipv6, that i can't make an HTTPRequest using NSURLConnection sendAsynchronousRequest: queue: completionHandler: on it.
How can i apply and HTTPRequest on url contains ipv6 ?
How can i deal with that problem ?
It looks like you're building a string like http://{IP}:{port}/ based on the information provided in NSNetService. And it works fine for an IPv4 address, the resulting string is like http://192.168.1.8:8080/.
However, IPv6 addresses use colons as a separator (instead of periods), so the same code generates a string like http://fe80::e31:db5a:0089:98ba:8080/, and the resulting address is incorrect. First, you need to wrap the address in square brackets: http://[fe80::e31:db5a:0089:98ba]:8080/. Second, fe80::/64 (as in the example) addresses are link-local and can be assigned to each IPv6-supporting interface, so you need to also provide the interface to use, e.g. http://[fe80::e31:db5a:0089:98ba%25en0]:8080/ where %25 is an encoded percent symbol and en0 is the interface name to use.
To sum up, you need to build different strings for IPv4 and IPv6 addresses. Speaking of which, there are Apple's recommendations:
As a rule, you should not resolve a service to an IP address and port number unless you are doing something very unusual.
– Connecting to a Bonjour Service by IP Address
Try to use this URL string if possible: http://{hostname}:{port}/, you won't need those extra IP address manipulations.
So this is what I end up using... it correctly translates address into URL including the interface:
NSString * result = nil;
char host[NI_MAXHOST];
char service[NI_MAXSERV];
int err;
err = getnameinfo(address.bytes, (socklen_t) address.length, host, sizeof(host), service, sizeof(service), NI_NUMERICHOST | NI_NUMERICSERV);
if (err == 0) {
struct sockaddr_storage *sockaddr = (struct sockaddr_storage *)address.bytes;
if (sockaddr->ss_family == AF_INET6) {
result = [NSString stringWithFormat:#"[%s]:%s", host, service];
} else if (sockaddr->ss_family == AF_INET) {
result = [NSString stringWithFormat:#"%s:%s", host, service];
}
}

Default DNS server in monotouch

I'm wondering how do I get default DNS server in monotouch?
this code works perfectly in simulator, but gives 0 records on device.
NetworkInterface.GetAllNetworkInterfaces();
foreach (IPAddress ipAddr in ipProps.DnsAddresses)
Console.WriteLine(ipAddr);
from the other hand, this code works on both simulator and device:
IPHostEntry he = Dns.GetHostEntry(domain);
dns = he.HostName.ToString();
having all this, I assume DNS server address is stored somewhere. I mean it is accessible. How to get its IP?
This will get the IP Address in MonoTouch:-
public string GetIPAddress()
{
string address = "Not Connected";
try
{
#if SIM
address = IPAddress.FileStyleUriParser("127.0.0.1");
#else
string str = Dns.GetHostName() + ".local";
IPHostEntry hostEntry = Dns.GetHostEntry(str);
address = (
from addr in hostEntry.AddressList
where addr.AddressFamily == AddressFamily.InterNetwork
select addr.ToString()
).FirstOrDefault();
#endif
}
catch (Exception ex)
{
// Add error handling....
}
return address;
}
Note the difference between using the simulator and device.
I do not believe such an API exists on iOS (but I would be happy to be proven wrong). Other projects, that needs this information, relies on hacks like using well known, static address to DNS servers) to overcome this.
Now the reason code like this:
var all = NetworkInterface.GetAllNetworkInterfaces ();
foreach (NetworkInterface ni in all) {
var props = ni.GetIPProperties ();
foreach (var dns in props.DnsAddresses) {
Console.WriteLine (dns);
}
}
works on the simulator is because it's a simulator and not an emulator. IOW the host (Mac) computer allows far more things than a real iOS device will allow.
More precisely props will be an instance of System.Net.NetworkInformation.MacOsIPInterfaceProperties, which inherits from UnixIPInterfaceProperties, and ends up reading the /etc/resolv.conf file (which iOS disallow your application from reading).
The second case, calling Dns.GetHostEntry, goes down into the Mono runtime but end up calling gethostname which does not require the caller to know the DNS server address.

Applying two transforms to a message on the send port

I have an urgent need to send a canonical message (M1) out of an orchestration and need to map the canonical message to another message (M2). The resulting message (M2) has to be Wrapped in another request message (M3) before sending it to a web service.
I can't perform the initial transform in the orchestration as I can only deal with the canonical schema internally.
Whats the best way to achieve this 2 stage transform outside of the orchestration?
Thanks in advance!
You could make a pipeline component that applies each map sequentially. Then configure the port to use a pipeline with this component.
private Stream ApplyMap(Stream originalStream, Type mapType)
{
var transform = TransformMetaData.For(mapType).Transform;
var argList = TransformMetaData.For(mapType).ArgumentList;
XmlReader input = XmlReader.Create(originalStream);
Stream outputStream = new VirtualStream();
using (var outputWriter = XmlWriter.Create(outputStream))
{
transform.Transform(new XPathDocument(input), argList, outputWriter, null);
}
outputStream.Flush();
outputStream.Position = 0;
XmlReader outputReader = XmlReader.Create(outputStream);
return outputReader;
}
Then in the pipeline component's Execute method:
Type mapType1 = Type.GetType("YourMapNamespace.Map1, YourAssemblyName,...");
Type mapType2 = Type.GetType("YourMapNamespace.Map2, YourAssemblyName,...");
Stream originalStream = inmsg.BodyPart.GetOriginalDataStream();
Stream mappedStream =
ApplyMap(
ApplyMap(originalStream, mapType1),
mapType2
);
inmsg.BodyPart.Data = mappedStream;
context.ResourceTracker.AddResource(mappedStream);
Note that this example does everything in memory so it could be a problem for large messages. I'll try to find a better example that uses streaming (or worse case, you can use VirtualStream to avoid keeping everything in memory)
If you can use the ESB Toolkit, the ideal approach would be to use an itinerary (Richard Seroter has a good article on that approach here). If that's not an option, here's an approach I've used in the past:
http://blogs.msdn.com/b/chrisromp/archive/2008/08/06/stacking-maps-in-biztalk-server.aspx

Resources