blob: 884f1a430d1fd0633abcebdddc7e0430209467a6 (
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
|
namespace Dino.Crypto.DtlsSrtp {
public abstract class CredentialsCapsule : Object {
public uint8[] own_fingerprint;
}
public abstract class AbstractHandler {
public signal void send_data(uint8[] data);
public bool ready { get {
return srtp_session.has_encrypt && srtp_session.has_decrypt;
}}
public Mode mode { get; set; default = Mode.CLIENT; }
public uint8[] own_fingerprint { get; private set; }
public uint8[] peer_fingerprint { get; set; }
public string peer_fp_algo { get; set; }
protected CredentialsCapsule credentials;
protected Cond buffer_cond = Cond();
protected Mutex buffer_mutex = Mutex();
protected Gee.LinkedList<Bytes> buffer_queue = new Gee.LinkedList<Bytes>();
protected bool running = false;
protected bool stop = false;
protected bool restart = false;
protected Crypto.Srtp.Session srtp_session = new Crypto.Srtp.Session();
protected AbstractHandler.with_cert(CredentialsCapsule creds) {
this.credentials = creds;
this.own_fingerprint = creds.own_fingerprint;
}
public uint8[]? process_incoming_data(uint component_id, uint8[] data) throws Crypto.Error {
if (data[0] >= 128) {
if (!srtp_session.has_decrypt) {
debug("Received data before SRTP session is ready, dropping.");
return null;
}
if (component_id == 1) {
if (data.length >= 2 && data[1] >= 192 && data[1] < 224) {
return srtp_session.decrypt_rtcp(data);
}
return srtp_session.decrypt_rtp(data);
}
if (component_id == 2) return srtp_session.decrypt_rtcp(data);
}
if (component_id == 1 && data.length >= 1 && (data[0] >= 20 && data[0] < 64)) {
on_data_rec(data);
return null;
}
debug("Dropping unknown data from component %u", component_id);
return null;
}
public uint8[]? process_outgoing_data(uint component_id, uint8[] data) throws Crypto.Error {
if (srtp_session.has_encrypt) {
if (component_id == 1) {
if (data.length >= 2 && data[1] >= 192 && data[1] < 224) {
return srtp_session.encrypt_rtcp(data);
}
return srtp_session.encrypt_rtp(data);
}
if (component_id == 2) return srtp_session.encrypt_rtcp(data);
}
return null;
}
public void on_data_rec(owned uint8[] data) {
buffer_mutex.lock();
buffer_queue.add(new Bytes.take(data));
buffer_cond.signal();
buffer_mutex.unlock();
}
public void stop_dtls_connection() {
buffer_mutex.lock();
stop = true;
buffer_cond.signal();
buffer_mutex.unlock();
}
protected Bytes get_buffer_if_present () {
buffer_mutex.lock();
if (buffer_queue.size == 0) {
buffer_mutex.unlock();
return null;
}
Bytes res = buffer_queue.remove_at(0);
buffer_mutex.unlock();
return res;
}
public async Xmpp.Xep.Jingle.ContentEncryption? setup_dtls_connection() {
MainContext context = MainContext.current_source().get_context();
var thread = new Thread<Xmpp.Xep.Jingle.ContentEncryption>("dtls-connection", () => {
// Check we can start working on the thread
buffer_mutex.lock();
if (stop) {
restart = true;
buffer_mutex.unlock();
return null;
}
if (running || ready) {
buffer_mutex.unlock();
return null;
}
running = true;
restart = false;
buffer_mutex.unlock();
// Actual work
var res = setup_dtls_connection_thread();
// Callback
Source source = new IdleSource();
source.set_callback(setup_dtls_connection.callback);
source.attach(context);
return res;
});
yield;
return thread.join();
}
protected abstract Xmpp.Xep.Jingle.ContentEncryption? setup_dtls_connection_thread();
}
private string format_fingerprint(uint8[] fingerprint) {
var sb = new StringBuilder();
for (int i = 0; i < fingerprint.length; i++) {
sb.append("%02X".printf(fingerprint[i]));
if (i < fingerprint.length - 1) {
sb.append(":");
}
}
return sb.str;
}
public enum Mode {
CLIENT, SERVER
}
}
|