mirror of
https://github.com/rizinorg/cutter.git
synced 2025-01-19 10:58:51 +00:00
Added listening r2 server for Jupyter + r2pipe
This commit is contained in:
parent
1ba8e03f04
commit
7526965b26
@ -83,7 +83,7 @@ static void registerCustomFonts()
|
|||||||
ret = QFontDatabase::addApplicationFont(":/fonts/Inconsolata-Regular.ttf");
|
ret = QFontDatabase::addApplicationFont(":/fonts/Inconsolata-Regular.ttf");
|
||||||
assert(-1 != ret && "unable to register Inconsolata-Regular.ttf");
|
assert(-1 != ret && "unable to register Inconsolata-Regular.ttf");
|
||||||
|
|
||||||
// do not issue a warning in release
|
// Do not issue a warning in release
|
||||||
Q_UNUSED(ret)
|
Q_UNUSED(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,6 +99,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
|
|
||||||
MainWindow::~MainWindow()
|
MainWindow::~MainWindow()
|
||||||
{
|
{
|
||||||
|
delete configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::initUI()
|
void MainWindow::initUI()
|
||||||
@ -389,22 +390,18 @@ void MainWindow::closeEvent(QCloseEvent *event)
|
|||||||
QMessageBox::StandardButton ret = QMessageBox::question(this, APPNAME,
|
QMessageBox::StandardButton ret = QMessageBox::question(this, APPNAME,
|
||||||
tr("Do you really want to exit?\nSave your project before closing!"),
|
tr("Do you really want to exit?\nSave your project before closing!"),
|
||||||
(QMessageBox::StandardButtons)(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel));
|
(QMessageBox::StandardButtons)(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel));
|
||||||
//qDebug() << ret;
|
|
||||||
if (ret == QMessageBox::Save)
|
if (ret == QMessageBox::Save)
|
||||||
{
|
{
|
||||||
if (saveProject(true))
|
if (saveProject(true))
|
||||||
{
|
{
|
||||||
saveSettings();
|
saveSettings();
|
||||||
|
}
|
||||||
QMainWindow::closeEvent(event);
|
QMainWindow::closeEvent(event);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
event->ignore();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (ret == QMessageBox::Discard)
|
else if (ret == QMessageBox::Discard)
|
||||||
{
|
{
|
||||||
saveSettings();
|
saveSettings();
|
||||||
|
QMainWindow::closeEvent(event);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -93,7 +93,8 @@ SOURCES += \
|
|||||||
widgets/VTablesWidget.cpp \
|
widgets/VTablesWidget.cpp \
|
||||||
CutterApplication.cpp \
|
CutterApplication.cpp \
|
||||||
utils/JupyterConnection.cpp \
|
utils/JupyterConnection.cpp \
|
||||||
widgets/JupyterWidget.cpp
|
widgets/JupyterWidget.cpp \
|
||||||
|
utils/CommandServer.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
cutter.h \
|
cutter.h \
|
||||||
@ -156,7 +157,8 @@ HEADERS += \
|
|||||||
CutterApplication.h \
|
CutterApplication.h \
|
||||||
widgets/VTablesWidget.h \
|
widgets/VTablesWidget.h \
|
||||||
utils/JupyterConnection.h \
|
utils/JupyterConnection.h \
|
||||||
widgets/JupyterWidget.h
|
widgets/JupyterWidget.h \
|
||||||
|
utils/CommandServer.h
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
dialogs/AboutDialog.ui \
|
dialogs/AboutDialog.ui \
|
||||||
|
89
src/utils/CommandServer.cpp
Normal file
89
src/utils/CommandServer.cpp
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
#include "CommandServer.h"
|
||||||
|
#include "cutter.h"
|
||||||
|
|
||||||
|
CommandServer::CommandServer(QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandServer::~CommandServer()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Open a local TCP server on port 1234 to read and execute commands.
|
||||||
|
* This is useful for Jupyter Notebook to access radare2 context using r2pipe
|
||||||
|
* Example usage:
|
||||||
|
* import r2pipe; r2 = r2pipe.open('tcp://localhost:1234'); print(r2.cmd('i'))
|
||||||
|
*/
|
||||||
|
bool CommandServer::startCommandServer()
|
||||||
|
{
|
||||||
|
RCore* core = Core()->core();
|
||||||
|
const char* port = "1234";
|
||||||
|
|
||||||
|
unsigned char buf[4097];
|
||||||
|
RSocket *ch = NULL;
|
||||||
|
RSocket *s;
|
||||||
|
int i, ret;
|
||||||
|
char *str;
|
||||||
|
|
||||||
|
s = r_socket_new (0);
|
||||||
|
r_socket_listen (s, port, NULL);
|
||||||
|
if (false) {
|
||||||
|
eprintf ("Error listening on port %s\n", port);
|
||||||
|
r_socket_free (s);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
eprintf ("Listening for commands on port %s\n", port);
|
||||||
|
while (isRunning) {
|
||||||
|
ch = r_socket_accept (s);
|
||||||
|
buf[0] = 0;
|
||||||
|
ret = r_socket_read (ch, buf, sizeof (buf) - 1);
|
||||||
|
if (ret > 0) {
|
||||||
|
buf[ret] = 0;
|
||||||
|
for (i = 0; buf[i]; i++) {
|
||||||
|
if (buf[i] == '\n') {
|
||||||
|
buf[i] = buf[i + 1]? ';': '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((!r_config_get_i (core->config, "scr.prompt") &&
|
||||||
|
!strcmp ((char *)buf, "q!")) ||
|
||||||
|
!strcmp ((char *)buf, ".--")) {
|
||||||
|
r_socket_close (ch);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
str = r_core_cmd_str (core, (const char *)buf);
|
||||||
|
if (str && *str) {
|
||||||
|
r_socket_write (ch, str, strlen (str));
|
||||||
|
} else {
|
||||||
|
const char nl[] = "\n";
|
||||||
|
r_socket_write (ch, (void*) nl, 1);
|
||||||
|
}
|
||||||
|
free (str);
|
||||||
|
}
|
||||||
|
r_socket_close (ch);
|
||||||
|
r_socket_free (ch);
|
||||||
|
ch = NULL;
|
||||||
|
}
|
||||||
|
r_socket_free (s);
|
||||||
|
r_socket_free (ch);
|
||||||
|
eprintf ("TCP Server (on %s) exited.\n", port);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandServer::process()
|
||||||
|
{
|
||||||
|
startCommandServer();
|
||||||
|
emit finished();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops the server.
|
||||||
|
*/
|
||||||
|
void CommandServer::stop()
|
||||||
|
{
|
||||||
|
isRunning = false;
|
||||||
|
}
|
26
src/utils/CommandServer.h
Normal file
26
src/utils/CommandServer.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef COMMANDSERVER_H
|
||||||
|
#define COMMANDSERVER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class CommandServer : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit CommandServer(QObject *parent = nullptr);
|
||||||
|
~CommandServer();
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void finished();
|
||||||
|
void error(QString err);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void process();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isRunning = true;
|
||||||
|
bool startCommandServer();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COMMANDSERVER_H
|
@ -2,6 +2,8 @@
|
|||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
#include "JupyterConnection.h"
|
#include "JupyterConnection.h"
|
||||||
|
|
||||||
@ -12,6 +14,9 @@ JupyterConnection::JupyterConnection(QObject *parent) : QObject(parent)
|
|||||||
|
|
||||||
JupyterConnection::~JupyterConnection()
|
JupyterConnection::~JupyterConnection()
|
||||||
{
|
{
|
||||||
|
cmdServer->stop();
|
||||||
|
process->terminate();
|
||||||
|
urlProcess->terminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *urlPy = "from notebook import notebookapp\n"
|
const char *urlPy = "from notebook import notebookapp\n"
|
||||||
@ -28,23 +33,34 @@ void JupyterConnection::start()
|
|||||||
process = new QProcess(this);
|
process = new QProcess(this);
|
||||||
connect(process, &QProcess::readyReadStandardError, this, &JupyterConnection::readStandardError);
|
connect(process, &QProcess::readyReadStandardError, this, &JupyterConnection::readStandardError);
|
||||||
connect(process, &QProcess::readyReadStandardOutput, this, &JupyterConnection::readStandardOutput);
|
connect(process, &QProcess::readyReadStandardOutput, this, &JupyterConnection::readStandardOutput);
|
||||||
|
connect(process, &QProcess::errorOccurred, this, [](QProcess::ProcessError error){ qWarning() << "Jupyter error occurred:" << error; });
|
||||||
process->start("jupyter", {"notebook", "--no-browser", "-y"});
|
process->start("jupyter", {"notebook", "--no-browser", "-y"});
|
||||||
|
|
||||||
urlProcess = new QProcess(this);
|
urlProcess = new QProcess(this);
|
||||||
connect(urlProcess, &QProcess::readyReadStandardOutput, this, &JupyterConnection::readUrlStandardOutput);
|
connect(urlProcess, &QProcess::readyReadStandardOutput, this, &JupyterConnection::readUrlStandardOutput);
|
||||||
urlProcess->start("python3", {"-c", urlPy});
|
urlProcess->start("python3", {"-c", urlPy});
|
||||||
|
|
||||||
|
QThread *cmdServerThread = new QThread(this);
|
||||||
|
cmdServer = new CommandServer();
|
||||||
|
cmdServer->moveToThread(cmdServerThread);
|
||||||
|
connect(cmdServer, &CommandServer::error, this, [](QString err){ qWarning() << "CmdServer error:" << err; });
|
||||||
|
connect(cmdServerThread, SIGNAL (started()), cmdServer, SLOT (process()));
|
||||||
|
connect(cmdServer, SIGNAL (finished()), cmdServerThread, SLOT (quit()));
|
||||||
|
connect(cmdServer, SIGNAL (finished()), cmdServer, SLOT (deleteLater()));
|
||||||
|
connect(cmdServerThread, SIGNAL (finished()), cmdServerThread, SLOT (deleteLater()));
|
||||||
|
cmdServerThread->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JupyterConnection::readStandardError()
|
void JupyterConnection::readStandardError()
|
||||||
{
|
{
|
||||||
auto data = process->readAllStandardError();
|
auto data = process->readAllStandardError();
|
||||||
printf("jupyter stderr: %s\n", data.constData());
|
printf("Jupyter stderr: %s", data.constData());
|
||||||
}
|
}
|
||||||
|
|
||||||
void JupyterConnection::readStandardOutput()
|
void JupyterConnection::readStandardOutput()
|
||||||
{
|
{
|
||||||
auto data = process->readAllStandardOutput();
|
auto data = process->readAllStandardOutput();
|
||||||
printf("jupyter stdout: %s\n", data.constData());
|
printf("Jupyter stdout: %s", data.constData());
|
||||||
}
|
}
|
||||||
|
|
||||||
void JupyterConnection::readUrlStandardOutput()
|
void JupyterConnection::readUrlStandardOutput()
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
|
|
||||||
#ifndef JUPYTERCONNECTION_H
|
#ifndef JUPYTERCONNECTION_H
|
||||||
#define JUPYTERCONNECTION_H
|
#define JUPYTERCONNECTION_H
|
||||||
|
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
|
#include "CommandServer.h"
|
||||||
|
|
||||||
class JupyterConnection : public QObject
|
class JupyterConnection : public QObject
|
||||||
{
|
{
|
||||||
@ -20,6 +20,7 @@ signals:
|
|||||||
private:
|
private:
|
||||||
QProcess *process;
|
QProcess *process;
|
||||||
QProcess *urlProcess;
|
QProcess *urlProcess;
|
||||||
|
CommandServer *cmdServer;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void readStandardError();
|
void readStandardError();
|
||||||
|
Loading…
Reference in New Issue
Block a user