How to connect to elasticsearch using boost asio? - c++

I'm trying to write a C++ snippet to make a POST to an elasticsearch server. The server is running on ip 172.20.1.160, and I can PUT data using curl, like in the Elasticsearch tutorial:
curl -XPUT 'localhost:9200/twitter/tweet/1?op_type=create&pretty' -H 'Content-Type: application/json' -d'
{
"user" : "kimchy",
"post_date" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}
'
But when I try to do something similar with boost ASIO, my connection is apparently refused.
Here's minimal compileable code showing how I try to create the connection, and which produces the error:
/// Compiled with:
/// g++ --std=c++14 foo.cpp -lboost_system -lpthread
#include <boost/asio.hpp>
constexpr const char *carbon_port = "2003";
constexpr const char *ES_port = "9200";
constexpr const char *server_ip = "172.20.1.160";
int main()
{
boost::asio::io_service io_service;
boost::asio::ip::tcp::resolver resolver(io_service);
boost::asio::ip::tcp::resolver::query query(server_ip, ES_port);
auto endpoint = *resolver.resolve(query);
boost::asio::ip::tcp::socket socket (io_service);
socket.connect(endpoint);
}
For what it's worth, I also have a carbon-graphite server running on the same machine, and I can connect and send data there via the plain-text protocol, but I am unable to make a socket connection to elasticsearch, I get the exception:
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> >'
what(): connect: Connection refused
Can someone enlighten me to what I need to know to get this working?

by default elasticsearch listens to localhost only , if you want it to listen to all ports , in config/elasticsearch.yml add the line network.host: 0.0.0.0 and restart elasticsearch.

Related

Is there a way to know whether Tracer is success fully connected to jaeger backend server in jaegerclientcpp?

In jaeger-client-cpp when I connect my Tracer variable to jaeger backend (I m using jaeger-all-in-one server) then upon successful connection LOG INFO message is shown telling me the connection is successful, but when connection is unsuccessful is just shows LOG ERROR message telling me that connection with server not successful.
So is there any way to check this programatically about the status of connection of Tracer with server.
OS-ubuntu 18.04
jaeger-client-cpp-v0.5.0
#include <jaegertracing/net/IPAddress.h>
#include <jaegertracing/net/Socket.h>
void check(){
try{
jaegertracing::net::Socket socket;
socket.open(AF_INET, SOCK_STREAM);
const std::string serverURL = configuration.sampler().kDefaultSamplingServerURL;
socket.connect(serverURL);
}catch(...){}
}
if it throws error then it is unable to reach host, this method is costly I agree but this is the only viable solution I find

Clarification needed about a SSL client using Boost asio

I have a C++ application that uses Boost_asio to do TCP/IP connection who read a .php document in a Web server that in turn uses the php script to update certain statistics.
The whole thing work as planned, but recently the server changed to use SSL (Google mandatory) and naturally, the previous connection stopped to work.
After a lot of theoretical reading about SSL, I'm still in the dark about certain practical details.
Using the example in the Boost asio documentation and a file “cacert.pem”, downloaded form somewhere following indications in this site, I'm able to run correctly the example using:
<host> = “www.google.com” and <port> = “https”.
Using the example “as is”, the Google server response is:
Verifying /OU=GlobalSign Root CA - R2/O=GlobalSign/CN=GlobalSign
Verifying /C=US/O=Google Trust Services/CN=Google Internet Authority G3
Verifying /C=US/ST=California/L=Mountain View/O=Google LLC/CN=www.google.com
Enter message: Reply:
But when using
<host> = “www.zator.com” and <port> = “https”
my domain, hosted in 1&1 IONOS, the reply is:
Handshake failed: tlsv1 alert internal error
At this point I have several questions:
What in the hell mean the sentence: ctx.load_verify_file("cacert.pem"); ?
The content of that file, can be the culprit of the fail when connecting with my domain?
Is that sentence essential to complete the connection?
In the case of google server (absence of error), is it supposed that after the sentence io_context.run(); the connection has been correctly established?
Assuming I make public the client's member socket_ (private in the example), can I continue with some as (I can't test that in google :-)
std::string request("GET /mystatistics.php HTTP/1.1\r\n\r\n");
boost::asio::write(c.socket_, boost::asio::buffer(request));
boost::system::error_code ec;
std::string response;
do { // read response
char buf[1024];
size_t bytes_transferred = c.socket_.read_some(boost::asio::buffer(buf), ec);
if (!ec) response.append(buf, buf + bytes_transferred);
} while (!ec);
std::cout << "Response received: '" << response << "'\n";
Thanks in advance.
I've found some useful information here. A good, albeit partial info, and a good start point to further search

Celery, mechanize and socks proxy

I'm working on a project that needs to access a webpage using mechanize with a socks proxy. After digging a bit, I came up with the following code:
def create_connection(address, timeout=None, source_address=None):
sock = socks.socksocket()
sock.connect(address)
return sock
CRAWLER_SOCKS_PROXY_HOST = '0.0.0.0'
CRAWLER_SOCKS_PROXY_PORT = 1080
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, CRAWLER_SOCKS_PROXY_HOST, CRAWLER_SOCKS_PROXY_PORT)
socket.socket = socks.socksocket
socket.create_connection = create_connection
Which indeed allows me to access the webpage using the proxy socks I created with the ssh -f -N -D 1080 user#host.
After doing that, I realized that Celery couldn't connect to my Redis broker giving Connection closed unexpectedly errors so I killed the ssh process and confirmed that the proxy socks configuration was the culprit. The error obtained is: Cannot connect to redis://127.0.0.1:6379//: Error connecting to SOCKS5 proxy 0.0.0.0:1080: [Errno 111] Connection refused.
So, my question is: Is there a way to set a proxy socks for mechanize but without affecting the other parts of the code? I suspect that if I try to use requests module, it will also use the proxy which is not my intention. I just want the proxy for a specific call.
I solved this by putting the
CRAWLER_SOCKS_PROXY_HOST = '0.0.0.0'
CRAWLER_SOCKS_PROXY_PORT = 1080
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, CRAWLER_SOCKS_PROXY_HOST, CRAWLER_SOCKS_PROXY_PORT)
socket.socket = socks.socksocket
socket.create_connection = create_connection
lines inside the function call (where I needed to do the call using proxy socks) rather than in the global scope of the module. This way seems Celery can connect to the broker (and also reconnect after quitting and launching again).

Obtaining public IP address rather than localhost (Boost Asio)

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);

Getting Started with POP3 Using Boost Asio

To help myself learn socket programming, I made a very simple SMTP client (see code below), using some code from the the Wt SMTP Library
As an exercise, I thought I would take a shot at implementing a POP3 client. Using the Wikipedia as a reference, it looked as if you must simply connect to the server on port 110 and send commands (just like SMTP connects on port 25 and sends commands).
However, I have so far been unable to even connect, and basically just timeout in the get_response() every time. I tried connecting to pop.gmail.com with no luck.
I don't believe that you need to send any user/password/other information when the connection is first established? I expected to receive something along the lines of +OK POP3 Server Ready once I connect, and I can then send the USER and PASS commands.
My question is: Am I missing something during the connection phase? Am I trying to connect to a bad host (gmail)? If so, is there a better host than pop.gmail.com with which I can test? Or am I going about this entirely wrong?
#include <string>
#include <sstream>
#include <iostream>
#include <iterator>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
int main()
{
boost::asio::io_service io_service;
tcp::socket socket(io_service);
tcp::resolver resolver(io_service);
tcp::resolver::query query("localhost", "25"); // Change this for POP3
tcp::resolver::iterator endpt_iter = resolver.resolve(query);
boost::system::error_code erc = boost::asio::error::host_not_found;
while(erc && endpt_iter != end)
{
socket.close();
socket.connect(*endpt_iter++, erc);
}
if(erc) { socket.close(); return }
std::cout << get_response(socket) << std::endl; // 220 <my-host-name> ESMTP Postfix
send(socket, "EHLO localhost\r\n");
std::cout << get_response(socket) << std::endl; // 250-<my-host-name>
return 0;
}
std::string get_response(tcp::socket& socket)
{
boost::asio::streambuf response;
for(;;)
{
std::string msg;
boost::asio::read_until(socket, response, "\r\n");
std::istream in(&response);
std::getline(in, msg);
return msg;
}
}
void send(tcp::socket& socket, std::string msg)
{
boost::asio::write(socket, boost::asio::buffer(msg));
}
Gmail requires SSL/TLS encryption on its POP3 and SMTP connections.
For POP3, you have to connect to port 995 and initiate an SSL/TLS handshake immediately upon connecting. Then you can read the server's initial +OK greeting from, and send commands to, the encrypted connection.
For SMTP, you have a couple of choices:
connect to port 465. Initiate an SSL/TLS handshake immediately upon connecting. Read the +OK greeting from, and send all commands to, the encrypted connection.
connect to port 587. Read the +OK greeting from, and send EHLO and STARTTLS commands to, the unencrypted connection. Initiate the SSL/TLS handshake. Send a new EHLO command, and other commands, to the encrypted connection.