Obtaining public IP address rather than localhost (Boost Asio) - c++

I have the following connection set up, this works correctly. This is part of a larger piece of code which listens (at a free port), for incoming messages. What I am trying to do is publish the uri so that other clients can connect to this. However I cannot figure out a way for the endpoint.address() to appear as the actual IP address on the interface being used rather than "localhost". Any ideas?
tcp::resolver::query query(address, "");
tcp:: endpoint endpoint = *resolver.resolve(query);
acc.open(endp.protocol());
acc.set_option(reuse_address(true));
acc.bind(endp);
acc.listen();
tcp::endpoint endpoint = acc.local_endpoint() ;
string uri = "tcp://" + endpoint.address().to_string() + ":" + lexical_cast<string>(endpoint.port()) ;

Boost ASIO has no way to enum all the interfaces of your computer. resolver query your DNS for your IP, witch is not the same as it can return whatever you have configured in it (even inacurrate information can be retrieved).
If you want to bind to the default interface. you don't need to make a resolve.
Just create the socket with the following endpoint :
boost::asio::ip::tcp::endpoint endpoint =
boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(),port);

Related

asio async_receive how to get sender ip address

I wrote a small protocol stack to connect to KNX/IP routers. The mechanism is as follows:
Discovery_Channel: For discovery the client sends out an UDP/IP packet to multicast address 224.0.23.12. KNX/IP routers listen to this multicast address and reply. The KNX/IP router can potentially be connected to multiple KNX media, so the answer contains a list of services with IP addresses and port, the client can connect to.
Communication_Channel: The discovered services from all KNX/IP routers are presented to the user to select which service a connection should be made to.
The problem is that the answer from the KNX/IP routers sometimes doesn't contain a valid IP address, but just 0.0.0.0. In this case I need to take the IP address from where the packet came from. But how can I get this with (non-boost version of) asio?
My code looks like this:
/** client socket */
asio::ip::udp::socket m_socket;
/** search request */
void search_request(
const IP_Host_Protocol_Address_Information & remote_discovery_endpoint = IP_Host_Protocol_Address_Information({224, 0, 23, 12}, Port_Number),
const std::chrono::seconds search_timeout = SEARCH_TIMEOUT);
/** search response initiator */
void Discovery_Channel::async_receive_response() {
/* prepare a buffer */
m_response_data.resize(256);
/* async receive */
m_socket.async_receive(
asio::buffer(m_response_data),
std::bind(&Discovery_Channel::response_received, this, std::placeholders::_1, std::placeholders::_2));
}
/** response received handler */
void Discovery_Channel::response_received(const std::error_code & error, std::size_t bytes_transferred) {
// here the answer provided in m_response_data gets interpreted.
// #todo how to get the IP address of the sender?
/* start initiators */
async_receive_response();
}
So how can I retrieve the IP address of the sender in the Discovery_Channel::response_received method? I basically only have the packet data in m_response_data available.
On datagram sockets you can (should, likely) use async_receive_from.
It takes a reference to an endpoint variable that will be set to the remote endpoint on success.

Querying custom DNS Server using boost asio resolver

I would like to make a reverse DNS lookup query to some custom nameserver (by specifying ip/port) instead of the default one.
Is it possible to use boost::asio::resolver for this purpose?
I have this so far:
asio::ip::address_v4 ipa = asio::ip::address_v4::from_string("8.8.8.8");
asio::ip::tcp::endpoint ep;
ep.address(ipa);
asio::io_service io_service;
asio::ip::tcp::resolver resolver(io_service);
asio::ip::tcp::resolver::iterator destination = resolver.resolve(ep);
Is there a way to specify dns ip/port to the resolver or to the service?

how to download files with ftp url behind http proxy

I am behind a http/https proxy. So to download a file using QNetworkAccessManager, i set the proxy as following:
if(no_proxy)
{
QNetworkProxyFactory::setUseSystemConfiguration (false);
QNetworkProxy::setApplicationProxy(QNetworkProxy::NoProxy);
}
else if(system_proxy)
{
QNetworkProxyQuery pQuery(QUrl(QLatin1String("http://www.google.com")));
QList<QNetworkProxy>listOfProxies =QNetworkProxyFactory::systemProxyForQuery(pQuery);
QNetworkProxy::setApplicationProxy(listOfProxies.first());
}
else if(manual_proxy)
{
proxy.setHostName(address);
proxy.setPort(port);
if(http_proxy)
proxy.setType(QNetworkProxy::HttpProxy);
else if(socks_proxy)
proxy.setType(QNetworkProxy::Socks5Proxy);
else if(ftp_proxy)
proxy.setType(QNetworkProxy::FtpCachingProxy);
QNetworkProxy::setApplicationProxy(proxy);
}
Now behind http squid proxy server, this code works fine in case of http urls. But, if i try to download a file with ftp url the download fails with the error
no suitable proxy found
It does not seem to use http proxy for ftp urls. But, we have such options like in firefox:
use this proxy server for all protocols
How to do similar thing in Qt!
Update:
void DownloadThread::startDownload()
{
QString args =downUrl,tempFN;
QUrl url = QUrl::fromEncoded(args.toLocal8Bit());
request.setUrl(url);
request.setRawHeader("User-Agent", userAgent);
request.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
reply.setCookieJar(cookieJar);
reply=manager.get(request);
connect(reply, SIGNAL(readyRead()),this,
SLOT(saveToDisk()));
...
}
Have you tried explicitly setting the Qftp proxy?
int setProxy ( const QString & host, quint16 port )
That might get you more joy, but yes, you have to set the proxies up for each connection normally, however, there is always the possibility that the proxy you are trying to use doesn't support FTP? If you pass me some more details about the proxy and where your problems lie (request/response code for example)
Also in squid.conf may want to change/add the following in case they are not present
acl SSL_ports port 443 21
acl FTP proto FTP
always_direct allow FTP
http_access allow ftp
Also, worth checking that the firewall allows port 20, 21 & 443 (I know its a simple check, but often I find its things like these that can be a real pain to find as a root cause).
Do you have a copy of the log file that is generated? it would be interesting/helpful to see what error code is being returned. Also, have you tried manually stepping through the program to see what is contained in the variables at run-time, that would give you a better picture of what is happening, as it may be that everything is fine and that there is a simple way to progress which the contents of the variables will lead you to in short order (might not be the case but it usually worth a try).

How do I set timeout for TIdHTTPProxyServer (not connection timout)

I am using TIdHTTPProxyServer and now I want to terminate connection when it is success to connect to the target HTTP server but receive no response for a long time(i.g. 3 mins)
Currently I find no related property or event about it. And even if the client terminate the connection before the proxy server receive the response from the HTTP server. OnException Event will not be fired until the proxy server receive the response. (That is, if the proxy server still receive no response from HTTP Server, I even do not know the client has already terminate the connection...)
Any help will be appreciated.
Thanks!
Willy
Indy uses infinite timeouts by default. To do what you are asking for, you need to set the ReadTimeout property of the outbound connection to the target server. You can access that connection via the TIdHTTPProxyServerContext.OutboundClient property. Use the OnHTTPBeforeCommand event, which is triggered just before the OutboundClient connects to the target server, eg:
#include "IdTCPClient.hpp"
void __fastcall TForm1::IdHTTPProxyServer1HTTPBeforeCommand(TIdHTTPProxyServerContext *AContext)
{
static_cast<TIdTCPClient*>(AContext->OutboundClient)->ReadTimeout = ...;
}

How to unpublish a web service using JAX-WS aadn bind to a different address

I've a JAX-WS web service deployed into an embedded Jetty server
I need to change the IP address which is associated with the Endpoint
In order to publish I do:
Service service = new Service();
Endpoint.publish(address, service);
What happen is that when i stop and restart the server, the Service is published again and bind to the new address I provide, but I get a Warning like this:
WARNING: "GMBAL901: JMX exception on registration of MBean MBeanImpl[type=WSEndpoint,name=MyServiceService-myservice_servicePort,oname=com.sun.metro:pp=/,type=WSEndpoint,name=MyServiceService-myservice_servicePort]"
and if I query both old address (e.g. 127.0.0.1) and new one (e.g. 192.168.X.X) both are still answering (with two different instances of myService.
I wouldn't have this behavior, I want that the WS is unbound from the old address.
How can I do?
Find out that I simply need to create the EndpointObject, publish it, and when I need to restart that will be enough to stop ep (it will ensure that same ep will not be republished), than creating a new one and republish it.
Endpoint ep;
...
if (ep != null && ep.isPublished()){
ep.stop();
}
ep = Endpoint.create(service);
ep.publish(getEndpointAddress(port, service));
till is better to wait half a second before restarting the server where the WS is published as sometime it stuck