├── .gitignore ├── AUTHORS.md ├── INSTALL.md ├── LICENSE ├── README.md ├── build └── general │ └── qtcreator │ └── sokit.pro ├── doc └── sokit │ ├── change.log │ ├── license.gpl3 │ └── readme.txt └── src └── sokit ├── baseform.cpp ├── baseform.h ├── clientform.cpp ├── clientform.h ├── clientform.ui ├── clientskt.cpp ├── clientskt.h ├── helpform.cpp ├── helpform.h ├── helpform.ui ├── icons.qrc ├── logger.cpp ├── logger.h ├── main.cpp ├── main.h ├── notepadform.cpp ├── notepadform.h ├── resource.h ├── serverform.cpp ├── serverform.h ├── serverform.ui ├── serverskt.cpp ├── serverskt.h ├── setting.cpp ├── setting.h ├── sokit.ico ├── sokit.png ├── sokit.rc ├── sokit.ts ├── toolkit.cpp ├── toolkit.h ├── transferform.cpp ├── transferform.h ├── transferform.ui ├── transferskt.cpp └── transferskt.h /.gitignore: -------------------------------------------------------------------------------- 1 | /bin 2 | /out 3 | /tmp 4 | *.swp 5 | *.ini 6 | sokit.txt 7 | *.pro.user 8 | build-*-Debug 9 | build-*-Release 10 | -------------------------------------------------------------------------------- /AUTHORS.md: -------------------------------------------------------------------------------- 1 | # 原项目作者信息 2 | - freeware version: 1.3.1 (GPLv3) 3 | - website: https://github.com/sinpolib/sokit 4 | - email: sinpowei@gmail.com 5 | 6 | # 二次开发项目主页及联系方式 7 | - website: https://github.com/liuqun/sokit 8 | - email: 517067180@qq.com 9 | -------------------------------------------------------------------------------- /INSTALL.md: -------------------------------------------------------------------------------- 1 | # 编译运行方法 2 | 本文档INSTALL.md描述如何安装并配置开发环境(主要是安装Qt5和QtCreator) 3 | 4 | ## 编译步骤 5 | 1. Ubuntu命令行执行`sudo apt install qtcreator qt5-default qtbase5-dev qttools5-dev`安装开发环境; 6 | 2. 安装成功后打开Ubuntu左下角开始菜单,找到QtCreator并运行; 7 | 3. 打开项目子目录内的工程文件build/general/qtcreator/sokit.pro; 8 | 4. 按照QtCreator主窗口的提示,对工程进行初始配置,勾选Select all kits然后点击Configure Project; 9 | 5. 点击左下方的三角形开始编译,编译耗时较长,耐心等待几分钟,编译成功后开始运行本程序。 10 | 11 | ## 编译输出 12 | 编译输出目录位于项目的bin/debug(或release)子文件夹下 13 | - sokit是主程序 14 | - sokit.lan是Qt中文界面翻译,应与主程序放在同一个目录内。 15 | 16 | # 运行依赖库 17 | 图形界面是基于Qt5设计的,所以在Ubuntu18.04下运行的话推荐安装qt5-default: 18 | 19 | sudo apt-get install qt5-default 20 | 21 | # 支持的Qt版本 22 | Qt5版本比较多,目前已经测试过的版本如下: 23 | - Ubuntu 18.04 软件源中的Qt版本为5.9.5; 24 | - Ubuntu 19.04 已更新至Qt5.12.2; 25 | 26 | 其他Linux操作系统建议查询各自软件源是否提供的QtCreator的rpm或deb安装包。如果找不到,就去www.qt.io官网下载完整版Qt开发环境,网址如下: 27 | https://www.qt.io/offline-installers 28 | 注意官网要求通过email邮箱方式注册一个帐号才能下载和安装。 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sokit 2 | 3 | Sokit is a TCP & UDP package send/receive/transfer tool, Write in c++ with qt under Windows and Linux. 4 | 5 | 6 | 7 | 8 | 9 | License 10 | ------- 11 | Sokit is licensed under GNU GPLv3 - see the ``LICENSE`` file. 12 | -------------------------------------------------------------------------------- /build/general/qtcreator/sokit.pro: -------------------------------------------------------------------------------- 1 | # ---------------------------------------------------- 2 | # sokit.pro 3 | # ---------------------------------------------------- 4 | 5 | TEMPLATE = app 6 | TARGET = sokit 7 | 8 | QT += gui widgets network 9 | CONFIG += debug_and_release build_all thread 10 | DEFINES += QT_NETWORK_LIB 11 | INCLUDEPATH += . ./../../../tmp ./../../../src/sokit 12 | DEPENDPATH += . 13 | UI_DIR += ./../../../tmp 14 | RCC_DIR += ./../../../tmp 15 | 16 | 17 | CONFIG(debug, debug|release) { 18 | DESTDIR = ../../../bin/debug 19 | MOC_DIR += ./../../../tmp/debug 20 | OBJECTS_DIR += ./../../../tmp/debug 21 | INCLUDEPATH += ./../../../tmp/debug 22 | 23 | QMAKE_CFLAGS_DEBUG = $$unique(QMAKE_CFLAGS_DEBUG) 24 | QMAKE_CXXFLAGS_DEBUG = $$unique(QMAKE_CFLAGS_DEBUG) 25 | 26 | CONFIG(qt_static) { 27 | QMAKE_CFLAGS_DEBUG -= $$QMAKE_CFLAGS_MT_DLLDBG 28 | QMAKE_CFLAGS_DEBUG += $$QMAKE_CFLAGS_MT_DBG 29 | QMAKE_CXXFLAGS_DEBUG -= $$QMAKE_CFLAGS_MT_DLLDBG 30 | QMAKE_CXXFLAGS_DEBUG += $$QMAKE_CFLAGS_MT_DBG 31 | } else { 32 | QMAKE_CFLAGS_DEBUG -= $$QMAKE_CFLAGS_MT_DBG 33 | QMAKE_CFLAGS_DEBUG += $$QMAKE_CFLAGS_MT_DLLDBG 34 | QMAKE_CXXFLAGS_DEBUG -= $$QMAKE_CFLAGS_MT_DBG 35 | QMAKE_CXXFLAGS_DEBUG += $$QMAKE_CFLAGS_MT_DLLDBG 36 | } 37 | } else { 38 | DESTDIR = ../../../bin/release 39 | MOC_DIR += ./../../../tmp/release 40 | OBJECTS_DIR += ./../../../tmp/release 41 | INCLUDEPATH += ./../../../tmp/release 42 | 43 | QMAKE_CFLAGS_RELEASE = $$unique(QMAKE_CFLAGS_RELEASE) 44 | QMAKE_CXXFLAGS_RELEASE = $$unique(QMAKE_CXXFLAGS_RELEASE) 45 | 46 | CONFIG(qt_static) { 47 | QMAKE_CFLAGS_RELEASE -= $$QMAKE_CFLAGS_MT_DLL 48 | QMAKE_CFLAGS_RELEASE += $$QMAKE_CFLAGS_MT 49 | QMAKE_CXXFLAGS_RELEASE -= $$QMAKE_CFLAGS_MT_DLL 50 | QMAKE_CXXFLAGS_RELEASE += $$QMAKE_CFLAGS_MT 51 | } else { 52 | QMAKE_CFLAGS_RELEASE -= $$QMAKE_CFLAGS_MT 53 | QMAKE_CFLAGS_RELEASE += $$QMAKE_CFLAGS_MT_DLL 54 | QMAKE_CXXFLAGS_RELEASE -= $$QMAKE_CFLAGS_MT 55 | QMAKE_CXXFLAGS_RELEASE += $$QMAKE_CFLAGS_MT_DLL 56 | } 57 | } 58 | 59 | HEADERS += ../../../src/sokit/resource.h \ 60 | ../../../src/sokit/setting.h \ 61 | ../../../src/sokit/toolkit.h \ 62 | ../../../src/sokit/baseform.h \ 63 | ../../../src/sokit/clientform.h \ 64 | ../../../src/sokit/clientskt.h \ 65 | ../../../src/sokit/helpform.h \ 66 | ../../../src/sokit/logger.h \ 67 | ../../../src/sokit/main.h \ 68 | ../../../src/sokit/notepadform.h \ 69 | ../../../src/sokit/transferskt.h \ 70 | ../../../src/sokit/transferform.h \ 71 | ../../../src/sokit/serverskt.h \ 72 | ../../../src/sokit/serverform.h 73 | SOURCES += ../../../src/sokit/baseform.cpp \ 74 | ../../../src/sokit/clientform.cpp \ 75 | ../../../src/sokit/clientskt.cpp \ 76 | ../../../src/sokit/helpform.cpp \ 77 | ../../../src/sokit/logger.cpp \ 78 | ../../../src/sokit/main.cpp \ 79 | ../../../src/sokit/notepadform.cpp \ 80 | ../../../src/sokit/serverform.cpp \ 81 | ../../../src/sokit/serverskt.cpp \ 82 | ../../../src/sokit/setting.cpp \ 83 | ../../../src/sokit/toolkit.cpp \ 84 | ../../../src/sokit/transferform.cpp \ 85 | ../../../src/sokit/transferskt.cpp 86 | FORMS += ../../../src/sokit/clientform.ui \ 87 | ../../../src/sokit/helpform.ui \ 88 | ../../../src/sokit/serverform.ui \ 89 | ../../../src/sokit/transferform.ui 90 | TRANSLATIONS += ../../../src/sokit/sokit.ts 91 | RESOURCES += ../../../src/sokit/icons.qrc 92 | 93 | QMAKE_PRE_LINK = $$[QT_INSTALL_BINS]/lupdate $$PWD/sokit.pro 94 | QMAKE_POST_LINK = $$[QT_INSTALL_BINS]/lrelease ../../../src/sokit/sokit.ts -qm $$DESTDIR/sokit.lan 95 | 96 | win32 { 97 | RC_FILE = ../../../src/sokit/sokit.rc 98 | 99 | CONFIG(qt_static) { 100 | exists( $(QTDIR)/lib_s ) { 101 | QMAKE_LIBDIR_QT = $(QTDIR)/lib_s 102 | } 103 | } else { 104 | exists( $(QTDIR)/lib_d ) { 105 | QMAKE_LIBDIR_QT = $(QTDIR)/lib_d 106 | } 107 | } 108 | } 109 | 110 | OTHER_FILES += \ 111 | ../../../src/sokit/sokit.ts \ 112 | ../../../LICENSE \ 113 | ../../../README.md 114 | 115 | -------------------------------------------------------------------------------- /doc/sokit/change.log: -------------------------------------------------------------------------------- 1 | 2015-05-07 sinpowei 2 | version 1.3.1 3 | build with QT v5.3.2 4 | 5 | Source code repository migrated from Google Code to GitHub 6 | 7 | 2011-11-30 sinpowei 8 | version 1.3 9 | build with QT v4.7.2 10 | 11 | fixed: reset receive & send counter when clear output window 12 | 13 | 2011-09-21 sinpowei 14 | version 1.2 15 | build with QT v4.7.2 16 | 17 | add linux version 18 | UI adjustment for linux desktop 19 | few small bug fixed 20 | 21 | 2010-11-17 sinpowei 22 | first release version 1.0 23 | build with QT v4.7.1 24 | 25 | -------------------------------------------------------------------------------- /doc/sokit/readme.txt: -------------------------------------------------------------------------------- 1 | sokit.lan is language file, if rename or delete it, then use default english UI 2 | 3 | F1 for more help or go https://github.com/sinpolib/sokit/ for sourcecode 4 | -------------------------------------------------------------------------------- /src/sokit/baseform.cpp: -------------------------------------------------------------------------------- 1 | #include "toolkit.h" 2 | #include "setting.h" 3 | #include "baseform.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define PROP_EDIT "edit" 16 | #define PROP_DIRT "dirt" 17 | #define PROP_TARG "targ" 18 | 19 | BaseForm::BaseForm(QWidget* p, Qt::WindowFlags f) 20 | :QWidget(p, f),m_cntRecv(0),m_cntSend(0),m_labRecv(0),m_labSend(0),m_cnlist(0) 21 | { 22 | } 23 | 24 | BaseForm::~BaseForm() 25 | { 26 | } 27 | 28 | bool BaseForm::init() 29 | { 30 | if (!initForm() || !initHotkeys()) 31 | return false; 32 | 33 | initConfig(); 34 | 35 | m_logger.setProperty(SET_SEC_DIR, property(SET_SEC_DIR).toString()); 36 | 37 | return true; 38 | } 39 | 40 | void BaseForm::initCounter(QLabel* r, QLabel* s) 41 | { 42 | m_labRecv = r; 43 | m_labSend = s; 44 | } 45 | 46 | void BaseForm::initLogger(QCheckBox* w, QToolButton* c, QTreeWidget* o, QPlainTextEdit* d) 47 | { 48 | m_logger.init(o, w, d); 49 | 50 | connect(c, SIGNAL(released()), this, SLOT(clear())); 51 | connect(&m_logger, SIGNAL(clearLog()), this, SLOT(clear())); 52 | 53 | bindFocus(o, Qt::Key_F3); 54 | 55 | QShortcut* wr = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_W), this); 56 | QShortcut* cl = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_D), this); 57 | QShortcut* sl = new QShortcut(QKeySequence(Qt::Key_F4), this); 58 | 59 | sl->setProperty(PROP_TARG, qVariantFromValue((void*)d)); 60 | 61 | connect(wr, SIGNAL(activated()), w, SLOT(click())); 62 | connect(sl, SIGNAL(activated()), this, SLOT(hotOutput())); 63 | connect(cl, SIGNAL(activated()), this, SLOT(clear())); 64 | 65 | connect(this, SIGNAL(output(const QString&)), &m_logger, SLOT(output(const QString&))); 66 | connect(this, SIGNAL(output(const QString&, const char*, quint32)), &m_logger, SLOT(output(const QString&, const char*, quint32))); 67 | } 68 | 69 | void BaseForm::initLister(QToolButton* a, QToolButton* k, QListWidget* l) 70 | { 71 | m_cnlist = l; 72 | 73 | QShortcut* sk = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_K), this); 74 | QShortcut* sa = new QShortcut(QKeySequence(Qt::ALT + Qt::Key_A), this); 75 | 76 | connect(sk, SIGNAL(activated()), this, SLOT(kill())); 77 | connect(sa, SIGNAL(activated()), m_cnlist, SLOT(selectAll())); 78 | 79 | connect(k, SIGNAL(released()), this, SLOT(kill())); 80 | connect(a, SIGNAL(released()), m_cnlist, SLOT(selectAll())); 81 | 82 | bindFocus(m_cnlist, Qt::Key_F2); 83 | } 84 | 85 | void BaseForm::bindBuffer(qint32 id, QLineEdit* e, QToolButton* s, QComboBox* d) 86 | { 87 | s->setProperty(PROP_EDIT, qVariantFromValue((void*)e)); 88 | s->setProperty(PROP_DIRT, qVariantFromValue((void*)d)); 89 | 90 | connect(s, SIGNAL(released()), this, SLOT(send())); 91 | 92 | bindClick(s, Qt::Key_0 + id + Qt::CTRL); 93 | bindFocus(e, Qt::Key_0 + id + Qt::ALT); 94 | bindFocus(d, Qt::Key_0 + id + Qt::CTRL + Qt::SHIFT); 95 | } 96 | 97 | void BaseForm::bindFocus(QWidget* w, qint32 k) 98 | { 99 | QShortcut* s = new QShortcut(QKeySequence(k), this); 100 | s->setProperty(PROP_TARG, qVariantFromValue((void*)w)); 101 | connect(s, SIGNAL(activated()), this, SLOT(focus())); 102 | } 103 | 104 | void BaseForm::bindClick(QAbstractButton* b, qint32 k) 105 | { 106 | QShortcut* s = new QShortcut(QKeySequence(k), this); 107 | connect(s, SIGNAL(activated()), b, SLOT(click())); 108 | } 109 | 110 | void BaseForm::bindSelect(QComboBox* b, qint32 i, qint32 k) 111 | { 112 | QShortcut* s = new QShortcut(QKeySequence(k), this); 113 | s->setProperty(PROP_TARG, qVariantFromValue((void*)b)); 114 | s->setObjectName(QString::number(i)); 115 | 116 | connect(s, SIGNAL(activated()), this, SLOT(select())); 117 | } 118 | 119 | void BaseForm::focus() 120 | { 121 | QWidget* w = (QWidget*)sender()->property(PROP_TARG).value(); 122 | if (w) w->setFocus(Qt::TabFocusReason); 123 | } 124 | 125 | void BaseForm::hotOutput() 126 | { 127 | QPlainTextEdit* t = (QPlainTextEdit*)sender()->property(PROP_TARG).value(); 128 | if (t) 129 | { 130 | t->setFocus(Qt::TabFocusReason); 131 | t->selectAll(); 132 | } 133 | } 134 | 135 | void BaseForm::select() 136 | { 137 | QComboBox* b = (QComboBox*)sender()->property(PROP_TARG).value(); 138 | if (b && b->isEnabled()) 139 | { 140 | qint32 i = sender()->objectName().toInt(); 141 | if (i < 0) 142 | { 143 | i = b->currentIndex() + 1; 144 | if (i >= b->count()) i = 0; 145 | } 146 | 147 | b->setCurrentIndex(i); 148 | } 149 | } 150 | 151 | void BaseForm::countRecv(qint32 bytes) 152 | { 153 | if (bytes < 0) 154 | m_cntRecv = 0; 155 | else 156 | m_cntRecv += bytes; 157 | 158 | m_labRecv->setText(QString::number(m_cntRecv)); 159 | } 160 | 161 | void BaseForm::countSend(qint32 bytes) 162 | { 163 | if (bytes < 0) 164 | m_cntSend = 0; 165 | else 166 | m_cntSend += bytes; 167 | 168 | m_labSend->setText(QString::number(m_cntSend)); 169 | } 170 | 171 | void BaseForm::send() 172 | { 173 | QLineEdit* e = (QLineEdit*)sender()->property(PROP_EDIT).value(); 174 | QComboBox* d = (QComboBox*)sender()->property(PROP_DIRT).value(); 175 | if (e) 176 | send(e->text(), (d?d->currentText():"")); 177 | } 178 | 179 | void BaseForm::clear() 180 | { 181 | m_logger.clear(); 182 | 183 | lock(); 184 | countRecv(-1); 185 | countSend(-1); 186 | unlock(); 187 | } 188 | 189 | void BaseForm::kill() 190 | { 191 | if (lock(1000)) 192 | { 193 | QStringList list; 194 | 195 | listerSelected(list); 196 | kill(list); 197 | 198 | unlock(); 199 | } 200 | } 201 | 202 | void BaseForm::listerSelected(QStringList& output) 203 | { 204 | qint32 i = m_cnlist->count(); 205 | while (i--) 206 | { 207 | QListWidgetItem* itm = m_cnlist->item(i); 208 | if (itm && itm->isSelected()) 209 | output << itm->text(); 210 | } 211 | } 212 | 213 | void BaseForm::listerAdd(const QString& caption) 214 | { 215 | listerRemove(caption); 216 | m_cnlist->addItem(caption); 217 | } 218 | 219 | void BaseForm::listerRemove(const QString& caption) 220 | { 221 | qint32 i = m_cnlist->count(); 222 | while (i--) 223 | { 224 | QListWidgetItem* itm = m_cnlist->item(i); 225 | if (itm && itm->text()==caption) 226 | delete m_cnlist->takeItem(i); 227 | } 228 | } 229 | 230 | -------------------------------------------------------------------------------- /src/sokit/baseform.h: -------------------------------------------------------------------------------- 1 | #ifndef __BASEFORM_H__ 2 | #define __BASEFORM_H__ 3 | 4 | #include 5 | #include "logger.h" 6 | #include 7 | #include 8 | 9 | class QLabel; 10 | class QListWidget; 11 | class BaseForm : public QWidget 12 | { 13 | Q_OBJECT 14 | 15 | public: 16 | BaseForm(QWidget* p=0, Qt::WindowFlags f=0); 17 | virtual ~BaseForm(); 18 | 19 | bool init(); 20 | 21 | protected: 22 | bool lock() { m_door.lock(); return true; }; 23 | bool lock(qint32 w) { return m_door.tryLock(w); }; 24 | void unlock() { m_door.unlock(); }; 25 | 26 | void initCounter(QLabel* r, QLabel* s); 27 | void initLogger(QCheckBox* w, QToolButton* c, QTreeWidget* o, QPlainTextEdit* d); 28 | void initLister(QToolButton* a, QToolButton* k, QListWidget* l); 29 | void bindBuffer(qint32 id, QLineEdit* e, QToolButton* s, QComboBox* d); 30 | void bindFocus(QWidget* w, qint32 k); 31 | void bindClick(QAbstractButton* b, qint32 k); 32 | void bindSelect(QComboBox* b, qint32 i, qint32 k); 33 | 34 | void listerSelected(QStringList& output); 35 | 36 | virtual bool initForm() =0; 37 | virtual bool initHotkeys() =0; 38 | virtual void initConfig() =0; 39 | virtual void saveConfig() =0; 40 | virtual void kill(QStringList& /*list*/) {}; 41 | virtual void send(const QString& data, const QString& dir) =0; 42 | 43 | signals: 44 | void output(const QString& info); 45 | void output(const QString& title, const char* buf, quint32 len); 46 | 47 | protected slots: 48 | void send(); 49 | void kill(); 50 | void clear(); 51 | void focus(); 52 | void select(); 53 | void hotOutput(); 54 | 55 | void countRecv(qint32 bytes); 56 | void countSend(qint32 bytes); 57 | 58 | void listerAdd(const QString& caption); 59 | void listerRemove(const QString& caption); 60 | 61 | private: 62 | QMutex m_door; 63 | Logger m_logger; 64 | 65 | quint32 m_cntRecv; 66 | quint32 m_cntSend; 67 | 68 | QLabel* m_labRecv; 69 | QLabel* m_labSend; 70 | 71 | QListWidget* m_cnlist; 72 | }; 73 | 74 | #endif // __BASEFORM_H__ 75 | 76 | 77 | -------------------------------------------------------------------------------- /src/sokit/clientform.cpp: -------------------------------------------------------------------------------- 1 | #include "toolkit.h" 2 | #include "setting.h" 3 | #include "clientskt.h" 4 | #include "clientform.h" 5 | 6 | #define SET_SEC_CLT "client" 7 | #define SET_KEY_CLT "/client" 8 | 9 | #define SET_KEY_CMBIP "/ip" 10 | #define SET_KEY_CMBPT "/port" 11 | 12 | #define SET_VAL_LGCLT "log_client" 13 | 14 | ClientForm::ClientForm(QWidget* p, Qt::WindowFlags f) 15 | :BaseForm(p, f),m_client(0) 16 | { 17 | m_ui.setupUi(this); 18 | } 19 | 20 | ClientForm::~ClientForm() 21 | { 22 | unplug(); 23 | saveConfig(); 24 | } 25 | 26 | bool ClientForm::initForm() 27 | { 28 | initCounter(m_ui.labRecv, m_ui.labSend); 29 | initLogger(m_ui.chkLog, m_ui.btnClear, m_ui.treeOutput, m_ui.txtOutput); 30 | 31 | bindBuffer(0, m_ui.edtBuf0, m_ui.btnSend0, 0); 32 | bindBuffer(1, m_ui.edtBuf1, m_ui.btnSend1, 0); 33 | bindBuffer(2, m_ui.edtBuf2, m_ui.btnSend2, 0); 34 | bindBuffer(3, m_ui.edtBuf3, m_ui.btnSend3, 0); 35 | 36 | connect(m_ui.btnTcp, SIGNAL(clicked(bool)), this, SLOT(trigger(bool))); 37 | connect(m_ui.btnUdp, SIGNAL(clicked(bool)), this, SLOT(trigger(bool))); 38 | 39 | return true; 40 | } 41 | 42 | void ClientForm::initConfig() 43 | { 44 | QString ssc(SET_SEC_CLT); 45 | Setting::load(ssc+SET_KEY_CMBIP, SET_PFX_CMBITM, *m_ui.cmbAddr); 46 | Setting::load(ssc+SET_KEY_CMBPT, SET_PFX_CMBITM, *m_ui.cmbPort); 47 | if (m_ui.cmbPort->currentText().length() <= 0) { 48 | const quint16 FailSafeDefaultPort = 8080; 49 | m_ui.cmbPort->setEditText(QString::number(FailSafeDefaultPort)); 50 | } 51 | 52 | QString skl(SET_SEC_DIR); skl += SET_KEY_LOG; 53 | skl = Setting::get(skl, SET_KEY_CLT, SET_VAL_LGCLT); 54 | setProperty(SET_SEC_DIR, skl); 55 | 56 | TK::initNetworkInterfaces(m_ui.cmbAddr); 57 | } 58 | 59 | void ClientForm::saveConfig() 60 | { 61 | QString ssc(SET_SEC_CLT); 62 | Setting::save(ssc+SET_KEY_CMBIP, SET_PFX_CMBITM, *m_ui.cmbAddr); 63 | Setting::save(ssc+SET_KEY_CMBPT, SET_PFX_CMBITM, *m_ui.cmbPort); 64 | 65 | QString skl(SET_SEC_DIR); skl += SET_KEY_LOG; 66 | Setting::set(skl, SET_KEY_CLT, property(SET_SEC_DIR).toString()); 67 | } 68 | 69 | bool ClientForm::initHotkeys() 70 | { 71 | bindFocus(m_ui.cmbAddr, Qt::Key_Escape); 72 | bindClick(m_ui.btnTcp, Qt::CTRL + Qt::Key_T); 73 | bindClick(m_ui.btnUdp, Qt::CTRL + Qt::Key_U); 74 | return true; 75 | } 76 | 77 | void ClientForm::unplug() 78 | { 79 | ClientSkt* client = 0; 80 | 81 | if (lock()) 82 | { 83 | client = m_client; 84 | m_client = NULL; 85 | unlock(); 86 | } 87 | 88 | if (client) 89 | client->unplug(); 90 | } 91 | 92 | void ClientForm::unpluged() 93 | { 94 | ClientSkt* c = qobject_cast(sender()); 95 | if (!c) return; 96 | 97 | if (lock()) 98 | { 99 | if (c==m_client) 100 | m_client = NULL; 101 | 102 | unlock(); 103 | } 104 | 105 | if (c->name().contains(TK::socketTypeName(true))) 106 | TK::resetPushBox(m_ui.btnTcp); 107 | else 108 | TK::resetPushBox(m_ui.btnUdp); 109 | 110 | c->disconnect(this); 111 | c->deleteLater(); 112 | } 113 | 114 | void ClientForm::trigger(bool checked) 115 | { 116 | unplug(); 117 | 118 | m_ui.cmbAddr->setDisabled(checked); 119 | m_ui.cmbPort->setDisabled(checked); 120 | 121 | QToolButton* btn = qobject_cast(sender()); 122 | if (checked && !plug(btn==m_ui.btnTcp)) 123 | btn->click(); 124 | } 125 | 126 | bool ClientForm::plug(bool istcp) 127 | { 128 | ClientSkt* skt = 0; 129 | 130 | lock(); 131 | 132 | if (m_client) 133 | { 134 | m_client->disconnect(this); 135 | m_client->deleteLater(); 136 | m_client = NULL; 137 | } 138 | 139 | IPAddr addr; 140 | bool res = TK::popIPAddr(m_ui.cmbAddr, m_ui.cmbPort, addr); 141 | 142 | if (res) 143 | { 144 | if (istcp) 145 | m_client = new ClientSktTcp(); 146 | else 147 | m_client = new ClientSktUdp(); 148 | 149 | if (!m_client) 150 | { 151 | res = false; 152 | } 153 | else 154 | { 155 | connect(m_client, SIGNAL(unpluged()), this, SLOT(unpluged())); 156 | connect(m_client, SIGNAL(message(const QString&)), this, SIGNAL(output(const QString&))); 157 | connect(m_client, SIGNAL(dumpbin(const QString&,const char*,quint32)), this, SIGNAL(output(const QString&,const char*,quint32))); 158 | connect(m_client, SIGNAL(countRecv(qint32)), this, SLOT(countRecv(qint32))); 159 | connect(m_client, SIGNAL(countSend(qint32)), this, SLOT(countSend(qint32))); 160 | 161 | skt = m_client; 162 | } 163 | } 164 | 165 | unlock(); 166 | 167 | if (res && skt) 168 | { 169 | res = skt->plug(addr.ip, addr.port); 170 | 171 | if (res) 172 | TK::pushIPAddr(m_ui.cmbAddr, m_ui.cmbPort); 173 | } 174 | 175 | return res; 176 | } 177 | 178 | void ClientForm::send(const QString& data, const QString&) 179 | { 180 | if (m_client && lock(1000)) 181 | { 182 | m_client->send(data); 183 | unlock(); 184 | } 185 | } 186 | 187 | 188 | -------------------------------------------------------------------------------- /src/sokit/clientform.h: -------------------------------------------------------------------------------- 1 | #ifndef __CLIENTFORM_H__ 2 | #define __CLIENTFORM_H__ 3 | 4 | #include "ui_clientform.h" 5 | #include "baseform.h" 6 | 7 | class ClientSkt; 8 | class ClientForm : public BaseForm 9 | { 10 | Q_OBJECT 11 | 12 | public: 13 | ClientForm(QWidget* p=0, Qt::WindowFlags f=0); 14 | virtual ~ClientForm(); 15 | 16 | protected: 17 | virtual bool initForm(); 18 | virtual bool initHotkeys(); 19 | virtual void initConfig(); 20 | virtual void saveConfig(); 21 | virtual void send(const QString& data, const QString& dir); 22 | 23 | private: 24 | bool plug(bool istcp); 25 | void unplug(); 26 | 27 | private slots: 28 | void trigger(bool checked); 29 | void unpluged(); 30 | 31 | private: 32 | ClientSkt* m_client; 33 | Ui::ClientForm m_ui; 34 | }; 35 | 36 | #endif // __CLIENTFORM_H__ 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/sokit/clientform.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | ClientForm 4 | 5 | 6 | 7 | 0 8 | 0 9 | 680 10 | 450 11 | 12 | 13 | 14 | 15 | 0 16 | 0 17 | 18 | 19 | 20 | Client 21 | 22 | 23 | 24 | 25 | 26 | 27 | 5 28 | 29 | 30 | 5 31 | 32 | 33 | 34 | 35 | 36 | 0 37 | 0 38 | 39 | 40 | 41 | 42 | 0 43 | 59 44 | 45 | 46 | 47 | 48 | 16777215 49 | 59 50 | 51 | 52 | 53 | Network Setup 54 | 55 | 56 | 57 | 5 58 | 59 | 60 | 5 61 | 62 | 63 | 0 64 | 65 | 66 | 5 67 | 68 | 69 | 2 70 | 71 | 72 | 73 | 74 | 75 | 0 76 | 0 77 | 78 | 79 | 80 | 81 | 0 82 | 24 83 | 84 | 85 | 86 | 87 | 16777215 88 | 24 89 | 90 | 91 | 92 | Qt::NoContextMenu 93 | 94 | 95 | Server IP: 96 | 97 | 98 | Qt::PlainText 99 | 100 | 101 | false 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 0 110 | 0 111 | 112 | 113 | 114 | 115 | 130 116 | 24 117 | 118 | 119 | 120 | 121 | 130 122 | 24 123 | 124 | 125 | 126 | true 127 | 128 | 129 | QComboBox::NoInsert 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 0 138 | 0 139 | 140 | 141 | 142 | 143 | 0 144 | 24 145 | 146 | 147 | 148 | 149 | 16777215 150 | 24 151 | 152 | 153 | 154 | Port: 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 0 163 | 0 164 | 165 | 166 | 167 | 168 | 75 169 | 24 170 | 171 | 172 | 173 | 174 | 75 175 | 24 176 | 177 | 178 | 179 | true 180 | 181 | 182 | QComboBox::InsertAtTop 183 | 184 | 185 | 186 | 187 | 188 | 189 | Qt::Horizontal 190 | 191 | 192 | QSizePolicy::Fixed 193 | 194 | 195 | 196 | 10 197 | 0 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 0 207 | 0 208 | 209 | 210 | 211 | 212 | 100 213 | 24 214 | 215 | 216 | 217 | 218 | 100 219 | 24 220 | 221 | 222 | 223 | 224 | 225 | 226 | TCP Connect 227 | 228 | 229 | true 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 0 238 | 0 239 | 240 | 241 | 242 | 243 | 100 244 | 24 245 | 246 | 247 | 248 | 249 | 100 250 | 24 251 | 252 | 253 | 254 | 255 | 256 | 257 | UDP Channel 258 | 259 | 260 | true 261 | 262 | 263 | 264 | 265 | 266 | 267 | Qt::Horizontal 268 | 269 | 270 | 271 | 0 272 | 0 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 10 284 | 285 | 286 | 5 287 | 288 | 289 | 290 | 291 | Buf 0: 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 60 300 | 24 301 | 302 | 303 | 304 | 305 | 60 306 | 24 307 | 308 | 309 | 310 | Send 311 | 312 | 313 | 314 | 315 | 316 | 317 | Buf 1: 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 60 326 | 24 327 | 328 | 329 | 330 | 331 | 60 332 | 24 333 | 334 | 335 | 336 | Send 337 | 338 | 339 | 340 | 341 | 342 | 343 | Buf 2: 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 0 352 | 24 353 | 354 | 355 | 356 | 357 | 16777215 358 | 24 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 60 368 | 24 369 | 370 | 371 | 372 | 373 | 60 374 | 24 375 | 376 | 377 | 378 | Send 379 | 380 | 381 | 382 | 383 | 384 | 385 | Buf 3: 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 0 394 | 24 395 | 396 | 397 | 398 | 399 | 16777215 400 | 24 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 60 410 | 24 411 | 412 | 413 | 414 | 415 | 60 416 | 24 417 | 418 | 419 | 420 | Send 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 0 429 | 24 430 | 431 | 432 | 433 | 434 | 16777215 435 | 24 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 0 445 | 24 446 | 447 | 448 | 449 | 450 | 16777215 451 | 24 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 5 462 | 463 | 464 | 0 465 | 466 | 467 | 5 468 | 469 | 470 | 0 471 | 472 | 473 | 0 474 | 475 | 476 | 477 | 478 | Output: 479 | 480 | 481 | 482 | 483 | 484 | 485 | Recv 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 0 494 | 0 495 | 496 | 497 | 498 | 499 | 500 | 501 | 0 502 | 503 | 504 | 505 | 506 | 507 | 508 | , Send 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 0 519 | 520 | 521 | 522 | 523 | 524 | 525 | Qt::Horizontal 526 | 527 | 528 | 529 | 0 530 | 0 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | Write log 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 60 547 | 24 548 | 549 | 550 | 551 | 552 | 60 553 | 24 554 | 555 | 556 | 557 | Clear 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | Qt::ScrollBarAlwaysOff 567 | 568 | 569 | QAbstractItemView::NoEditTriggers 570 | 571 | 572 | false 573 | 574 | 575 | false 576 | 577 | 578 | QAbstractItemView::SingleSelection 579 | 580 | 581 | QAbstractItemView::SelectRows 582 | 583 | 584 | true 585 | 586 | 587 | false 588 | 589 | 590 | true 591 | 592 | 593 | 594 | 1 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 0 604 | 0 605 | 606 | 607 | 608 | 609 | 0 610 | 70 611 | 612 | 613 | 614 | 615 | 16777215 616 | 70 617 | 618 | 619 | 620 | false 621 | 622 | 623 | QFrame::Box 624 | 625 | 626 | QFrame::Plain 627 | 628 | 629 | Qt::ScrollBarAlwaysOff 630 | 631 | 632 | true 633 | 634 | 635 | false 636 | 637 | 638 | true 639 | 640 | 641 | Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse 642 | 643 | 644 | 645 | 646 | 647 | 648 | cmbAddr 649 | cmbPort 650 | btnTcp 651 | btnUdp 652 | edtBuf0 653 | btnSend0 654 | edtBuf1 655 | btnSend1 656 | edtBuf2 657 | btnSend2 658 | edtBuf3 659 | btnSend3 660 | chkLog 661 | btnClear 662 | treeOutput 663 | 664 | 665 | 666 | 667 | -------------------------------------------------------------------------------- /src/sokit/clientskt.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "toolkit.h" 3 | #include "clientskt.h" 4 | 5 | #define MAXBUFFER 1024*1024 6 | 7 | ClientSkt::ClientSkt(QObject *parent) 8 | : QObject(parent),m_port(0) 9 | { 10 | } 11 | 12 | ClientSkt::~ClientSkt() 13 | { 14 | } 15 | 16 | bool ClientSkt::plug(const QHostAddress& ip, quint16 port) 17 | { 18 | m_ip = ip; 19 | m_port = port; 20 | 21 | m_error.clear(); 22 | 23 | return open(); 24 | } 25 | 26 | void ClientSkt::unplug() 27 | { 28 | close(); 29 | 30 | emit unpluged(); 31 | } 32 | 33 | void ClientSkt::setError(const QString& err) 34 | { 35 | m_error = err; 36 | } 37 | 38 | void ClientSkt::recordRecv(qint32 bytes) 39 | { 40 | emit countRecv(bytes); 41 | } 42 | 43 | void ClientSkt::recordSend(qint32 bytes) 44 | { 45 | emit countSend(bytes); 46 | } 47 | 48 | void ClientSkt::send(const QString& data) 49 | { 50 | QString err; 51 | QByteArray bin; 52 | 53 | if (!TK::ascii2bin(data, bin, err)) 54 | { 55 | show("bad data format to send: "+err); 56 | return; 57 | } 58 | 59 | send(bin); 60 | } 61 | 62 | void ClientSkt::dump(const char* buf, qint32 len, bool isSend) 63 | { 64 | emit dumpbin(QString("DAT %1").arg(isSend?"<---":"--->"), buf, (quint32)len); 65 | } 66 | 67 | void ClientSkt::show(const QString& msg) 68 | { 69 | emit message(msg); 70 | } 71 | 72 | ClientSktTcp::ClientSktTcp(QObject *parent) 73 | :ClientSkt(parent) 74 | { 75 | } 76 | 77 | ClientSktTcp::~ClientSktTcp() 78 | { 79 | } 80 | 81 | bool ClientSktTcp::open() 82 | { 83 | connect(&m_socket, SIGNAL(readyRead()), this, SLOT(newData())); 84 | connect(&m_socket, SIGNAL(disconnected()), this, SLOT(closed())); 85 | connect(&m_socket, SIGNAL(connected()), this, SLOT(asynConn())); 86 | connect(&m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error())); 87 | 88 | m_socket.connectToHost(addr(), port()); 89 | 90 | return true; 91 | } 92 | 93 | void ClientSktTcp::close() 94 | { 95 | m_socket.close(); 96 | m_socket.disconnect(this); 97 | } 98 | 99 | void ClientSktTcp::error() 100 | { 101 | QTcpSocket* s = qobject_cast(sender()); 102 | 103 | show(QString("TCP socket error %1, %2").arg(s->error()).arg(s->errorString())); 104 | 105 | unplug(); 106 | } 107 | 108 | void ClientSktTcp::asynConn() 109 | { 110 | show(QString("TCP connection to %1:%2 opened!") 111 | .arg(addr().toString()).arg(port())); 112 | } 113 | 114 | void ClientSktTcp::closed() 115 | { 116 | show(QString("TCP connection closed!")); 117 | } 118 | 119 | void ClientSktTcp::newData() 120 | { 121 | QTcpSocket* s = qobject_cast(sender()); 122 | if (!s) return; 123 | 124 | qint64 bufLen = s->bytesAvailable(); 125 | char* buf = TK::createBuffer(bufLen, MAXBUFFER); 126 | if (!buf) return; 127 | 128 | qint64 readLen = 0; 129 | qint64 ioLen = s->read(buf, bufLen); 130 | 131 | while (ioLen > 0) 132 | { 133 | readLen += ioLen; 134 | ioLen = s->read(buf+readLen, bufLen-readLen); 135 | } 136 | 137 | if (ioLen >= 0) 138 | { 139 | recordRecv(readLen); 140 | dump(buf, readLen, false); 141 | } 142 | 143 | TK::releaseBuffer(buf); 144 | } 145 | 146 | void ClientSktTcp::send(const QByteArray& bin) 147 | { 148 | const char * src = bin.constData(); 149 | qint64 srcLen = bin.length(); 150 | 151 | qint64 writeLen = 0; 152 | qint64 ioLen = m_socket.write(src, srcLen); 153 | 154 | while (ioLen > 0) 155 | { 156 | writeLen += ioLen; 157 | ioLen = m_socket.write(src+writeLen, srcLen-writeLen); 158 | } 159 | 160 | if (writeLen != srcLen) 161 | { 162 | show(QString("failed to send data to %1:%2 [%3]") 163 | .arg(addr().toString()).arg(port()).arg(writeLen)); 164 | return; 165 | } 166 | 167 | recordSend(writeLen); 168 | dump(src, srcLen, true); 169 | } 170 | 171 | ClientSktUdp::ClientSktUdp(QObject *parent) 172 | :ClientSkt(parent) 173 | { 174 | } 175 | 176 | ClientSktUdp::~ClientSktUdp() 177 | { 178 | } 179 | 180 | void ClientSktUdp::asynConn() 181 | { 182 | show(QString("UDP channel to %1:%2 opened!") 183 | .arg(addr().toString()).arg(port())); 184 | } 185 | 186 | void ClientSktUdp::closed() 187 | { 188 | show(QString("UDP channel closed!")); 189 | } 190 | 191 | void ClientSktUdp::close() 192 | { 193 | m_socket.close(); 194 | m_socket.disconnect(this); 195 | } 196 | 197 | void ClientSktUdp::error() 198 | { 199 | QUdpSocket* s = qobject_cast(sender()); 200 | 201 | show(QString("UDP socket error %1, %2").arg(s->error()).arg(s->errorString())); 202 | 203 | unplug(); 204 | } 205 | 206 | bool ClientSktUdp::open() 207 | { 208 | connect(&m_socket, SIGNAL(readyRead()), this, SLOT(newData())); 209 | connect(&m_socket, SIGNAL(disconnected()), this, SLOT(closed())); 210 | connect(&m_socket, SIGNAL(connected()), this, SLOT(asynConn())); 211 | connect(&m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error())); 212 | 213 | m_socket.connectToHost(addr(), port()); 214 | 215 | return true; 216 | } 217 | 218 | void ClientSktUdp::newData() 219 | { 220 | QUdpSocket* s = qobject_cast(sender()); 221 | if (!s) return; 222 | 223 | qint64 bufLen = s->bytesAvailable(); 224 | char* buf = TK::createBuffer(bufLen, MAXBUFFER); 225 | if (!buf) return; 226 | 227 | qint64 readLen = 0; 228 | qint64 ioLen = s->read(buf, bufLen); 229 | 230 | while (ioLen > 0) 231 | { 232 | readLen += ioLen; 233 | ioLen = s->read(buf+readLen, bufLen-readLen); 234 | } 235 | 236 | if (ioLen >= 0) 237 | { 238 | recordRecv(readLen); 239 | dump(buf, readLen, false); 240 | } 241 | 242 | TK::releaseBuffer(buf); 243 | } 244 | 245 | void ClientSktUdp::send(const QByteArray& bin) 246 | { 247 | const char * src = bin.constData(); 248 | qint64 srcLen = bin.length(); 249 | 250 | qint64 writeLen = 0; 251 | qint64 ioLen = m_socket.write(src, srcLen); 252 | 253 | while (ioLen > 0) 254 | { 255 | writeLen += ioLen; 256 | ioLen = (writeLen >= srcLen) ? 0 : 257 | m_socket.write(src+writeLen, srcLen-writeLen); 258 | } 259 | 260 | if (writeLen != srcLen) 261 | { 262 | show(QString("failed to send data to %1:%2 [%3]") 263 | .arg(addr().toString()).arg(port()).arg(writeLen)); 264 | return; 265 | } 266 | 267 | recordSend(writeLen); 268 | dump(src, srcLen, true); 269 | } 270 | 271 | -------------------------------------------------------------------------------- /src/sokit/clientskt.h: -------------------------------------------------------------------------------- 1 | #ifndef __CLIENTSKT_H__ 2 | #define __CLIENTSKT_H__ 3 | 4 | #include 5 | #include 6 | 7 | class ClientSkt : public QObject 8 | { 9 | Q_OBJECT 10 | 11 | public: 12 | ClientSkt(QObject *parent=0); 13 | virtual ~ClientSkt(); 14 | 15 | virtual QString name() const { return "General"; }; 16 | 17 | bool plug(const QHostAddress& ip, quint16 port); 18 | void unplug(); 19 | void send(const QString& data); 20 | 21 | const QHostAddress& addr() const { return m_ip; }; 22 | quint16 port() const { return m_port; }; 23 | 24 | signals: 25 | void unpluged(); 26 | 27 | void message(const QString& msg); 28 | void dumpbin(const QString& title, const char* data, quint32 len); 29 | 30 | void countRecv(qint32 bytes); 31 | void countSend(qint32 bytes); 32 | 33 | protected: 34 | void dump(const char* buf, qint32 len, bool isSend); 35 | void show(const QString& msg); 36 | void setError(const QString& err); 37 | 38 | void recordRecv(qint32 bytes); 39 | void recordSend(qint32 bytes); 40 | 41 | virtual bool open() =0; 42 | virtual void close() =0; 43 | virtual void send(const QByteArray& data) =0; 44 | 45 | private: 46 | QHostAddress m_ip; 47 | quint16 m_port; 48 | 49 | QString m_error; 50 | }; 51 | 52 | class ClientSktTcp : public ClientSkt 53 | { 54 | Q_OBJECT 55 | 56 | public: 57 | ClientSktTcp(QObject *parent=0); 58 | ~ClientSktTcp(); 59 | 60 | virtual QString name() const { return "TCP"; }; 61 | 62 | protected: 63 | virtual bool open(); 64 | virtual void close(); 65 | virtual void send(const QByteArray& bin); 66 | 67 | private slots: 68 | void asynConn(); 69 | void newData(); 70 | void closed(); 71 | void error(); 72 | 73 | private: 74 | QTcpSocket m_socket; 75 | }; 76 | 77 | class ClientSktUdp : public ClientSkt 78 | { 79 | Q_OBJECT 80 | 81 | public: 82 | ClientSktUdp(QObject *parent=0); 83 | ~ClientSktUdp(); 84 | 85 | virtual QString name() const { return "UDP"; }; 86 | 87 | protected: 88 | virtual bool open(); 89 | virtual void close(); 90 | virtual void send(const QByteArray& bin); 91 | 92 | private slots: 93 | void asynConn(); 94 | void newData(); 95 | void closed(); 96 | void error(); 97 | 98 | private: 99 | QUdpSocket m_socket; 100 | }; 101 | 102 | #endif // __CLIENTSKT_H__ 103 | 104 | -------------------------------------------------------------------------------- /src/sokit/helpform.cpp: -------------------------------------------------------------------------------- 1 | #include "toolkit.h" 2 | #include "setting.h" 3 | #include "helpform.h" 4 | 5 | #include 6 | #include 7 | 8 | HelpForm::HelpForm(QWidget* p, Qt::WindowFlags f):QDialog(p, f) 9 | { 10 | m_ui.setupUi(this); 11 | init(); 12 | } 13 | 14 | HelpForm::~HelpForm() 15 | { 16 | } 17 | 18 | void HelpForm::init() 19 | { 20 | QShortcut* k = new QShortcut(QKeySequence(Qt::Key_F1), this); 21 | connect(k, SIGNAL(activated()), this, SLOT(close())); 22 | 23 | } 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/sokit/helpform.h: -------------------------------------------------------------------------------- 1 | #ifndef __HELPFORM_H__ 2 | #define __HELPFORM_H__ 3 | 4 | #include "ui_helpform.h" 5 | 6 | class HelpForm : public QDialog 7 | { 8 | Q_OBJECT 9 | 10 | public: 11 | HelpForm(QWidget* p=0, Qt::WindowFlags f=0); 12 | virtual ~HelpForm(); 13 | 14 | private: 15 | void init(); 16 | 17 | private: 18 | Ui::HelpForm m_ui; 19 | }; 20 | 21 | #endif // __HELPFORM_H__ 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/sokit/helpform.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | HelpForm 4 | 5 | 6 | 7 | 0 8 | 0 9 | 416 10 | 378 11 | 12 | 13 | 14 | 15 | 0 16 | 0 17 | 18 | 19 | 20 | Help 21 | 22 | 23 | 24 | 25 | 26 | 27 | 5 28 | 29 | 30 | 5 31 | 32 | 33 | 34 | 35 | Qt::NoContextMenu 36 | 37 | 38 | false 39 | 40 | 41 | Qt::ScrollBarAlwaysOff 42 | 43 | 44 | true 45 | 46 | 47 | false 48 | 49 | 50 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> 51 | <html><head><meta name="qrichtext" content="1" /><style type="text/css"> 52 | p, li { white-space: pre-wrap; } 53 | </style></head><body style=" font-weight:400; font-style:normal;"> 54 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">sokit</span></p> 55 | <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; "></p> 56 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" ">freeware version: 1.3.1 (GPLv3)</span></p> 57 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" ">website: https://github.com/sinpolib/sokit/</span></p> 58 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" ">email: sinpowei@gmail.com</span></p> 59 | <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; "></p> 60 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" ">this is a TCP / UDP package send &amp; receive &amp; transfer tool</span></p> 61 | <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; "></p> 62 | <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; "></p> 63 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" ">--------------------------------------------------------------</span></p> 64 | <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; "></p> 65 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Send buffer syntax:</span></p> 66 | <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; "></p> 67 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" ">all characters in a send buf is traited as it is (or UTF8 for multibyte char) , if you want send a hexdecimal characters, you should put those sub string in [ ], etc, [FF AB CD 12 12], space and [ ] will be trimmed when send out. (double [[ for a normal [ character)</span></p> 68 | <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; "></p> 69 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Keyboard Shortcuts:</span></p> 70 | <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;"></p> 71 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">F1</span><span style=" "> show/hide this window</span></p> 72 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">F10</span><span style=" "> set/unset main windows at top of desktop</span></p> 73 | <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; "></p> 74 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Esc</span><span style=" "> focus on first input control</span></p> 75 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">F2</span><span style=" "> focus on connects list (if exist)</span></p> 76 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">F3</span><span style=" "> focus on log's list</span></p> 77 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">F4</span><span style=" "> focus on log's entry details</span></p> 78 | <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; "></p> 79 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Alt-0</span><span style=" "> focus on data in buf 0 (if exist)</span></p> 80 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Alt-1</span><span style=" "> focus on data in buf 1</span></p> 81 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Alt-2</span><span style=" "> focus on data in buf 2</span></p> 82 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Alt-3</span><span style=" "> focus on data in buf 3</span></p> 83 | <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; "></p> 84 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Ctr-Shf-1</span><span style=" "> focus on data in dir-combobox 1 (if exist)</span></p> 85 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Ctr-Shf-2</span><span style=" "> focus on data in dir-combobox 2 (if exist)</span></p> 86 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Ctr-Shf-3</span><span style=" "> focus on data in dir-combobox 3 (if exist)</span></p> 87 | <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; "></p> 88 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Ctrl-0</span><span style=" "> send data in buf 0 (if exist)</span></p> 89 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Ctrl-1</span><span style=" "> send data in buf 1</span></p> 90 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Ctrl-2</span><span style=" "> send data in buf 2</span></p> 91 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Ctrl-3</span><span style=" "> send data in buf 3</span></p> 92 | <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; "></p> 93 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Ctrl-T</span><span style=" "> trig TCP button or combobox</span></p> 94 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Ctrl-U</span><span style=" "> trig UDP button or combobox</span></p> 95 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Ctrl-S</span><span style=" "> trig START button</span></p> 96 | <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; "></p> 97 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">F5</span><span style=" "> trig dir-combobox 1 (if exist)</span></p> 98 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">F6</span><span style=" "> trig dir-combobox 2 (if exist)</span></p> 99 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">F7</span><span style=" "> trig dir-combobox 3 (if exist)</span></p> 100 | <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; "></p> 101 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Ctrl-W</span><span style=" "> trig write log to file</span></p> 102 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Ctrl-D</span><span style=" "> clear log window</span></p> 103 | <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; "></p> 104 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Alt-A</span><span style=" "> select all connects (if exist)</span></p> 105 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Ctrl-K</span><span style=" "> kill all selected connects (if exist)</span></p> 106 | <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; "></p> 107 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Ctrl-A</span><span style=" "> select all in current input control</span></p> 108 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Ctrl-C</span><span style=" "> copy selected content in current input control</span></p> 109 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Ctrl-V</span><span style=" "> paste into current input control</span></p> 110 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Ctrl-X</span><span style=" "> cut&amp;copy selected content in current input control</span></p> 111 | <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; "></p></body></html> 112 | 113 | 114 | Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /src/sokit/icons.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | sokit.png 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/sokit/logger.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "toolkit.h" 10 | #include "setting.h" 11 | #include "logger.h" 12 | 13 | #define SET_MAX_LOGITM 100 14 | #define SET_MAX_LOGTRM 30 15 | 16 | Logger::Logger(QObject *parent) 17 | : QObject(parent),m_chkWrite(0),m_treeOut(0),m_textOut(0) 18 | { 19 | } 20 | 21 | Logger::~Logger() 22 | { 23 | m_file.close(); 24 | } 25 | 26 | void Logger::init(QTreeWidget* o, QCheckBox* w, QPlainTextEdit* d) 27 | { 28 | m_cmlog.clear(); 29 | m_cmtxt.clear(); 30 | 31 | if (m_treeOut) 32 | m_treeOut->disconnect(this); 33 | 34 | if (m_textOut) 35 | m_textOut->disconnect(this); 36 | 37 | if (m_chkWrite) 38 | m_chkWrite->disconnect(this); 39 | 40 | m_treeOut = o; 41 | m_textOut = d; 42 | m_chkWrite = w; 43 | 44 | if (m_treeOut && m_textOut && m_chkWrite) 45 | { 46 | QList ks; 47 | ks << QKeySequence(Qt::CTRL + Qt::Key_D); 48 | 49 | QAction* copy = new QAction(tr("Copy"), this); 50 | copy->setShortcuts(QKeySequence::Copy); 51 | connect(copy, SIGNAL(triggered()), this, SLOT(copy())); 52 | 53 | QAction* clear = new QAction(tr("Clear"), this); 54 | clear->setShortcuts(ks); 55 | connect(clear, SIGNAL(triggered()), this, SIGNAL(clearLog())); 56 | 57 | QAction* all = new QAction(tr("Select All"), this); 58 | all->setShortcuts(QKeySequence::SelectAll); 59 | connect(all, SIGNAL(triggered()), m_textOut, SLOT(selectAll())); 60 | 61 | m_cmlog.addAction(copy); 62 | m_cmlog.addSeparator(); 63 | m_cmlog.addAction(clear); 64 | 65 | m_cmtxt.addAction(copy); 66 | m_cmtxt.addSeparator(); 67 | m_cmtxt.addAction(all); 68 | 69 | QPalette pal = m_textOut->palette(); 70 | pal.setBrush(QPalette::Base, m_treeOut->palette().brush(QPalette::Window)); 71 | m_textOut->setPalette(pal); 72 | 73 | m_treeOut->setContextMenuPolicy(Qt::CustomContextMenu); 74 | connect(m_treeOut, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(ctxmenu(const QPoint&))); 75 | connect(m_treeOut, SIGNAL(itemSelectionChanged()), this, SLOT(syncOutput())); 76 | 77 | m_textOut->setContextMenuPolicy(Qt::CustomContextMenu); 78 | connect(m_textOut, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(ctxmenu(const QPoint&))); 79 | } 80 | } 81 | 82 | void Logger::syncOutput() 83 | { 84 | QList list = m_treeOut->selectedItems(); 85 | if (!list.isEmpty()) 86 | m_textOut->setPlainText(list.first()->text(0)); 87 | else 88 | m_textOut->clear(); 89 | } 90 | 91 | void Logger::ctxmenu(const QPoint& pos) 92 | { 93 | if (sender() == (QObject*)m_treeOut) 94 | m_cmlog.exec(m_treeOut->mapToGlobal(pos)); 95 | else 96 | m_cmtxt.exec(m_textOut->mapToGlobal(pos)); 97 | } 98 | 99 | void Logger::copy() 100 | { 101 | if (sender() == (QObject*)m_treeOut) 102 | { 103 | QList list = m_treeOut->selectedItems(); 104 | if (!list.isEmpty()) 105 | QApplication::clipboard()->setText(list.first()->text(0)); 106 | } 107 | else 108 | { 109 | m_textOut->copy(); 110 | } 111 | } 112 | 113 | const QString Logger::getLogFileName() 114 | { 115 | int i = 0; 116 | while (2 > i++) 117 | { 118 | if (!m_dir.isEmpty()) 119 | { 120 | QDir d; 121 | if (d.exists(m_dir) || d.mkpath(m_dir)) { 122 | i = 0; 123 | break; 124 | } 125 | } 126 | 127 | m_dir = Setting::path() + "/" + property(SET_SEC_DIR).toString(); 128 | } 129 | 130 | return (i==2) ? QString() : m_dir + QDir::separator() + 131 | QDate::currentDate().toString("yyyyMMdd.log"); 132 | } 133 | 134 | void Logger::writeLogFile(const QString& info) 135 | { 136 | if (!m_chkWrite->isChecked()) 137 | return; 138 | 139 | m_file.close(); 140 | m_file.setFileName(getLogFileName()); 141 | 142 | if (m_file.open(QIODevice::Append| 143 | QIODevice::WriteOnly| 144 | QIODevice::Text)) 145 | { 146 | QByteArray a(info.toUtf8()); 147 | 148 | const char* d = a.data(); 149 | for (int n=a.size(); n>0;) 150 | { 151 | int w = m_file.write(d, n); 152 | 153 | d += w; 154 | n -= w; 155 | } 156 | 157 | m_file.close(); 158 | } 159 | } 160 | 161 | void Logger::clear() 162 | { 163 | m_treeOut->clear(); 164 | m_textOut->clear(); 165 | } 166 | 167 | void Logger::output(const QString& info) 168 | { 169 | output("MSG", info); 170 | } 171 | 172 | void Logger::output(const char* buf, uint len) 173 | { 174 | output("DAT", buf, len); 175 | } 176 | 177 | void Logger::pack() 178 | { 179 | if (m_treeOut->topLevelItemCount() > SET_MAX_LOGITM) 180 | m_treeOut->model()->removeRows(0, SET_MAX_LOGTRM); 181 | 182 | m_treeOut->scrollToBottom(); 183 | } 184 | 185 | QTreeWidgetItem* Logger::appendLogEntry(QTreeWidgetItem* p, const QString& t) 186 | { 187 | QTreeWidgetItem* res = new QTreeWidgetItem(p); 188 | if (res) 189 | { 190 | res->setText(0, t); 191 | 192 | if (p) 193 | { 194 | p->addChild(res); 195 | } 196 | else 197 | { 198 | m_treeOut->addTopLevelItem(res); 199 | m_textOut->setPlainText(t); 200 | } 201 | } 202 | return res; 203 | } 204 | 205 | void Logger::output(const QString& title, const QString& info) 206 | { 207 | QTreeWidgetItem* it = new QTreeWidgetItem(0); 208 | if (!it) return; 209 | 210 | QString lab(QTime::currentTime().toString("HH:mm:ss ")); 211 | 212 | lab += title; 213 | lab += ' '; 214 | lab += info; 215 | 216 | appendLogEntry(0, lab); 217 | 218 | pack(); 219 | 220 | lab += '\n'; 221 | lab += '\n'; 222 | 223 | writeLogFile(lab); 224 | } 225 | 226 | void Logger::output(const QString& title, const char* buf, quint32 len) 227 | { 228 | QString lab(QTime::currentTime().toString("HH:mm:ss ")); 229 | 230 | QTextStream out(&lab); 231 | 232 | out << title 233 | << " <" << len << "> " 234 | << TK::bin2ascii(buf, len); 235 | 236 | QString hex = TK::bin2hex(buf, len); 237 | 238 | QTreeWidgetItem* it = appendLogEntry(0, lab); 239 | if (it) 240 | { 241 | appendLogEntry(it, hex); 242 | 243 | pack(); 244 | } 245 | 246 | out << '\n' << hex << '\n' << '\n'; 247 | 248 | writeLogFile(lab); 249 | } 250 | -------------------------------------------------------------------------------- /src/sokit/logger.h: -------------------------------------------------------------------------------- 1 | #ifndef __LOGGER_H__ 2 | #define __LOGGER_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class QTreeWidget; 10 | class QTreeWidgetItem; 11 | class QPlainTextEdit; 12 | class Logger : public QObject 13 | { 14 | Q_OBJECT 15 | 16 | public: 17 | Logger(QObject *parent = 0); 18 | ~Logger(); 19 | 20 | void init(QTreeWidget* o, QCheckBox* w, QPlainTextEdit* d); 21 | 22 | void clear(); 23 | void output(const QString& title, const QString& info); 24 | void output(const char* buf, quint32 len); 25 | 26 | signals: 27 | void clearLog(); 28 | 29 | public slots: 30 | void output(const QString& info); 31 | void output(const QString& title, const char* buf, quint32 len); 32 | 33 | private slots: 34 | void ctxmenu(const QPoint& pos); 35 | void copy(); 36 | void syncOutput(); 37 | 38 | private: 39 | const QString getLogFileName(); 40 | void writeLogFile(const QString& info); 41 | void pack(); 42 | QTreeWidgetItem* appendLogEntry(QTreeWidgetItem* p, const QString& t); 43 | 44 | private: 45 | QString m_dir; 46 | QFile m_file; 47 | 48 | QMenu m_cmlog, m_cmtxt; 49 | QCheckBox* m_chkWrite; 50 | QTreeWidget* m_treeOut; 51 | QPlainTextEdit* m_textOut; 52 | }; 53 | 54 | #endif // __LOGGER_H__ 55 | 56 | -------------------------------------------------------------------------------- /src/sokit/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "toolkit.h" 6 | #include "setting.h" 7 | #include "clientform.h" 8 | #include "serverform.h" 9 | #include "transferform.h" 10 | #include "notepadform.h" 11 | #include "helpform.h" 12 | #include "main.h" 13 | 14 | #define SET_KEY_FTNM "/font/name" 15 | #define SET_KEY_FTSZ "/font/size" 16 | 17 | #define SET_KEY_LANG "/lang" 18 | #define SET_VAL_LANG "sokit" 19 | #define SET_VAL_LANX ".lan" 20 | 21 | Sokit::Sokit(int& argc, char** argv) 22 | :QApplication(argc,argv) 23 | { 24 | } 25 | 26 | Sokit::~Sokit() 27 | { 28 | } 29 | 30 | void Sokit::show() 31 | { 32 | m_wnd.show(); 33 | } 34 | 35 | void Sokit::close() 36 | { 37 | m_wnd.close(); 38 | } 39 | 40 | void Sokit::initDefaultActionsName() 41 | { 42 | translate("QLineEdit", "&Undo"); 43 | translate("QLineEdit", "&Redo"); 44 | translate("QLineEdit", "Cu&t"); 45 | translate("QLineEdit", "&Copy"); 46 | translate("QLineEdit", "&Paste"); 47 | translate("QLineEdit", "Delete"); 48 | translate("QLineEdit", "Select All"); 49 | 50 | translate("QTextControl", "&Undo"); 51 | translate("QTextControl", "&Redo"); 52 | translate("QTextControl", "Cu&t"); 53 | translate("QTextControl", "&Copy"); 54 | translate("QTextControl", "&Paste"); 55 | translate("QTextControl", "Delete"); 56 | translate("QTextControl", "Select All"); 57 | } 58 | 59 | bool Sokit::initTranslator() 60 | { 61 | QString file = Setting::get(SET_SEC_CFG, SET_KEY_LANG, SET_VAL_LANG); 62 | 63 | QStringList paths; 64 | paths << "." 65 | << "../share/" SET_APP_NAME 66 | << "../share/apps/" SET_APP_NAME 67 | << Setting::path(); 68 | 69 | foreach (QString p, paths) 70 | { 71 | if (m_trans.load(file, p, "", SET_VAL_LANX)) 72 | { 73 | installTranslator(&m_trans); 74 | Setting::set(SET_SEC_CFG, SET_KEY_LANG, file); 75 | break; 76 | } 77 | } 78 | 79 | return true; 80 | } 81 | 82 | void Sokit::initFont() 83 | { 84 | QFontDatabase db; 85 | QStringList fs = db.families(); 86 | 87 | QFont font; 88 | 89 | int match = 0; 90 | 91 | QString family = Setting::get(SET_SEC_CFG, SET_KEY_FTNM, "").trimmed(); 92 | QString size = Setting::get(SET_SEC_CFG, SET_KEY_FTSZ, "").trimmed(); 93 | 94 | if (family.isEmpty() || fs.filter(family).isEmpty()) 95 | { 96 | QStringList defs = translate("Sokit", "font").split(";", QString::SkipEmptyParts); 97 | foreach (QString d, defs) 98 | { 99 | family = d.section(',', 0, 0).trimmed(); 100 | size = d.section(',', 1, 1).trimmed(); 101 | 102 | if (!family.isEmpty() && !fs.filter(family).isEmpty()) 103 | { 104 | match = 2; 105 | break; 106 | } 107 | } 108 | } 109 | else 110 | { 111 | match = 1; 112 | } 113 | 114 | if (match > 0) 115 | { 116 | font.setFamily(family); 117 | 118 | if (db.isSmoothlyScalable(family)) 119 | font.setStyleStrategy((QFont::StyleStrategy)(QFont::PreferAntialias|QFont::PreferOutline|QFont::PreferQuality)); 120 | 121 | int nsize = size.toInt(); 122 | if (nsize > 0 && nsize < 20) 123 | font.setPointSize(nsize); 124 | 125 | setFont(font); 126 | 127 | if (match > 1) 128 | { 129 | Setting::set(SET_SEC_CFG, SET_KEY_FTNM, family); 130 | Setting::set(SET_SEC_CFG, SET_KEY_FTSZ, size); 131 | } 132 | } 133 | } 134 | 135 | bool Sokit::initUI() 136 | { 137 | initTranslator(); 138 | initFont(); 139 | 140 | HelpForm* h = new HelpForm(&m_wnd, Qt::WindowCloseButtonHint); 141 | 142 | QShortcut* k = new QShortcut(QKeySequence(Qt::Key_F1), &m_wnd); 143 | QShortcut* t = new QShortcut(QKeySequence(Qt::Key_F10), &m_wnd); 144 | connect(k, SIGNAL(activated()), h, SLOT(exec())); 145 | connect(t, SIGNAL(activated()), this, SLOT(ontop())); 146 | 147 | m_wnd.setWindowTitle(translate("Sokit", "sokit -- F1 for help")); 148 | m_wnd.setWindowIcon(QIcon(":/sokit.png")); 149 | 150 | QWidget* pnl = new QWidget(&m_wnd); 151 | m_wnd.setCentralWidget(pnl); 152 | 153 | BaseForm* server = new ServerForm(); 154 | BaseForm* transf = new TransferForm(); 155 | BaseForm* client = new ClientForm(); 156 | NotepadForm* npd = new NotepadForm(); 157 | 158 | QTabWidget* tab = new QTabWidget(pnl); 159 | tab->addTab(server, server->windowTitle()); 160 | tab->addTab(transf, transf->windowTitle()); 161 | tab->addTab(client, client->windowTitle()); 162 | tab->addTab(npd, npd->windowTitle()); 163 | tab->setCurrentIndex(0); 164 | 165 | QLayout* lay = new QVBoxLayout(pnl); 166 | lay->setSpacing(5); 167 | lay->setContentsMargins(5, 5, 5, 5); 168 | lay->addWidget(tab); 169 | 170 | return server->init() && transf->init() && 171 | client->init() && npd->init(); 172 | } 173 | 174 | void Sokit::ontop() 175 | { 176 | Qt::WindowFlags f = m_wnd.windowFlags(); 177 | if (f & Qt::WindowStaysOnTopHint) 178 | f &= ~Qt::WindowStaysOnTopHint; 179 | else 180 | f |= Qt::WindowStaysOnTopHint; 181 | 182 | m_wnd.setWindowFlags(f); 183 | m_wnd.show(); 184 | } 185 | 186 | int main(int argc, char *argv[]) 187 | { 188 | Sokit a(argc, argv); 189 | 190 | if (a.initUI()) 191 | a.show(); 192 | else 193 | a.close(); 194 | 195 | return a.exec(); 196 | } 197 | -------------------------------------------------------------------------------- /src/sokit/main.h: -------------------------------------------------------------------------------- 1 | #ifndef __MAIN_H__ 2 | #define __MAIN_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class Sokit :public QApplication 9 | { 10 | Q_OBJECT 11 | 12 | public: 13 | Sokit(int& argc, char** argv); 14 | ~Sokit(); 15 | 16 | bool initTranslator(); 17 | bool initUI(); 18 | void show(); 19 | void close(); 20 | 21 | private slots: 22 | void ontop(); 23 | 24 | private: 25 | void initFont(); 26 | void initDefaultActionsName(); 27 | 28 | private: 29 | QMainWindow m_wnd; 30 | QTranslator m_trans; 31 | }; 32 | 33 | #endif //__MAIN_H__ 34 | -------------------------------------------------------------------------------- /src/sokit/notepadform.cpp: -------------------------------------------------------------------------------- 1 | #include "toolkit.h" 2 | #include "setting.h" 3 | #include "notepadform.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define SET_NP_FILE "sokit.txt" 12 | 13 | NotepadForm::NotepadForm(QWidget* p, Qt::WindowFlags f) 14 | :QWidget(p, f) 15 | { 16 | setupUi(); 17 | } 18 | 19 | NotepadForm::~NotepadForm() 20 | { 21 | uninit(); 22 | } 23 | 24 | void NotepadForm::setupUi() 25 | { 26 | resize(680, 450); 27 | 28 | QVBoxLayout* lay = new QVBoxLayout(this); 29 | lay->setSpacing(5); 30 | lay->setContentsMargins(5, 5, 5, 5); 31 | 32 | m_board = new QPlainTextEdit(this); 33 | m_board->setAcceptDrops(false); 34 | m_board->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 35 | m_board->setTabChangesFocus(false); 36 | m_board->setUndoRedoEnabled(true); 37 | m_board->setTextInteractionFlags(Qt::TextEditorInteraction); 38 | 39 | lay->addWidget(m_board); 40 | 41 | setWindowTitle(tr("Notepad")); 42 | 43 | QMetaObject::connectSlotsByName(this); 44 | 45 | QShortcut* n = new QShortcut(QKeySequence(Qt::Key_Tab+Qt::CTRL), this); 46 | QShortcut* l = new QShortcut(QKeySequence(Qt::Key_Tab+Qt::CTRL+Qt::SHIFT), this); 47 | n->setObjectName("n"); 48 | l->setObjectName("l"); 49 | 50 | connect(n, SIGNAL(activated()), this, SLOT(jumptab())); 51 | connect(l, SIGNAL(activated()), this, SLOT(jumptab())); 52 | } 53 | 54 | bool NotepadForm::init() 55 | { 56 | QFile file(Setting::path() + "/" + SET_NP_FILE); 57 | 58 | if (file.open(QIODevice::ReadOnly|QIODevice::Text)) 59 | { 60 | QTextStream str(&file); 61 | m_board->setPlainText(str.readAll()); 62 | 63 | file.close(); 64 | } 65 | 66 | return true; 67 | } 68 | 69 | void NotepadForm::uninit() 70 | { 71 | QFile file(Setting::path() + "/" + SET_NP_FILE); 72 | 73 | if (file.open(QIODevice::WriteOnly|QIODevice::Text|QIODevice::Truncate)) 74 | { 75 | QTextStream str(&file); 76 | str << m_board->toPlainText(); 77 | 78 | str.flush(); 79 | file.close(); 80 | } 81 | } 82 | 83 | void NotepadForm::jumptab() 84 | { 85 | if (parent()) 86 | { 87 | QTabWidget* p = qobject_cast(parent()->parent()); 88 | if (p) 89 | { 90 | qint32 max = p->count(); 91 | qint32 cur = p->indexOf(this); 92 | 93 | if (sender()->objectName().startsWith('n')) { 94 | if (++cur >= max) cur = 0; 95 | } else { 96 | if (--cur < 0) cur = (max>0) ? (max-1) : 0; 97 | } 98 | 99 | p->setCurrentIndex(cur); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/sokit/notepadform.h: -------------------------------------------------------------------------------- 1 | #ifndef __NOTEPADFORM_H__ 2 | #define __NOTEPADFORM_H__ 3 | 4 | #include 5 | 6 | class NotepadForm : public QWidget 7 | { 8 | Q_OBJECT 9 | 10 | public: 11 | NotepadForm(QWidget* p=0, Qt::WindowFlags f=0); 12 | virtual ~NotepadForm(); 13 | 14 | public: 15 | bool init(); 16 | 17 | private slots: 18 | void jumptab(); 19 | 20 | private: 21 | void setupUi(); 22 | void uninit(); 23 | 24 | private: 25 | QPlainTextEdit* m_board; 26 | }; 27 | 28 | #endif // __NOTEPADFORM_H__ 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/sokit/resource.h: -------------------------------------------------------------------------------- 1 | 2 | #define IDI_ICON1 101 3 | 4 | -------------------------------------------------------------------------------- /src/sokit/serverform.cpp: -------------------------------------------------------------------------------- 1 | #include "toolkit.h" 2 | #include "setting.h" 3 | #include "serverform.h" 4 | 5 | #include 6 | 7 | #define SET_SEC_SVR "server" 8 | #define SET_KEY_SVR "/server" 9 | 10 | #define SET_KEY_CMBTA "/tip" 11 | #define SET_KEY_CMBUA "/uip" 12 | #define SET_KEY_CMBTP "/tport" 13 | #define SET_KEY_CMBUP "/uport" 14 | 15 | #define SET_VAL_LGSVR "log_server" 16 | 17 | ServerForm::ServerForm(QWidget *parent, Qt::WindowFlags flags) 18 | : BaseForm(parent, flags) 19 | { 20 | m_ui.setupUi(this); 21 | } 22 | 23 | ServerForm::~ServerForm() 24 | { 25 | if (lock(1000)) 26 | { 27 | m_tcp.disconnect(this); 28 | m_udp.disconnect(this); 29 | 30 | m_tcp.stop(); 31 | m_udp.stop(); 32 | 33 | unlock(); 34 | } 35 | 36 | saveConfig(); 37 | } 38 | 39 | void ServerForm::initConfig() 40 | { 41 | QString sss(SET_SEC_SVR); 42 | Setting::load(sss+SET_KEY_CMBTA, SET_PFX_CMBITM, *m_ui.cmbTcpAddr, false); 43 | Setting::load(sss+SET_KEY_CMBUA, SET_PFX_CMBITM, *m_ui.cmbUdpAddr, false); 44 | Setting::load(sss+SET_KEY_CMBTP, SET_PFX_CMBITM, *m_ui.cmbTcpPort); 45 | Setting::load(sss+SET_KEY_CMBUP, SET_PFX_CMBITM, *m_ui.cmbUdpPort); 46 | const quint16 FailSafeDefaultPort = 8080; 47 | if (m_ui.cmbTcpPort->currentText().length() <= 0) { 48 | m_ui.cmbTcpPort->setEditText(QString::number(FailSafeDefaultPort)); 49 | } 50 | if (m_ui.cmbUdpPort->currentText().length() <= 0) { 51 | m_ui.cmbUdpPort->setEditText(QString::number(FailSafeDefaultPort)); 52 | } 53 | 54 | QString skl(SET_SEC_DIR); skl += SET_KEY_LOG; 55 | skl = Setting::get(skl, SET_KEY_SVR, SET_VAL_LGSVR); 56 | setProperty(SET_SEC_DIR, skl); 57 | 58 | TK::initNetworkInterfaces(m_ui.cmbTcpAddr, true); 59 | TK::initNetworkInterfaces(m_ui.cmbUdpAddr, true); 60 | } 61 | 62 | void ServerForm::saveConfig() 63 | { 64 | QString sss(SET_SEC_SVR); 65 | Setting::save(sss+SET_KEY_CMBTA, SET_PFX_CMBITM, *m_ui.cmbTcpAddr, false); 66 | Setting::save(sss+SET_KEY_CMBUA, SET_PFX_CMBITM, *m_ui.cmbUdpAddr, false); 67 | Setting::save(sss+SET_KEY_CMBTP, SET_PFX_CMBITM, *m_ui.cmbTcpPort); 68 | Setting::save(sss+SET_KEY_CMBUP, SET_PFX_CMBITM, *m_ui.cmbUdpPort); 69 | 70 | QString skl(SET_SEC_DIR); skl += SET_KEY_LOG; 71 | Setting::set(skl, SET_KEY_SVR, property(SET_SEC_DIR).toString()); 72 | } 73 | 74 | bool ServerForm::initForm() 75 | { 76 | initCounter(m_ui.labRecv, m_ui.labSend); 77 | initLogger(m_ui.chkLog, m_ui.btnClear, m_ui.treeOutput, m_ui.txtOutput); 78 | initLister(m_ui.btnConnAll, m_ui.btnConnDel, m_ui.lstConn); 79 | 80 | bindBuffer(1, m_ui.edtBuf1, m_ui.btnSend1, 0); 81 | bindBuffer(2, m_ui.edtBuf2, m_ui.btnSend2, 0); 82 | bindBuffer(3, m_ui.edtBuf3, m_ui.btnSend3, 0); 83 | 84 | connect(m_ui.btnTcp, SIGNAL(clicked(bool)), this, SLOT(trigger(bool))); 85 | connect(m_ui.btnUdp, SIGNAL(clicked(bool)), this, SLOT(trigger(bool))); 86 | 87 | connect(&m_tcp, SIGNAL(connOpen(const QString&)), this, SLOT(listerAdd(const QString&))); 88 | connect(&m_tcp, SIGNAL(connClose(const QString&)), this, SLOT(listerRemove(const QString&))); 89 | connect(&m_tcp, SIGNAL(message(const QString&)), this, SIGNAL(output(const QString&))); 90 | connect(&m_tcp, SIGNAL(dumpbin(const QString&,const char*,quint32)), this, SIGNAL(output(const QString&,const char*,quint32))); 91 | connect(&m_tcp, SIGNAL(countRecv(qint32)), this, SLOT(countRecv(qint32))); 92 | connect(&m_tcp, SIGNAL(countSend(qint32)), this, SLOT(countSend(qint32))); 93 | 94 | connect(&m_udp, SIGNAL(connOpen(const QString&)), this, SLOT(listerAdd(const QString&))); 95 | connect(&m_udp, SIGNAL(connClose(const QString&)), this, SLOT(listerRemove(const QString&))); 96 | connect(&m_udp, SIGNAL(message(const QString&)), this, SIGNAL(output(const QString&))); 97 | connect(&m_udp, SIGNAL(dumpbin(const QString&,const char*,quint32)), this, SIGNAL(output(const QString&,const char*,quint32))); 98 | connect(&m_udp, SIGNAL(countRecv(qint32)), this, SLOT(countRecv(qint32))); 99 | connect(&m_udp, SIGNAL(countSend(qint32)), this, SLOT(countSend(qint32))); 100 | 101 | return true; 102 | } 103 | 104 | bool ServerForm::initHotkeys() 105 | { 106 | bindFocus(m_ui.cmbTcpAddr, Qt::Key_Escape); 107 | bindClick(m_ui.btnTcp, Qt::CTRL + Qt::Key_T); 108 | bindClick(m_ui.btnUdp, Qt::CTRL + Qt::Key_U); 109 | 110 | return true; 111 | } 112 | 113 | void ServerForm::kill(QStringList& list) 114 | { 115 | QString tcpname(TK::socketTypeName(true)); 116 | 117 | while (!list.isEmpty()) 118 | { 119 | QString key = list.takeFirst(); 120 | if (key.contains(tcpname)) 121 | m_tcp.kill(key); 122 | else 123 | m_udp.kill(key); 124 | } 125 | } 126 | 127 | void ServerForm::trigger(bool start) 128 | { 129 | QToolButton* btnTrigger = qobject_cast(sender()); 130 | if (!btnTrigger) return; 131 | 132 | bool istcp = (btnTrigger==m_ui.btnTcp); 133 | QComboBox* cbAddr = istcp ? m_ui.cmbTcpAddr : m_ui.cmbUdpAddr; 134 | QComboBox* cbPort = istcp ? m_ui.cmbTcpPort : m_ui.cmbUdpPort; 135 | ServerSkt* server = istcp ? (ServerSkt*)&m_tcp : (ServerSkt*)&m_udp; 136 | 137 | IPAddr addr; 138 | if (start) 139 | start = TK::popIPAddr(cbAddr, cbPort, addr); 140 | 141 | lock(); 142 | 143 | if (start) 144 | start = server->start(addr.ip, addr.port); 145 | else 146 | server->stop(); 147 | 148 | unlock(); 149 | 150 | cbAddr->setDisabled(start); 151 | cbPort->setDisabled(start); 152 | 153 | if (start) 154 | TK::pushIPAddr(0, cbPort); 155 | else 156 | TK::resetPushBox(btnTrigger); 157 | } 158 | 159 | void ServerForm::send(const QString& data, const QString&) 160 | { 161 | QStringList list; 162 | if (lock(1000)) 163 | { 164 | listerSelected(list); 165 | unlock(); 166 | } 167 | 168 | QString tcpname(TK::socketTypeName(true)); 169 | while (!list.isEmpty()) 170 | { 171 | QString key = list.takeFirst(); 172 | 173 | ServerSkt* server = key.contains(tcpname) 174 | ? (ServerSkt*)&m_tcp : (ServerSkt*)&m_udp; 175 | 176 | server->send(key, data); 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /src/sokit/serverform.h: -------------------------------------------------------------------------------- 1 | #ifndef __SERVERFORM_H__ 2 | #define __SERVERFORM_H__ 3 | 4 | #include "ui_serverform.h" 5 | #include "baseform.h" 6 | #include "serverskt.h" 7 | 8 | class ServerForm : public BaseForm 9 | { 10 | Q_OBJECT 11 | 12 | public: 13 | ServerForm(QWidget* p=0, Qt::WindowFlags f=0); 14 | virtual ~ServerForm(); 15 | 16 | protected: 17 | virtual bool initForm(); 18 | virtual bool initHotkeys(); 19 | virtual void initConfig(); 20 | virtual void saveConfig(); 21 | virtual void send(const QString& data, const QString& dir); 22 | virtual void kill(QStringList& list); 23 | 24 | private slots: 25 | void trigger(bool start); 26 | 27 | private: 28 | ServerSktTcp m_tcp; 29 | ServerSktUdp m_udp; 30 | Ui::ServerForm m_ui; 31 | }; 32 | 33 | #endif // __SERVERFORM_H__ 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/sokit/serverform.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | ServerForm 4 | 5 | 6 | 7 | 0 8 | 0 9 | 680 10 | 450 11 | 12 | 13 | 14 | 15 | 0 16 | 0 17 | 18 | 19 | 20 | Server 21 | 22 | 23 | 24 | 25 | 26 | 27 | 5 28 | 29 | 30 | 5 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 0 39 | 0 40 | 41 | 42 | 43 | 44 | 0 45 | 93 46 | 47 | 48 | 49 | 50 | 16777215 51 | 93 52 | 53 | 54 | 55 | Network Setup 56 | 57 | 58 | 59 | 5 60 | 61 | 62 | 4 63 | 64 | 65 | 0 66 | 67 | 68 | 10 69 | 70 | 71 | 5 72 | 73 | 74 | 75 | 76 | QLayout::SetFixedSize 77 | 78 | 79 | 5 80 | 81 | 82 | 8 83 | 84 | 85 | 0 86 | 87 | 88 | 89 | 90 | 91 | 0 92 | 0 93 | 94 | 95 | 96 | Port: 97 | 98 | 99 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 0 108 | 0 109 | 110 | 111 | 112 | 113 | 70 114 | 0 115 | 116 | 117 | 118 | Qt::NoContextMenu 119 | 120 | 121 | TCP Addr: 122 | 123 | 124 | Qt::PlainText 125 | 126 | 127 | false 128 | 129 | 130 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 0 139 | 0 140 | 141 | 142 | 143 | 144 | 130 145 | 24 146 | 147 | 148 | 149 | 150 | 130 151 | 24 152 | 153 | 154 | 155 | true 156 | 157 | 158 | QComboBox::NoInsert 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 0 167 | 0 168 | 169 | 170 | 171 | 172 | 75 173 | 24 174 | 175 | 176 | 177 | 178 | 75 179 | 24 180 | 181 | 182 | 183 | true 184 | 185 | 186 | QComboBox::InsertAtTop 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 0 195 | 0 196 | 197 | 198 | 199 | 200 | 70 201 | 0 202 | 203 | 204 | 205 | Qt::NoContextMenu 206 | 207 | 208 | UDP Addr: 209 | 210 | 211 | Qt::PlainText 212 | 213 | 214 | false 215 | 216 | 217 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 0 226 | 0 227 | 228 | 229 | 230 | 231 | 130 232 | 24 233 | 234 | 235 | 236 | 237 | 130 238 | 24 239 | 240 | 241 | 242 | true 243 | 244 | 245 | QComboBox::NoInsert 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 0 254 | 0 255 | 256 | 257 | 258 | Port: 259 | 260 | 261 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 0 270 | 0 271 | 272 | 273 | 274 | 275 | 75 276 | 24 277 | 278 | 279 | 280 | 281 | 75 282 | 24 283 | 284 | 285 | 286 | true 287 | 288 | 289 | QComboBox::InsertAtTop 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 0 298 | 0 299 | 300 | 301 | 302 | 303 | 90 304 | 24 305 | 306 | 307 | 308 | 309 | 90 310 | 24 311 | 312 | 313 | 314 | 315 | 316 | 317 | UDP Listen 318 | 319 | 320 | true 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 90 329 | 24 330 | 331 | 332 | 333 | 334 | 90 335 | 24 336 | 337 | 338 | 339 | TCP Listen 340 | 341 | 342 | true 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 0 356 | 0 357 | 358 | 359 | 360 | 361 | 0 362 | 93 363 | 364 | 365 | 366 | 367 | 16777215 368 | 93 369 | 370 | 371 | 372 | Connections 373 | 374 | 375 | 376 | 5 377 | 378 | 379 | 10 380 | 381 | 382 | 5 383 | 384 | 385 | 10 386 | 387 | 388 | 10 389 | 390 | 391 | 392 | 393 | 394 | 0 395 | 0 396 | 397 | 398 | 399 | 400 | 0 401 | 58 402 | 403 | 404 | 405 | 406 | 16777215 407 | 58 408 | 409 | 410 | 411 | Qt::ScrollBarAlwaysOff 412 | 413 | 414 | Qt::ScrollBarAlwaysOff 415 | 416 | 417 | QAbstractItemView::NoEditTriggers 418 | 419 | 420 | false 421 | 422 | 423 | QAbstractItemView::MultiSelection 424 | 425 | 426 | QAbstractItemView::SelectRows 427 | 428 | 429 | false 430 | 431 | 432 | 433 | 434 | 435 | 436 | 10 437 | 438 | 439 | 0 440 | 441 | 442 | 443 | 444 | 445 | 0 446 | 0 447 | 448 | 449 | 450 | 451 | 0 452 | 24 453 | 454 | 455 | 456 | 457 | 16777215 458 | 24 459 | 460 | 461 | 462 | All 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 0 471 | 0 472 | 473 | 474 | 475 | 476 | 0 477 | 24 478 | 479 | 480 | 481 | 482 | 16777215 483 | 24 484 | 485 | 486 | 487 | Disconn 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 5 502 | 503 | 504 | 5 505 | 506 | 507 | 508 | 509 | Buf 1: 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 60 518 | 24 519 | 520 | 521 | 522 | 523 | 60 524 | 24 525 | 526 | 527 | 528 | Send 529 | 530 | 531 | false 532 | 533 | 534 | 535 | 536 | 537 | 538 | Buf 2: 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 0 547 | 24 548 | 549 | 550 | 551 | 552 | 16777215 553 | 24 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 60 563 | 24 564 | 565 | 566 | 567 | 568 | 60 569 | 24 570 | 571 | 572 | 573 | Send 574 | 575 | 576 | 577 | 578 | 579 | 580 | Buf 3: 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 0 589 | 24 590 | 591 | 592 | 593 | 594 | 16777215 595 | 24 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 60 605 | 24 606 | 607 | 608 | 609 | 610 | 60 611 | 24 612 | 613 | 614 | 615 | Send 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 0 624 | 24 625 | 626 | 627 | 628 | 629 | 16777215 630 | 24 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 5 641 | 642 | 643 | 0 644 | 645 | 646 | 5 647 | 648 | 649 | 0 650 | 651 | 652 | 0 653 | 654 | 655 | 656 | 657 | 658 | 0 659 | 0 660 | 661 | 662 | 663 | Output: 664 | 665 | 666 | 667 | 668 | 669 | 670 | Recv 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 0 679 | 0 680 | 681 | 682 | 683 | 684 | 685 | 686 | 0 687 | 688 | 689 | 690 | 691 | 692 | 693 | , Send 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 0 704 | 705 | 706 | 707 | 708 | 709 | 710 | Qt::Horizontal 711 | 712 | 713 | 714 | 0 715 | 0 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | Write log 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 60 732 | 24 733 | 734 | 735 | 736 | 737 | 60 738 | 24 739 | 740 | 741 | 742 | Clear 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 0 753 | 0 754 | 755 | 756 | 757 | Qt::ScrollBarAlwaysOff 758 | 759 | 760 | QAbstractItemView::NoEditTriggers 761 | 762 | 763 | false 764 | 765 | 766 | false 767 | 768 | 769 | QAbstractItemView::SingleSelection 770 | 771 | 772 | QAbstractItemView::SelectRows 773 | 774 | 775 | true 776 | 777 | 778 | false 779 | 780 | 781 | true 782 | 783 | 784 | 785 | 1 786 | 787 | 788 | 789 | 790 | 791 | 792 | 793 | 794 | 0 795 | 0 796 | 797 | 798 | 799 | 800 | 0 801 | 70 802 | 803 | 804 | 805 | 806 | 16777215 807 | 70 808 | 809 | 810 | 811 | false 812 | 813 | 814 | QFrame::Box 815 | 816 | 817 | QFrame::Plain 818 | 819 | 820 | Qt::ScrollBarAlwaysOff 821 | 822 | 823 | true 824 | 825 | 826 | false 827 | 828 | 829 | true 830 | 831 | 832 | Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse 833 | 834 | 835 | 836 | 837 | 838 | 839 | cmbTcpAddr 840 | cmbTcpPort 841 | btnTcp 842 | cmbUdpAddr 843 | cmbUdpPort 844 | btnUdp 845 | lstConn 846 | btnConnAll 847 | btnConnDel 848 | edtBuf1 849 | btnSend1 850 | edtBuf2 851 | btnSend2 852 | edtBuf3 853 | btnSend3 854 | chkLog 855 | btnClear 856 | treeOutput 857 | 858 | 859 | 860 | 861 | -------------------------------------------------------------------------------- /src/sokit/serverskt.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "toolkit.h" 4 | #include "serverskt.h" 5 | 6 | #define PROP_CONN "CONN" 7 | 8 | #define MAXBUFFER 1024*1024 9 | 10 | ServerSkt::ServerSkt(QObject *parent) 11 | : QObject(parent),m_port(0) 12 | { 13 | m_started = false; 14 | } 15 | 16 | ServerSkt::~ServerSkt() 17 | { 18 | } 19 | 20 | bool ServerSkt::start(const QHostAddress& ip, quint16 port) 21 | { 22 | m_ip = ip; 23 | m_port = port; 24 | 25 | m_conns.clear(); 26 | m_error.clear(); 27 | 28 | m_started = open(); 29 | 30 | QString msg("start %1 server %2!"); 31 | if (!m_started) 32 | { 33 | msg = msg.arg(name(),"failed"); 34 | if (!m_error.isEmpty()) 35 | { msg += " error:["; 36 | msg += m_error; 37 | msg += "]."; 38 | } 39 | } 40 | else 41 | { 42 | msg = msg.arg(name(),"successfully"); 43 | } 44 | 45 | show(msg); 46 | 47 | return m_started; 48 | } 49 | 50 | void ServerSkt::stop() 51 | { 52 | if (!m_started) 53 | return; 54 | 55 | OBJMAP::const_iterator i; 56 | for (i = m_conns.constBegin(); i != m_conns.constEnd(); ++i) 57 | { 58 | QString k = i.key(); 59 | void* v = i.value(); 60 | 61 | if (close(v)) 62 | emit connClose(k); 63 | } 64 | 65 | m_conns.clear(); 66 | 67 | close(); 68 | 69 | show(QString("stop %1 server!").arg(name())); 70 | 71 | m_started = false; 72 | } 73 | 74 | void ServerSkt::setError(const QString& err) 75 | { 76 | m_error = err; 77 | } 78 | 79 | void ServerSkt::recordRecv(qint32 bytes) 80 | { 81 | emit countRecv(bytes); 82 | } 83 | 84 | void ServerSkt::recordSend(qint32 bytes) 85 | { 86 | emit countSend(bytes); 87 | } 88 | 89 | void ServerSkt::getKeys(QStringList& res) 90 | { 91 | res = m_conns.keys(); 92 | } 93 | 94 | void ServerSkt::setCookie(const QString& k, void* v) 95 | { 96 | void* o = m_conns.value(k); 97 | if (o) 98 | { 99 | if (close(o)) 100 | emit connClose(k); 101 | } 102 | 103 | m_conns.insert(k, v); 104 | emit connOpen(k); 105 | } 106 | 107 | void ServerSkt::unsetCookie(const QString& k) 108 | { 109 | m_conns.remove(k); 110 | emit connClose(k); 111 | } 112 | 113 | void* ServerSkt::getCookie(const QString& k) 114 | { 115 | return m_conns.value(k); 116 | } 117 | 118 | void ServerSkt::kill(const QString& key) 119 | { 120 | void* v = m_conns.value(key); 121 | if (v) 122 | { 123 | if (close(v)) 124 | unsetCookie(key); 125 | } 126 | else 127 | { 128 | unsetCookie(key); 129 | } 130 | } 131 | 132 | void ServerSkt::send(const QString& key, const QString& data) 133 | { 134 | void* v = m_conns.value(key); 135 | if (v) 136 | { 137 | QString err; 138 | QByteArray bin; 139 | 140 | if (!TK::ascii2bin(data, bin, err)) 141 | show("bad data format to send: "+err); 142 | else 143 | send(v, bin); 144 | } 145 | } 146 | 147 | void ServerSkt::dump(const char* buf, qint32 len, bool isSend, const QString& key) 148 | { 149 | emit dumpbin(QString("DAT %1 %2").arg(isSend?"<---":"--->",key), buf, (quint32)len); 150 | } 151 | 152 | void ServerSkt::show(const QString& msg) 153 | { 154 | emit message(msg); 155 | } 156 | 157 | ServerSktTcp::ServerSktTcp(QObject *parent) 158 | :ServerSkt(parent) 159 | { 160 | } 161 | 162 | ServerSktTcp::~ServerSktTcp() 163 | { 164 | m_server.disconnect(this); 165 | stop(); 166 | } 167 | 168 | bool ServerSktTcp::open() 169 | { 170 | if (m_server.listen(addr(), port())) 171 | { 172 | connect(&m_server, SIGNAL(newConnection()), this, SLOT(newConnection())); 173 | return true; 174 | } 175 | else 176 | { 177 | setError(QString("%1, %2").arg(m_server.serverError()).arg(m_server.errorString())); 178 | } 179 | 180 | return false; 181 | } 182 | 183 | bool ServerSktTcp::close(void* cookie) 184 | { 185 | Conn* conn = (Conn*)cookie; 186 | 187 | if (conn->client) 188 | conn->client->disconnect(this); 189 | 190 | delete conn->client; 191 | delete conn; 192 | 193 | return true; 194 | } 195 | 196 | void ServerSktTcp::close(QObject* obj) 197 | { 198 | Conn* conn = (Conn*)obj->property(PROP_CONN).value(); 199 | if (!conn) return; 200 | 201 | unsetCookie(conn->key); 202 | delete conn; 203 | } 204 | 205 | void ServerSktTcp::error() 206 | { 207 | QTcpSocket* s = qobject_cast(sender()); 208 | 209 | show(QString("TCP socket error %1, %2").arg(s->error()).arg(s->errorString())); 210 | 211 | s->deleteLater(); 212 | } 213 | 214 | void ServerSktTcp::close() 215 | { 216 | m_server.close(); 217 | m_server.disconnect(this); 218 | } 219 | 220 | void ServerSktTcp::newConnection() 221 | { 222 | QTcpServer* server = qobject_cast(sender()); 223 | if (!server) return; 224 | 225 | QTcpSocket* client = server->nextPendingConnection(); 226 | while (client) 227 | { 228 | Conn* conn = new Conn; 229 | if (!conn) 230 | { 231 | client->deleteLater(); 232 | } 233 | else 234 | { 235 | client->setProperty(PROP_CONN, qVariantFromValue((void*)conn)); 236 | 237 | conn->client = client; 238 | conn->key = TK::ipstr(client->peerAddress(),client->peerPort(), true); 239 | 240 | connect(client, SIGNAL(readyRead()), this, SLOT(newData())); 241 | connect(client, SIGNAL(destroyed(QObject*)), this, SLOT(close(QObject*))); 242 | connect(client, SIGNAL(disconnected()), client, SLOT(deleteLater())); 243 | connect(client, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error())); 244 | 245 | setCookie(conn->key, conn); 246 | } 247 | client = server->nextPendingConnection(); 248 | } 249 | } 250 | 251 | void ServerSktTcp::newData() 252 | { 253 | QTcpSocket* client = qobject_cast(sender()); 254 | if (!client) return; 255 | 256 | Conn* conn = (Conn*)client->property(PROP_CONN).value(); 257 | if (!conn) return; 258 | 259 | qint64 bufLen = client->bytesAvailable(); 260 | char* buf = TK::createBuffer(bufLen, MAXBUFFER); 261 | if (!buf) return; 262 | 263 | qint64 readLen = 0; 264 | qint64 ioLen = client->read(buf, bufLen); 265 | 266 | while (ioLen > 0) 267 | { 268 | readLen += ioLen; 269 | ioLen = client->read(buf+readLen, bufLen-readLen); 270 | } 271 | 272 | if (ioLen >= 0) 273 | { 274 | recordRecv(readLen); 275 | dump(buf, readLen, false, conn->key); 276 | } 277 | 278 | TK::releaseBuffer(buf); 279 | } 280 | 281 | void ServerSktTcp::send(void* cookie, const QByteArray& bin) 282 | { 283 | Conn* conn = (Conn*)cookie; 284 | 285 | const char * src = bin.constData(); 286 | qint64 srcLen = bin.length(); 287 | 288 | qint64 writeLen = 0; 289 | qint64 ioLen = conn->client->write(src, srcLen); 290 | 291 | while (ioLen > 0) 292 | { 293 | writeLen += ioLen; 294 | ioLen = conn->client->write(src+writeLen, srcLen-writeLen); 295 | } 296 | 297 | if (writeLen != srcLen) 298 | { 299 | show(QString("failed to send data to %1:%2 [%3]") 300 | .arg(addr().toString()).arg(port()).arg(writeLen)); 301 | return; 302 | } 303 | 304 | recordSend(writeLen); 305 | dump(src, srcLen, true, conn->key); 306 | } 307 | 308 | ServerSktUdp::ServerSktUdp(QObject *parent) 309 | :ServerSkt(parent) 310 | { 311 | } 312 | 313 | ServerSktUdp::~ServerSktUdp() 314 | { 315 | m_server.disconnect(this); 316 | stop(); 317 | } 318 | 319 | void ServerSktUdp::error() 320 | { 321 | QUdpSocket* s = qobject_cast(sender()); 322 | 323 | show(QString("UDP socket error %1, %2").arg(s->error()).arg(s->errorString())); 324 | } 325 | 326 | bool ServerSktUdp::open() 327 | { 328 | if (m_server.bind(addr(), port(), QUdpSocket::ShareAddress)) 329 | { 330 | connect(&m_server, SIGNAL(readyRead()), this, SLOT(newData())); 331 | connect(&m_server, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error())); 332 | connect(&m_timer, SIGNAL(timeout()), this, SLOT(check())); 333 | 334 | m_timer.start(2000); 335 | return true; 336 | } 337 | else 338 | { 339 | setError(QString("%1, %2").arg(m_server.error()).arg(m_server.errorString())); 340 | } 341 | 342 | return false; 343 | } 344 | 345 | bool ServerSktUdp::close(void* cookie) 346 | { 347 | delete (Conn*)cookie; 348 | return true; 349 | } 350 | 351 | void ServerSktUdp::close() 352 | { 353 | m_timer.disconnect(this); 354 | m_timer.stop(); 355 | m_server.close(); 356 | m_server.disconnect(this); 357 | } 358 | 359 | void ServerSktUdp::newData() 360 | { 361 | QUdpSocket* s = qobject_cast(sender()); 362 | if (!s) return; 363 | 364 | qint64 bufLen = s->pendingDatagramSize(); 365 | char* buf = TK::createBuffer(bufLen, MAXBUFFER); 366 | if (!buf) return; 367 | 368 | QHostAddress addr; quint16 port(0); 369 | 370 | qint64 readLen = 0; 371 | qint64 ioLen = s->readDatagram(buf, bufLen, &addr, &port); 372 | 373 | //while (ioLen > 0) 374 | //{ 375 | readLen += ioLen; 376 | // ioLen = s->readDatagram(buf+readLen, bufLen-readLen, &addr, &port); 377 | //} 378 | 379 | if (ioLen >= 0) 380 | { 381 | Conn* conn = (Conn*)getCookie(TK::ipstr(addr, port, false)); 382 | if (!conn) 383 | { 384 | conn = new Conn; 385 | if (conn) 386 | { 387 | conn->key = TK::ipstr(addr, port, false); 388 | conn->addr = addr; 389 | conn->port = port; 390 | setCookie(conn->key, conn); 391 | } 392 | } 393 | 394 | if (conn) 395 | { 396 | recordRecv(readLen); 397 | 398 | conn->stamp = QDateTime::currentDateTime(); 399 | dump(buf, readLen, false, conn->key); 400 | } 401 | } 402 | 403 | TK::releaseBuffer(buf); 404 | } 405 | 406 | void ServerSktUdp::send(void* cookie, const QByteArray& bin) 407 | { 408 | Conn* conn = (Conn*)cookie; 409 | 410 | const char* src = bin.constData(); 411 | qint64 srcLen = bin.length(); 412 | 413 | qint64 writeLen = 0; 414 | qint64 ioLen = m_server.writeDatagram(src, srcLen, conn->addr, conn->port); 415 | 416 | while (ioLen > 0) 417 | { 418 | writeLen += ioLen; 419 | 420 | ioLen = (writeLen >= srcLen) ? 0 : 421 | m_server.writeDatagram(src+writeLen, srcLen-writeLen, conn->addr, conn->port); 422 | } 423 | 424 | if (writeLen != srcLen) 425 | { 426 | show(QString("failed to send data to %1:%2 [%3]") 427 | .arg(conn->addr.toString()).arg(conn->port).arg(writeLen)); 428 | return; 429 | } 430 | 431 | recordSend(writeLen); 432 | dump(src, srcLen, true, conn->key); 433 | } 434 | 435 | void ServerSktUdp::check() 436 | { 437 | QStringList list; 438 | getKeys(list); 439 | 440 | while (!list.isEmpty()) 441 | { 442 | QString k = list.takeFirst(); 443 | 444 | void* c = getCookie(k); 445 | 446 | if (c && (((Conn*)c)->stamp.addSecs(120) < QDateTime::currentDateTime())) 447 | { 448 | close(c); 449 | unsetCookie(k); 450 | } 451 | } 452 | } 453 | 454 | -------------------------------------------------------------------------------- /src/sokit/serverskt.h: -------------------------------------------------------------------------------- 1 | #ifndef __SERVERSKT_H__ 2 | #define __SERVERSKT_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class ServerSkt : public QObject 11 | { 12 | typedef QHash OBJMAP; 13 | 14 | Q_OBJECT 15 | 16 | public: 17 | ServerSkt(QObject *parent=0); 18 | virtual ~ServerSkt(); 19 | 20 | virtual QString name() const { return "General"; }; 21 | 22 | bool start(const QHostAddress& ip, quint16 port); 23 | void kill(const QString& key); 24 | void stop(); 25 | 26 | void send(const QString& key, const QString& data); 27 | 28 | const QHostAddress& addr() const { return m_ip; }; 29 | quint16 port() const { return m_port; }; 30 | 31 | signals: 32 | void connOpen(const QString& key); 33 | void connClose(const QString& key); 34 | void message(const QString& msg); 35 | void dumpbin(const QString& title, const char* data, quint32 len); 36 | 37 | void countRecv(qint32 bytes); 38 | void countSend(qint32 bytes); 39 | 40 | protected: 41 | void dump(const char* buf, qint32 len, bool isSend, const QString& key); 42 | void show(const QString& msg); 43 | 44 | void setError(const QString& err); 45 | 46 | void recordRecv(qint32 bytes); 47 | void recordSend(qint32 bytes); 48 | 49 | void getKeys(QStringList& res); 50 | void setCookie(const QString& k, void* v); 51 | void unsetCookie(const QString& k); 52 | void* getCookie(const QString& k); 53 | 54 | 55 | virtual bool open() =0; 56 | virtual bool close(void* cookie) =0; 57 | virtual void send(void* cookie, const QByteArray& bin) =0; 58 | virtual void close() =0; 59 | 60 | private: 61 | bool m_started; 62 | QHostAddress m_ip; 63 | quint16 m_port; 64 | 65 | OBJMAP m_conns; 66 | QString m_error; 67 | }; 68 | 69 | class ServerSktTcp : public ServerSkt 70 | { 71 | typedef struct _Conn 72 | { 73 | QTcpSocket* client; 74 | QString key; 75 | } Conn; 76 | 77 | Q_OBJECT 78 | 79 | public: 80 | ServerSktTcp(QObject *parent=0); 81 | virtual ~ServerSktTcp(); 82 | 83 | virtual QString name() const { return "TCP"; }; 84 | 85 | protected: 86 | virtual bool open(); 87 | virtual bool close(void* cookie); 88 | virtual void send(void* cookie, const QByteArray& bin); 89 | virtual void close(); 90 | 91 | private slots: 92 | void newConnection(); 93 | void newData(); 94 | void error(); 95 | void close(QObject* obj); 96 | 97 | private: 98 | QTcpServer m_server; 99 | }; 100 | 101 | class ServerSktUdp : public ServerSkt 102 | { 103 | typedef struct _Conn 104 | { 105 | QHostAddress addr; 106 | quint16 port; 107 | QDateTime stamp; 108 | QString key; 109 | } Conn; 110 | 111 | Q_OBJECT 112 | 113 | public: 114 | ServerSktUdp(QObject *parent=0); 115 | virtual ~ServerSktUdp(); 116 | 117 | virtual QString name() const { return "UDP"; }; 118 | 119 | protected: 120 | virtual bool open(); 121 | virtual bool close(void* cookie); 122 | virtual void send(void* cookie, const QByteArray& bin); 123 | virtual void close(); 124 | 125 | private slots: 126 | void newData(); 127 | void error(); 128 | void check(); 129 | 130 | private: 131 | QUdpSocket m_server; 132 | QTimer m_timer; 133 | }; 134 | 135 | #endif // __SERVERSKT_H__ 136 | 137 | -------------------------------------------------------------------------------- /src/sokit/setting.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "setting.h" 7 | 8 | Setting::Setting() 9 | { 10 | QString path(QDir::currentPath()); 11 | if (!QFileInfo(path).isWritable() || 12 | path == QDir::homePath ()) 13 | { 14 | QDir dir(QDir::home()); 15 | dir.mkdir("." SET_APP_NAME); 16 | if (dir.cd("." SET_APP_NAME)) 17 | path = dir.absolutePath(); 18 | } 19 | 20 | QSettings::setPath(QSettings::IniFormat, QSettings::UserScope, path); 21 | } 22 | 23 | QSettings& Setting::storage() 24 | { 25 | static Setting dummy; // to ensure call QSettings::setPath before create the g_settings 26 | static QSettings g_settings(QSettings::IniFormat, QSettings::UserScope, SET_APP_NAME); 27 | return g_settings; 28 | } 29 | 30 | QString Setting::path() 31 | { 32 | return QFileInfo(storage().fileName()).dir().absolutePath(); 33 | } 34 | 35 | void Setting::flush() 36 | { 37 | storage().sync(); 38 | } 39 | 40 | void Setting::set(const QString& section, const QString& key, const QString& val) 41 | { 42 | storage().setValue(section+key, val); 43 | } 44 | 45 | QString Setting::get(const QString& section, const QString& key, const QString& def) 46 | { 47 | return storage().value(section+key, def).toString(); 48 | } 49 | 50 | void Setting::save(const QString& section, const QString& prefix, const QComboBox& cmb, bool all) 51 | { 52 | QSettings& store = storage(); 53 | 54 | store.beginGroup(section); 55 | 56 | QString tkey = prefix + SET_PFX_CMBTXT; 57 | 58 | QString tval = cmb.currentText().trimmed(); 59 | if (!tval.isEmpty()) 60 | store.setValue(tkey, tval); 61 | 62 | if (all) 63 | { 64 | QStringList keys, vals; 65 | 66 | keys = store.childKeys(); 67 | qint32 n = keys.size(); 68 | if (n > 0) 69 | { 70 | keys.sort(); 71 | 72 | while (n--) 73 | { 74 | QString k = keys[n]; 75 | if ((k!=tkey) && k.startsWith(prefix)) 76 | { 77 | QString v = store.value(k).toString().trimmed(); 78 | if (!v.isEmpty() && (-1 == cmb.findText(v))) 79 | vals.prepend(v); 80 | 81 | store.remove(k); 82 | } 83 | } 84 | } 85 | 86 | n = cmb.count(); 87 | if (n > SET_MAX_CMBITM) 88 | n = SET_MAX_CMBITM; 89 | 90 | qint32 i = 0; 91 | for (i=0; i SET_MAX_CMBITM) ? SET_MAX_CMBITM : vals.count(); 95 | for (qint32 j=0; i 0) 115 | { 116 | QString tval; 117 | QString tkey = prefix + SET_PFX_CMBTXT; 118 | 119 | keys.sort(); 120 | 121 | while (n--) 122 | { 123 | QString k = keys[n]; 124 | if (k.startsWith(prefix)) 125 | { 126 | QString v = store.value(k).toString().trimmed(); 127 | if (k == tkey) 128 | tval = v; 129 | else if (all && !v.isEmpty()) 130 | vals.append(v); 131 | } 132 | } 133 | 134 | vals.removeDuplicates(); 135 | 136 | n = vals.count(); 137 | if (n > 0) 138 | { 139 | if (n > SET_MAX_CMBITM) 140 | n = SET_MAX_CMBITM; 141 | 142 | while (n--) 143 | cmb.addItem(vals[n]); 144 | } 145 | 146 | if (!tval.isEmpty()) 147 | cmb.setEditText(tval); 148 | } 149 | 150 | store.endGroup(); 151 | } 152 | 153 | -------------------------------------------------------------------------------- /src/sokit/setting.h: -------------------------------------------------------------------------------- 1 | #ifndef __SETTING_H__ 2 | #define __SETTING_H__ 3 | 4 | #define SET_APP_NAME "sokit" 5 | 6 | #define SET_MAX_CMBITM 10 7 | #define SET_PFX_CMBITM "item" 8 | #define SET_PFX_CMBTXT 'x' 9 | 10 | #define SET_SEC_CFG "config" 11 | #define SET_SEC_DIR "dir" 12 | #define SET_KEY_LOG "/log" 13 | 14 | class QString; 15 | class QComboBox; 16 | class QSettings; 17 | class Setting 18 | { 19 | public: 20 | static void set(const QString& section, const QString& key, const QString& val); 21 | static QString get(const QString& section, const QString& key, const QString& def); 22 | 23 | static QString path(); 24 | static void save(const QString& section, const QString& prefix, const QComboBox& cmb, bool all=true); 25 | static void load(const QString& section, const QString& prefix, QComboBox& cmb, bool all=true); 26 | 27 | static void flush(); 28 | 29 | private: 30 | Setting(); 31 | static QSettings& storage(); 32 | }; 33 | 34 | #endif // __SETTING_H__ 35 | 36 | -------------------------------------------------------------------------------- /src/sokit/sokit.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liuqun/sokit/c458efc3f434daf5e0a72d88a982d5347ee5093c/src/sokit/sokit.ico -------------------------------------------------------------------------------- /src/sokit/sokit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liuqun/sokit/c458efc3f434daf5e0a72d88a982d5347ee5093c/src/sokit/sokit.png -------------------------------------------------------------------------------- /src/sokit/sokit.rc: -------------------------------------------------------------------------------- 1 | IDI_ICON1 ICON "sokit.ico" 2 | 3 | -------------------------------------------------------------------------------- /src/sokit/toolkit.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "toolkit.h" 9 | 10 | const char* TK::socketTypeName(bool tcp) 11 | { 12 | return tcp ? "TCP" : "UDP"; 13 | } 14 | 15 | const char* TK::socketTypeName(QAbstractSocket* skt) 16 | { 17 | return (skt->socketType()==QAbstractSocket::TcpSocket) ? "TCP" : "UDP"; 18 | } 19 | 20 | void TK::initNetworkInterfaces(QComboBox* box, bool testDef) 21 | { 22 | QString def; 23 | 24 | if (testDef) 25 | { 26 | def = box->currentText(); 27 | box->clearEditText(); 28 | } 29 | 30 | QList lst = QNetworkInterface::allAddresses(); 31 | foreach (QHostAddress a, lst) 32 | { 33 | if (QAbstractSocket::IPv4Protocol == a.protocol()) 34 | pushComboBox(box, a.toString()); 35 | } 36 | 37 | if (!def.isEmpty() && (-1 != box->findText(def))) 38 | box->setEditText(def); 39 | } 40 | 41 | void TK::pushComboBox(QComboBox* box, const QString& item) 42 | { 43 | if (-1==box->findText(item)) 44 | box->insertItem(0,item); 45 | } 46 | 47 | void TK::resetPushBox(QToolButton* btn) 48 | { 49 | if (btn->isChecked()) 50 | btn->click(); 51 | } 52 | 53 | QString TK::ipstr(const QHostAddress& addr, quint16 port) 54 | { 55 | return addr.toString() + ':' + QString::number(port); 56 | } 57 | 58 | QString TK::ipstr(const QHostAddress& addr, quint16 port, bool tcp) 59 | { 60 | return QString("%1 %2").arg((tcp?"[TCP]":"[UDP]"),ipstr(addr,port)); 61 | } 62 | 63 | bool TK::popIPAddr(QComboBox* ip, QComboBox* port, IPAddr& addr) 64 | { 65 | QString sip = ip->currentText().trimmed(); 66 | QString spt = port->currentText().trimmed(); 67 | 68 | bool res = false; 69 | addr.port = spt.toUShort(&res, 10); 70 | return (res && addr.ip.setAddress(sip)); 71 | } 72 | 73 | void TK::pushIPAddr(QComboBox* ip, QComboBox* port) 74 | { 75 | if (ip) 76 | pushComboBox(ip, ip->currentText().trimmed()); 77 | 78 | if (port) 79 | pushComboBox(port, port->currentText().trimmed()); 80 | } 81 | 82 | const char* TK::hextab = "0123456789ABCDEF"; 83 | 84 | #define TOHEXSTR(v, c, tab) \ 85 | if (v) { \ 86 | *c++ = tab[(v>>4)&0xF]; \ 87 | *c++ = tab[v & 0xF]; \ 88 | } 89 | 90 | QString TK::ascii2hex(const QString& src, QVector& posmap, uint& count) 91 | { 92 | posmap = src.toUcs4(); 93 | count = 0; 94 | 95 | uint val; 96 | char ch[16]; 97 | 98 | QString res; 99 | 100 | PARSE_STA status = OUT; 101 | 102 | int bound = 0; 103 | int hexpos = 0; 104 | 105 | int len = posmap.count(); 106 | for (int i=0; i= '0' && val <='9')|| 146 | (val >= 'A' && val <='F')) 147 | { 148 | status = IN; 149 | } 150 | else 151 | if (val >= 'a' && val <='f') 152 | { 153 | val = 'A' + (val - 'a'); 154 | status = IN; 155 | } 156 | else 157 | if (val == ' ') 158 | { 159 | status = IN; 160 | continue; 161 | } 162 | else 163 | { 164 | status = ERR; 165 | } 166 | } 167 | 168 | if (OUT == status) 169 | { 170 | if (bound & 1) 171 | { 172 | status = ERR; 173 | } 174 | else 175 | { 176 | t = val >> 24 & 0xFF; 177 | TOHEXSTR(t,c,hextab) 178 | 179 | t = val >> 16 & 0xFF; 180 | TOHEXSTR(t,c,hextab) 181 | 182 | t = val >> 8 & 0xFF; 183 | TOHEXSTR(t,c,hextab) 184 | 185 | t = val & 0xFF; 186 | TOHEXSTR(t,c,hextab) 187 | } 188 | bound = 0; 189 | } 190 | else 191 | if (IN == status) 192 | { 193 | bound += 1; 194 | *c++ = (char)val; 195 | } 196 | 197 | if (ERR == status) 198 | { 199 | res += QString("ERROR[%1]").arg(i); 200 | 201 | hexpos = 0; 202 | while (i < len) 203 | posmap[i++] = 0; 204 | 205 | break; 206 | } 207 | 208 | count += (c-ch); 209 | 210 | if (0 == (bound&1)) 211 | *c++ = ' '; 212 | 213 | *c = 0; 214 | 215 | res += ch; 216 | hexpos = res.length(); 217 | } 218 | 219 | posmap.append(hexpos); 220 | count /= 2; 221 | return res; 222 | } 223 | 224 | #undef TOHEXSTR 225 | 226 | QString TK::bin2hex(const char* buf, uint len) 227 | { 228 | char* tmp = new char[len * 3 + 3]; 229 | 230 | const char* s = buf; 231 | const char* e = buf + len; 232 | char* d = tmp; 233 | 234 | if (s && d) 235 | { 236 | *d++ = '['; 237 | 238 | while (s < e) 239 | { 240 | char c = *s++; 241 | *d++ = hextab[(c>>4)&0xF]; 242 | *d++ = hextab[c & 0xF]; 243 | *d++ = ' '; 244 | } 245 | 246 | *d++ = ']'; 247 | *d = 0; 248 | } 249 | 250 | QString res(tmp); 251 | 252 | delete tmp; 253 | 254 | return res; 255 | } 256 | 257 | QString TK::bin2ascii(const char* buf, uint len) 258 | { 259 | char* tmp = new char[len + 1]; 260 | 261 | const char* s = buf; 262 | const char* e = buf + len; 263 | char* d = tmp; 264 | 265 | if (s && d) 266 | { 267 | while (s < e) 268 | { 269 | char c = *s++; 270 | *d++ = isprint((uchar)c) ? c : '.'; 271 | } 272 | 273 | *d = 0; 274 | } 275 | 276 | QString res(tmp); 277 | 278 | delete tmp; 279 | 280 | return res; 281 | } 282 | 283 | bool TK::ascii2bin(const QString& src, QByteArray& dst, QString& err) 284 | { 285 | dst.clear(); 286 | err.clear(); 287 | 288 | QDataStream os(&dst, QIODevice::WriteOnly); 289 | 290 | 291 | QVector lst = src.toUcs4(); 292 | 293 | PARSE_STA status = OUT; 294 | 295 | int bound = 0; 296 | quint8 hexval = 0; 297 | 298 | int len = lst.count(); 299 | for (int i=0; i= '0' && val <='9') 333 | { 334 | val -= '0'; 335 | status = IN; 336 | } 337 | else 338 | if (val >= 'A' && val <='F') 339 | { 340 | val -= 'A'; 341 | val += 10; 342 | status = IN; 343 | } 344 | else 345 | if (val >= 'a' && val <='f') 346 | { 347 | val -= 'a'; 348 | val += 10; 349 | status = IN; 350 | } 351 | else 352 | if (val == ' ') 353 | { 354 | status = IN; 355 | continue; 356 | } 357 | else 358 | { 359 | status = ERR; 360 | } 361 | } 362 | 363 | if (OUT == status) 364 | { 365 | if (bound & 1) 366 | { 367 | status = ERR; 368 | } 369 | else 370 | { 371 | if (val >> 16) 372 | os << (quint32)val; 373 | else 374 | if (val >> 8) 375 | os << (quint16)val; 376 | else 377 | os << (quint8)val; 378 | } 379 | 380 | bound = 0; 381 | hexval = 0; 382 | } 383 | else 384 | if (IN == status) 385 | { 386 | if (bound & 1) 387 | os << (quint8)(((quint8)(val&0xF)) | (hexval<<4)); 388 | else 389 | hexval = (quint8)(val & 0xF); 390 | 391 | ++bound; 392 | } 393 | 394 | if (ERR == status) 395 | { 396 | dst.clear(); 397 | err.append(QString("ERROR[%1]").arg(i)); 398 | break; 399 | } 400 | } 401 | 402 | return (ERR != status); 403 | } 404 | 405 | char* TK::createBuffer(qint64& cap, qint64 limit) 406 | { 407 | if (cap < 0 || cap > limit) 408 | return 0; 409 | 410 | if (0 == cap) 411 | cap = 1; 412 | 413 | return new char[cap]; 414 | } 415 | 416 | void TK::releaseBuffer(char*& buf) 417 | { 418 | delete buf; 419 | buf = 0; 420 | } 421 | -------------------------------------------------------------------------------- /src/sokit/toolkit.h: -------------------------------------------------------------------------------- 1 | #ifndef __TOOLKIT_H__ 2 | #define __TOOLKIT_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class QComboBox; 9 | class QAbstractSocket; 10 | class QToolButton; 11 | 12 | typedef struct _IPAddr 13 | { 14 | QHostAddress ip; 15 | quint16 port; 16 | } IPAddr; 17 | 18 | class TK 19 | { 20 | public: 21 | typedef enum { OUT=0, OUT2IN, IN, ERR } PARSE_STA; 22 | 23 | static const char* hextab; 24 | static QString ascii2hex(const QString& src, QVector& posmap, uint& count); 25 | static QString bin2hex(const char* buf, uint len); 26 | static QString bin2ascii(const char* buf, uint len); 27 | static bool ascii2bin(const QString& src, QByteArray& dst, QString& err); 28 | 29 | static char* createBuffer(qint64& cap, qint64 limit); 30 | static void releaseBuffer(char*& buf); 31 | 32 | static const char* socketTypeName(bool tcp); 33 | static const char* socketTypeName(QAbstractSocket* skt); 34 | 35 | static void initNetworkInterfaces(QComboBox* box, bool testDef=false); 36 | 37 | static QString ipstr(const QHostAddress& addr, quint16 port); 38 | static QString ipstr(const QHostAddress& addr, quint16 port, bool tcp); 39 | static bool popIPAddr(QComboBox* ip, QComboBox* port, IPAddr& addr); 40 | static void pushIPAddr(QComboBox* ip, QComboBox* port); 41 | 42 | static void pushComboBox(QComboBox* box, const QString& item); 43 | static void resetPushBox(QToolButton* btn); 44 | }; 45 | 46 | #endif // __TOOLKIT_H__ 47 | 48 | -------------------------------------------------------------------------------- /src/sokit/transferform.cpp: -------------------------------------------------------------------------------- 1 | #include "toolkit.h" 2 | #include "setting.h" 3 | #include "transferskt.h" 4 | #include "transferform.h" 5 | 6 | #include 7 | 8 | #define SET_SEC_TRANS "transfer" 9 | #define SET_KEY_TRANS "/transfer" 10 | #define SET_KEY_CMBSA "/srcip" 11 | #define SET_KEY_CMBDA "/dstip" 12 | #define SET_KEY_CMBSP "/srcport" 13 | #define SET_KEY_CMBDP "/dstport" 14 | 15 | #define SET_VAL_LGTAN "log_transf" 16 | 17 | #define PROP_EDIT "edit" 18 | #define PROP_DIRT "dirt" 19 | 20 | TransferForm::TransferForm(QWidget *parent, Qt::WindowFlags flags) 21 | : BaseForm(parent, flags),m_server(0) 22 | { 23 | m_ui.setupUi(this); 24 | } 25 | 26 | TransferForm::~TransferForm() 27 | { 28 | if (m_server && lock(1000)) 29 | { 30 | m_server->disconnect(this); 31 | delete m_server; 32 | m_server = NULL; 33 | 34 | unlock(); 35 | } 36 | 37 | saveConfig(); 38 | } 39 | 40 | void TransferForm::initConfig() 41 | { 42 | QString sst(SET_SEC_TRANS); 43 | Setting::load(sst+SET_KEY_CMBSA, SET_PFX_CMBITM, *m_ui.cmbSrcAddr, false); 44 | Setting::load(sst+SET_KEY_CMBDA, SET_PFX_CMBITM, *m_ui.cmbDstAddr); 45 | Setting::load(sst+SET_KEY_CMBSP, SET_PFX_CMBITM, *m_ui.cmbSrcPort); 46 | Setting::load(sst+SET_KEY_CMBDP, SET_PFX_CMBITM, *m_ui.cmbDstPort); 47 | const quint16 FailSafeSrcPort = 8081; 48 | const quint16 FailSafeDstPort = 8082; 49 | if (m_ui.cmbSrcPort->currentText().length() <= 0) { 50 | m_ui.cmbSrcPort->setEditText(QString::number(FailSafeSrcPort)); 51 | } 52 | if (m_ui.cmbDstPort->currentText().length() <= 0) { 53 | m_ui.cmbDstPort->setEditText(QString::number(FailSafeDstPort)); 54 | } 55 | 56 | QString skl(SET_SEC_DIR); skl += SET_KEY_LOG; 57 | skl = Setting::get(skl, SET_KEY_TRANS, SET_VAL_LGTAN); 58 | setProperty(SET_SEC_DIR, skl); 59 | 60 | TK::initNetworkInterfaces(m_ui.cmbSrcAddr, true); 61 | TK::initNetworkInterfaces(m_ui.cmbDstAddr); 62 | } 63 | 64 | void TransferForm::saveConfig() 65 | { 66 | QString sst(SET_SEC_TRANS); 67 | Setting::save(sst+SET_KEY_CMBSA, SET_PFX_CMBITM, *m_ui.cmbSrcAddr, false); 68 | Setting::save(sst+SET_KEY_CMBDA, SET_PFX_CMBITM, *m_ui.cmbDstAddr); 69 | Setting::save(sst+SET_KEY_CMBSP, SET_PFX_CMBITM, *m_ui.cmbSrcPort); 70 | Setting::save(sst+SET_KEY_CMBDP, SET_PFX_CMBITM, *m_ui.cmbDstPort); 71 | 72 | QString skl(SET_SEC_DIR); skl += SET_KEY_LOG; 73 | Setting::set(skl, SET_KEY_TRANS, property(SET_SEC_DIR).toString()); 74 | } 75 | 76 | bool TransferForm::initForm() 77 | { 78 | initCounter(m_ui.labRecv, m_ui.labSend); 79 | initLogger(m_ui.chkLog, m_ui.btnClear, m_ui.treeOutput, m_ui.txtOutput); 80 | initLister(m_ui.btnConnAll, m_ui.btnConnDel, m_ui.lstConn); 81 | 82 | bindBuffer(1, m_ui.edtBuf1, m_ui.btnSend1, m_ui.cmbDir1); 83 | bindBuffer(2, m_ui.edtBuf2, m_ui.btnSend2, m_ui.cmbDir2); 84 | bindBuffer(3, m_ui.edtBuf3, m_ui.btnSend3, m_ui.cmbDir3); 85 | 86 | bindSelect(m_ui.cmbDir1, -1, Qt::Key_F5); 87 | bindSelect(m_ui.cmbDir2, -1, Qt::Key_F6); 88 | bindSelect(m_ui.cmbDir3, -1, Qt::Key_F7); 89 | 90 | connect(m_ui.btnTrigger, SIGNAL(clicked(bool)), this, SLOT(trigger(bool))); 91 | 92 | return true; 93 | } 94 | 95 | bool TransferForm::initHotkeys() 96 | { 97 | bindFocus(m_ui.cmbSrcAddr, Qt::Key_Escape); 98 | bindClick(m_ui.btnTrigger, Qt::CTRL + Qt::Key_S); 99 | bindSelect(m_ui.cmbType, 0, Qt::CTRL + Qt::Key_T); 100 | bindSelect(m_ui.cmbType, 1, Qt::CTRL + Qt::Key_U); 101 | 102 | return true; 103 | } 104 | 105 | void TransferForm::kill(QStringList& list) 106 | { 107 | if (m_server) 108 | { 109 | while (!list.isEmpty()) 110 | m_server->kill(list.takeFirst()); 111 | } 112 | } 113 | 114 | void TransferForm::trigger(bool start) 115 | { 116 | if (lock(1000)) 117 | { 118 | if (m_server) 119 | { 120 | m_server->stop(); 121 | m_server->disconnect(this); 122 | delete m_server; 123 | m_server = NULL; 124 | } 125 | 126 | IPAddr sa, da; 127 | if (start) 128 | { 129 | start = TK::popIPAddr(m_ui.cmbSrcAddr, m_ui.cmbSrcPort, sa) && 130 | TK::popIPAddr(m_ui.cmbDstAddr, m_ui.cmbDstPort, da); 131 | } 132 | 133 | if (start) 134 | { 135 | QString type = m_ui.cmbType->currentText(); 136 | if (type.contains(TK::socketTypeName(true))) 137 | m_server = new TransferSktTcp(this); 138 | else 139 | m_server = new TransferSktUdp(this); 140 | 141 | if (m_server) 142 | { 143 | connect(m_server, SIGNAL(connOpen(const QString&)), this, SLOT(listerAdd(const QString&))); 144 | connect(m_server, SIGNAL(connClose(const QString&)), this, SLOT(listerRemove(const QString&))); 145 | connect(m_server, SIGNAL(message(const QString&)), this, SIGNAL(output(const QString&))); 146 | connect(m_server, SIGNAL(dumpbin(const QString&,const char*,quint32)), this, SIGNAL(output(const QString&,const char*,quint32))); 147 | connect(m_server, SIGNAL(countRecv(qint32)), this, SLOT(countRecv(qint32))); 148 | connect(m_server, SIGNAL(countSend(qint32)), this, SLOT(countSend(qint32))); 149 | connect(m_server, SIGNAL(stopped()), this, SLOT(stop())); 150 | 151 | start = m_server->start(sa.ip, sa.port, da.ip, da.port); 152 | if (!start) 153 | { 154 | m_server->disconnect(this); 155 | delete m_server; 156 | m_server = NULL; 157 | } 158 | } 159 | else 160 | { 161 | start = false; 162 | } 163 | } 164 | 165 | unlock(); 166 | } 167 | 168 | m_ui.cmbSrcAddr->setDisabled(start); 169 | m_ui.cmbSrcPort->setDisabled(start); 170 | m_ui.cmbDstAddr->setDisabled(start); 171 | m_ui.cmbDstPort->setDisabled(start); 172 | m_ui.cmbType->setDisabled(start); 173 | 174 | if (start) 175 | { 176 | TK::pushIPAddr(m_ui.cmbSrcPort, m_ui.cmbSrcAddr); 177 | TK::pushIPAddr(0, m_ui.cmbDstPort); 178 | } 179 | else 180 | { 181 | TK::resetPushBox(m_ui.btnTrigger); 182 | } 183 | } 184 | 185 | void TransferForm::stop() 186 | { 187 | trigger(false); 188 | } 189 | 190 | void TransferForm::send(const QString& data, const QString& dir) 191 | { 192 | bool s2d = dir.startsWith('S'); 193 | 194 | if (m_server &&lock(1000)) 195 | { 196 | QStringList list; 197 | listerSelected(list); 198 | 199 | while (!list.isEmpty()) 200 | m_server->send(list.takeFirst(), s2d, data); 201 | 202 | unlock(); 203 | } 204 | } 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | -------------------------------------------------------------------------------- /src/sokit/transferform.h: -------------------------------------------------------------------------------- 1 | #ifndef __TRANSFERFORM_H__ 2 | #define __TRANSFERFORM_H__ 3 | 4 | #include "ui_transferform.h" 5 | #include "baseform.h" 6 | 7 | class TransferSkt; 8 | class TransferForm : public BaseForm 9 | { 10 | Q_OBJECT 11 | 12 | public: 13 | TransferForm(QWidget* p=0, Qt::WindowFlags f=0); 14 | ~TransferForm(); 15 | 16 | protected: 17 | virtual bool initForm(); 18 | virtual bool initHotkeys(); 19 | virtual void initConfig(); 20 | virtual void saveConfig(); 21 | virtual void send(const QString& data, const QString& dir); 22 | virtual void kill(QStringList& list); 23 | 24 | private slots: 25 | void trigger(bool start); 26 | void stop(); 27 | 28 | private: 29 | TransferSkt* m_server; 30 | Ui::TransferForm m_ui; 31 | }; 32 | 33 | #endif // __TRANSFERFORM_H__ 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/sokit/transferform.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | TransferForm 4 | 5 | 6 | 7 | 0 8 | 0 9 | 680 10 | 450 11 | 12 | 13 | 14 | 15 | 0 16 | 0 17 | 18 | 19 | 20 | Transfer 21 | 22 | 23 | 24 | 25 | 26 | 27 | 5 28 | 29 | 30 | 5 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 0 39 | 0 40 | 41 | 42 | 43 | 44 | 0 45 | 93 46 | 47 | 48 | 49 | 50 | 16777215 51 | 93 52 | 53 | 54 | 55 | Network Setup 56 | 57 | 58 | 59 | 5 60 | 61 | 62 | 4 63 | 64 | 65 | 0 66 | 67 | 68 | 10 69 | 70 | 71 | 5 72 | 73 | 74 | 75 | 76 | QLayout::SetFixedSize 77 | 78 | 79 | 5 80 | 81 | 82 | 8 83 | 84 | 85 | 86 | 87 | 88 | 0 89 | 0 90 | 91 | 92 | 93 | Port: 94 | 95 | 96 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 0 105 | 0 106 | 107 | 108 | 109 | 110 | 70 111 | 0 112 | 113 | 114 | 115 | Qt::NoContextMenu 116 | 117 | 118 | SRC Addr: 119 | 120 | 121 | Qt::PlainText 122 | 123 | 124 | false 125 | 126 | 127 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 0 136 | 0 137 | 138 | 139 | 140 | 141 | 130 142 | 24 143 | 144 | 145 | 146 | 147 | 130 148 | 24 149 | 150 | 151 | 152 | true 153 | 154 | 155 | QComboBox::NoInsert 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 0 164 | 0 165 | 166 | 167 | 168 | 169 | 75 170 | 24 171 | 172 | 173 | 174 | 175 | 75 176 | 24 177 | 178 | 179 | 180 | true 181 | 182 | 183 | QComboBox::InsertAtTop 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 0 192 | 0 193 | 194 | 195 | 196 | 197 | 70 198 | 0 199 | 200 | 201 | 202 | Qt::NoContextMenu 203 | 204 | 205 | DST Addr: 206 | 207 | 208 | Qt::PlainText 209 | 210 | 211 | false 212 | 213 | 214 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 0 223 | 0 224 | 225 | 226 | 227 | 228 | 130 229 | 24 230 | 231 | 232 | 233 | 234 | 130 235 | 24 236 | 237 | 238 | 239 | true 240 | 241 | 242 | QComboBox::NoInsert 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 0 251 | 0 252 | 253 | 254 | 255 | Port: 256 | 257 | 258 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 0 267 | 0 268 | 269 | 270 | 271 | 272 | 75 273 | 24 274 | 275 | 276 | 277 | 278 | 75 279 | 24 280 | 281 | 282 | 283 | true 284 | 285 | 286 | QComboBox::InsertAtTop 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 0 295 | 0 296 | 297 | 298 | 299 | 300 | 90 301 | 24 302 | 303 | 304 | 305 | 306 | 90 307 | 24 308 | 309 | 310 | 311 | 312 | 313 | 314 | Start 315 | 316 | 317 | true 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 0 326 | 0 327 | 328 | 329 | 330 | 331 | 90 332 | 24 333 | 334 | 335 | 336 | 337 | 90 338 | 24 339 | 340 | 341 | 342 | 343 | -- TCP -- 344 | 345 | 346 | 347 | 348 | -- UDP -- 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 0 363 | 0 364 | 365 | 366 | 367 | 368 | 0 369 | 93 370 | 371 | 372 | 373 | 374 | 16777215 375 | 93 376 | 377 | 378 | 379 | Connections 380 | 381 | 382 | 383 | 5 384 | 385 | 386 | 10 387 | 388 | 389 | 5 390 | 391 | 392 | 10 393 | 394 | 395 | 10 396 | 397 | 398 | 399 | 400 | 401 | 0 402 | 0 403 | 404 | 405 | 406 | 407 | 0 408 | 58 409 | 410 | 411 | 412 | 413 | 16777215 414 | 58 415 | 416 | 417 | 418 | Qt::ScrollBarAlwaysOff 419 | 420 | 421 | Qt::ScrollBarAlwaysOff 422 | 423 | 424 | QAbstractItemView::NoEditTriggers 425 | 426 | 427 | false 428 | 429 | 430 | QAbstractItemView::MultiSelection 431 | 432 | 433 | QAbstractItemView::SelectRows 434 | 435 | 436 | false 437 | 438 | 439 | 440 | 441 | 442 | 443 | 10 444 | 445 | 446 | 0 447 | 448 | 449 | 450 | 451 | 452 | 0 453 | 0 454 | 455 | 456 | 457 | 458 | 0 459 | 24 460 | 461 | 462 | 463 | 464 | 16777215 465 | 24 466 | 467 | 468 | 469 | All 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 0 478 | 0 479 | 480 | 481 | 482 | 483 | 0 484 | 24 485 | 486 | 487 | 488 | 489 | 16777215 490 | 24 491 | 492 | 493 | 494 | Disconn 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 5 509 | 510 | 511 | 5 512 | 513 | 514 | 515 | 516 | Buf 1: 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 60 525 | 24 526 | 527 | 528 | 529 | 530 | 60 531 | 24 532 | 533 | 534 | 535 | Send 536 | 537 | 538 | false 539 | 540 | 541 | 542 | 543 | 544 | 545 | Buf 2: 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 0 554 | 24 555 | 556 | 557 | 558 | 559 | 16777215 560 | 24 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 60 570 | 24 571 | 572 | 573 | 574 | 575 | 60 576 | 24 577 | 578 | 579 | 580 | Send 581 | 582 | 583 | 584 | 585 | 586 | 587 | Buf 3: 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 0 596 | 24 597 | 598 | 599 | 600 | 601 | 16777215 602 | 24 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 60 612 | 24 613 | 614 | 615 | 616 | 617 | 60 618 | 24 619 | 620 | 621 | 622 | Send 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 0 631 | 24 632 | 633 | 634 | 635 | 636 | 16777215 637 | 24 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 0 647 | 0 648 | 649 | 650 | 651 | 652 | 0 653 | 24 654 | 655 | 656 | 657 | 658 | 16777215 659 | 24 660 | 661 | 662 | 663 | true 664 | 665 | 666 | 667 | S -> D 668 | 669 | 670 | 671 | 672 | D -> S 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 0 682 | 0 683 | 684 | 685 | 686 | 687 | 0 688 | 24 689 | 690 | 691 | 692 | 693 | 16777215 694 | 24 695 | 696 | 697 | 698 | 699 | S -> D 700 | 701 | 702 | 703 | 704 | D -> S 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 0 714 | 0 715 | 716 | 717 | 718 | 719 | 0 720 | 24 721 | 722 | 723 | 724 | 725 | 16777215 726 | 24 727 | 728 | 729 | 730 | 731 | S -> D 732 | 733 | 734 | 735 | 736 | D -> S 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 5 747 | 748 | 749 | 0 750 | 751 | 752 | 5 753 | 754 | 755 | 0 756 | 757 | 758 | 0 759 | 760 | 761 | 762 | 763 | 764 | 0 765 | 0 766 | 767 | 768 | 769 | Output: 770 | 771 | 772 | 773 | 774 | 775 | 776 | Recv 777 | 778 | 779 | 780 | 781 | 782 | 783 | 784 | 0 785 | 0 786 | 787 | 788 | 789 | 790 | 791 | 792 | 0 793 | 794 | 795 | 796 | 797 | 798 | 799 | , Send 800 | 801 | 802 | 803 | 804 | 805 | 806 | 807 | 808 | 809 | 0 810 | 811 | 812 | 813 | 814 | 815 | 816 | Qt::Horizontal 817 | 818 | 819 | 820 | 0 821 | 0 822 | 823 | 824 | 825 | 826 | 827 | 828 | 829 | Write log 830 | 831 | 832 | 833 | 834 | 835 | 836 | 837 | 60 838 | 24 839 | 840 | 841 | 842 | 843 | 60 844 | 24 845 | 846 | 847 | 848 | Clear 849 | 850 | 851 | 852 | 853 | 854 | 855 | 856 | 857 | 858 | 0 859 | 0 860 | 861 | 862 | 863 | Qt::ScrollBarAlwaysOff 864 | 865 | 866 | QAbstractItemView::NoEditTriggers 867 | 868 | 869 | false 870 | 871 | 872 | false 873 | 874 | 875 | QAbstractItemView::SingleSelection 876 | 877 | 878 | QAbstractItemView::SelectRows 879 | 880 | 881 | true 882 | 883 | 884 | false 885 | 886 | 887 | true 888 | 889 | 890 | 891 | 1 892 | 893 | 894 | 895 | 896 | 897 | 898 | 899 | 900 | 0 901 | 0 902 | 903 | 904 | 905 | 906 | 0 907 | 70 908 | 909 | 910 | 911 | 912 | 16777215 913 | 70 914 | 915 | 916 | 917 | false 918 | 919 | 920 | QFrame::Box 921 | 922 | 923 | QFrame::Plain 924 | 925 | 926 | Qt::ScrollBarAlwaysOff 927 | 928 | 929 | true 930 | 931 | 932 | false 933 | 934 | 935 | true 936 | 937 | 938 | Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse 939 | 940 | 941 | 942 | 943 | 944 | 945 | cmbSrcAddr 946 | cmbSrcPort 947 | cmbDstAddr 948 | cmbDstPort 949 | cmbType 950 | btnTrigger 951 | lstConn 952 | btnConnAll 953 | btnConnDel 954 | edtBuf1 955 | cmbDir1 956 | btnSend1 957 | edtBuf2 958 | cmbDir2 959 | btnSend2 960 | edtBuf3 961 | cmbDir3 962 | btnSend3 963 | chkLog 964 | btnClear 965 | treeOutput 966 | 967 | 968 | 969 | 970 | -------------------------------------------------------------------------------- /src/sokit/transferskt.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "toolkit.h" 5 | #include "transferskt.h" 6 | 7 | #define PROP_CONN "CONN" 8 | 9 | #define MAXBUFFER 1024*1024 10 | 11 | TransferSkt::TransferSkt(QObject *parent) 12 | : QObject(parent),m_spt(0),m_dpt(0) 13 | { 14 | } 15 | 16 | TransferSkt::~TransferSkt() 17 | { 18 | } 19 | 20 | bool TransferSkt::start(const QHostAddress& sip, quint16 spt, const QHostAddress& dip, quint16 dpt) 21 | { 22 | m_sip = sip; 23 | m_dip = dip; 24 | m_spt = spt; 25 | m_dpt = dpt; 26 | 27 | m_conns.clear(); 28 | m_error.clear(); 29 | 30 | bool res = open(); 31 | 32 | QString msg("start %1 transfer server %2!"); 33 | if (!res) 34 | { 35 | msg = msg.arg(name(),"failed"); 36 | if (!m_error.isEmpty()) 37 | { msg += " error:["; 38 | msg += m_error; 39 | msg += "]."; 40 | } 41 | } 42 | else 43 | { 44 | msg = msg.arg(name(),"successfully"); 45 | } 46 | 47 | show(msg); 48 | 49 | return res; 50 | } 51 | 52 | void TransferSkt::stop() 53 | { 54 | OBJMAP::const_iterator i; 55 | for (i = m_conns.constBegin(); i != m_conns.constEnd(); ++i) 56 | { 57 | QString k = i.key(); 58 | void* v = i.value(); 59 | 60 | if (close(v)) 61 | emit connClose(k); 62 | } 63 | 64 | m_conns.clear(); 65 | 66 | close(); 67 | 68 | show(QString("stop %1 transfer server!").arg(name())); 69 | } 70 | 71 | void TransferSkt::setError(const QString& err) 72 | { 73 | m_error = err; 74 | } 75 | 76 | void TransferSkt::recordRecv(qint32 bytes) 77 | { 78 | emit countRecv(bytes); 79 | } 80 | 81 | void TransferSkt::recordSend(qint32 bytes) 82 | { 83 | emit countSend(bytes); 84 | } 85 | 86 | void TransferSkt::getKeys(QStringList& res) 87 | { 88 | res = m_conns.keys(); 89 | } 90 | 91 | void TransferSkt::setCookie(const QString& k, void* v) 92 | { 93 | void* o = m_conns.value(k); 94 | if (o) 95 | { 96 | if (close(o)) 97 | emit connClose(k); 98 | } 99 | 100 | m_conns.insert(k, v); 101 | emit connOpen(k); 102 | } 103 | 104 | void TransferSkt::unsetCookie(const QString& k) 105 | { 106 | m_conns.remove(k); 107 | emit connClose(k); 108 | } 109 | 110 | void* TransferSkt::getCookie(const QString& k) 111 | { 112 | return m_conns.value(k); 113 | } 114 | 115 | void TransferSkt::kill(const QString& key) 116 | { 117 | void* v = m_conns.value(key); 118 | if (v) 119 | { 120 | if (close(v)) 121 | unsetCookie(key); 122 | } 123 | else 124 | { 125 | unsetCookie(key); 126 | } 127 | } 128 | 129 | void TransferSkt::send(const QString& key, bool s2d, const QString& data) 130 | { 131 | void* v = m_conns.value(key); 132 | if (v) 133 | { 134 | QString err; 135 | QByteArray bin; 136 | 137 | if (!TK::ascii2bin(data, bin, err)) 138 | show("bad data format to send: "+err); 139 | else 140 | send(v, s2d, bin); 141 | } 142 | } 143 | 144 | void TransferSkt::dump(const char* buf, qint32 len, TransferSkt::DIR dir, const QString& key) 145 | { 146 | QString title("TRN"); 147 | switch (dir) 148 | { 149 | case TS2D: title += " -->> "; break; 150 | case TD2S: title += " <<-- "; break; 151 | case SS2D: title += " --+> "; break; 152 | case SD2S: title += " <+-- "; break; 153 | default: title += " ???? "; break; 154 | } 155 | title += key; 156 | 157 | emit dumpbin(title, buf, (quint32)len); 158 | } 159 | 160 | void TransferSkt::show(const QString& msg) 161 | { 162 | emit message(msg); 163 | } 164 | 165 | TransferSktTcp::TransferSktTcp(QObject *parent) 166 | :TransferSkt(parent) 167 | { 168 | } 169 | 170 | TransferSktTcp::~TransferSktTcp() 171 | { 172 | m_server.disconnect(this); 173 | } 174 | 175 | bool TransferSktTcp::open() 176 | { 177 | if (m_server.listen(srcAddr(), srcPort())) 178 | { 179 | connect(&m_server, SIGNAL(newConnection()), this, SLOT(newConnection())); 180 | 181 | return true; 182 | } 183 | else 184 | { 185 | setError(QString("%1, %2").arg(m_server.serverError()).arg(m_server.errorString())); 186 | } 187 | 188 | return false; 189 | } 190 | 191 | bool TransferSktTcp::close(void* cookie) 192 | { 193 | Conn* conn = (Conn*)cookie; 194 | 195 | if (conn->src) 196 | conn->src->disconnect(this); 197 | 198 | if (conn->dst) 199 | conn->dst->disconnect(this); 200 | 201 | delete conn->src; 202 | delete conn->dst; 203 | delete conn; 204 | 205 | return true; 206 | } 207 | 208 | void TransferSktTcp::close(QObject* obj) 209 | { 210 | QMutexLocker locker(&m_door); 211 | 212 | Conn* conn = (Conn*)obj->property(PROP_CONN).value(); 213 | if (!conn) return; 214 | 215 | if (conn->src) 216 | { 217 | conn->src->disconnect(this); 218 | 219 | if (obj == conn->dst) 220 | conn->src->deleteLater(); 221 | } 222 | 223 | if (conn->dst) 224 | { 225 | conn->dst->disconnect(this); 226 | 227 | if (obj == conn->src) 228 | conn->dst->deleteLater(); 229 | } 230 | 231 | unsetCookie(conn->key); 232 | delete conn; 233 | } 234 | 235 | void TransferSktTcp::error() 236 | { 237 | QTcpSocket* s = qobject_cast(sender()); 238 | 239 | show(QString("TCP socket error %1, %2").arg(s->error()).arg(s->errorString())); 240 | 241 | s->deleteLater(); 242 | } 243 | 244 | void TransferSktTcp::close() 245 | { 246 | m_server.close(); 247 | m_server.disconnect(this); 248 | } 249 | 250 | void TransferSktTcp::newConnection() 251 | { 252 | QTcpServer* svr = qobject_cast(sender()); 253 | if (!svr) return; 254 | 255 | QTcpSocket* src = svr->nextPendingConnection(); 256 | while (src) 257 | { 258 | Conn* conn = new Conn; 259 | if (!conn) 260 | { 261 | src->deleteLater(); 262 | } 263 | else 264 | { 265 | QTcpSocket* dst = new QTcpSocket(); 266 | if (!dst) 267 | { 268 | delete conn; 269 | src->deleteLater(); 270 | } 271 | else 272 | { 273 | src->setProperty(PROP_CONN, qVariantFromValue((void*)conn)); 274 | dst->setProperty(PROP_CONN, qVariantFromValue((void*)conn)); 275 | 276 | conn->src = src; 277 | conn->dst = dst; 278 | conn->key = TK::ipstr(src->peerAddress(),src->peerPort()); 279 | 280 | connect(src, SIGNAL(readyRead()), this, SLOT(newData())); 281 | connect(src, SIGNAL(destroyed(QObject*)), this, SLOT(close(QObject*))); 282 | connect(src, SIGNAL(disconnected()), src, SLOT(deleteLater())); 283 | connect(src, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error())); 284 | 285 | connect(dst, SIGNAL(readyRead()), this, SLOT(newData())); 286 | connect(dst, SIGNAL(destroyed(QObject*)), this, SLOT(close(QObject*))); 287 | connect(dst, SIGNAL(disconnected()), dst, SLOT(deleteLater())); 288 | connect(dst, SIGNAL(connected()), this, SLOT(asynConnection())); 289 | connect(dst, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error())); 290 | 291 | dst->connectToHost(dstAddr(), dstPort()); 292 | 293 | setCookie(conn->key, conn); 294 | } 295 | } 296 | src = svr->nextPendingConnection(); 297 | } 298 | } 299 | 300 | void TransferSktTcp::asynConnection() 301 | { 302 | QTcpSocket* s = qobject_cast(sender()); 303 | if (!s) return; 304 | 305 | Conn* conn = (Conn*)s->property(PROP_CONN).value(); 306 | if (!conn) return; 307 | 308 | show(QString("connection %1 to %2:%3 opened!") 309 | .arg(conn->key, s->peerName()).arg(s->peerPort())); 310 | } 311 | 312 | void TransferSktTcp::newData() 313 | { 314 | QMutexLocker locker(&m_door); 315 | 316 | QTcpSocket* s = qobject_cast(sender()); 317 | if (!s) return; 318 | 319 | Conn* conn = (Conn*)s->property(PROP_CONN).value(); 320 | if (!conn) return; 321 | 322 | QTcpSocket* d = (s == conn->src) ? conn->dst : conn->src; 323 | 324 | qint64 bufLen = s->bytesAvailable(); 325 | char* buf = TK::createBuffer(bufLen, MAXBUFFER); 326 | if (!buf) return; 327 | 328 | qint64 readLen, writeLen, ioLen; 329 | 330 | readLen = 0; 331 | ioLen = s->read(buf, bufLen); 332 | while (ioLen > 0) 333 | { 334 | readLen += ioLen; 335 | ioLen = s->read(buf+readLen, bufLen-readLen); 336 | } 337 | 338 | if (ioLen >= 0) 339 | { 340 | recordRecv(readLen); 341 | 342 | writeLen = 0; 343 | ioLen = d->write(buf, readLen); 344 | while (ioLen > 0) 345 | { 346 | writeLen += ioLen; 347 | ioLen = d->write(buf+writeLen, readLen-writeLen); 348 | } 349 | 350 | if (ioLen >= 0) 351 | { 352 | recordSend(writeLen); 353 | dump(buf, readLen, ((s==conn->src) ? TS2D:TD2S), conn->key); 354 | } 355 | } 356 | 357 | TK::releaseBuffer(buf); 358 | } 359 | 360 | void TransferSktTcp::send(void* cookie, bool s2d, const QByteArray& bin) 361 | { 362 | Conn* conn = (Conn*)cookie; 363 | 364 | QTcpSocket* d = s2d ? conn->dst : conn->src; 365 | QHostAddress a = s2d ? dstAddr() : conn->src->peerAddress(); 366 | quint16 p = s2d ? dstPort() : conn->src->peerPort(); 367 | 368 | const char * src = bin.constData(); 369 | qint64 srcLen = bin.length(); 370 | 371 | qint64 writeLen = 0; 372 | qint64 ioLen = d->write(src, srcLen); 373 | 374 | while (ioLen > 0) 375 | { 376 | writeLen += ioLen; 377 | ioLen = d->write(src+writeLen, srcLen-writeLen); 378 | } 379 | 380 | if (writeLen != srcLen) 381 | { 382 | show(QString("failed to send data to %1:%2 [%3]") 383 | .arg(a.toString()).arg(p).arg(writeLen)); 384 | return; 385 | } 386 | 387 | recordSend(writeLen); 388 | dump(src, srcLen, (s2d?SS2D:SD2S), conn->key); 389 | } 390 | 391 | TransferSktUdp::TransferSktUdp(QObject *parent) 392 | :TransferSkt(parent) 393 | { 394 | } 395 | 396 | TransferSktUdp::~TransferSktUdp() 397 | { 398 | m_server.disconnect(this); 399 | } 400 | 401 | void TransferSktUdp::error() 402 | { 403 | QUdpSocket* s = qobject_cast(sender()); 404 | 405 | show(QString("UDP socket error %1, %2").arg(s->error()).arg(s->errorString())); 406 | 407 | if (s != &m_server) 408 | s->deleteLater(); 409 | } 410 | 411 | bool TransferSktUdp::open() 412 | { 413 | if (m_server.bind(srcAddr(), srcPort(), QUdpSocket::ShareAddress)) 414 | { 415 | connect(&m_server, SIGNAL(readyRead()), this, SLOT(newData())); 416 | connect(&m_server, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error())); 417 | connect(&m_timer, SIGNAL(timeout()), this, SLOT(check())); 418 | 419 | m_timer.start(2000); 420 | return true; 421 | } 422 | else 423 | { 424 | setError(QString("%1, %2").arg(m_server.error()).arg(m_server.errorString())); 425 | } 426 | 427 | return false; 428 | } 429 | 430 | bool TransferSktUdp::close(void* cookie) 431 | { 432 | Conn* conn = (Conn*)cookie; 433 | 434 | if (conn->dst) 435 | conn->dst->disconnect(this); 436 | 437 | delete conn->dst; 438 | delete conn; 439 | 440 | return true; 441 | } 442 | 443 | void TransferSktUdp::close(QObject* obj) 444 | { 445 | Conn* conn = (Conn*)obj->property(PROP_CONN).value(); 446 | if (!conn) return; 447 | 448 | unsetCookie(conn->key); 449 | delete conn; 450 | } 451 | 452 | void TransferSktUdp::close() 453 | { 454 | m_timer.disconnect(this); 455 | m_timer.stop(); 456 | m_server.close(); 457 | m_server.disconnect(this); 458 | } 459 | 460 | void TransferSktUdp::newData() 461 | { 462 | QUdpSocket* s = qobject_cast(sender()); 463 | if (!s) return; 464 | 465 | qint64 bufLen = s->pendingDatagramSize(); 466 | char* buf = TK::createBuffer(bufLen, MAXBUFFER); 467 | if (!buf) return; 468 | 469 | QHostAddress addr; quint16 port(0); 470 | 471 | qint64 readLen = 0; 472 | qint64 ioLen = s->readDatagram(buf, bufLen, &addr, &port); 473 | 474 | //while (ioLen > 0) 475 | //{ 476 | readLen += ioLen; 477 | // ioLen = s->readDatagram(buf+readLen, bufLen-readLen, &addr, &port); 478 | //} 479 | 480 | if (ioLen >= 0) 481 | { 482 | Conn* conn = NULL; 483 | if (s == &m_server) 484 | { 485 | conn = (Conn*)getCookie(TK::ipstr(addr, port)); 486 | if (!conn) 487 | { 488 | conn = new Conn; 489 | if (conn) 490 | { 491 | QUdpSocket* dst = new QUdpSocket(); 492 | if (!dst) 493 | { 494 | delete conn; 495 | conn = NULL; 496 | } 497 | else 498 | { 499 | dst->setProperty(PROP_CONN, qVariantFromValue((void*)conn)); 500 | 501 | conn->dst = dst; 502 | conn->key = TK::ipstr(addr, port); 503 | conn->addr = addr; 504 | conn->port = port; 505 | 506 | connect(dst, SIGNAL(readyRead()), this, SLOT(newData())); 507 | connect(dst, SIGNAL(destroyed(QObject*)), this, SLOT(close(QObject*))); 508 | connect(dst, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error())); 509 | 510 | dst->connectToHost(dstAddr(), dstPort()); 511 | 512 | setCookie(conn->key, conn); 513 | } 514 | } 515 | } 516 | } 517 | else 518 | { 519 | conn = (Conn*)s->property(PROP_CONN).value(); 520 | if (!conn) 521 | { 522 | s->disconnect(this); 523 | s->deleteLater(); 524 | } 525 | } 526 | 527 | if (conn) 528 | { 529 | recordRecv(readLen); 530 | 531 | conn->stamp = QDateTime::currentDateTime(); 532 | 533 | qint64 writeLen = 0; 534 | if (s == &m_server) 535 | { 536 | ioLen = conn->dst->write(buf, readLen); 537 | while (ioLen > 0) 538 | { 539 | writeLen += ioLen; 540 | ioLen = (writeLen >= readLen) ? 0 : 541 | conn->dst->write(buf+writeLen, readLen-writeLen); 542 | } 543 | 544 | dump(buf, readLen, TS2D, conn->key); 545 | } 546 | else 547 | { 548 | ioLen = m_server.writeDatagram(buf, readLen, conn->addr, conn->port); 549 | while (ioLen > 0) 550 | { 551 | writeLen += ioLen; 552 | ioLen = (writeLen >= readLen) ? 0 : 553 | m_server.writeDatagram(buf+writeLen, readLen-writeLen, conn->addr, conn->port); 554 | } 555 | 556 | dump(buf, readLen, TD2S, conn->key); 557 | } 558 | 559 | recordSend(writeLen); 560 | } 561 | } 562 | 563 | TK::releaseBuffer(buf); 564 | } 565 | 566 | void TransferSktUdp::send(void* cookie, bool s2d, const QByteArray& bin) 567 | { 568 | Conn* conn = (Conn*)cookie; 569 | 570 | QHostAddress a = s2d ? dstAddr() : conn->addr; 571 | quint16 p = s2d ? dstPort() : conn->port; 572 | 573 | const char * src = bin.constData(); 574 | qint64 srcLen = bin.length(); 575 | 576 | qint64 writeLen = 0; 577 | qint64 ioLen = s2d ? conn->dst->write(src, srcLen) : m_server.writeDatagram(src, srcLen, a, p); 578 | 579 | while (ioLen > 0) 580 | { 581 | writeLen += ioLen; 582 | 583 | if (writeLen >= srcLen) 584 | break; 585 | 586 | ioLen = s2d ? conn->dst->write(src+writeLen, srcLen-writeLen) : 587 | m_server.writeDatagram(src+writeLen, srcLen-writeLen, a, p); 588 | } 589 | 590 | if (writeLen != srcLen) 591 | { 592 | show(QString("failed to send data to %1:%2 [%3]") 593 | .arg(a.toString()).arg(p).arg(writeLen)); 594 | return; 595 | } 596 | 597 | recordSend(writeLen); 598 | dump(src, srcLen, (s2d?SS2D:SD2S), conn->key); 599 | } 600 | 601 | void TransferSktUdp::check() 602 | { 603 | QStringList list; 604 | getKeys(list); 605 | 606 | while (!list.isEmpty()) 607 | { 608 | QString k = list.takeFirst(); 609 | 610 | void* c = getCookie(k); 611 | 612 | if (c && (((Conn*)c)->stamp.addSecs(120) < QDateTime::currentDateTime())) 613 | { 614 | close(c); 615 | unsetCookie(k); 616 | } 617 | } 618 | } 619 | 620 | -------------------------------------------------------------------------------- /src/sokit/transferskt.h: -------------------------------------------------------------------------------- 1 | #ifndef __TRANSFERSKT_H__ 2 | #define __TRANSFERSKT_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | class TransferSkt : public QObject 12 | { 13 | typedef QHash OBJMAP; 14 | 15 | Q_OBJECT 16 | 17 | public: 18 | TransferSkt(QObject *parent=0); 19 | virtual ~TransferSkt(); 20 | 21 | virtual QString name() const { return "General"; }; 22 | 23 | bool start(const QHostAddress& sip, quint16 spt, const QHostAddress& dip, quint16 dpt); 24 | void kill(const QString& key); 25 | void stop(); 26 | 27 | void send(const QString& key, bool s2d, const QString& data); 28 | 29 | const QHostAddress& srcAddr() const { return m_sip; }; 30 | const QHostAddress& dstAddr() const { return m_dip; }; 31 | 32 | quint16 srcPort() const { return m_spt; }; 33 | quint16 dstPort() const { return m_dpt; }; 34 | 35 | signals: 36 | void connOpen(const QString& key); 37 | void connClose(const QString& key); 38 | void message(const QString& msg); 39 | void dumpbin(const QString& title, const char* data, quint32 len); 40 | void stopped(); 41 | 42 | void countRecv(qint32 bytes); 43 | void countSend(qint32 bytes); 44 | 45 | protected: 46 | enum DIR { TS2D, TD2S, SS2D, SD2S, }; 47 | void dump(const char* buf, qint32 len, DIR dir, const QString& key); 48 | void show(const QString& msg); 49 | 50 | void setError(const QString& err); 51 | 52 | void recordRecv(qint32 bytes); 53 | void recordSend(qint32 bytes); 54 | 55 | void getKeys(QStringList& res); 56 | void setCookie(const QString& k, void* v); 57 | void unsetCookie(const QString& k); 58 | void* getCookie(const QString& k); 59 | 60 | 61 | virtual bool open() =0; 62 | virtual bool close(void* cookie) =0; 63 | virtual void send(void* cookie, bool s2d, const QByteArray& bin) =0; 64 | virtual void close() =0; 65 | 66 | private: 67 | QHostAddress m_sip; 68 | QHostAddress m_dip; 69 | 70 | quint16 m_spt; 71 | quint16 m_dpt; 72 | 73 | OBJMAP m_conns; 74 | QString m_error; 75 | }; 76 | 77 | class TransferSktTcp : public TransferSkt 78 | { 79 | typedef struct _Conn 80 | { 81 | QTcpSocket* src; 82 | QTcpSocket* dst; 83 | QString key; 84 | } Conn; 85 | 86 | Q_OBJECT 87 | 88 | public: 89 | TransferSktTcp(QObject *parent=0); 90 | virtual ~TransferSktTcp(); 91 | 92 | virtual QString name() const { return "TCP"; }; 93 | 94 | protected: 95 | virtual bool open(); 96 | virtual bool close(void* cookie); 97 | virtual void send(void* cookie, bool s2d, const QByteArray& bin); 98 | virtual void close(); 99 | 100 | private slots: 101 | void newConnection(); 102 | void asynConnection(); 103 | void newData(); 104 | void error(); 105 | void close(QObject* obj); 106 | 107 | private: 108 | QTcpServer m_server; 109 | QMutex m_door; 110 | }; 111 | 112 | class TransferSktUdp : public TransferSkt 113 | { 114 | typedef struct _Conn 115 | { 116 | QUdpSocket* dst; 117 | QHostAddress addr; 118 | quint16 port; 119 | QDateTime stamp; 120 | QString key; 121 | } Conn; 122 | 123 | Q_OBJECT 124 | 125 | public: 126 | TransferSktUdp(QObject *parent=0); 127 | virtual ~TransferSktUdp(); 128 | 129 | virtual QString name() const { return "UDP"; }; 130 | 131 | protected: 132 | virtual bool open(); 133 | virtual bool close(void* cookie); 134 | virtual void send(void* cookie, bool s2d, const QByteArray& bin); 135 | virtual void close(); 136 | 137 | private slots: 138 | void newData(); 139 | void error(); 140 | void check(); 141 | void close(QObject* obj); 142 | 143 | private: 144 | QUdpSocket m_server; 145 | QTimer m_timer; 146 | }; 147 | 148 | #endif // __TRANSFERSKT_H__ 149 | 150 | --------------------------------------------------------------------------------