I am trying to use Boost Asio on iOS, and have figured out everything, but how to check the certificate of the server I am connecting to.
How do you check the connecting server's certificate in iOS with Boost Asio?
In another answer of mine you can see a simple SSL client.
In this code you'll quickly note verify_certificate which you can use to (additionally) verify the server certificate.
Sidenote
Note that I don't know which libraries are underlying the Asio SSL implementation iOS, but keep in mind verifying (or even pinning) theserver certificate could be rather useless. It would only verify the authenticity of the certificate presented. In the light of yesterday's security debacle I don't think this helps much, because unless properly patched the server could have presented a valid certificate, but still use unrelated encryption keys - this still allows a MiTM scenario
Just noting this in case your question is somehow related to this situration
From A: HTTPS POST request with boost asio
#define DEMO_USING_SSL
#define BOOST_ASIO_ENABLE_HANDLER_TRACKING
#include <iostream>
#include <iomanip>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
class client
{
public:
client(boost::asio::io_service& io_service,
boost::asio::ssl::context& context,
boost::asio::ip::tcp::resolver::iterator endpoint_iterator)
: socket_(io_service
#ifdef DEMO_USING_SSL
, context)
{
socket_.set_verify_mode(boost::asio::ssl::verify_peer);
socket_.set_verify_callback(
boost::bind(&client::verify_certificate, this, _1, _2));
#else
)
{
(void) context;
#endif
boost::asio::async_connect(socket_.lowest_layer(), endpoint_iterator,
boost::bind(&client::handle_connect, this,
boost::asio::placeholders::error));
}
bool verify_certificate(bool preverified,
boost::asio::ssl::verify_context& ctx)
{
// The verify callback can be used to check whether the certificate that is
// being presented is valid for the peer. For example, RFC 2818 describes
// the steps involved in doing this for HTTPS. Consult the OpenSSL
// documentation for more details. Note that the callback is called once
// for each certificate in the certificate chain, starting from the root
// certificate authority.
// In this example we will simply print the certificate's subject name.
char subject_name[256];
X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256);
std::cout << "Verifying " << subject_name << "\n";
return preverified;
}
void handle_connect(const boost::system::error_code& error)
{
#ifdef DEMO_USING_SSL
if (!error)
{
socket_.async_handshake(boost::asio::ssl::stream_base::client,
boost::bind(&client::handle_handshake, this,
boost::asio::placeholders::error));
}
else
{
std::cout << "Connect failed: " << error.message() << "\n";
}
#else
handle_handshake(error);
#endif
}
void handle_handshake(const boost::system::error_code& error)
{
if (!error)
{
std::cout << "Enter message: ";
static char const raw[] = "POST / HTTP/1.1\r\nHost: www.example.com\r\nConnection: close\r\n\r\n";
static_assert(sizeof(raw)<=sizeof(request_), "too large");
size_t request_length = strlen(raw);
std::copy(raw, raw+request_length, request_);
{
// used this for debugging:
std::ostream hexos(std::cout.rdbuf());
for(auto it = raw; it != raw+request_length; ++it)
hexos << std::hex << std::setw(2) << std::setfill('0') << std::showbase << ((short unsigned) *it) << " ";
std::cout << "\n";
}
boost::asio::async_write(socket_,
boost::asio::buffer(request_, request_length),
boost::bind(&client::handle_write, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
else
{
std::cout << "Handshake failed: " << error.message() << "\n";
}
}
void handle_write(const boost::system::error_code& error,
size_t /*bytes_transferred*/)
{
if (!error)
{
std::cout << "starting read loop\n";
boost::asio::async_read_until(socket_,
//boost::asio::buffer(reply_, sizeof(reply_)),
reply_, '\n',
boost::bind(&client::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
else
{
std::cout << "Write failed: " << error.message() << "\n";
}
}
void handle_read(const boost::system::error_code& error, size_t /*bytes_transferred*/)
{
if (!error)
{
std::cout << "Reply: " << &reply_ << "\n";
}
else
{
std::cout << "Read failed: " << error.message() << "\n";
}
}
private:
#ifdef DEMO_USING_SSL
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_;
#else
boost::asio::ip::tcp::socket socket_;
#endif
char request_[1024];
boost::asio::streambuf reply_;
};
int main(int argc, char* argv[])
{
try
{
if (argc != 3)
{
std::cerr << "Usage: client <host> <port>\n";
return 1;
}
boost::asio::io_service io_service;
boost::asio::ip::tcp::resolver resolver(io_service);
boost::asio::ip::tcp::resolver::query query(argv[1], argv[2]);
boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);
boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
ctx.set_default_verify_paths();
client c(io_service, ctx, iterator);
io_service.run();
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
Related
With the Jetson Nano I connected a PS4 controller via bluetooth and the device showed up under /dev/input/js0. However when I connect the controller via bluetooth to my Coral board, I am seeing nothing at that location, maybe because of Mendel instead of Ubuntu? What is the recommended way to connect a PS4 controller and access it from C++? Is there a different joystick I should use?
After doing some research I learned about the difference between joydev and evdev on linux. It seems my PS4 controller showed up as a joydev device on the Jetson, whereas on the Coral running Mendel it showed up as an evdev device. I found some example C++ code for evdev devices from Croepha
/ David Butler here: https://handmade.network/forums/t/3673-modern_way_to_read_gamepad_input_with_c_on_linux
I modified this code for the PS4 controller like this:
void runJoystick() {
auto gamepad = open("/dev/input/event4", O_RDONLY | O_NONBLOCK); //todo use /proc/bus/input/devices instead
assert(gamepad != -1);
std::cout << "Running joystick" << std::endl;
while (m_still_running) {
struct input_event events[8]; // 8 events per frame is pretty extreme, more like 1 or 2, sometimes as high as 4
auto r1 = read(gamepad, events, sizeof events);
if (r1 != -1) {
int new_event_count = r1 / sizeof(struct input_event);
for (int evi = 0; evi < new_event_count; evi++) {
auto& ev = events[evi];
switch (ev.type) {
case EV_ABS: {
switch (ev.code) {
case ABS_X: { // left x
// std::cout << "type " << ev.code << "value:" << ev.value << std::endl;
} break;
case ABS_Y: { // left y
// std::cout << "type " << ev.code << "value:" << ev.value << std::endl;
} break;
case ABS_Z: { // right x
// std::cout << "type " << ev.code << "value:" << ev.value << std::endl;
} break;
case ABS_RZ: { // right y
// std::cout << "type " << ev.code << "value:" << ev.value << std::endl;
} break;
}
} break;
case EV_KEY: {
switch (ev.code) {
case BTN_A: { // square
std::cout << "Square ";
} break;
case BTN_B: { // x
std::cout << "X ";
} break;
case BTN_C: { // circle
std::cout << "Circle ";
} break;
case BTN_X: { // triangle
std::cout << "Triangle ";
} break;
}
if (ev.value) {
std::cout << "Pressed " << std::endl;
} else {
std::cout << "Released " << std::endl;
}
} break;
}
}
}
assert(r1 != -1 || errno == EWOULDBLOCK || errno == EAGAIN);
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
}
Why the interpreter complains that library named "math" does not exist?
As far as I know, this library is loaded when invoking luaL_newstate on Lua-5.3.5.
#include "lua.hpp"
#include <iostream>
#include <assert.h>
#include <fstream>
int main()
{
struct lua_State *L = luaL_newstate();
int ret;
std::string fileName("co.lua");
if(fileName.empty())
{
std::cout << "the filename is empty" << std::endl;
return -1;
}
std::ifstream fileScript(fileName, fileScript.in|std::ios::ate);
if(!fileScript.is_open())
{
std::cout << "open file failed" << std::endl;
return -2;
}
size_t size = fileScript.tellg();
if(size <= 0)
{
std::cout << "file has no valid content" << std::endl;
return -3;
}
std::string textCont(size, '\0');
fileScript.seekg(0);
fileScript.read(&textCont[0], size);
if((ret=luaL_loadbuffer(L, textCont.data(), textCont.length(), "co.lua")) == LUA_OK)
{
if((ret=lua_pcall(L, 0, LUA_MULTRET, 0)) != LUA_OK)
{
std::cout << "error in invoking lua_pcall():" << ret << std::endl;
if(lua_isstring(L, -1))
{
const char *errMsg = lua_tostring(L, -1);
lua_pop(L, 1);
std::cout << "script run encounter err:" << errMsg << std::endl;
}
}
}
}
Here is the code snippet(it's very simple) for the file named "co.lua":
a = 1;
b=2;
a=a+1;
math.sin(a)
Here is the error message in the console:
error in invoking lua_pcall():2
script run encounter err:[string "co.lua"]:29: attempt to index a nil value (global 'math')
The documentation states that you need to call luaL_openlibs or luaL_requiref which does not seem to be the case with your posted program.
To have access to these libraries, the C host program should call the luaL_openlibs function, which opens all standard libraries.
Alternatively (emphasis mine):
Alternatively, the host program can open them individually by using luaL_requiref to call:
luaopen_base (for the basic library)
luaopen_package (for the package library)
luaopen_coroutine (for the coroutine library)
luaopen_string (for the string library)
luaopen_utf8 (for the UTF8 library)
luaopen_table (for the table library)
luaopen_math (for the mathematical library)
luaopen_io (for the I/O library)
luaopen_os (for the operating system library)
luaopen_debug (for the debug library).
These functions are declared in lualib.h.
So change your program's first few lines to something like below.
You also need to compare the return value from luaL_newstate with NULL and handle that error condition.
int main()
{
struct lua_State *L = luaL_newstate();
if( L == NULL ) {
puts( "Lua failed to initialize." );
exit(1);
}
luaL_openlibs( L );
// etc
I am new to libqmi and wanted to start by just opening a new device. But the callback function is never getting called and therefore no device object returned.
I running the code on Ubuntu 64 Bit.
On this website: https://developer.gnome.org/gio/stable/GAsyncResult.html
I found how this should be handled and programmed it that way, but it still doesn't work.
#include <iostream>
#include <libqmi-glib/libqmi-glib.h>
#include <gio/gio.h>
using namespace std;
void device_create_start(const char* device_file);
void device_create_stop(GObject* obj, GAsyncResult* res, gpointer data);
int something = 0;
int main()
{
cout << "Start\n";
device_create_start("/dev/cdc-wdm0");
cout << "DEBUG: Something: " << something << "\n";
cout << "Stop\n";
return 0;
}
void device_create_start(const char* device_file)
{
GFile* file = g_file_new_for_path(device_file);
if(file)
{
GCancellable* cancellable = g_cancellable_new();
GAsyncReadyCallback callback = device_create_stop;
gpointer user_data = NULL;
cout << "INFO: qmi_device_new starting!\n";
qmi_device_new(file, cancellable, callback, user_data);
cout << "INFO: qmi_device_new started!\n";
cout << "INFO: Waiting!\n";
usleep(10000);
cout << "INFO: Is cancelled?: " << g_cancellable_is_cancelled(cancellable) << "\n";
cout << "INFO: canceling!\n";
g_cancellable_cancel(cancellable);
cout << "INFO: Waiting again!\n";
usleep(100000);
cout << "INFO: Is cancelled?: " << g_cancellable_is_cancelled(cancellable) << "\n";
something = 1;
}
else
{
cout << "ERROR: Could not create device file!\n";
}
}
void device_create_stop(GObject* obj, GAsyncResult* res, gpointer data)
{
cout << "INFO: device_create_stop\n";
something = 2;
cout << "INFO: qmi_device_new_finish starting\n";
GError *error;
QmiDevice* device = qmi_device_new_finish(res, &error);
cout << "INFO: qmi_device_new_finish started\n";
if(device == NULL)
{
cout << "ERROR: Could not create device!\n";
}
else
{
cout << "INFO: Device created!\n";
//device_open(device);
}
}
When I run this code the output is:
Start
INFO: qmi_device_new starting!
INFO: qmi_device_new started!
INFO: Waiting!
INFO: Is cancelled?: 0
INFO: canceling!
INFO: Waiting again!
INFO: Is cancelled?: 1
DEBUG: Something: 1
Stop
The code in the callback function is never called.
Update 1
I simplified the code and changed some things that I oversaw on the gnome reference site, like a static callback function. But this doesn't work either
#include <iostream>
#include <libqmi-glib/libqmi-glib.h>
#include <gio/gio.h>
#include <glib/gprintf.h>
using namespace std;
void device_create_start(const char* device_file);
static void device_create_stop(GObject* obj, GAsyncResult* res, gpointer data);
int something = 0;
int main()
{
g_printf ("Start\n");
device_create_start("/dev/cdc-wdm0");
cout << "DEBUG: Something: " << something << "\n";
while(true)
{
;
}
cout << "Stop\n";
return 0;
}
void device_create_start(const char* device_file)
{
GFile* file = g_file_new_for_path(device_file);
if(file)
{
cout << "INFO: qmi_device_new starting!\n";
qmi_device_new(file, NULL, device_create_stop, NULL);
cout << "INFO: qmi_device_new started!\n";
something = 1;
}
else
{
cout << "ERROR: Could not create device!\n";
}
}
static void device_create_stop(GObject* obj, GAsyncResult* res, gpointer data)
{
g_printf ("Hurray!\n");
something = 2;
}
The new output:
Start
INFO: qmi_device_new starting!
INFO: qmi_device_new started!
DEBUG: Something: 1
Does anyone has a clue why this is not working?
As Philip said (hey Philip!), you're missing the main loop. The qmi_device_new() function is an method that finishes asynchronously, and once finished, the result of the operation is provided in the callback function you provide. In order for the asynchronous function to even do something, you need to have a GMainLoop running for as long as your program logic runs.
I want to use Google protocol buffer in c++ on Ubuntu in first step I created .proto file
package business;
message Employee
{
required string first_name = 1;
required string last_name = 2;
required string email = 3;
}
message Company
{
required string name = 1;
optional string url = 2;
repeated Employee employee = 3;
}
I can easily translate it to the C++ data access classes by calling:
protoc -I=. --cpp_out=. business.proto
after this step protoc create to file
business.pb.h
business.pb.cc
when I want compile this code I see error
#include <iostream>
#include <fstream>
#include "business.pb.h"
using namespace std;
/// Saves a demo company object to 'company.bin'.
void save()
{
business::Company company;
company.set_name("Example Ltd.");
company.set_url("http://www.example.com");
// 1st employee
{
business::Employee *employee = company.add_employee();
employee->set_first_name("John");
employee->set_last_name("Doe");
employee->set_email("john.doe#example.com");
}
// 2nd employee
{
business::Employee *employee = company.add_employee();
employee->set_first_name("Jane");
employee->set_last_name("Roe");
employee->set_email("jane.roe#example.com");
}
fstream output("company.bin", ios::out | ios::trunc | ios::binary);
company.SerializeToOstream(&output);
}
/// Loads a demo company object from 'company.bin' and dumps its data.
void load()
{
business::Company company;
fstream input("company.bin", ios::in | ios::binary);
company.ParseFromIstream(&input);
cout << "Company: " << company.name() << "\n";
cout << "URL: " << (company.has_url() ? company.url() : "N/A") << "\n";
cout << "\nEmployees: \n\n";
for(int i = 0, n = company.employee_size(); i < n; ++i)
{
const business::Employee &employee = company.employee(i);
cout << "First name: " << employee.first_name() << "\n";
cout << "Last name: " << employee.last_name() << "\n";
cout << "Email: " << employee.email() << "\n";
cout << "\n";
}
}
int main()
{
save();
load();
return 0;
}
for compile I use this command
g++ p1.cpp business.pb.cc `pkg-config --cflags --libs protobuf`
but I see this error
https://i.stack.imgur.com/soQ3Z.png
i solved the problem
1)uninstall old version Google Protocol Buffer
2) instal new version Google Protocol Buffer
I'm trying to make a "wrapper" of the VideoCapture class of OpenCV, but I can't get it correctly working, my code is as follows:
#include "opencv2/opencv.hpp"
#include "opencv2/highgui/highgui.hpp"
class wrapper
{
private:
cv::VideoCapture cap;
int device_id;
public:
wrapper();
~wrapper();
void setup(int _device_id);
};
// wrapper.cpp
wrapper::wrapper()
{
device_id = 0;
}
wrapper::~wrapper()
{
cap.release();
}
wrapper::setup(int _device_id)
{
device_id = _device_id;
cap = cv::VideoCapture(device_id);
cout << "Checking device" << endl;
if(!cap.isOpened())
{
cout << "Couldn't open device" << endl;
return;
}
else
{
cout << "Device opened " << endl;
}
}
The problem is that it doesn't open the device. I have checked my device on the starter_video.exe (OpenCV examples) and it does open.
Any thoughts?
I never try to assign a videocapture like you do.
Please, try to replace the line :
cap = cv::VideoCapture(device_id);
by
cap.open(device_id);