summaryrefslogtreecommitdiffstats
path: root/src/abstract_dialog.h
blob: 5d544152cc6572fd54610112ece558ae73182d70 (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
/*
    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/>.
*/

/**
 * @file
 * Abstract class for all types of SIP dialogs.
 */

#ifndef _ABSTRACT_DIALOG_H
#define _ABSTRACT_DIALOG_H

#include <string>
#include <list>
#include <set>
#include <queue>
#include "client_request.h"
#include "id_object.h"
#include "protocol.h"
#include "sockets/url.h"
#include "parser/request.h"

using namespace std;

// Forward declaration
class t_phone_user;

/**
 * Abstract class for all types of SIP dialogs.
 * Concrete classes for all SIP dialogs inherit from this class.
 */
class t_abstract_dialog : public t_id_object {
protected:	
	/** 
	 * Phone user for which this dialog is created.
	 * This pointer should never be deleted.
	 */
	t_phone_user	*phone_user;

	string		call_id;	/**< SIP call id. */
	bool		call_id_owner;	/**< Indicates if the call id is generated locally. */
	string		local_tag;	/**< Local tag value. */
	string		remote_tag;	/**< Remote tag value. */
	unsigned long	local_seqnr;	/**< Last local sequence number issued. */
	unsigned long	remote_seqnr;	/**< Last remote sequence number received. */

	/**
	 * The remote_seqnr_set indicates if the remote_seqnr is set by the far-end.
	 * RFC 3261 allows the CSeq sequence number to be 0. So there is no
	 * invalid sequence number.
	 */
	bool		remote_seqnr_set;
	
	t_url		local_uri;		/**< URI of the local party (From/To headers). */
	string		local_display;		/**< Display name of the local party. */
	t_url		remote_uri;		/**< URI of the remote party (From/To headers). */
	string		remote_display;		/**< Display name of the remote party. */
	 
	/** URI of the remote target (Contact header). This is the destination for a request. */
	t_url		remote_target_uri;
	string		remote_target_display;	/**< Display name of the remote target. */
	
	list<t_route>	route_set;		/**< The route set. */
	unsigned long	local_resp_nr;		/**< Last local response number (for 100rel) issued. */
	unsigned long	remote_resp_nr;		/**< Last remote response number (for 100rel) received. */
	set<string>	remote_extensions;      /**< SIP extensions supported by the remote party. */
	
	/** The IP transport/address/port from which the last SIP message was received. */
	t_ip_port	remote_ip_port;

	/**
	 * Remove a client request. Pass one of the client request
	 * pointers to this member. The reference count of the
	 * request will be decremented. If it becomes zero, then
	 * the request object is deleted.
	 * In all cases the passed pointer will be set to NULL.
	 * @param cr [in] The client request.
	 */
	void remove_client_request(t_client_request **cr);

	/**
	 * Create route set from the Record-Route header of a response.
	 * If the response does not have a Record-Route header, then the route
	 * set is cleared.
	 * @param r [in] The response.
	 */
	void create_route_set(t_response *r);

	/**
	 * Create remote target uri and display from the Contact header of a response.
	 * @param r [in] The response.
	 */
	void create_remote_target(t_response *r);
	
	/**
	 * Send a request within the dialog.
	 * Sending a request will create a SIP transaction.
	 * @param r [in] The request.
	 * @param tuid [in] The transaction user id to be assigend to the transaction.
	 */
	virtual void send_request(t_request *r, t_tuid tuid) = 0;

	/**
	 * Resend an existing client request.
	 * A new Via and CSeq header will be put in the request.
	 * Resending is different from retransmitting. Requests are automatically
	 * retransmitted by the transaction layer. Resending creates a new SIP
	 * transaction. Resending is f.i. done when a request must be redirected.
	 * @param cr [in] The client request.
	 */
	virtual void resend_request(t_client_request *cr);
	
	/**
	 * Resend mid-dialog request with an authorization header containing
	 * credentials for the challenge in the response. 
	 * @param cr [in] The request.
	 * @param resp [in] The 401 or 407 response.
	 * @return true, if resending succeeded.
	 * @return false, if credentials could not be determined.
	 *
	 * @pre The response must be a 401 or 407.
	 */
	bool resend_request_auth(t_client_request *cr, t_response *resp);
	
	/**
	 * Redirect mid-dialog request to the next destination.
	 * There are multiple reasons for redirection:
	 *  - A 3XX response was received.
	 *  - The request failed with a non-3XX response. A next contact should be tried.
	 *
	 * @param cr [in] The request.
	 * @param resp [in] The failure response that was received on the request. 
	 * @param contact [out] Contains on successful return the contact to which the request is sent.
	 * @return true, if the request is sent to a next destination.
	 * @return false, if no next destination exists.
	 */
	bool redirect_request(t_client_request *cr, t_response *resp,
			t_contact_param &contact);
	
	/**
	 * Failover request to the next destination from DNS lookup.
	 * @param cr [in] The request.
	 * @return true, if the request is sent to a next destination.
	 * @return false, if no next destination exists.
	 */
	bool failover_request(t_client_request *cr);

public:
	/**
	 * Constructor.
	 * @param pu [in] Phone user for which the dialog must be created.
	 */
	t_abstract_dialog(t_phone_user *pu);
	
	/**
	 * Destructor.
	 */
	virtual ~t_abstract_dialog();

	/**
	 * Create a request using the stored dialog state information.
	 * @param m [in] Request method.
	 * @return The request.
	 */
	virtual t_request *create_request(t_method m);

	/**
	 * Copy a dialog.
	 * @return A copy of the dialog.
	 */
	virtual t_abstract_dialog *copy(void) = 0;
	
	/**
	 * Get a pointer to the user profile of the user for whom this dialog
	 * was created.
	 * @return The user profile.
	 */
	t_user *get_user(void) const;

	/**
	 * Resend mid-dialog request with an authorization header containing
	 * credentials for the challenge in the response.
	 * @param resp [in] The 401 or 407 response to the request that must be resent.
	 * @return true, if resending succeeded.
	 * @return false, if credentials could not be determined.
	 *
	 * @pre The response must be a 401 or 407.
	 */
	virtual bool resend_request_auth(t_response *resp) = 0;

	/**
	 * Redirect mid-dialog request to the next destination.
	 * @param resp [in] The response to the request that must be resent.
	 * @return true, if the request is sent to a next destination.
	 * @return false, if no next destination exists.
	 */
	virtual bool redirect_request(t_response *resp) = 0;
	
	/**
	 * Failover request to the next destination from DNS lookup.
	 * @param resp [in] The response to the request that must be resent.
	 * @return true, if the request is sent to a next destination.
	 * @return false, if no next destination exists.
	 */
	virtual bool failover_request(t_response *resp) = 0;

	/**
	 * Process a received response.
	 * @param r [in] The received response.
	 * @param tuid [in] The transaction user id of the transaction for the response.
	 * @param tid [in] The transaction id of the transaction for the response.
	 */
	virtual void recvd_response(t_response *r, t_tuid tuid, t_tid tid);
	
	/**
	 * Process a received request.
	 * @param r [in] The received request.
	 * @param tuid [in] The transaction user id of the transaction for the request.
	 * @param tid [in] The transaction id of the transaction for the request.
	 */
	virtual void recvd_request(t_request *r, t_tuid tuid, t_tid tid);

	/**
	 * Match a response with the dialog.
	 * @param r [in] The response.
	 * @param tuid [in] The transaction user id of the transaction for the response.
	 * @return true, if the response matches the dialog.
	 * @return false, otherwise.
	 */
	virtual bool match_response(t_response *r, t_tuid tuid);

	/**
	 * Match a request with the dialog.
	 * @param r [in] The request.
	 * @return true, if the request matches the dialog.
	 * @return false, otherwise.
	 */
	virtual bool match_request(t_request *r);
	
	/**
	 * Partially match a request with the dialog, i.e. do not match remote tag.
	 * @param r [in] The request.
	 * @return true, if the request partially matches the dialog.
	 * @return false, otherwise.
	 */
	virtual bool match_partial_request(t_request *r);
	
	/**
	 * Match call-id and tags with the dialog.
	 * @param _call_id [in] SIP call-id.
	 * @param to_tag [in] SIP to-tag.
	 * @param from_tag [in] SIP from-tag.
	 * @return true, if call-id and tags match the dialog.
	 * @return false, otherwise.
	 */
	virtual bool match(const string &_call_id, const string &to_tag, 
		const string &from_tag) const;
	
	/**
	 * Get the URI of the remote target.
	 * @return remote target URI.
	 * @see remote_target_uri
	 */
	t_url get_remote_target_uri(void) const;
	
	/**
	 * Get the display name of the remote target.
	 * @return display name of remote target.
	 * @see remote_target_display
	 */
	string get_remote_target_display(void) const;
	
	/**
	 * Get the URI of the remote party.
	 * @return URI of remote party.
	 * @see remote_uri
	 */
	t_url get_remote_uri(void) const;
	
	/**
	 * Get the display name of the remote party.
	 * @return display name of the remote party.
	 * @see remote_display
	 */
	string get_remote_display(void) const;
	
	/**
	 * Get the IP transport/address/port from which the last SIP message was received.
	 * @return transport/address/port
	 */
	t_ip_port get_remote_ip_port(void) const;
	
	/**
	 * Get the SIP call id.
	 * @return SIP call id.
	 */
	string get_call_id(void) const;
	
	/**
	 * Get the local tag.
	 * @return local tag.
	 */
	string get_local_tag(void) const;
	
	/**
	 * Get the remote tag.
	 * @return remote tag.
	 */
	string get_remote_tag(void) const;
	
	/**
	 * Check if the remote party supports a particular SIP exentsion.
	 * @param extension [in] Name of the SIP extension.
	 * @return true, if remote party supports the extension.
	 * @return false, otherwise.
	 */
	virtual bool remote_extension_supported(const string &extension) const;

	/**
	 * Check if this dialog is the owner of the call id.
	 * @return true, if this dialog is the owner.
	 * @return false, otherwise.
	 * @see call_id_owner
	 */
	bool is_call_id_owner(void) const;
};

#endif