Every code works fine. Debugging with visual studio is problem.
I'm making Linux server using openSSL library with c++11.
The server runs on CentOS in VMware. (Will move to Azure when completed)
I work on Visual studio 2017, cross-compile linked with that CentOS.
When I call
int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type);
this funcntion in ssl library, it opens private key file, require me password on standard input, showing up message on standard out and wait for my input.
But if I run on Visual studio debug mode, it just passes away.
It works fine when I use .out file on CentOS, and that '.out' file is compiled by visual studio for debugging.
It's not a path problem. '.crt' file opens well and only '.key' file in the same folder not opens well.
these are the code where problem occur.
SslUtil, ExceptionSslUtil class is in my own code. but the other all functions and structures in this code are in ssl library.
void SslUtil::InitAsServer(const char* pathCert, const char* pathKey) {
amIServer = true;
SSL_load_error_strings();
SSLeay_add_ssl_algorithms();
meth = SSLv23_server_method();
ctx = SSL_CTX_new(meth);
if (!ctx)
throw ExceptionSslUtil("ctx create error");
if (SSL_CTX_use_certificate_file(ctx, pathCert, SSL_FILETYPE_PEM) <= 0)
throw ExceptionSslUtil("cert file open error");
if (SSL_CTX_use_PrivateKey_file( ctx, pathKey, SSL_FILETYPE_PEM) <= 0)// here's the problem.
throw ExceptionSslUtil("private key file open error");
if (!SSL_CTX_check_private_key(ctx))
throw ExceptionSslUtil("Private key does not match the certificate public keyn");
return;
}
SSL_CTX_use_PrivateKey_file function not blocked for input, just returning minus value. It has to wait for input but not.
I have no idea what's happening there.
It worked previously,
but when I change original main(argc, argv) function into mainSslEpoll(argc, argv) and make it called by other main function, this problem happen... why?
The following is my new main function.
int main(int argc, char** argv) {
string str;
while (true) {
cout << "select mode" << endl;
cout << "\t" << "0:SSL + Epoll server" << endl;
cout << "\t" << "1:SSL server" << endl;
cout << "\t" << "2:SSL client" << endl;
cin >> str;
if (str[0] == '0') return mainSslEpoll(argc, argv);
if (str[0] == '1') return mainSslServer(argc, argv);
if (str[0] == '2') return mainSslClient(argc, argv);
}
}
Related
On Linux, I am trying to detect a bluetooth controller being connected and start reading from it. I know there's SDL to do that, but I just wanted to learn how to do it specifically on Linux. So I'm using the inotify api to wait for the file /dev/input/js0 to show up. But when I detect the file I cannot open it. I have the following c++ code:
#include <iostream>
#include <fstream>
#include <sys/inotify.h>
#include <unistd.h>
#include <linux/joystick.h>
#include <string.h>
constexpr int NAME_MAX = 16;
int main(int argc, char **argv) {
std::string path = std::string(argv[1]);
std::string directory = path.substr(0, path.find_last_of("/"));
std::string file = path.substr(path.find_last_of("/") + 1);
std::cout << "Directory is " << directory << ", file is " << file << std::endl;
int fd = inotify_init();
if (inotify_add_watch(fd, directory.c_str(), IN_CREATE) < 0) {
std::cout << "Could not watch: " << file << std::endl;
return -1;
}
else
std::cout << "Watching: " << file << std::endl;
char buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
while (true) {
if (read(fd, buffer, sizeof(buffer)) < 0) {
std::cout << "Error reading event" << std::endl;
break;
}
struct inotify_event &event = (struct inotify_event &) buffer;
std::cout << event.name << std::endl;
if ((strcmp(event.name, file.c_str()) == 0) && (event.mask & IN_CREATE)) {
std::cout << "File has been created" << std::endl;
close(fd);
break;
}
}
std::fstream file_stream(file, std::fstream::in);
std::cout << file_stream.is_open() << std::endl;
}
If I run it to detect a regular file, it works, it waits for the file creation event, and when trying to open it with a std::fstream, is_open returns true. But if I run it to detect /dev/input/js0, even when the event comes and the file is detected, opening the fstream does not work, as is_open returns false. Is inotify appropriate to detect device files? If not, what would be the right way to do so?
According to inotify(7)
Inotify reports only events that a user-space program triggers
through the filesystem API. As a result, it does not catch
remote events that occur on network filesystems. (Applications
must fall back to polling the filesystem to catch such events.)
Furthermore, various pseudo-filesystems such as /proc, /sys, and
/dev/pts are not monitorable with inotify.
I would say that /dev/input/ also falls into this bucket.
I wonder if udev could be used: you should get info about the device using udevinfo -a -p /dev/input/js0, but also see what events connecting the peripheral generates using udevadm monitor --environment --udev.
Edit: if you successfuly get an inotify event but can't read the file:
Did you try reading the file with another simpler program when the BT device is already connected?
Is there a difference between fstream::open and open from <cstdio>?
Have you checked the permissions on the device? Also what does cat /dev/input/js0 produces?
I am creating a background music player and I wanted to use the MPV C Plugin to do so, but my problem arrives when I disable displaying the video (with check_error(mpv_set_option_string(ctx, "vid", "no"));, this does the job of disabling the video, but then I can't use keys (like q (quit) or > (skip)) anymore... How do I allow them to be used in the terminal without the video GUI?
My Code:
#include <iostream>
#include <mpv/client.h>
static inline void check_error(int status)
{
if (status < 0)
{
std::cout << "mpv API error: " << mpv_error_string(status) << std::endl;
exit(1);
}
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
std::cout << "pass a single media file as argument" << std::endl;
return 1;
}
mpv_handle *ctx = mpv_create();
if (!ctx)
{
std::cout << "failed creating context" << std::endl;
return 1;
}
check_error(mpv_set_option_string(ctx, "input-default-bindings", "yes"));
mpv_set_option_string(ctx, "input-vo-keyboard", "yes");
int val = 1;
check_error(mpv_set_option(ctx, "osc", MPV_FORMAT_FLAG, &val));
check_error(mpv_initialize(ctx));
const char *cmd[] = {"loadfile", argv[1], NULL};
check_error(mpv_command(ctx, cmd));
// THIS IS WHAT I USE TO DISABLE THE VIDEO
// check_error(mpv_set_option_string(ctx, "vid", "no"));
// Let it play, and wait until the user quits.
while (1)
{
mpv_event *event = mpv_wait_event(ctx, 10000);
std::cout << "event: " << mpv_event_name(event->event_id) << std::endl;
if (event->event_id == MPV_EVENT_SHUTDOWN)
break;
}
mpv_terminate_destroy(ctx);
return 0;
}
As you can see with mpv_set_option_string(ctx, "input-default-bindings", "yes") I allow it to use keybinding, but how do I make the keybinding works with just the terminal, since it only works when the GUI is visible? If you ran: mpv path/to/video.mp3 --no-video then the key bindings would still work fine, even without the video GUI.
Questions:
1) Where do files go that are created by a C++ Google unit test?
2) Is there a way to write a persistent data file in a C++ Google unit test, such that the file is accessible after the test runs?
Code and desired behavior
I'm running the unit test on Ubuntu 14.04 with catkin_make. I would like the code to write a file somewhere that I can find it after the test runs. The following code writes a file, but I don't know where it goes, or if it persists after the unit tests complete.
TEST(GUnitTestFileIo, Test_One)
{
std::ofstream csvFile;
csvFile.open("helloWorldTestFile.csv");
if (csvFile.is_open()) {
csvFile << "Hello, World, !" << std::endl;
csvFile.close();
} else {
std::cout << "Failed to open the file!" << std::endl;
}
}
int main(int argc, char **argv){
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
One solution is to simply write to an absolute file path. The following code writes a file to the user's home directory from inside of a google unit test:
TEST(GUnitTestFileIo, Test_One)
{
char const* tmp = getenv( "HOME" );
if ( tmp == NULL ) {
std::cout << "$(HOME) environment variable is not defined!";
} else {
std::string home( tmp ); // string for the home directory
std::ofstream csvFile; // write the file
csvFile.open(home + "/helloWorldTestFile.csv");
if (csvFile.is_open()) {
csvFile << "Hello, World, !" << std::endl;
csvFile.close();
} else {
std::cout << "Failed to open the file!" << std::endl;
}
}
}
// Run all the tests that were declared with TEST()
int main(int argc, char **argv){
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
I modified this code on a Windows 10 PC, and it compiled and ran without crashing.
#include <QtSerialPort/QSerialPort>
#include <QTextStream>
#include <QCoreApplication>
#include <QFile>
#include <QStringList>
QT_USE_NAMESPACE
int main(int argc, char *argv[])
{
QCoreApplication coreApplication(argc, argv);
int argumentCount = QCoreApplication::arguments().size();
QStringList argumentList = QCoreApplication::arguments();
QTextStream standardOutput(stdout);
if (argumentCount == 1) {
standardOutput << QObject::tr("Usage: %1 <serialportname> [baudrate]").arg(argumentList.first()) << endl;
return 1;
}
QSerialPort serialPort;
QString serialPortName = argumentList.at(1);
serialPort.setPortName(serialPortName);
int serialPortBaudRate = (argumentCount > 2) ? argumentList.at(2).toInt() : QSerialPort::Baud9600;
serialPort.setBaudRate(serialPortBaudRate);
if (!serialPort.open(QIODevice::WriteOnly)) {
standardOutput << QObject::tr("Failed to open port %1, error: %2").arg(serialPortName).arg(serialPort.errorString()) << endl;
return 1;
}
QFile dataFile("C:\\SerialCommand.dat");
if (!dataFile.open(QIODevice::ReadOnly)) {
standardOutput << QObject::tr("Failed to open file for reading") << endl;
return 1;
}
QByteArray writeData(dataFile.readAll());
dataFile.close();
if (writeData.isEmpty()) {
standardOutput << QObject::tr("Either no data was currently available on the standard input for reading, or an error occurred for port %1, error: %2").arg(serialPortName).arg(serialPort.errorString()) << endl;
return 1;
}
qint64 bytesWritten = serialPort.write(writeData);
if (bytesWritten == -1) {
standardOutput << QObject::tr("Failed to write the data to port %1, error: %2").arg(serialPortName).arg(serialPort.errorString()) << endl;
return 1;
} else if (bytesWritten != writeData.size()) {
standardOutput << QObject::tr("Failed to write all the data to port %1, error: %2").arg(serialPortName).arg(serialPort.errorString()) << endl;
return 1;
} else if (!serialPort.waitForBytesWritten(5000)) {
standardOutput << QObject::tr("Operation timed out or an error occurred for port %1, error: %2").arg(serialPortName).arg(serialPort.errorString()) << endl;
return 1;
}
standardOutput << QObject::tr("Data successfully sent to port %1").arg(serialPortName) << endl;
printf("\n\ntest");
return 0;
}
I set Qt to release mode, and packaged the application with the following .dll files:
msvcp120d.dll
msvcr120d.dll
Qt5Core.dll
Qt5Cored.dll
Qt5SerialPort.dll
Qt5SerialPortd.dll
Qt5Widgets.dll
qwindows.dll
When I ran the application on another system (also windows 10), the program crashes immediately - and yes, I did move SerialCommand.dat to its correct location on the C drive. Any thoughts?
You're packaging the debug versions of the dlls (ending with a d) instead of release ones.
Read the Qt deployment docs, especially the last part (from "Application Dependencies" to the end).
The dependency walker helps find the actual dependencies, and in theory windeployqt should automate the work of creating a release dir with all the files you need.
See also this other question, but it's for an app using QML, so it's more complex than your case.
im just starting to learn about sockets and i have been given this code, and i have to make the port lookup logic work. But the problem is i keep getting this run time error and I dont know why?
// portlookup.cpp
// Given a service name, this program displays the corresponding port number.
#include <iostream>
#pragma comment(lib, "ws2_32.lib")
#include <winsock2.h>
using namespace std;
int main (int argc, char **argv)
{
char service[80]; // This string contains name of desired service
struct servent *pse; // pointer to service information entry
short port; // Port # (in Network Byte Order) of desired service
if (argc < 2)
{
cout << "Please specify a service." << endl;
}
strcpy_s(service, sizeof(service), argv[1]);
WORD wVersion = 0x0202;
WSADATA wsaData;
int iResult = WSAStartup(wVersion, &wsaData); // Returns zero if successful
if (iResult != 0) {
cout << "Insufficient resources to startup WINSOCK." << endl;
return 0;
}
port = htons( (u_short) atoi(service)); // 1st try to convert string to integer
if (port == 0) { // if that doesn't work, call service function
pse = getservbyname(service,NULL);
if (pse) {
port = pse->s_port;
}
else
{
cout << "Invalid service request." << endl;
return INVALID_SOCKET;
}
}
cout << "Service: " << service << endl;
cout << "Port: " << htons(port) << endl;
}
Your problem appears to be that you aren't passing a command line, you check argc < 2, but when it is < 2 you execute the strcpy_s anyway.
In Visual Studio, Got to the Project Properties dialog, from there go to the Debugging page
and add the service name to Command Arguments
And fix your argument checking code
if (argc < 2)
{
//cout << "Please specify a service." << endl;
cerr << "error: no service specified." << endl;
return EXIT_FAILURE; // return some non-zero value to indicate failure.
}
You need to start your program with an argument. The line strcpy_s(service, sizeof(service),argv[1]); assumes you've given the program 1 argument, which will be stored in argv[1].
If you don't run it with any arguments, argv[1] will be NULL and your program will crash.
Make sure to exit if no parameter is specified.
if (argc < 2)
{
cout << "Please specify a service." << endl;
return 0; // exit!
}
also,
port = htons( (u_short) atoi(service));
...
cout << htons(port);