+ Implement a lightweight TCP server

This commit is contained in:
wmayer 2014-01-07 17:56:20 +01:00
parent 19865c252b
commit 19c6105389
8 changed files with 496 additions and 0 deletions

View File

@ -0,0 +1,50 @@
/***************************************************************************
* Copyright (c) 2014 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <Python.h>
#endif
#include <Base/Console.h>
/* registration table */
extern struct PyMethodDef Web_methods[];
PyDoc_STRVAR(module_Web_doc,
"This module is the Web module.");
/* Python entry */
extern "C" {
void WebAppExport initWeb() {
// ADD YOUR CODE HERE
//
//
(void) Py_InitModule3("Web", Web_methods, module_Web_doc); /* mod name, table ptr */
Base::Console().Log("Loading Web module... done\n");
}
} // extern "C"

View File

@ -0,0 +1,103 @@
/***************************************************************************
* Copyright (c) 2014 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#endif
#include <Python.h>
#include <Base/Console.h>
#include <Base/PyObjectBase.h>
#include <Base/Exception.h>
#include <CXX/Objects.hxx>
#include "Server.h"
using namespace Web;
// See http://docs.python.org/2/library/socketserver.html
/*
import socket
import threading
import SocketServer
ip = "127.0.0.1"
port=54880
def client(ip, port, message):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((ip, port))
try:
sock.sendall(message)
response = sock.recv(1024)
print "Received: {}".format(response)
finally:
sock.close()
client(ip, port, "print 'Hello World 1'")
client(ip, port, "import FreeCAD\nFreeCAD.newDocument()")
client(ip, port, "Hello World 3\n")
*/
/* module functions */
static PyObject * startServer(PyObject *self, PyObject *args)
{
const char* addr = "127.0.0.1";
int port=0;
if (!PyArg_ParseTuple(args, "|si",&addr,&port))
return NULL;
PY_TRY {
AppServer* server = new AppServer();
if (server->listen(QHostAddress(QString::fromLatin1(addr)), port)) {
QString a = server->serverAddress().toString();
quint16 p = server->serverPort();
Py::Tuple t(2);
t.setItem(0, Py::String((const char*)a.toLatin1()));
t.setItem(1, Py::Int(p));
return Py::new_reference_to(t);
}
else {
QString a = server->serverAddress().toString();
quint16 p = server->serverPort();
server->deleteLater();
PyErr_Format(PyExc_RuntimeError, "Server failed to listen at address %s and port %d", (const char*)a.toLatin1(), p);
return 0;
}
} PY_CATCH;
Py_Return;
}
/* registration table */
struct PyMethodDef Web_methods[] = {
{"startServer",startServer ,METH_VARARGS,
"startServer(address=127.0.0.1,port=0) -- Start a server."},
{NULL, NULL} /* end of table marker */
};

View File

@ -0,0 +1,65 @@
include_directories(
${CMAKE_CURRENT_BINARY_DIR}
${Boost_INCLUDE_DIRS}
${OCC_INCLUDE_DIR}
${PYTHON_INCLUDE_PATH}
${ZLIB_INCLUDE_DIR}
${XERCESC_INCLUDE_DIR}
${QT_INCLUDE_DIR}
)
if(MSVC)
set(Web_LIBS
FreeCADApp
${QT_DEBUG_LIBRARIES}
${QT_LIBRARIES}
)
else(MSVC)
set(Web_LIBS
FreeCADApp
${QT_LIBRARIES}
)
endif(MSVC)
set(Web_MOC_HDRS
Server.h
)
fc_wrap_cpp(Web_MOC_SRCS ${Web_MOC_HDRS})
SOURCE_GROUP("Moc" FILES ${Web_MOC_SRCS})
SET(Web_SRCS
AppWeb.cpp
AppWebPy.cpp
PreCompiled.cpp
PreCompiled.h
Server.cpp
Server.h
)
add_library(Web SHARED ${Web_SRCS})
target_link_libraries(Web ${Web_LIBS})
fc_target_copy_resource(Web
${CMAKE_SOURCE_DIR}/src/Mod/Web
${CMAKE_BINARY_DIR}/Mod/Web
Init.py)
if(MSVC)
set_target_properties(Web PROPERTIES SUFFIX ".pyd")
set_target_properties(Web PROPERTIES DEBUG_OUTPUT_NAME "Web_d")
set_target_properties(Web PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/Mod/Web)
set_target_properties(Web PROPERTIES PREFIX "../")
elseif(MINGW)
set_target_properties(Web PROPERTIES SUFFIX ".pyd")
set_target_properties(Web PROPERTIES DEBUG_OUTPUT_NAME "Web_d")
set_target_properties(Web PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/Mod/Web)
set_target_properties(Web PROPERTIES PREFIX "")
else(MSVC)
set_target_properties(Web PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/Mod/Web)
set_target_properties(Web PROPERTIES PREFIX "")
set_target_properties(Fem PROPERTIES INSTALL_RPATH ${INSTALL_RPATH})
endif(MSVC)
install(TARGETS Web DESTINATION lib)

View File

@ -0,0 +1,24 @@
/***************************************************************************
* Copyright (c) 2014 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"

View File

@ -0,0 +1,61 @@
/***************************************************************************
* Copyright (c) 2014 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef APP_PRECOMPILED_H
#define APP_PRECOMPILED_H
#include <FCConfig.h>
// Exporting of App classes
#ifdef FC_OS_WIN32
# define WebAppExport __declspec(dllexport)
#else // for Linux
# define WebAppExport
#endif
#ifdef _PreComp_
// standard
#include <cstdio>
#include <cassert>
#include <iostream>
// STL
#include <algorithm>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
// Xerces
#include <xercesc/util/XercesDefs.hpp>
#endif //_PreComp_
#endif

118
src/Mod/Web/App/Server.cpp Normal file
View File

@ -0,0 +1,118 @@
/***************************************************************************
* Copyright (c) 2014 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#include <QCoreApplication>
#include <QTcpSocket>
# include <stdexcept>
#include "Server.h"
#include <Base/Exception.h>
#include <Base/Interpreter.h>
using namespace Web;
ServerEvent::ServerEvent(QTcpSocket* sock, const QByteArray& msg)
: QEvent(QEvent::User), sock(sock), text(msg)
{
}
ServerEvent::~ServerEvent()
{
}
QTcpSocket* ServerEvent::socket() const
{
return sock;
}
const QByteArray& ServerEvent::request() const
{
return text;
}
AppServer::AppServer(QObject* parent)
: QTcpServer(parent)
{
}
void AppServer::incomingConnection(int socket)
{
QTcpSocket* s = new QTcpSocket(this);
connect(s, SIGNAL(readyRead()), this, SLOT(readClient()));
connect(s, SIGNAL(disconnected()), this, SLOT(discardClient()));
s->setSocketDescriptor(socket);
}
void AppServer::readClient()
{
QTcpSocket* socket = (QTcpSocket*)sender();
if (socket->bytesAvailable() > 0) {
QByteArray request = socket->readAll();
QCoreApplication::postEvent(this, new ServerEvent(socket, request));
}
// if (socket->state() == QTcpSocket::UnconnectedState) {
// //mark the socket for deletion but do not destroy immediately
// socket->deleteLater();
// }
}
void AppServer::discardClient()
{
QTcpSocket* socket = (QTcpSocket*)sender();
socket->deleteLater();
}
void AppServer::customEvent(QEvent* e)
{
ServerEvent* ev = static_cast<ServerEvent*>(e);
QByteArray msg = ev->request();
QTcpSocket* socket = ev->socket();
std::string str;
try {
Base::Interpreter().runString(msg);
}
catch (Base::PyException &e) {
str = e.what();
str += "\n\n";
str += e.getStackTrace();
}
catch (Base::Exception &e) {
str = e.what();
}
catch (std::exception &e) {
str = e.what();
}
catch (...) {
str = "Unknown exception thrown";
}
socket->write(str.c_str());
socket->close();
}
#include "moc_Server.cpp"

74
src/Mod/Web/App/Server.h Normal file
View File

@ -0,0 +1,74 @@
/***************************************************************************
* Copyright (c) 2014 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef WEB_SERVER_H
#define WEB_SERVER_H
#include <QByteArray>
#include <QObject>
#include <QEvent>
#include <QTcpSocket>
#include <QTcpServer>
namespace Web {
class ServerEvent : public QEvent
{
public:
ServerEvent(QTcpSocket* socket, const QByteArray&);
~ServerEvent();
QTcpSocket* socket() const;
const QByteArray& request() const;
private:
QTcpSocket* sock;
QByteArray text;
};
/**
* The Server class implements a simple TCP server.
*/
class AppServer : public QTcpServer
{
Q_OBJECT
public:
AppServer(QObject* parent = 0);
void incomingConnection(int socket);
protected:
void customEvent(QEvent* e);
private Q_SLOTS:
void readClient();
void discardClient();
private:
};
}
#endif //Web_SERVER_H

View File

@ -1,4 +1,5 @@
add_subdirectory(App)
if(FREECAD_BUILD_GUI)
add_subdirectory(Gui)
endif(FREECAD_BUILD_GUI)