Gibberish coming from ASIO SSL Server code after the first message - ssl

I'm trying to write a SSL-based async server using Boost ASIO example code from here.
I get the first message and its response correctly at the client side. Then, I send a second message which is received fine at the server, however when the response is sent to client. It comes as some gibberish.
I have uploaded the server code to pastebin. Also, find it below:
// file - Server.h
class Server
{
public:
explicit Server(const std::string &address,
int port,
std::size_t threadPoolSize);
// run the io_service loop
void run();
// stop the server
void stop();
private:
//handle async accept operation
void handleAccept(const boost::system::error_code &e);
// number of threads in thread pool
std::size_t _threadPoolSize;
// the io_service
boost::asio::io_service _ioService;
// acceptor to listen for incoming connections
boost::asio::ip::tcp::acceptor _acceptor;
std::string get_password()
{
return "password";
}
// ssl context
boost::asio::ssl::context _context;
ConnectionPtr _connection;
};
//////////////////////////////////////////////////////////////////////////
// file - Server.cpp
//////////////////////////////////////////////////////////////////////////
Server::Server(const std::string& address,
int port,
std::size_t threadPoolSize)
: _threadPoolSize(threadPoolSize),
_acceptor(_ioService),
_context(_ioService, boost::asio::ssl::context::sslv23),
_connection()
{
try {
DEBUG_2("Starting server on port: ", port);
boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port);
_acceptor.open(endpoint.protocol());
_acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
_acceptor.bind(endpoint);
_acceptor.listen();
_context.set_options(
boost::asio::ssl::context::default_workarounds
| boost::asio::ssl::context::no_sslv2
| boost::asio::ssl::context::single_dh_use);
_context.set_password_callback(boost::bind(&Server::get_password, this));
_context.use_certificate_chain_file("./demoCA/cacert.pem");
_context.use_private_key_file("./demoCA/private/cakey.pem",
boost::asio::ssl::context::pem);
// _context.use_tmp_dh_file("dh512.pem");
_connection.reset(new CclConnection(_ioService, _context));
_acceptor.async_accept(_connection->socket(),
boost::bind(&Server::handleAccept,
this,
boost::asio::placeholders::error));
}
catch(std::exception& e)
{
STD_EXCEPTION_MESSAGE;
throw;
}
}
void Server::run()
{
// Create a pool of threads to run all of the io_services.
std::vector<boost::shared_ptr<boost::thread> > threads;
for (std::size_t i = 0; i < _threadPoolSize; ++i)
{
boost::shared_ptr<boost::thread>
thread(new boost::thread(
boost::bind(&boost::asio::io_service::run,
&_ioService)
)
);
threads.push_back(thread);
}
// Wait for all threads in the pool to exit.
for (std::size_t i = 0; i < threads.size(); ++i)
threads[i]->join();
}
void Server::stop()
{
_ioService.stop();
}
void Server::handleAccept(const boost::system::error_code& e)
{
if (!e)
{
_connection->handshake();
_connection.reset(new CclConnection(_ioService, _context));
_acceptor.async_accept(_connection->socket(),
boost::bind(&Server::handleAccept,
this,
boost::asio::placeholders::error));
}
}
////////////////////////////////////////////////////////////
// file - Connection.h
////////////////////////////////////////////////////////////
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
typedef boost::asio::ssl::stream< boost::asio::ip::tcp::socket >
ssl_socket;
class Connection
: public boost::enable_shared_from_this<Connection>
{
public:
explicit Connection(boost::asio::io_service& io_service,
boost::asio::ssl::context& context);
//get socket from the connection
ssl_socket::lowest_layer_type& socket();
// do an SSL handshake
void handshake();
//get socket from the connection
boost::asio::io_service::strand& strand();
// start first async operation
void start();
void sendResponse(const Response& response);
void close();
// get remote IP address for this connection
std::string getIPAddress();
private:
void handleRead(const boost::system::error_code& e,
std::size_t bytesTransferred);
void handleWrite(const boost::system::error_code& e);
boost::asio::io_service::strand _strand;
ssl_socket _socket;
void handleHandshake(const boost::system::error_code& e);
boost::array<char, 8192> _buffer;
};
typedef boost::shared_ptr<Connection> ConnectionPtr;
///////////////////////////////////////////////////////////////
// File - Connection.cpp
///////////////////////////////////////////////////////////////
Connection::Connection(boost::asio::io_service& io_service,
boost::asio::ssl::context& context)
: _strand(io_service),
_socket(io_service, context)
{
}
ssl_socket::lowest_layer_type& Connection::socket()
{
return _socket.lowest_layer();
}
boost::asio::io_service::strand& Connection::strand()
{
return _strand;
}
void Connection::start()
{
_socket.async_read_some(boost::asio::buffer(_buffer),
_strand.wrap(
boost::bind(
&Connection::handleRead,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
)
);
}
void Connection::handshake()
{
std::cout << "doing ssl handshake" << std::endl;
_socket.async_handshake(boost::asio::ssl::stream_base::server,
_strand.wrap(
boost::bind(
&Connection::handleHandshake,
shared_from_this(),
boost::asio::placeholders::error
)
)
);
}
void Connection::handleHandshake(const boost::system::error_code& error)
{
if (!error)
{
_socket.async_read_some(boost::asio::buffer(_buffer),
_strand.wrap(
boost::bind(
&Connection::handleRead,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
)
);
}
else
{
std::cout << "error occured: " << error.message();
this->close();
}
}
void Connection::handleRead(const boost::system::error_code& e,
std::size_t bytesTransferred)
{
if (!e) {
// handle read data
this->start();
}
else {
this->close();
}
}
void Connection::handleWrite(const boost::system::error_code& e)
{
if (!e) {
this->start();
}
else {
this->close();
}
}
void Connection::sendResponse(const Response& response)
{
boost::asio::async_write(_socket,
boost::asio::buffer(convertToString(response)),
_strand.wrap(
boost::bind(
&Connection::handleWrite,
shared_from_this(),
boost::asio::placeholders::error
)
)
);
}
void Connection::close()
{
boost::system::error_code ignoredCode;
socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both,
ignoredCode);
}
std::string Connection::getIPAddress()
{
return socket().remote_endpoint().address().to_string();
}
Can someone point me out as to what is being done wrongly here?
Update: The issue is resolved as noted by me in the comment. The issue was exactly similar to another old question on stackoverflow.

Your code doesn't recognize, that boost::asio::buffer is only the wrapper for objects from which it was constructed.
Here (in Connection::sendResponse):
boost::asio::buffer(convertToString(response))
You created buffer out of a (probably) temporary object, which was destroyed before it was used by boost::asio::async_write.
Boost.Asio documentation specifically tells you about that in the paragraph "Buffer invalidation"
For the boost::asio::buffer overloads that accept an argument of type
std::string, the buffer objects returned are invalidated according to
the rules defined for invalidation of references, pointers and
iterators referring to elements of the sequence (C++ Std, 21.3).

Related

ANTLR4 C++ listener not calling overriden enterRule methods

I need some help with walking a tree with a listener (using C++). After initiating the tree walk with my listener and using gdb to attach to the process (I built the C++ runtime library with the Debug flag to be able to have the debug info in gdb), I can see it enters ParseTreeWalker::walk(), and if I execute getText() on the ParseTree* parameter I can see it has all the tokens from my input, so far so good. But when walk() calls enterRule():
void ParseTreeWalker::enterRule(ParseTreeListener *listener, ParseTree *r) const {
auto *ctx = downCast<ParserRuleContext*>(r);
listener->enterEveryRule(ctx);
ctx->enterRule(listener);
}
When I try to step in ctx->enterRule(listener) it just goes back to walk(). I've added breakpoints to my listener methods I want to debug but it appears they're not being called. I even added some std::cout statements in them but I don't see them being executed. I also added some std::cout statements to my overriden version of visitTerminal and those are getting printed...
If I inspect the ctx variable inside this method, it does seem to have the right type
_vptr.ParseTree = 0x6e6048 <vtable for MyParser::DocumentContext+16>...
So, I'm very confused, am I missing something obvious that's causing my enter* methods not get executed?
The generated BaseListener looks like this:
#include "antlr4-runtime.h"
#include "MyDCXParserListener.h"
class MyDCXParserBaseListener : public MyDCXParserListener {
public:
virtual void enterDocument(MyDCXParser::DocumentContext * /*ctx*/) override { }
virtual void exitDocument(MyDCXParser::DocumentContext * /*ctx*/) override { }
virtual void enterLine(MyDCXParser::LineContext * /*ctx*/) override { }
virtual void exitLine(MyDCXParser::LineContext * /*ctx*/) override { }
virtual void enterEveryRule(antlr4::ParserRuleContext * /*ctx*/) override { }
virtual void exitEveryRule(antlr4::ParserRuleContext * /*ctx*/) override { }
virtual void visitTerminal(antlr4::tree::TerminalNode * /*node*/) override { }
virtual void visitErrorNode(antlr4::tree::ErrorNode * /*node*/) override { }
};
The derived class I created looks like this:
.h
#include "antlr4-runtime.h"
#include "MyDCXParser.h"
#include "MyDCXParserBaseListener.h"
#include <iostream>
using namespace std;
class MyDCXListener : public MyDCXParserBaseListener
{
private:
public:
//
MyDCXListener();
//
~MyDCXListener();
// Don't allow copy constructor nor assignment operator
MyDCXListener(const MyDCXListener&) = delete;
MyDCXListener& operator=(const MyDCXListener&) = delete;
//
void enterDocument(MyDCXParser::DocumentContext * /*ctx*/) override;
void exitDocument(MyDCXParser::DocumentContext * /*ctx*/) override {}
void enterLine(MyDCXParser::LineContext * /*ctx*/) override;
void exitLine(MyDCXParser::LineContext * /*ctx*/) override {}
void visitTerminal(antlr4::tree::TerminalNode *node) override { std::cout << "visitTerminal(): '" << node->getText().c_str() << std::endl; }
};
.cpp
#include "MyDCXListener.h"
//
MyDCXListener::MyDCXListener()
{
}
MyDCXListener::~MyDCXListener()
{
}
void MyDCXListener::enterDocument(MyDCXParser::DocumentContext * ctx)
{
std::cout << "MyDCXListener::enterDocument()" << std::endl;
}
void MyDCXListener::enterLine(MyDCXParser::LineContext * ctx)
{
std::cout << "MyDCXListener::enterLine()" << std::endl;
}
I see the "visitTerminal" message but not the ones for enterDocument() nor enterLine()

boost::asio: how can I make some clients listen to server and other client read/write to server at the same time

I am a novice about boost::asio, I write a server, some clients can connect to it and keep listening.
class socket_server {
public:
~socket_server() { io_context.stop(); };
int server_process();
private:
boost::asio::io_context io_context;
};
int socket_server::server_process() {
try {
unlink("/var/run/socket");
server s(io_context, "/var/run/socket");
INFO("server_process, start run\n");
io_context.run();
} catch (std::exception &e) {
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
class server {
public:
server(boost::asio::io_context &io_context, const std::string &file)
: acceptor_(io_context, stream_protocol::endpoint(file)), socket_id_(0) {
do_accept();
}
private:
void do_accept();
stream_protocol::acceptor acceptor_;
int socket_id_;
};
void server::do_accept() {
INFO("do accept\n");
acceptor_.async_accept(
[this](std::error_code ec, stream_protocol::socket socket) {
if (!ec) {
INFO("new session create\n");
std::make_shared<session>(std::move(socket), socket_id_++)->start();
}
do_accept();
});
}
class session : public std::enable_shared_from_this<session> {
public:
session(stream_protocol::socket sock, int socket_id)
: socket_(std::move(sock)), socket_id_(socket_id) {}
~session() { socket_id_--; }
void start();
private:
void do_read();
void do_write(std::array<char, 1024> data);
int get_id() { return socket_id_; }
// The socket used to communicate with the client.
stream_protocol::socket socket_;
// Buffer used to store data received from the client.
std::array<char, 1024> data_;
int socket_id_;
};
void session::start() { do_read(); }
void session::do_read() {
INFO("in do_read\n");
auto self(shared_from_this());
socket_.async_read_some(
boost::asio::buffer(data_),
[this, self](std::error_code ec, std::size_t length) {
if (!ec) {
if (request.find("listen") != std::string::npos) {
std::unique_lock<std::mutex> lock(unsol_mutex);
unsol_cond.wait(lock)
do_write(get_unsol_data());
} else {
std::unique_lock<std::mutex> lock(send_mutex);
if (send_cond.wait_for(lock, std::chrono::seconds(2)) ==
std::cv_status::timeout) {
ERROR("response time out\n");
}
do_write(get_write_data());
}
}
});
}
In do_read(), I found when a client is listening (block in unsol_cond.wait(lock)), another client can not go to do_read().
Is it due to make_shared session? Is there a better implementation suggestion?
Thanks~
You're using blocking synchronization primitives in async code. That's an anti-pattern.
Firstly, as you noticed, the blocking operations will prevent the event loop from progressing.
Secondly, holding locks across async calls is often a bug (it doesn't guard the critical execution during execution of the async operation).
For simple integration with Asio proactor model, you can often
use a strand instead.
Under the hood, it will end up using mutexes, just like now, but only
if the concurrency model requires it. That mainly depends on the
execution context used and/or how many threads are running the
services.
Use a queue with a async send-chain. I have quite a few answers on this site that show you how to do that.
I would gladly demonstrate, but the code is too incomplete, and the naming doesn't really give me an idea what things mean ("listen"/"unsol"?, nothing ever signals those conditions so... hard to guess what they do in reality)

Access struct directly of c++ from java code

I am new to javacpp i know java have not much experience in c++. This might be one of very simple question but i am struggling with this. How to access any variable type value written in header of c++ into java code using javacpp. Let us consider example:
C++ Code example:
There is function written in C++ which return the frame of video below is the code for it and expects an Struct argument to be passed.
unsigned char *
Videodecode::getframe_data (void *ptr)
{
GstSample *sample;
GstBuffer *buffer;
GstMapInfo map;
GstCaps *caps;
GstStructure *str;
gint width, height;
gstData *dataa = (gstData *) ptr;
sample = gst_app_sink_pull_sample ((GstAppSink*)dataa->sink);
if (sample != NULL) {
buffer = gst_sample_get_buffer (sample);
gst_buffer_map (buffer, &map, GST_MAP_READ);
if (map.data != NULL) {
caps = gst_sample_get_caps (sample);
if (caps != NULL);
str = gst_caps_get_structure (caps, 0);
if (!gst_structure_get_int (str, "width", &width) ||
!gst_structure_get_int (str, "height", &height)) {
g_print ("No width/height available\n");
}
display_data = map.data;
//displayImg = Mat (Size (width, height ), CV_8UC3, map.data);
// cvtColor (displayImg, displayImg, COLOR_YUV2BGR_YUY2);
gst_buffer_unmap (buffer, &map);
gst_buffer_unref (buffer);
} else
gst_sample_unref (sample);
}
else {
//cout << "gstImageBuffer is NULL" << endl;
return NULL;
}
//return displayImg.data;
return display_data;
}
The structure which need to be passed as argument is below
typedef struct gstData_t
{
GstElement *pipeline;
GstElement *source;
GstElement *demux;
GstElement *parser;
GstElement *decoder;
GstElement *convert;
GstElement *capsfilter;
GstElement *sink;
GstElement *typefind;
} gstData;
Corresponding java code written to access it is below:
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import org.bytedeco.javacpp.FunctionPointer;
import org.bytedeco.javacpp.Loader;
import org.bytedeco.javacpp.Pointer;
import org.bytedeco.javacpp.annotation.Name;
import org.bytedeco.javacpp.annotation.NoOffset;
import org.bytedeco.javacpp.annotation.Platform;
import org.bytedeco.javacpp.annotation.Raw;
import org.bytedeco.javacpp.tools.Builder;
import org.bytedeco.javacpp.tools.ParserException;
#Platform(include = {"Videodecode.h",
},
includepath = {"/usr/include/gstreamer-1.0/","/usr/include/glib-2.0/","/usr/lib/x86_64-linux-gnu/glib-2.0/include/"},
//linkpath = {"/home/ign/git/JavaCppExample/src/main/resources/de/oltzen/javacppexample/"},
link = {"Videodecode"})
public class Videodecode {
NativeVideodecode nda;
static {
Class c = Videodecode.class;
Builder builder = null;
try {
builder = new Builder().classesOrPackages(c.getName());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoClassDefFoundError e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
File[] outputFiles = builder.build();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Loader.load(c);
// Loader.load();
}
public Videodecode() {
nda = new NativeVideodecode();
}
public Videodecode(String filename) {
nda = new NativeVideodecode(filename);
}
public boolean filePathCpp(String str){
return nda.filePathCpp(str);
}
public boolean settingValCpp(String str){
return nda.settingValCpp(str);
}
public boolean process_event (int event) {
return nda.process_event(event);
}
public java.nio.ByteBuffer test1122 (String buffer) {
return nda.test1122(buffer);
}
public java.nio.ByteBuffer test112233 (String buffer) {
return nda.test1122(buffer);
}
public java.nio.ByteBuffer getframe_data(java.nio.ByteBuffer buffer){
return nda.getframe_data(buffer);
}
public Pointer gstData(){
return nda.gstData();
}
#Name("Videodecode")
public static class NativeVideodecode extends Pointer {
static {
Loader.load();
}
public NativeVideodecode() {
allocate();
}
public NativeVideodecode(String filename) {
System.out.println("filename "+filename);
allocate(filename);
}
public NativeVideodecode(Pointer p) {
super(p);
}
private native void allocate(String filename);
private native void allocate();
private native boolean filePathCpp(String str);
private native boolean settingValCpp(String str);
private native boolean process_event(int event);
private native java.nio.ByteBuffer test1122(String buffer);
private native java.nio.ByteBuffer test112233(String buffer);
// private native boolean test1122(byte[] buffer);
private native java.nio.ByteBuffer getframe_data (java.nio.ByteBuffer buffer);
#NoOffset private native Pointer gstData();
}
}
Problems being faced by me :
How to access Struct from C++ and pass it as an argument using java.
How to access frame data which is unsigned char*.
Approach which i tried to perform this.
To access Struct, i tried using offsetof but not sure how to use it in javacpp.
To access frame data i tried using java.nio.ByteBuffer but seems its not working properly.
While trying to compile code using mvn clean install below error is getting triggered.
[INFO] --- javacpp:1.3:build (javacpp.compiler) # projecustom ---
[INFO] Detected platform "linux-x86_64"
[INFO] Building for platform "linux-x86_64"
[WARNING] Could not load platform properties for class com.proje.decoder.connectorJavaCpp
[WARNING] Could not load platform properties for class com.proje.decoder.test1234
[INFO] Generating /home/ign/eclipse-workspace/projecustom/target/classes/com/proje/decoder/jniVideodecode.cpp
[INFO] Compiling /home/ign/eclipse-workspace/projecustom/target/classes/com/proje/decoder/linux-x86_64/libjniVideodecode.so
[INFO] g++ -I/usr/include/gstreamer-1.0/ -I/usr/include/glib-2.0/ -I/usr/lib/x86_64-linux-gnu/glib-2.0/include/ -I/usr/lib/jvm/java-8-openjdk-amd64/include -I/usr/lib/jvm/java-8-openjdk-amd64/include/linux /home/ign/eclipse-workspace/projecustom/target/classes/com/proje/decoder/jniVideodecode.cpp -march=x86-64 -m64 -O3 -s -Wl,-rpath,$ORIGIN/ -Wl,-z,noexecstack -Wl,-Bsymbolic -Wall -fPIC -shared -o libjniVideodecode.so -lVideodecode
/home/ign/eclipse-workspace/projecustom/target/classes/com/proje/decoder/jniVideodecode.cpp: In function ‘_jobject* Java_com_proje_decoder_Videodecode_00024NativeVideodecode_gstData(JNIEnv*, jobject)’:
/home/ign/eclipse-workspace/projecustom/target/classes/com/proje/decoder/jniVideodecode.cpp:1532:21: error: ‘class Videodecode’ has no member named ‘gstData’
rptr = ptr->gstData();
edit:
let me try to take one simple example :
C++ Code:
#include <stdio.h>
struct test
{
int a;
std::string b;
};
class Foo {
public:
int n;
int m=70;
test tst;
// tst.a=10;
// tst.b="hi";
Foo(int n) : n(n) { }
virtual ~Foo() { }
virtual void bar() {
printf("Callback in C++ (n == %d)\n", n);
}
};
void callback(Foo *foo) {
foo->bar();
}
is it possible to write modify java code below to access a and b variables of struct
package com.ign.examples;
import org.bytedeco.javacpp.*;
import org.bytedeco.javacpp.annotation.*;
#Platform(include="Foo.h")
public class VirtualFoo1 {
static { Loader.load(); }
public static class Foo extends Pointer {
static { Loader.load(); }
public Foo(int n) { allocate(n); }
private native void allocate(int n);
#NoOffset public native int n(); public native Foo n(int n);
#Virtual public native void bar();
public native int m(); public native void m(int m);
// public native #Cast("int") int a(); public native Foo a(int a);
public native Pointer tst(); public native void tst(Pointer tst);
}
public static native void callback(Foo foo);
public static void main(String[] args) {
Foo foo = new Foo(13);
System.out.println(foo.m());
}
}

MFC DLL: class object value is not persisting throughout the exported call

I have written MFC dll having 3 methods are exported. I have declared class object as global and initialized it in first method then second and third method use and process it.
Issue is that class obeject's value is not getting persisting throughout the file. when second or third method gets call from C# client application, class
object value is getting NULL.
Could anybody tell me why this is happening! I have tried this same scnaerio in another application but this issue is not reproduced.
Code:
Interface File:
#include "StdAfx.h"
#define DLLEXPORT __declspec(dllexport)
using namespace nsAnalyzer;
static CWindowsAnalyzer *pWindowsAnalyzer = NULL;
extern "C" DLLEXPORT void Init( const wchar_t *sCurrentUserDataDir,
const wchar_t *sMachineName,
const wchar_t *sMacId )
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
try
{
nsAnalyzer::CWindowsAnalyzer *pWindowsAnalyzer = new CWindowsAnalyzer( CString(sCurrentUserDataDir),
CString(sMachineName),
CString(sMacId) );
if(pWindowsAnalyzer)
{
pWindowsAnalyzer->Init();
}
}
catch(const std::exception& e)
{
cout<<"Error: Exception occured in Init: "<<e.what()<<endl;
}
}
extern "C" DLLEXPORT bool Analyze()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
bool bResult = false;
try
{
if(pWindowsAnalyzer->ConsolidateRawActivities())
{
cout<<"ConsolidateRawActivities succeed"<<endl;
bResult = true;
}
else
{
cout<<"ConsolidateRawActivities failed"<<endl;
bResult = false;
}
}
catch(const std::exception& e)
{
cout<<"Error: Exception occured in Analyze: "<<e.what()<<endl;
}
return bResult;
}
extern "C" DLLEXPORT void Dispose()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
try
{
// Disponse windows analyzer
if(pWindowsAnalyzer)
{
delete pWindowsAnalyzer;
}
// Dispose Logger
CLogger::DisposeInstance();
}
catch(const std::exception& e)
{
cout<<"Error: Exception occured in Dispose: "<<e.what()<<endl;
}
}

terminate the BB 10 app on Alert button ok pressed

I have a socket connection App in my BB 10 cascades, when ever socket connection is closed i need to show a dialog box and when pressed on OK button app need to close.
please find my code here...
void SocketBase::writeLine(QTcpSocket *socket, const QString &line)
{
if (socket->state() != QAbstractSocket::ConnectedState)
{
onOkAlert("Please check your internet connection and restart the app again");
}
}
void SocketBase::onOkAlert(const QString &message)
{
dialog = new SystemDialog(tr("OK"), 0);
dialog->setTitle(tr("Alert"));
dialog->setBody(message);
bool success= QObject::connect(dialog,SIGNAL(finished(bb::system::SystemUiResult::Type)),
this,
SLOT(onDialogFinishe(bb::system::SystemUiResult::Type)));
if(success){
dialog->show();
}
}
and I also added at top of my class,
using namespace bb::data;
using namespace bb::cascades;
using namespace bb::system;
SystemDialog *dialog;
and my socketBase.h is like,
class SocketBase: public QObject{
Q_OBJECT
public:
SocketBase(const QString &ipAddr, const ushort port) :
mIP(ipAddr), mPort(port) {
mRunThread = false;
}
enum Identity {
BAD_IDENTITY, SERVER, CLIENT
};
virtual void startThread() = 0;
virtual void stopThread() = 0;
virtual Identity getIdentity() = 0;
Q_INVOKABLE void showDialog(int id);
void onOkAlert(const QString &message);
private slots:
void onAPPFinished();
void onDialogFinishe(bb::system::SystemUiResult::Type);
}
here is the app termination code
void SocketBase::onDialogFinishe(bb::system::SystemUiResult::Type)
{
qDebug()<<" dialog->result():::"<<dialog->result();
if(dialog->result()==2)
{
qDebug()<<"::: Terminate App :::";
bb::Application::exit(0);
}
}
what is wrong in my code, please help!!!