Spring AMQP and CachingConnectionFactory - spring-amqp

If I have a CachingConnectionFactory with two addresses, how can I know at any time which server I am connected to? And what would be the best way to manually change from one to the other?
CachingConnectionFactory cf = new CachingConnectionFactory(factory);
String _addresses = host + ":" + port + "," + host2 + ":" + port2;
cf.setAddresses(_addresses);
Thanks

To know the host/port you are connected you should consult already the target NetworkConnection:
/** Retrieve address of peer. */
InetAddress getAddress();
/** Retrieve port number of peer. */
int getPort();
That's not CachingConnectionFactory to control that info.
On another hand that addresses option is exactly about this:
* #param addrs an array of known broker addresses (hostname/port pairs) to try in order
See com.rabbitmq.client.ConnectionFactory#createConnection().
So, all the addresses entries must be in the same cluster. Otherwise you may end up with unexpected behavior when the same name might be used for different entities on different servers.
To control manually I would suggest to change that setAddresses() property at runtime or have different CachingConnectionFactory instances with different orders.

Related

Can I uniquely identify a client machine in an ASP.NET application

Is there a way to uniquely identify a user that has logged on my application based on his device/machine ?
In a lot of cases, the IP is enough, but in case when the client has multiple machines behind a NAT, then the same IP is exposed, so I can't tell them apart. it should have same id irrespective of browser.
for e.g. If the user logs in on his account with computer A, then log in on the same account with computer B that share the same router, I need to get id apart those two devices.
I don't know if this is possible, but it would be life saving if it is.
I was faced with this problem where I wanted to ask for Google Authenticator on sign in but only once for each device used by a user. I used a function to give me a device id based on the hostname, the MAC address, and the IP address. I know the MAC address isn't always reliable so I thought combining the data into one string might be a way round it. Our application is limited to <100 users and most of them access from the office or home so I feel it should be good enough.
I put the IP address function (which gets the IPV4) into a separate function as I check whether they are in office (on 192.168..) or external before checking the device ID. The list of device ID's associated with a user is stored in a SQL table and checked after username/password entry but before log in is completed to decide whether to request a 2FA code.
Here's the code:
dim thisDeviceId as String=GetClientDeviceId()
public Function GetClientDeviceId() As string
Dim mac As String = String.Empty
For Each netInterface In NetworkInterface.GetAllNetworkInterfaces()
If _
netInterface.NetworkInterfaceType = NetworkInterfaceType.Wireless80211 OrElse
netInterface.NetworkInterfaceType = NetworkInterfaceType.Ethernet Then
Dim address = netInterface.GetPhysicalAddress()
mac = BitConverter.ToString(address.GetAddressBytes())
End If
Next
return string.Format("{0}-{1}-{2}",dns.GetHostEntry(HttpContext.current.Request.ServerVariables("REMOTE_ADDR")).HostName, mac,GetClientDeviceIpAddress())
End Function
public Function GetClientDeviceIpAddress() As string
Dim ipv4Address As String = String.Empty
For Each currentIpAddress As IPAddress In Dns.GetHostAddresses(Dns.GetHostName())
If currentIpAddress.AddressFamily.ToString() = System.Net.Sockets.AddressFamily.InterNetwork.ToString() Then
ipv4Address = currentIpAddress.ToString()
Exit For
End If
Next
return ipv4Address
End Function
Even though it's not bulletproof and could be improved upon it might help someone.

Retrieve IP Address of the Default Printer Driver in UWP

We have a requirement to get the printer IP Address configured in the default printer driver in Control Panel in our UWP app.
I was able to retrieve the "System.DeviceInterface.PrinterPortName" by fetching interface class GUID and passing this above property for retrieval.
But I couldn't get "System.Devices.IpAddress" similarly.
Code pasted below for PortName.
I badly need the IP address as the port name is user's choice and could be modified to any name removing the IP address.
Kindly help sharing working code to retrieve the IP Address using above property or any other way in UWP app.
Below is Working Code for Port Name, Kindly help to fetch IP Address of the same port similarly.
string aqsFilter = "System.Devices.InterfaceClassGuid:=\"{0ecef634-6ef0-472a-8085-5ad023ecbccd}\"";
string[] propertiesToRetrieve = new string[] { "System.DeviceInterface.PrinterPortName"};
DeviceInformationCollection deviceInfoCollection = await DeviceInformation.FindAllAsync(aqsFilter, propertiesToRetrieve);
foreach (DeviceInformation deviceInfo in deviceInfoCollection)
{
if (deviceInfo.IsDefault == true)
{
string strPortName = (string)deviceInfo.Properties["System.DeviceInterface.PrinterPortName"];
if (!string.IsNullOrEmpty(strPortName))
{
strPortName = await ParsePortName(strPortName);
if (!string.IsNullOrEmpty(strPortName))
{
_strIPAddress = strPortName;
}
}
break;
}
}
This is not endorsed because the IP address can change and so it is unreliable.
That being said, if your printer is installed using wsd, it is technically supported
E.g.,
DEVPKEY_PNPX_IpAddress DEVPROP_TYPE_STRING_LIST 32 "10.137.192.202"
But there is no way to reliably use this without a lot of various scenario checks since the IP address may change.
Furthermore, looking at this example, you are not hitting the DAF providers but looking for devices. You are using 0ecef634-6ef0-472a-8085-5ad023ecbccd which is the printer class guid. It also does not look like IP address is propagated in the PnP Explorer property bag so the IP address is not accessible.

ESP8266 UPnP Port Forwarding - IoT [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
Is it possible to use the UPNP protocol for automatic port forwarding on the router using ESP8266?
I need to be able to access my ESP8266 module even when I am away from home.
Currently I have configured port forwarding manually in my router settings.
But in the future, in order for my project to become a commercial product, it needs to be able to do automatic port forwarding as this would be a barrier for the average user.
On the internet I found something talking about UPNP on ESP8266, but it was not about port forwarding.
Thank you very much in advance!
You can have a look at my library that I made just for that:
https://github.com/ofekp/TinyUPnP
I have an example for an IOT device (LED lights) within the package, I cannot attach the link due to low reputation.
You can have a look at the example code. All made for ESP8266.
Very simple to use, just call addPortMapping with the port you want to open, just as showed in the example.
You have to do this every 36000 (LEASE_DURATION) seconds, since UPnP is lease based protocol.
Declare:
unsigned long lastUpdateTime = 0;
TinyUPnP *tinyUPnP = new TinyUPnP(-1); // -1 means blocking, preferably, use a timeout value (ms)
Setup:
if (tinyUPnP->addPortMapping(WiFi.localIP(), LISTEN_PORT, RULE_PROTOCOL_TCP, LEASE_DURATION, FRIENDLY_NAME)) {
lastUpdateTime = millis();
}
Loop:
// update UPnP port mapping rule if needed
if ((millis() - lastUpdateTime) > (long) (0.8D * (double) (LEASE_DURATION * 1000.0))) {
Serial.print("UPnP rule is about to be revoked, renewing lease");
if (tinyUPnP->addPortMapping(WiFi.localIP(), LISTEN_PORT, RULE_PROTOCOL_TCP, LEASE_DURATION, FRIENDLY_NAME)) {
lastUpdateTime = millis();
}
}
I only checked it with my D-Link router.
To anyone interested in how the library works:
It sends an M_SEARCH message to UPnP UDP multicast address.
The gateway router will respond with a message including an HTTP header called Location.
Location is a link to an XML file containing the IGD (Internet Gateway Device) API in order to create the needed calls which will add the new port mapping to your gateway router.
One of the services that is depicted in the XML is <serviceType>urn:schemas-upnp-org:service:WANPPPConnection:1</serviceType> which is what the library is looking for.
That service will include a eventSubURL tag which is a link to your router's IGD API. (The base URL is also depicted in the same file under the tag URLBase)
Using the base URL and the WANPPPConnection link you can issue an HTTP query to the router that will add the UPnP rule.
As a side note, the service depicted in the XML also includes a SCPDURL tag which is a link to another XML that depicts commands available for the service and their parameters. The package skips this stage as I assumed the query will be similar for many routers, this may very well not be the case, though, so it is up to you to check.
From this stage the package will issue the service command using an HTTP query to the router. The actual query can be seen in the code quite clearly but for anyone interested:
Headers:
"POST " + <link to service command from XML> + " HTTP/1.1"
"Content-Type: text/xml; charset=\"utf-8\""
"SOAPAction: \"urn:schemas-upnp-org:service:WANPPPConnection:1#AddPortMapping\""
"Content-Length: " + body.length()
Body:
"<?xml version=\"1.0\"?>\r\n"
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n"
"<s:Body>\r\n"
"<u:AddPortMapping xmlns:u=\"urn:schemas-upnp-org:service:WANPPPConnection:1\">\r\n"
" <NewRemoteHost></NewRemoteHost>\r\n"
" <NewExternalPort>" + String(rulePort) + "</NewExternalPort>\r\n"
" <NewProtocol>" + ruleProtocol + "</NewProtocol>\r\n"
" <NewInternalPort>" + String(rulePort) + "</NewInternalPort>\r\n"
" <NewInternalClient>" + ipAddressToString(ruleIP) + "</NewInternalClient>\r\n"
" <NewEnabled>1</NewEnabled>\r\n"
" <NewPortMappingDescription>" + ruleFriendlyName + "</NewPortMappingDescription>\r\n"
" <NewLeaseDuration>" + String(ruleLeaseDuration) + "</NewLeaseDuration>\r\n"
"</u:AddPortMapping>\r\n"
"</s:Body>\r\n"
"</s:Envelope>\r\n";
I hope this helps.
I don't see why not. UPnP implements multiple profiles, the one you are interested in is named IGD (Internet Gateway Device), which most home routers implement to allow client applications on the local network (e.g Skype, uTorrent, etc.) to map ports on the router's NAT.
UPnP works over IP multicast to discover and announce devices implementing UPnP services over the address 239.255.255.250. Devices interested in such announcements subscribe to this multicast group and listen on port 1900. In fact, UPnP does not itself provide a discovery mechanism, but relies on a protocol called SSDP (Simple Service Discovery Protocol) to discover hosts on the local network.
All that's needed is an UDP socket bound to the aforementioned address and port to subscribe and publish messages on your home multicast group. You'd need to use an implementation of SSDP to discover your router, once you have discovered your router, you can send commands using UPnP wrapped around SOAP enveloppes.
There are many implementations of the UPnP IGD profile in Posix C, which you may reuse and port to the ESP 8266 (e.g MiniUPnP, gupnp-igd).

Using agent name instead of IP as Address in SNMP4J

I'm trying to make a program that sends SNMP queries to some switches in the network.
Using the Net-snmp tools, I can send get requests to the switch using its name, and it works fine. But SNMP4J requires an IP address in CommunityTarget, so I get an IllegalArgumentException.
This is the relevant part of the code:
TransportMapping transport = new DefaultUdpTransportMapping();
transport.listen();
CommunityTarget comtarget = new CommunityTarget();
comtarget.setCommunity(new OctetString("public"));
comtarget.setVersion(SnmpConstants.version1);
comtarget.setAddress(new UdpAddress("switchName")); // exception happens here
comtarget.setRetries(2);
comtarget.setTimeout(1000);
How can I work around this?
You can get the IP address by using DNS resolution, like this answer says:
InetAddress address = InetAddress.getByName(switchName);
System.out.println(address.getHostAddress());

MBeanServerConnection.invoke hangs forever

We have an app that invokes various remote methods on MBeans using MBeanServerConnection.invoke.
Occasionally one of these methods hangs.
Is there any way to have a timeout on the call? so that it will return with an exception if the call takes too long?
Or do I have to move all those calls into separate threads so they don't lock up the UI and require killing the app?
See http://weblogs.java.net/blog/emcmanus/archive/2007/05/making_a_jmx_co.html
===== Update =====
I was thinking about this stuff when I first responded, but I was on my mobile and I can't type worth a damn on it.....
This is really an RMI problem, and unless you use a different protocol, there's not much you can do, except, as you say, move all those calls into separate threads so they don't lock up the UI.
But.... if you have the option of fiddling with the target server and you can customize the connecting client, you have at least 1 option which is to customize the JMXConnectorServer on your target servers.
The standard JMXConnectorServer implementation is the RMIConnectorServer. Part of it's specification is that when you create a new instance using any of the constructors (like RMIConnectorServer(JMXServiceURL url, Map environment)), the environment map can contain a key/value pair where the key is RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE and the value is a RMIClientSocketFactory. Therefore, you can specify a socket factory method like this:
RMIClientSocketFactory clientSocketFatory = new RMIClientSocketFactory() {
public Socket createSocket(String host, int port) {
Socket s = new Socket(host, port);
s.setSoTimeout(3000);
}
};
This factory creates a Socket and then sets its SO_TIMEOUT using setSoTimeout, so when the client connects using this socket, all operations, including connecting, will timeout after 3000 ms.
You could also checkout the JMXMP connector and server in the jmx-optional package of the OpenDMK. (links are to my github mavenized). No built in solution, mind you, but they're super easy to extend and JMXMP is simple TCP socket based rather than RMI, so this type of customization would be trivial.
Cheers.
# Nicholas : The above code is not working.I mean request is not getting timeout after 3000. ms.
map.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE , new RMIClientSocketFactory() {
#Override
public Socket createSocket(String host, int port) throws IOException {
if(logger.isInfoEnabled() ){
logger.info("JMXManager inside createSocket..." + host + ": port :" + port);
}
Socket s = new Socket(host, port);
s.setSoTimeout(3000);
return s;
}
});
cs = JMXConnectorServerFactory.newJMXConnectorServer(url,map,mbeanServer);
As I answered on: How to set request timeout for JMX Connector the RMI properties can help you. All the properties are on Oracle documentation site:
http://docs.oracle.com/javase/7/docs/technotes/guides/rmi/sunrmiproperties.html.
For example: -Dsun.rmi.transport.tcp.responseTimeout=60000 is a client side tcp response timeout. There are also properties for connect timeout and for server side connections.
I also am not happy how the JMX/RMI/TCP stack hides important settings from lower level protocols, and makes it not available for a single connection.

Resources