]> git.zarvox.org Git - imoo.git/commitdiff
Add a TCP socket server
authorDrew Fisher <drew.m.fisher@gmail.com>
Sun, 13 Apr 2014 05:52:15 +0000 (22:52 -0700)
committerDrew Fisher <drew.m.fisher@gmail.com>
Sun, 13 Apr 2014 05:52:15 +0000 (22:52 -0700)
TODO: actually make said server do anything useful.

ribbon/main.cpp
ribbon/ribbon.pro
ribbon/ribbonmanager.cpp
ribbon/ribbonmanager.h
ribbon/ribbonserver.cpp [new file with mode: 0644]
ribbon/ribbonserver.h [new file with mode: 0644]
ribbon/ribbonsocket.cpp [new file with mode: 0644]
ribbon/ribbonsocket.h [new file with mode: 0644]

index ae507c14dd50df9b178fee1ba93dc151244c3903..3f1f7acf16264c16ec2a587018908df8162c7a4c 100644 (file)
@@ -8,6 +8,7 @@
 #include <signal.h>
 
 #include "ribbonmanager.h"
+#include "ribbonserver.h"
 
 
 int main(int argc, char** argv)
@@ -26,13 +27,16 @@ int main(int argc, char** argv)
        b->show();
 
        RibbonManager* purple = new RibbonManager();
-       purple->init_libpurple();
+       purple->init();
 
        qDebug() << "libpurple initialized, version" << purple->get_version();
 
        QObject::connect(b, SIGNAL(clicked()),
                        purple, SLOT(sign_in_user()));
 
+       RibbonServer* server = new RibbonServer();
+       server->listen(QHostAddress::Any, 8888);
+
        return app->exec();
 }
 
index 03e93f31ea751b3cfe89e1b28ba71c5291cd0dc2..f1cea56c0c79ed10c65f4cdd1f838c8b876656fd 100644 (file)
@@ -6,14 +6,22 @@ TEMPLATE = app
 TARGET = ribbon
 DEPENDPATH += .
 INCLUDEPATH += . 
+QT += network
 
 unix {
        CONFIG += link_pkgconfig
        PKGCONFIG += glib-2.0 purple
+       # PKGCONFIG += QJson
 }
 
+QMAKE_CXXFLAGS += -Werror -W
+
 # Input
-HEADERS += ribbonmanager.h
+HEADERS += ribbonmanager.h \
+           ribbonserver.h \
+           ribbonsocket.h
 
 SOURCES += ribbonmanager.cpp \
+           ribbonserver.cpp \
+           ribbonsocket.cpp \
            main.cpp
index 304fa03fa35de5b502a4366dfa3aaa02b389b080..fff8d56877a8feabd33a7669df8e32e3663b23b3 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <QDebug>
 #include <QFile>
+#include <QDateTime>
 #include <libpurple/purple.h>
 #include <cstdio>
 
@@ -77,27 +78,27 @@ static PurpleEventLoopUiOps glib_eventloops =
 /* End verbatim copied code */
 
 /* noops for now, add features later */
-static PurpleConversationUiOps ribbon_conversation_callbacks = {
-       NULL,                      /* create_conversation  */
-       NULL,                      /* destroy_conversation */
-       NULL,                      /* write_chat           */
-       NULL,                      /* write_im             */
-       NULL,                      /* write_conv           */
-       NULL,                      /* chat_add_users       */
-       NULL,                      /* chat_rename_user     */
-       NULL,                      /* chat_remove_users    */
-       NULL,                      /* chat_update_user     */
-       NULL,                      /* present              */
-       NULL,                      /* has_focus            */
-       NULL,                      /* custom_smiley_add    */
-       NULL,                      /* custom_smiley_write  */
-       NULL,                      /* custom_smiley_close  */
-       NULL,                      /* send_confirm         */
-       NULL,
-       NULL,
-       NULL,
-       NULL
-};
+//static PurpleConversationUiOps ribbon_conversation_callbacks = {
+//     NULL,                      /* create_conversation  */
+//     NULL,                      /* destroy_conversation */
+//     NULL,                      /* write_chat           */
+//     NULL,                      /* write_im             */
+//     NULL,                      /* write_conv           */
+//     NULL,                      /* chat_add_users       */
+//     NULL,                      /* chat_rename_user     */
+//     NULL,                      /* chat_remove_users    */
+//     NULL,                      /* chat_update_user     */
+//     NULL,                      /* present              */
+//     NULL,                      /* has_focus            */
+//     NULL,                      /* custom_smiley_add    */
+//     NULL,                      /* custom_smiley_write  */
+//     NULL,                      /* custom_smiley_close  */
+//     NULL,                      /* send_confirm         */
+//     NULL,
+//     NULL,
+//     NULL,
+//     NULL
+//};
 
 static void connect_progress(PurpleConnection *gc, const char* text, size_t step, size_t step_count)
 {
@@ -169,29 +170,44 @@ static PurpleCoreUiOps ribbon_core_callbacks = {
        NULL
 };
 
-static void signed_on(PurpleConnection *gc)
+// TODO: note that the void* data can be set at purple_signal_connect time, and
+// set it to the class instance to allow for convenient upcalls
+// Then, actually do upcalls and emit the appropriate signals.
+static void signed_on(PurpleConnection *gc, void* data)
 {
+       Q_UNUSED(data);
        PurpleAccount *account = purple_connection_get_account(gc);
        printf("Account connected: \"%s\" (%s)\n", purple_account_get_username(account), purple_account_get_protocol_id(account));
 }
 
 static void received_im_msg(PurpleAccount *account, char *sender, char *message,
-                            PurpleConversation *conv, PurpleMessageFlags flags)
+                            PurpleConversation *conv, PurpleMessageFlags flags, void* data)
 {
-       Q_UNUSED(flags);
-       if (conv==NULL) {
-               conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, sender);
-       }
-       printf("(%s) %s (%s): %s\n", purple_utf8_strftime("%H:%M:%S", NULL), sender, purple_conversation_get_name(conv), message);
+       Q_UNUSED(data);
+       RibbonManager* r = static_cast<RibbonManager*>(account->ui_data);
+       r->received_im_msg(account, sender, message, conv, flags);
+}
+
+static void buddy_signed_on(PurpleBuddy* buddy, void* data)
+{
+       Q_UNUSED(data);
+       qDebug() << purple_buddy_get_contact_alias(buddy) << "signed on";
 }
 
-void connect_to_signals(void)
+static void connect_to_signals(void)
 {
        static int handle;
-       purple_signal_connect(purple_connections_get_handle(), "signed-on", &handle,
+       void *blist_handle = purple_blist_get_handle();
+       void *connections_handle = purple_connections_get_handle();
+       void *conversations_handle = purple_conversations_get_handle();
+
+       purple_signal_connect(connections_handle, "signed-on", &handle,
                        PURPLE_CALLBACK(signed_on), NULL);
-       purple_signal_connect(purple_conversations_get_handle(), "received-im-msg", &handle,
+       purple_signal_connect(conversations_handle, "received-im-msg", &handle,
                        PURPLE_CALLBACK(received_im_msg), NULL);
+       purple_signal_connect(blist_handle, "buddy-signed-on", &handle,
+                       PURPLE_CALLBACK(buddy_signed_on), NULL);
+       //purple_signal_connect(
 }
 
 RibbonManager::RibbonManager(QObject* parent) : QObject(parent)
@@ -202,7 +218,7 @@ RibbonManager::~RibbonManager()
 {
 }
 
-void RibbonManager::init_libpurple(void)
+void RibbonManager::init(void)
 {
        /* optional:
        purple_util_set_user_dir(CUSTOM_USER_DIRECTORY);
@@ -237,6 +253,15 @@ const char* RibbonManager::get_version(void)
        return purple_core_get_version();
 }
 
+void RibbonManager::received_im_msg(PurpleAccount *account, char *sender, char *message,
+                            PurpleConversation *conv, PurpleMessageFlags flags) {
+       Q_UNUSED(flags);
+       if (conv==NULL) {
+               conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, sender);
+       }
+       qDebug() << QDateTime::currentDateTime().toString("hh:mm:ss") << sender << purple_conversation_get_name(conv) << message;
+}
+
 void RibbonManager::sign_in_user(void)
 {
        QFile file("account.txt");
@@ -244,13 +269,14 @@ void RibbonManager::sign_in_user(void)
                qDebug() << "Couldn't load account information from account.txt!";
                return;
        }
-       QByteArray protocol = file.readLine().trimmed();
+       QByteArray protocol = file.readLine().trimmed();//this could be prpl-aim, prpl-yahoo, prpl-msn, prpl-icq, etc.
        QByteArray username = file.readLine().trimmed();
        QByteArray password = file.readLine().trimmed();
        // Allocate and enable an account.
-       // PurpleAccount *account = purple_account_new("YOUR_IM_ACCOUNTS_USERNAME_HERE", "prpl-IM_NETWORK_HERE"); //this could be prpl-aim, prpl-yahoo, prpl-msn, prpl-icq, etc.
        PurpleAccount *account = purple_account_new(username.data(), protocol.data());
-       // purple_account_set_password(account, "YOUR_IM_ACCOUNTS_PASSWORD_HERE");
+       // ui_data needed for upcalls
+       account->ui_data = this;
+
        purple_account_set_password(account, password.data());
        purple_accounts_add(account);
        purple_account_set_enabled(account, UI_ID, TRUE);
index a9d15f904821495b8d03e449c075ddfd928056f5..0e808e6da2e0ca96a40663099ac550292cae4b5c 100644 (file)
@@ -2,21 +2,31 @@
 #define RIBBONMANAGER_H
 
 #include <QObject>
+#include <libpurple/purple.h>
 
-#define UI_ID                  "ribbon"
+#define UI_ID "ribbon"
 
 class RibbonManager : public QObject {
        Q_OBJECT
 public:
        RibbonManager(QObject* parent = 0);
        ~RibbonManager();
-       void init_libpurple(void);
-       //void connect_to_signals(void);
+
+       // Called to configure libpurple and connect to purple signals
+       void init(void);
+
+       // Exposes purple_get_version()
        const char* get_version(void);
+
+       // Event handlers
+       void received_im_msg(PurpleAccount* account, char* sender, char* message, PurpleConversation* conv, PurpleMessageFlags flags);
+
 public slots:
        void sign_in_user(void);
-private:
 
+private:
+       // TODO: add a map of currently-open conversations?
+       Q_DISABLE_COPY(RibbonManager)
 };
 
 #endif /* RIBBONMANAGER_H */
diff --git a/ribbon/ribbonserver.cpp b/ribbon/ribbonserver.cpp
new file mode 100644 (file)
index 0000000..ec3d902
--- /dev/null
@@ -0,0 +1,49 @@
+#include "ribbonserver.h"
+#include "ribbonsocket.h"
+
+#include <QtNetwork/QTcpServer>
+#include <QtNetwork/QTcpSocket>
+#include <QDebug>
+
+RibbonServer::RibbonServer(QObject* parent) :
+       QObject(parent)
+{
+       server = new QTcpServer(this);
+       QObject::connect(server, SIGNAL(newConnection()),
+                       this, SLOT(onNewConnection()));
+}
+
+RibbonServer::~RibbonServer()
+{
+}
+
+bool RibbonServer::listen(const QHostAddress& address, quint16 port)
+{
+       _addr = address;
+       _port = port;
+       return server->listen(_addr, _port);
+}
+
+void RibbonServer::onNewConnection()
+{
+       QTcpSocket* sock = server->nextPendingConnection();
+       qDebug() << "Accepted connection from" << sock->peerAddress() << ":" << sock->peerPort();
+       RibbonSocket* rsock = new RibbonSocket(sock, this);
+       sockets.append(rsock);
+       if (sockets.length() >= 1) {
+               server->close();
+               qDebug() << "Server closed";
+       }
+       QObject::connect(rsock, SIGNAL(disconnected(RibbonSocket*)),
+                       this, SLOT(onDisconnection(RibbonSocket*)));
+}
+
+void RibbonServer::onDisconnection(RibbonSocket* r)
+{
+       sockets.removeOne(r);
+       qDebug() << "Socket disconnected:" << r->s();
+       if (!server->isListening()) {
+               server->listen(_addr, _port);
+               qDebug() << "Server listening on" << _addr << ":" << _port;
+       }
+}
diff --git a/ribbon/ribbonserver.h b/ribbon/ribbonserver.h
new file mode 100644 (file)
index 0000000..f5fd8f2
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef RIBBONSERVER_H
+#define RIBBONSERVER_H
+
+#include <QObject>
+#include <QList>
+#include <QtNetwork/QHostAddress>
+
+// forward declarations
+class QTcpServer;
+class QTcpSocket;
+class RibbonSocket;
+
+class RibbonServer : public QObject {
+       Q_OBJECT
+public:
+       RibbonServer(QObject* parent = 0);
+       ~RibbonServer();
+       bool listen(const QHostAddress& address = QHostAddress::Any, quint16 port = 0);
+public slots:
+       //void dispatch(QByteArray ba);
+signals:
+       void newConnection();
+private:
+       QTcpServer* server;
+       QHostAddress _addr;
+       quint16 _port;
+       QList<RibbonSocket*> sockets;
+private slots:
+       void onNewConnection();
+       void onDisconnection(RibbonSocket* r);
+};
+
+#endif /* RIBBONSERVER_H */
diff --git a/ribbon/ribbonsocket.cpp b/ribbon/ribbonsocket.cpp
new file mode 100644 (file)
index 0000000..722cdd1
--- /dev/null
@@ -0,0 +1,35 @@
+#include "ribbonsocket.h"
+
+RibbonSocket::RibbonSocket(QTcpSocket* sock, QObject* parent) : QObject(parent), socket(sock)
+{
+       QObject::connect(socket, SIGNAL(connected()),
+                       this, SLOT(onConnect()));
+       QObject::connect(socket, SIGNAL(disconnected()),
+                       this, SLOT(onDisconnect()));
+       QObject::connect(socket, SIGNAL(readyRead()),
+                       this, SLOT(onReadyRead()));
+}
+
+RibbonSocket::~RibbonSocket()
+{
+}
+
+const QTcpSocket* RibbonSocket::s()
+{
+       return socket;
+}
+
+void RibbonSocket::onConnect()
+{
+       emit connected(this);
+}
+
+void RibbonSocket::onDisconnect()
+{
+       emit disconnected(this);
+}
+
+void RibbonSocket::onReadyRead()
+{
+       emit readyRead(this);
+}
diff --git a/ribbon/ribbonsocket.h b/ribbon/ribbonsocket.h
new file mode 100644 (file)
index 0000000..32327ae
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef RIBBONSOCKET_H
+#define RIBBONSOCKET_H
+
+#include <QtNetwork/QTcpSocket>
+
+class RibbonSocket : public QObject {
+       Q_OBJECT
+public:
+       RibbonSocket(QTcpSocket* socket, QObject* parent=0);
+       // Consider s to be final.  Don't modify it.
+       const QTcpSocket* s();
+signals:
+       void connected(RibbonSocket* s);
+       void disconnected(RibbonSocket* s);
+       void readyRead(RibbonSocket* s);
+private:
+       virtual ~RibbonSocket();
+       QTcpSocket* socket;
+private slots:
+       void onConnect();
+       void onDisconnect();
+       void onReadyRead();
+};
+
+#endif /* RIBBONSOCKET_H */