summaryrefslogtreecommitdiffstats
blob: 586a94efbc8c665e7dd432807ee73d11560449df (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/*
 * Copyright (c) 2014-2018 Isode Limited.
 * All rights reserved.
 * See the COPYING file for more information.
 */

#pragma once

#include <deque>

#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/optional.hpp>

#include <Swiften/Client/ClientOptions.h>
#include <Swiften/Component/Component.h>
#include <Swiften/Component/ComponentError.h>
#include <Swiften/Elements/IQ.h>
#include <Swiften/Elements/Message.h>
#include <Swiften/Elements/Presence.h>
#include <Swiften/EventLoop/SimpleEventLoop.h>
#include <Swiften/Network/NetworkFactories.h>
#include <Swiften/Queries/GenericRequest.h>
#include <Swiften/Roster/XMPPRosterItem.h>

#include <Sluift/Response.h>
#include <Sluift/Watchdog.h>

namespace Swift {
    struct SluiftGlobals;
    class ComponentXMLTracer;
    class Component;
    class Stanza;
    class Payload;
    class ErrorPayload;
    class JID;

    class SluiftComponent {
        public:
            struct Event {
                enum Type {
                    MessageType,
                    PresenceType
                };

                Event(std::shared_ptr<Message> stanza) : type(MessageType), stanza(stanza) {}
                Event(std::shared_ptr<Presence> stanza) : type(PresenceType), stanza(stanza) {}

                Type type;

                // Message & Presence
                std::shared_ptr<Stanza> stanza;
            };

            SluiftComponent(
                    const JID& jid,
                    const std::string& password,
                    NetworkFactories* networkFactories,
                    SimpleEventLoop* eventLoop);
            ~SluiftComponent();

            Component* getComponent() {
                return component;
            }

            void connect(const std::string& host, unsigned short port);
            void waitConnected(int timeout);
            bool isConnected() const;
            void setTraceEnabled(bool b);

            template<typename REQUEST_TYPE>
            Sluift::Response sendRequest(REQUEST_TYPE request, int timeout) {
                boost::signals2::scoped_connection c(request->onResponse.connect(
                        boost::bind(&SluiftComponent::handleRequestResponse, this, _1, _2)));
                return doSendRequest(request, timeout);
            }

            template<typename REQUEST_TYPE>
            Sluift::Response sendVoidRequest(REQUEST_TYPE request, int timeout) {
                boost::signals2::scoped_connection c(request->onResponse.connect(
                        boost::bind(&SluiftComponent::handleRequestResponse, this, std::shared_ptr<Payload>(), _1)));
                return doSendRequest(request, timeout);
            }

            void disconnect();
            void setSoftwareVersion(const std::string& name, const std::string& version, const std::string& os);
            boost::optional<SluiftComponent::Event> getNextEvent(int timeout,
                    boost::function<bool (const Event&)> condition = boost::function<bool (const Event&)>());

        private:
            Sluift::Response doSendRequest(std::shared_ptr<Request> request, int timeout);

            void handleIncomingMessage(std::shared_ptr<Message> stanza);
            void handleIncomingPresence(std::shared_ptr<Presence> stanza);
            void handleRequestResponse(std::shared_ptr<Payload> response, std::shared_ptr<ErrorPayload> error);
            void handleError(const boost::optional<ComponentError>& error);

        private:
            NetworkFactories* networkFactories;
            SimpleEventLoop* eventLoop;
            Component* component;
            ComponentXMLTracer* tracer;
            std::deque<Event> pendingEvents;
            boost::optional<ComponentError> disconnectedError;
            bool requestResponseReceived = false;
            std::shared_ptr<Payload> requestResponse;
            std::shared_ptr<ErrorPayload> requestError;
    };
}