File: SnoopPrivate.hh

package info (click to toggle)
cadabra2 2.4.3.2-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 78,732 kB
  • sloc: ansic: 133,450; cpp: 92,064; python: 1,530; javascript: 203; sh: 184; xml: 182; objc: 53; makefile: 51
file content (187 lines) | stat: -rw-r--r-- 6,666 bytes parent folder | download | duplicates (3)
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187

#pragma once

#include <websocketpp/config/asio_no_tls_client.hpp>
#include <websocketpp/client.hpp>
#include <websocketpp/common/thread.hpp>
#include <websocketpp/common/functional.hpp>
#include <mutex>
#include <condition_variable>
#include <thread>
#include <set>

typedef websocketpp::client<websocketpp::config::asio_client> WebsocketClient;
typedef websocketpp::config::asio_client::message_type::ptr   message_ptr;

namespace snoop {
	
	class SnoopImpl {
		public:
			SnoopImpl(Snoop *);
			~SnoopImpl();

         Snoop& operator<<(const Flush&);

			/// Initialise the logging stream. Should be called once at
         /// program startup, but can be called multiple times without
         /// causing problems. The 'local_database_name' should be a full
			/// path but without extension; the main database name will be this
			/// path with '.sql' added, while the payload database will have
			/// '_payload.sql' at the end.

			void init(const std::string& app_name, const std::string& app_version, 
						 std::string server="", std::string local_database_name="");

			/// Get a string which uniquely identifies the current user. This is
			/// stored in ~/.config/snoop/appname.conf.

			std::string get_user_uuid(const std::string& app_name);

			/// Log payload data.
			Snoop& payload(const std::vector<char>&);

         /// Operator to initialise a logging entry with the type of
			/// the log message as well as (optionally) the file, line
			/// number and method. Thread-safe: can be called from
			/// different threads at the same time.

			Snoop& operator()(const std::string& type, std::string fl="", int loc=-1, std::string method="");

         void set_local_type(const std::string& type);

	      /// Ensure that the local database is synchronised with the
			/// server (this sends multiple app or log entries in one
			/// websocket message). Leave the bool argument at its
			/// default argument under all normal circumstances.

			void sync_with_server(bool from_wsthread=false);
			
			/// As above, but only for run entries. 

			void sync_runs_with_server(bool from_wsthread=false);
			
			/// As above, but only for log entries. 

			void sync_logs_with_server(bool from_wsthread=false);

			/// As above, but only for payload data.

			void sync_payloads_with_server(bool from_wsthread=false);

         /// Are we connected to the log server?

         bool is_connected() const;         

         /// Return version of last run seen on given device.
         
         std::string last_seen_version(std::string machine_id);

         /// Authentication logic; passes ticket or credentials
         /// to server, and registers callback function for when
         /// the response comes back.

	      bool authenticate(std::function<void (std::string, bool)>, std::string user="", std::string pass="");

         /// Get status of a given authentication ticket.

         bool is_ticket_valid(std::string ticket_uuid);

         /// Get status of given user/pass combo. This queries the
         /// underlying authentication database table. If the login
         /// is valid, a ticket will be inserted in the database and
         /// returned. An empty string is returned if login is invalid.

         std::string ticket_for_login(std::string user, std::string password);
         
         /// Add a user/password combo to the user database.

         bool add_user(std::string user, std::string password);

	      Snoop             *snoop_;

	      sqlite3           *db, *payload_db, *auth_db;
			
			Snoop::AppEntry    this_app_;
			Snoop::LogEntry    this_log_;
			std::string        server_;

			/// Start the websocket client. This tries to connect to the server and then
         /// waits in a separate thread until the server sends us something (typically
         /// in response to something the main thread makes by calling wsclient.send).

			void start_websocket_client();

			/// Ensure that the required tables are present in the
			/// database file.

			void create_tables();

	      /// Ensure that the required authentication tables are present
	      /// in the authentication database. Only used on the server.

	      void create_authentication_tables();

			/// Obtain a uuid by finding the last AppEntry stored in the
			/// local database. Will attempt to re-turn a previously
			/// generated uuid but will do so only if one is stored for
			/// the current pid; if no entry with the current pid is
			/// stored then a new one will always be generated.

			void obtain_uuid();

			/// Store an app entry in the database. Will update the 'id'
			/// field in the AppEntry.

			bool store_app_entry(Snoop::AppEntry&);
			bool store_app_entry_without_lock(Snoop::AppEntry&);

			/// Store a log entry in the local database. Generates its
			/// own receive_millis field (the one given gets
			/// overwritten). Will update the 'id' field in the LogEntry.
			/// Returns 'true' if the entry was stored, or 'false' if an
			/// entry with this client_log_id was already present (except
			/// when it is 0).

			bool store_log_entry(Snoop::LogEntry&, bool avoid_server_duplicates);

			/// Store payload data in the local database.

			bool store_payload_entry(Snoop::PayLoad&);
			
			/// Return a vector of all aps registered in the database. If
			/// the uuid filter is non-empty, will filter on the given
			/// uuid.

			std::vector<Snoop::AppEntry> get_app_registrations(std::string uuid_filter="");

			/// Prepared statements (only need to prepare these once).
			
			sqlite3_stmt *insert_statement, *id_for_uuid_statement, *payload_insert_statement;
			std::mutex    sqlite_mutex;

			/// Websocket client to talk to a remote logging server.
			
			WebsocketClient                 wsclient;
			std::thread                     wsclient_thread;
			std::mutex                      connection_mutex;
			std::condition_variable         connection_cv;
			bool                            connection_is_open, connection_attempt_failed;
			WebsocketClient::connection_ptr connection;
			websocketpp::connection_hdl     our_connection_hdl;
			
			void on_client_open(websocketpp::connection_hdl hdl);
			void on_client_fail(websocketpp::connection_hdl hdl);
			void on_client_close(websocketpp::connection_hdl hdl);
			void on_client_message(websocketpp::connection_hdl hdl, message_ptr msg);

		private:
			std::mutex   call_mutex;
			bool         secure;

	      std::set<std::string> local_types;
//	      std::set<std::string> ...
         std::function<void (std::string, bool)> authentication_callback;

	      void store_ticket(std::string ticket_uuid, int user_id, bool valid);
	};
}