summaryrefslogtreecommitdiffstats
path: root/src/userintf.h
blob: 48a4c508877fd87966f9a5f20961ad3c1a9b213e (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
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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
/*
    Copyright (C) 2005-2009  Michel de Boer <michel@twinklephone.com>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

#ifndef _USERINTF_H
#define _USERINTF_H

#include <list>
#include <string>

#include "events.h"
#include "phone.h"
#include "protocol.h"
#include "parser/request.h"
#include "parser/response.h"
#include "audio/tone_gen.h"
#include "threads/thread.h"
#include "im/msg_session.h"
#include "presence/presence_state.h"

#include "twinkle_config.h"

#define PRODUCT_DATE VERSION_DATE
#define PRODUCT_AUTHOR	"Michel de Boer and contributors"

// Tone definitions
// The intervals indicate the length of silence between repetitions
// of the wav file. Duration is in ms
#define FILE_RINGTONE           "ringtone.wav"
#define INTERVAL_RINGTONE       3000
#define FILE_RINGBACK           "ringback.wav"
#define INTERVAL_RINGBACK       3000

using namespace std;

struct t_command_arg {
        char    flag;
        string  value;
};

class t_userintf : public i_prohibit_thread {
protected:
	enum t_zrtp_cmd {
		ZRTP_ENCRYPT,
		ZRTP_GO_CLEAR,
		ZRTP_CONFIRM_SAS,
		ZRTP_RESET_SAS
	};
	
private:
        bool            end_interface; // indicates if interface loop should quit
        list<string>    all_commands;  // list of all commands
        t_tone_gen      *tone_gen;     // tone generator for ringing
        
        // The user for which out-of-dialog requests are executed.
        t_user		*active_user;

        // The user can type a prefix of the command only. This method
        // completes a prefix to a full command.
        // If no command is found then the empty string is returned.
        // If the prefix is ambiguous, then argument ambiguous is set to true
        // and the empty string is returned.
        string complete_command(const string &c, bool &ambiguous);

        // Parse command arguments. The list must contain the command as first
        // element followed by the arguments.
        bool parse_args(const list<string> command_list, list<t_command_arg> &al);

        // The command_list must contain the command itself as first
        // argument. Subsequent elements are the arguments.
        bool exec_invite(const list<string> command_list, bool immediate = false);
        bool exec_redial(const list<string> command_list);
        bool exec_answer(const list<string> command_list);
        bool exec_answerbye(const list<string> command_list);
        bool exec_reject(const list<string> command_list);
	bool exec_redirect(const list<string> command_list, bool immediate = false);
	bool exec_dnd(const list<string> command_list);
	bool exec_auto_answer(const list<string> command_list);
        bool exec_bye(const list<string> command_list);
        bool exec_hold(const list<string> command_list);
        bool exec_retrieve(const list<string> command_list);
	bool exec_refer(const list<string> command_list, bool immediate = false);
	bool exec_conference(const list<string> command_list);
	bool exec_mute(const list<string> command_list);
	bool exec_dtmf(const list<string> command_list);
        bool exec_register(const list<string> command_list);
        bool exec_deregister(const list<string> command_list);
        bool exec_fetch_registrations(const list<string> command_list);
        bool exec_options(const list<string> command_list, bool immediate = false);
        bool exec_line(const list<string> command_list);
        bool exec_user(const list<string> command_list);
        bool exec_zrtp(const list<string> command_list);
        bool exec_message(const list<string> command_list);
        bool exec_presence(const list<string> command_list);
        bool exec_quit(const list<string> command_list);
        bool exec_help(const list<string> command_list);

protected:
        t_phone         *phone;
        
        // Asynchronous event queue
        t_event_queue	evq_ui_events;
        t_thread	*thr_process_events;
        
        // Indicates if commands should print output to stdout
        bool		use_stdout;

	// Throttle dtmtf not supported messages
	bool		throttle_dtmf_not_supported;

	// Last call information
	t_url		last_called_url;
	string		last_called_display;
	string		last_called_subject;
	string		last_called_profile; // profile used to make the call
	bool		last_called_hide_user;
	
	// The do_* methods perform the commands parsed by the exec_* methods.
	virtual bool do_invite(const string &destination, const string &display, 
			const string &subject, bool immediate, bool anonymous);
	virtual void do_redial(void);
	virtual void do_answer(void);
	virtual void do_answerbye(void);
	virtual void do_reject(void);
	virtual void do_redirect(bool show_status, bool type_present, t_cf_type cf_type, 
		bool action_present, bool enable, int num_redirections,
		const list<string> &dest_strlist, bool immediate);
	virtual void do_dnd(bool show_status, bool toggle, bool enable);
	virtual void do_auto_answer(bool show_status, bool toggle, bool enable);
	virtual void do_bye(void);
	virtual void do_hold(void);
	virtual void do_retrieve(void);
	virtual bool do_refer(const string &destination, t_transfer_type transfer_type, 
		bool immediate);
	virtual void do_conference(void);
	virtual void do_mute(bool show_status, bool toggle, bool enable);
	virtual void do_dtmf(const string &digits);
	virtual void do_register(bool reg_all_profiles);
	virtual void do_deregister(bool dereg_all_profiles, bool dereg_all_devices);
	virtual void do_fetch_registrations(void);
	virtual bool do_options(bool dest_set, const string &destination, bool immediate);
	virtual void do_line(int line);
	virtual void do_user(const string &profile_name);
	virtual void do_zrtp(t_zrtp_cmd zrtp_cmd);
	virtual bool do_message(const string &destination, const string &display,
		const im::t_msg &msg);
	virtual void do_presence(t_presence_state::t_basic_state basic_state);
	virtual void do_quit(void);
	virtual void do_help(const list<t_command_arg> &al);

public:
        t_userintf(t_phone *_phone);
        virtual ~t_userintf();

	/**
         * Expand a SIP destination to a full SIP/TEL uri, i.e. add sip/tel scheme
         * and domain if these are missing.
         * @param user_config [in] User profile of the user for which the expansion is done.
         * @param dst [in] The address string to expand.
         * @param scheme [in] Scheme to expand to (sip/tel/""). If scheme is empty then
         *        the expansion is done according to preferences from the user profile.
         * @return The expanded address.
         */
        string expand_destination(t_user *user_config, const string &dst, const string &scheme = "");
        
        // Expand a SIP destination into a display and a full SIP uri
        void expand_destination(t_user *user_config, 
        	const string &dst, string &display, string &dst_url);
        void expand_destination(t_user *user_config, 
        	const string &dst, t_display_url &display_url);
        	
        // Expand a SIP destination as above, but split off any headers if any.
        // If the subject header is present, then its value will be returned in
        // subject.
        // The dst_no_headers parameter will contain the dst string with the headers
        // cut off.
	void expand_destination(t_user *user_config,
		const string &dst, t_display_url &display_url, string &subject,
		string &dst_no_headers);

	// Format a SIP address for user display
	virtual string format_sip_address(t_user *user_config, const string &display,
	                                  const t_url &uri) const;

	// Format a warning for user display
	virtual list<string> format_warnings(const t_hdr_warning &hdr_warning) const;

	// Format a codec for user display
	virtual string format_codec(t_audio_codec codec) const;

	// The immediate flag is by the cmd_cli method (see below)
        bool exec_command(const string &command_line, bool immediate = false);
        
        // Run the user interface
        virtual void run(void);
        
        // This method executes asynchronous uier interface events
        virtual void process_events(void);
        
        // Save user interface state to system settings
        virtual void save_state(void);
        
        // Restore user interface state from system settings
        virtual void restore_state(void);

	// Lock the user interface to synchornize output
	virtual void lock(void);
	virtual void unlock(void);

        // Select a network interface. Returns string representation of IP address.
        virtual string select_network_intf(void);

	// Select a user configuration file. Returns false if selection failed.
	virtual bool select_user_config(list<string> &config_files);

        // Call back functions
        virtual void cb_incoming_call(t_user *user_config, int line, const t_request *r);
        virtual void cb_call_cancelled(int line);
        virtual void cb_far_end_hung_up(int line);
        virtual void cb_answer_timeout(int line);
        virtual void cb_sdp_answer_not_supported(int line, const string &reason);
        virtual void cb_sdp_answer_missing(int line);
	virtual void cb_unsupported_content_type(int line, const t_sip_message *r);
        virtual void cb_ack_timeout(int line);
	virtual void cb_100rel_timeout(int line);
	virtual void cb_prack_failed(int line, const t_response *r);
        virtual void cb_provisional_resp_invite(int line, const t_response *r);
        virtual void cb_cancel_failed(int line, const t_response *r);
        virtual void cb_call_answered(t_user *user_config, int line, const t_response *r);
        virtual void cb_call_failed(t_user *user_config, int line, const t_response *r);
        virtual void cb_stun_failed_call_ended(int line);
        virtual void cb_call_ended(int line);
        virtual void cb_call_established(int line);
        virtual void cb_options_response(const t_response *r);
        virtual void cb_reinvite_success(int line, const t_response *r);
        virtual void cb_reinvite_failed(int line, const t_response *r);
	virtual void cb_retrieve_failed(int line, const t_response *r);
        virtual void cb_invalid_reg_resp(t_user *user_config, 
        		const t_response *r, const string &reason);
        virtual void cb_register_success(t_user *user_config, 
        		const t_response *r, unsigned long expires, bool first_success);
        virtual void cb_register_failed(t_user *user_config, 
        		const t_response *r, bool first_failure);
        virtual void cb_register_stun_failed(t_user *user_config, bool first_failure);
        virtual void cb_deregister_success(t_user *user_config, const t_response *r);
        virtual void cb_deregister_failed(t_user *user_config, const t_response *r);
        virtual void cb_fetch_reg_failed(t_user *user_config, const t_response *r);
        virtual void cb_fetch_reg_result(t_user *user_config, const t_response *r);
	virtual void cb_register_inprog(t_user *user_config, t_register_type register_type);
	virtual void cb_redirecting_request(t_user *user_config, 
			int line, const t_contact_param &contact);
	virtual void cb_redirecting_request(t_user *user_config, 
			const t_contact_param &contact);
        virtual void cb_play_ringtone(int line);
	virtual void cb_play_ringback(t_user *user_config);
        virtual void cb_stop_tone(int line);
        virtual void cb_notify_call(int line, string from_party);
        virtual void cb_stop_call_notification(int line);
	virtual void cb_dtmf_detected(int line, t_dtmf_ev dtmf_event);
	virtual void cb_async_dtmf_detected(int line, t_dtmf_ev dtmf_event);
	virtual void cb_send_dtmf(int line, t_dtmf_ev dtmf_event);
	virtual void cb_async_send_dtmf(int line, t_dtmf_ev dtmf_event);
	virtual void cb_dtmf_not_supported(int line);
	virtual void cb_dtmf_supported(int line);
	virtual void cb_line_state_changed(void);
	virtual void cb_async_line_state_changed(void);
	virtual void cb_send_codec_changed(int line, t_audio_codec codec);
	virtual void cb_recv_codec_changed(int line, t_audio_codec codec);
	virtual void cb_async_recv_codec_changed(int line, t_audio_codec codec);
	virtual void cb_notify_recvd(int line, const t_request *r);
	virtual void cb_refer_failed(int line, const t_response *r);
	virtual void cb_refer_result_success(int line);
	virtual void cb_refer_result_failed(int line);
	virtual void cb_refer_result_inprog(int line);

	// A call is being referred by the far end. r must be the REFER request.
	virtual void cb_call_referred(t_user *user_config, int line, t_request *r);

	// The reference failed. Call to referrer is retrieved.
	virtual void cb_retrieve_referrer(t_user *user_config, int line);
	
	// A consulation call for a call transfer is being setup.
	virtual void cb_consultation_call_setup(t_user *user_config, int line);
	
	// STUN errors
	virtual void cb_stun_failed(t_user *user_config, int err_code, const string &err_reason);
	virtual void cb_stun_failed(t_user *user_config);

	// Interactive call back functions
	virtual bool cb_ask_user_to_redirect_invite(t_user *user_config, 
			const t_url &destination, const string &display);
	virtual bool cb_ask_user_to_redirect_request(t_user *user_config, 
			const t_url &destination, const string &display, t_method method);
	virtual bool cb_ask_credentials(t_user *user_config, 
			const string &realm, string &username, string &password);
			
	// Ask questions asynchronously.
	virtual void cb_ask_user_to_refer(t_user *user_config, 
			const t_url &refer_to_uri,
			const string &refer_to_display,
			const t_url &referred_by_uri,
			const string &referred_by_display);
			
	// Send the answer for refer permission to the transaction layer.
	void send_refer_permission(bool permission);

	// Show an error message to the user. Depending on the interface mode
	// the user has to acknowledge the error before processing continues.
	virtual void cb_show_msg(const string &msg, t_msg_priority prio = MSG_INFO);
	
	// Ask a yes/no question to the user.
	// Returns true for yes and false for no.
	virtual bool cb_ask_msg(const string &msg, t_msg_priority prio = MSG_INFO);

	/** 
	 * Display an error/information message.
	 * @param msg [in] Message to display.
	 * @param prio [in] Priority associated with the message.
	 */
	virtual void cb_display_msg(const string &msg,
			t_msg_priority prio = MSG_INFO);
			
	/**
	 * Display an error/information message in an asynchronous way.
	 * @param msg [in] Message to display.
	 * @param prio [in] Priority associated with the message.
	 */
	virtual void cb_async_display_msg(const string &msg, 
			t_msg_priority prio = MSG_INFO);
			
	// Log file has been updated
	virtual void cb_log_updated(bool log_zapped = false);
	
	// Call history has been updated
	virtual void cb_call_history_updated(void);
	virtual void cb_missed_call(int num_missed_calls);
	
	// Show firewall/NAT discovery progress
	virtual void cb_nat_discovery_progress_start(int num_steps);
	virtual void cb_nat_discovery_progress_step(int step);
	virtual void cb_nat_discovery_finished(void);
	virtual bool cb_nat_discovery_cancelled(void);
	
	// ZRTP
	virtual void cb_line_encrypted(int line, bool encrypted, const string &cipher_mode = "");
	virtual void cb_async_line_encrypted(int line, bool encrypted, const string &cipher_mode = "");
	virtual void cb_show_zrtp_sas(int line, const string &sas);
	virtual void cb_async_show_zrtp_sas(int line, const string &sas);
	virtual void cb_zrtp_confirm_go_clear(int line);
	virtual void cb_async_zrtp_confirm_go_clear(int line);
	virtual void cb_zrtp_sas_confirmed(int line);
	virtual void cb_zrtp_sas_confirmation_reset(int line);
	
	// MWI
	virtual void cb_update_mwi(void);
	virtual void cb_mwi_subscribe_failed(t_user *user_config, t_response *r, bool first_failure);
	virtual void cb_mwi_terminated(t_user *user_config, const string &reason);
	
	/** @name Instant messaging */
	//@{
	/**
	 * Incoming MESSAGE request callback.
	 * @param user_config [in] User profile of the user receiving this MESSAGE request.
	 * @param r [in] The MESSAGE request.
	 * @return True if the message is accepted.
	 * @return False if the message is rejected, i.e. maximum number of sessions reached.
	 */
	virtual bool cb_message_request(t_user *user_config, t_request *r);
	
	/**
	 * Incoming MESSAGE response callback.
	 * @param user_config [in] User profile of the user receiving this MESSAGE response.
	 * @param r [in] The MESSAGE response.
	 * @param req [in] The MESSAGE request for which the response is received.
	 */
	virtual void cb_message_response(t_user *user_config, t_response *r, t_request *req);
	
	/**
	 * Incoming MESSAGE request with composing indication callback.
	 * @param user_config [in] User profile of the user receiving this MESSAGE response.
	 * @param r [in] The MESSAGE request containing the composing indication.
	 * @param state [in] The message composing state.
	 * @param refresh [in] The refresh interval in seconds when state is active.
	 */
	virtual void cb_im_iscomposing_request(t_user *user_config, t_request *r,
			im::t_composing_state state, time_t refresh);
		
	/** 
	 * Indication that the far-end does not support message composing indications.
	 * @param user_config [in] User profile of the user receiving this MESSAGE response.
	 * @param r [in] The MESSAGE response on the composing indication.
	 */
	virtual void cb_im_iscomposing_not_supported(t_user *user_config, t_response *r);
	//@}

	// Get last call information
	// Returns true if last call information is valid
	// Returns false is there is no valid last call information
	virtual bool get_last_call_info(t_url &url, string &display,
				string &subject, t_user **user_config,
				bool &hide_user) const;
	virtual bool can_redial(void) const;
	
	// Execute external commands
	// Some comments require confirmation from the user via the user
	// interface, e.g. in GUI mode, a call dialog may popup for cmd_call.
	// The 'immediate' flag indicates that no user confirmation is required.
	// The command should be executed immediately.
	virtual void cmd_call(const string &destination, bool immediate);
	virtual void cmd_quit(void);
	void cmd_quit_async(void);
	virtual void cmd_cli(const string &command, bool immeidate);
	
	/** Execute the SHOW command. */
	virtual void cmd_show(void);
	
	/** Execute the HIDE command. */
	virtual void cmd_hide(void);
	
	// Lookup a URL in the address book
	virtual string get_name_from_abook(t_user *user_config, const t_url &u);

	// Get all command names
	const list<string>& get_all_commands(void);

	// Asynchronously run a function on this class' event queue
	void run_on_event_queue(std::function<void()> fn);

};

void *process_events_main(void *arg);

extern t_userintf *ui;

#endif