summaryrefslogtreecommitdiffstats
blob: 4e5e763ed2b82eb5823c53ae086c5373a8ee1def (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
/*
 * Copyright (c) 2014 Isode Limited.
 * All rights reserved.
 * See the COPYING file for more information.
 */

#pragma once

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

#include <Swiften/Client/ClientOptions.h>
#include <Swiften/Elements/IQ.h>
#include <Swiften/Elements/Message.h>
#include <Swiften/Elements/Presence.h>
#include <Swiften/Queries/GenericRequest.h>
#include <Swiften/Roster/XMPPRosterItem.h>
#include <Swiften/Component/ComponentError.h>
#include <Swiften/Network/NetworkFactories.h>
#include <Swiften/Component/Component.h>
#include <Swiften/EventLoop/SimpleEventLoop.h>
#include <Sluift/Watchdog.h>
#include <Sluift/Response.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(boost::shared_ptr<Message> stanza) : type(MessageType), stanza(stanza) {}
				Event(boost::shared_ptr<Presence> stanza) : type(PresenceType), stanza(stanza) {}

				Type type;

				// Message & Presence
				boost::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, int 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::signals::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::signals::scoped_connection c = request->onResponse.connect(
						boost::bind(&SluiftComponent::handleRequestResponse, this, boost::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 = 0);

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

			void handleIncomingMessage(boost::shared_ptr<Message> stanza);
			void handleIncomingPresence(boost::shared_ptr<Presence> stanza);
			void handleRequestResponse(boost::shared_ptr<Payload> response, boost::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;
			boost::shared_ptr<Payload> requestResponse;
			boost::shared_ptr<ErrorPayload> requestError;
	};
}