summaryrefslogtreecommitdiffstats
path: root/src/stun/stun_transaction.h
blob: 132bfc2471c1ef4e6ae259489fd8476ee87552ef (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
/*
    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 _STUN_TRANSACTION_H
#define _STUN_TRANSACTION_H

#include "stun.h"
#include "phone_user.h"
#include "protocol.h"
#include "user.h"
#include "transaction.h"
#include "threads/mutex.h"
#include "threads/thread.h"
#include "sockets/socket.h"
#include "sockets/url.h"

// Create a binding in a NAT.
// Returns true on success. Returns false when the STUN server returned
// an error. Throws an int exception (containing errno) when some
// socket operation fails.
bool get_stun_binding(t_user *user_config, unsigned short src_port, unsigned long &mapped_ip,
	unsigned short &mapped_port, int &err_code, string &err_reason);
	
	
// Discover the type of NAT and determine is STUN should be used or
// wether STUN is useless.
// It sets the use_stun attribute of phone if STUN should be used.
// Return false if STUN cannot be used. err_msg will contain an
// error message that can be displayed to the user.
bool stun_discover_nat(t_phone_user *pu, string &err_msg);


//////////////////////////////////////////////
// Base STUN transaction
//////////////////////////////////////////////

class t_stun_transaction {
private:
	static t_mutex		mtx_class; // protect static members
	static t_tid		next_id; // next id to be issued

protected:
	t_tid			id; 	// transaction id
	unsigned short		tuid;	// TU id
	t_trans_state		state;
	
	// Timer for retransmissions
	unsigned short		timer_req_timeout;
	
	// Duration for the next timer start in msec
	unsigned long		dur_req_timeout;
	
	// Number of transmissions of the request
	unsigned short		num_transmissions;

	// Destinations for the request	
	list<t_ip_port> 	destinations;
	
	// User profile of user that created this transaction
	t_user			*user_config;
	
	void start_timer_req_timeout(void);
	void stop_timer_req_timeout(void);
	
	// Retransmit STUN request
	virtual void retransmit(void) = 0;

public:
	StunMessage		*request;

	t_tid get_id(void) const;
	
	// Get state of the transaction
	t_trans_state get_state(void) const;

	// The transaction will keep a copy of the request
	t_stun_transaction(t_user *user, StunMessage *r,
			   unsigned short _tuid, const list<t_ip_port> &dst);

	// All request and response pointers contained by the
	// transaction will be deleted.
	virtual ~t_stun_transaction();

	// Process STUN response
	virtual void process_response(StunMessage *r);
	
	// Process ICMP error
	virtual void process_icmp(const t_icmp_msg &icmp);
	
	// Process timeout
	virtual void timeout(t_stun_timer t);	
	
	// Match response with transaction
	bool match(StunMessage *resp) const;
	
	// Match ICMP error with transaction
	bool match(const t_icmp_msg &icmp) const;
};

//////////////////////////////////////////////
// SIP STUN transaction
//////////////////////////////////////////////

// A SIP STUN transaction is a STUN request to get a binding
// for the SIP port. Such a request must be sent from the SIP port.
// So it must be sent out via the SIP sender thread.

class t_sip_stun_trans : public t_stun_transaction {
protected:
	virtual void retransmit(void);
	
public:
	// Create transaction and send out STUN request		
	t_sip_stun_trans(t_user *user, StunMessage *r,
			 unsigned short _tuid, const list<t_ip_port> &dst);
};

//////////////////////////////////////////////
// Media STUN transaction
//////////////////////////////////////////////

// TODO: this code is not used anymore. Remove?

// A media STUN transaction is a STUN request to get a binding
// for a media port. Such a request must be sent from the media
// port.

class t_media_stun_trans : public t_stun_transaction {
private:
	t_socket_udp	*sock;		// UDP socket for STUN
	t_thread	*thr_listen;	// Listener thread
	
protected:
	virtual void retransmit(void);
	
public:
	// Create transaction and send out STUN request		
	t_media_stun_trans(t_user *user, StunMessage *r,
			 unsigned short _tuid, const list<t_ip_port> &dst, 
			 unsigned short src_port);
	~t_media_stun_trans();
};

#endif