1 /*
2 *
3 * Inter Asterisk Exchange 2
4 *
5 * Class to manage information information about the remote node.
6 *
7 * Open Phone Abstraction Library (OPAL)
8 *
9 * Copyright (c) 2005 Indranet Technologies Ltd.
10 *
11 * The contents of this file are subject to the Mozilla Public License
12 * Version 1.0 (the "License"); you may not use this file except in
13 * compliance with the License. You may obtain a copy of the License at
14 * http://www.mozilla.org/MPL/
15 *
16 * Software distributed under the License is distributed on an "AS IS"
17 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
18 * the License for the specific language governing rights and limitations
19 * under the License.
20 *
21 * The Original Code is Open Phone Abstraction Library.
22 *
23 * The Initial Developer of the Original Code is Indranet Technologies Ltd.
24 *
25 * The author of this code is Derek J Smithies
26 *
27 * $Revision: 24607 $
28 * $Author: dereksmithies $
29 * $Date: 2010-07-28 22:53:29 -0500 (Wed, 28 Jul 2010) $
30 */
31
32 #include <ptlib.h>
33 #include <opal/buildopts.h>
34
35 #if OPAL_IAX2
36
37 #ifdef P_USE_PRAGMA
38 #pragma implementation "remote.h"
39 #endif
40
41 #include <iax2/remote.h>
42 #include <iax2/frame.h>
43
44 #define new PNEW
45
46
IAX2Remote()47 IAX2Remote::IAX2Remote()
48 {
49 sourceCallNumber = callNumberUndefined;
50 destCallNumber = callNumberUndefined;
51
52 remotePort = 0;
53 }
54
55
56
Assign(IAX2Remote & source)57 void IAX2Remote::Assign(IAX2Remote & source)
58 {
59 destCallNumber = source.SourceCallNumber();
60 sourceCallNumber = source.DestCallNumber();
61 remoteAddress = source.RemoteAddress();
62 remotePort = source.RemotePort();
63 }
64
operator ==(IAX2Remote & other)65 PBoolean IAX2Remote::operator==(IAX2Remote & other)
66 {
67 if (remoteAddress != other.RemoteAddress()) {
68 PTRACE(5, "Comparison of two remotes " << endl << other << endl << (*this) );
69 PTRACE(5, "comparison of two remotes Addresses are different");
70 return PFalse;
71 }
72
73 if (remotePort != other.RemotePort()) {
74 PTRACE(5, "Comparison of two remotes " << endl << other << endl << (*this) );
75 PTRACE(5, "comparison of two remotes remote ports are different");
76 return PFalse;
77 }
78
79 if (destCallNumber != other.DestCallNumber()) {
80 PTRACE(5, "Comparison of two remotes " << endl << other << endl << (*this) );
81 PTRACE(5, "comparison of two remotes. Dest call numbers differ");
82 return PFalse;
83 }
84
85 if (sourceCallNumber != other.SourceCallNumber()) {
86 PTRACE(5, "Comparison of two remotes " << endl << other << endl << (*this) );
87 PTRACE(5, "comparison of two remotes. Source call numbers differ");
88 return PFalse;
89 }
90
91 return PTrue;
92 }
93
94
operator *=(IAX2Remote & other)95 PBoolean IAX2Remote::operator*=(IAX2Remote & other)
96 {
97 PTRACE(6, "Incoming ethernet frame. Compare" << endl << other << endl << (*this) );
98
99 if (remoteAddress != other.RemoteAddress()) {
100 PTRACE(3, "comparison of two remotes Addresses are different");
101 return PFalse;
102 }
103
104 if (remotePort != other.RemotePort()) {
105 PTRACE(5, "comparison of two remotes remote ports are different");
106 return PFalse;
107 }
108
109 if (sourceCallNumber != other.DestCallNumber()) {
110 PTRACE(5, "comparison of two remotes. Local source number differs to incoming dest call number");
111 PTRACE(5, " local sourceCallNumber " << sourceCallNumber
112 << " incoming Dest " << other.DestCallNumber());
113 return PFalse;
114 }
115
116 PTRACE(6, "comparison of two remotes They are the same ");
117 return PTrue;
118 }
119
120
operator !=(IAX2Remote & other)121 PBoolean IAX2Remote::operator!=(IAX2Remote & other)
122 {
123 return !(*this == other);
124 }
125
SetDestCallNumber(PINDEX newVal)126 void IAX2Remote::SetDestCallNumber(PINDEX newVal)
127 {
128 destCallNumber = newVal;
129 }
130
PrintOn(ostream & strm) const131 void IAX2Remote::PrintOn(ostream & strm) const
132 {
133 strm << "src" << sourceCallNumber
134 << " dest" << destCallNumber
135 << " " << remoteAddress
136 << ":" << remotePort ;
137 }
138
BuildConnectionToken()139 PString IAX2Remote::BuildConnectionToken()
140 {
141 return PString("iax2:")
142 + RemoteAddress().AsString()
143 + PString("-")
144 + PString(SourceCallNumber());
145 }
146
BuildOurConnectionToken()147 PString IAX2Remote::BuildOurConnectionToken()
148 {
149 return PString("iax2:")
150 + RemoteAddress().AsString()
151 + PString("-")
152 + PString(DestCallNumber());
153 }
154
155 ////////////////////////////////////////////////////////////////////////////////
156 //paranoia here. Use brackets to guarantee the order of calculation.
IAX2FrameIdValue(PINDEX timeStamp,PINDEX seqVal)157 IAX2FrameIdValue::IAX2FrameIdValue(PINDEX timeStamp, PINDEX seqVal)
158 {
159 value = (timeStamp << 8) + (seqVal & 0xff);
160 }
161
IAX2FrameIdValue(PINDEX val)162 IAX2FrameIdValue::IAX2FrameIdValue(PINDEX val)
163 {
164 value = val;
165 }
166
167
GetPlainSequence() const168 PINDEX IAX2FrameIdValue::GetPlainSequence() const
169 {
170 return (PINDEX)(value & P_MAX_INDEX);
171 }
172
GetTimeStamp() const173 PINDEX IAX2FrameIdValue::GetTimeStamp() const
174 {
175 return (PINDEX)(value >> 8);
176 }
177
GetSequenceVal() const178 PINDEX IAX2FrameIdValue::GetSequenceVal() const
179 {
180 return (PINDEX)(value & 0xff);
181 }
182
PrintOn(ostream & strm) const183 void IAX2FrameIdValue::PrintOn(ostream & strm) const
184 {
185 strm << setw(8) << GetTimeStamp() << " --" << setw(4) << GetSequenceVal();
186 }
187
188
Compare(const PObject & obj) const189 PObject::Comparison IAX2FrameIdValue::Compare(const PObject & obj) const
190 {
191 PAssert(PIsDescendant(&obj, IAX2FrameIdValue), PInvalidCast);
192 const IAX2FrameIdValue & other = (const IAX2FrameIdValue &)obj;
193
194 if ((value > 224) && (other.value < 32))
195 return LessThan; //value has wrapped around 256, other has not.
196
197 if ((value < 32) && (other.value > 224))
198 return GreaterThan; //value has wrapped around 256, other has not.
199
200 if (value < other.value)
201 return LessThan;
202
203 if (value > other.value)
204 return GreaterThan;
205
206 return EqualTo;
207 }
208
209 ////////////////////////////////////////////////////////////////////////////////
Contains(IAX2FrameIdValue & src)210 PBoolean IAX2PacketIdList::Contains(IAX2FrameIdValue &src)
211 {
212 PINDEX idex = GetValuesIndex(src);
213 return idex != P_MAX_INDEX;
214 }
215
GetFirstValue()216 PINDEX IAX2PacketIdList::GetFirstValue()
217 {
218 if (GetSize() == 0)
219 return 255;
220
221 return ((IAX2FrameIdValue *)GetAt(0))->GetPlainSequence();
222 }
223
RemoveOldContiguousValues()224 void IAX2PacketIdList::RemoveOldContiguousValues()
225 {
226 PBoolean contiguous = PTrue;
227 while((GetSize() > 1) && contiguous) {
228 PINDEX first = ((IAX2FrameIdValue *)GetAt(0))->GetPlainSequence();
229 PINDEX second = ((IAX2FrameIdValue *)GetAt(1))->GetPlainSequence();
230 contiguous = ((first + 1) & 0xff) == second;
231 if (contiguous)
232 RemoveAt(0);
233 }
234 }
235
PrintOn(ostream & strm) const236 void IAX2PacketIdList::PrintOn(ostream & strm) const
237 {
238 strm << "Packet Id List Size=" << GetSize() << endl;
239 for(PINDEX i = 0; i < GetSize(); i++)
240 strm << (*((IAX2FrameIdValue *)GetAt(i))) << endl;
241 }
242
AppendNewFrame(IAX2FullFrame & src)243 void IAX2PacketIdList::AppendNewFrame(IAX2FullFrame &src)
244 {
245 IAX2FrameIdValue *f = new IAX2FrameIdValue(src.GetSequenceInfo().OutSeqNo());
246 PTRACE(5, "AppendNewFrame " << (*f));
247
248 if(GetSize() == 0) {
249 PTRACE(5, "SeqNos\tList empty, so add now. " << (*f));
250 Append(f);
251 return;
252 }
253
254 if (Contains(*f)) {
255 PTRACE(5, "SeqNos\tJustRead frame is " << (*f));
256 PTRACE(5, "SeqNos\tIn queue waiting removal " << (*f));
257 delete f;
258 return;
259 }
260
261 if (((IAX2FrameIdValue *)GetAt(0))->Compare(*f) == GreaterThan) {
262 PTRACE(5, "SeqNos\tHave already processed " << (*f));
263 PTRACE(5, "SeqNos\tFirst frame in que " << (*(IAX2FrameIdValue *)GetAt(0)));
264 PTRACE(5, "SeqNos\tFrame just read is " << (*f));
265 delete f;
266 return;
267 }
268
269 PTRACE(5, "SeqNos\tList is younger than this value. " << (*f));
270 Append(f);
271 RemoveOldContiguousValues();
272
273 PTRACE(5, "SeqNos\t" << (*this));
274 }
275
276 ////////////////////////////////////////////////////////////////////////////////
277
ZeroAllValues()278 void IAX2SequenceNumbers::ZeroAllValues()
279 {
280 PWaitAndSignal m(mutex);
281
282 inSeqNo = 0;
283 outSeqNo = 0;
284 lastSentTimeStamp = 0;
285 }
286
287
288
operator !=(IAX2SequenceNumbers & other)289 PBoolean IAX2SequenceNumbers::operator != (IAX2SequenceNumbers &other)
290 {
291 PWaitAndSignal m(mutex);
292 if (inSeqNo == other.InSeqNo())
293 return PFalse;
294
295 if (inSeqNo == other.OutSeqNo())
296 return PFalse;
297
298 if (outSeqNo == other.InSeqNo())
299 return PFalse;
300
301 if (outSeqNo == other.OutSeqNo())
302 return PFalse;
303
304 return PTrue;
305 }
306
SetAckSequenceInfo(IAX2SequenceNumbers & other)307 void IAX2SequenceNumbers::SetAckSequenceInfo(IAX2SequenceNumbers & other)
308 {
309 PWaitAndSignal m(mutex);
310 outSeqNo = other.InSeqNo();
311 }
312
operator ==(IAX2SequenceNumbers & other)313 PBoolean IAX2SequenceNumbers::operator == (IAX2SequenceNumbers &other)
314 {
315 PWaitAndSignal m(mutex);
316 if ((inSeqNo == other.InSeqNo()) && (outSeqNo == other.OutSeqNo()))
317 return PTrue;
318
319
320 if ((inSeqNo == other.OutSeqNo()) && (outSeqNo == other.InSeqNo()))
321 return PTrue;
322
323 return PFalse;
324 }
325
326
MassageSequenceForSending(IAX2FullFrame & src)327 void IAX2SequenceNumbers::MassageSequenceForSending(IAX2FullFrame &src)
328 {
329 PWaitAndSignal m(mutex);
330
331 if (src.IsAckFrame()) {
332 src.ModifyFrameHeaderSequenceNumbers(inSeqNo, src.GetSequenceInfo().OutSeqNo());
333 return;
334 }
335
336 PTRACE(5, "SeqNos\tMassage - SequenceForSending(FullFrame &src) ordinary Frame");
337
338 PINDEX timeStamp = src.GetTimeStamp();
339 if ((timeStamp < (lastSentTimeStamp + minSpacing)) && !src.IsNewFrame() &&
340 !src.IsPongFrame() && !src.IsLagRpFrame() &&
341 !src.IsAckFrame()) {
342 timeStamp = lastSentTimeStamp + minSpacing;
343 src.ModifyFrameTimeStamp(timeStamp);
344 }
345
346 lastSentTimeStamp = timeStamp;
347
348 if (src.IsVnakFrame()) {
349 src.ModifyFrameHeaderSequenceNumbers(inSeqNo, inSeqNo);
350 return;
351 } else
352 src.ModifyFrameHeaderSequenceNumbers(inSeqNo, outSeqNo);
353
354 outSeqNo++;
355 }
356
IncomingMessageInOrder(IAX2FullFrame & src)357 IAX2SequenceNumbers::IncomingOrder IAX2SequenceNumbers::IncomingMessageInOrder(IAX2FullFrame &src)
358 {
359 if (src.IsAckFrame())
360 return InSequence;
361
362 if (src.IsHangupFrame())
363 return InSequence;
364
365 PINDEX newFrameOutSeqNo = src.GetSequenceInfo().OutSeqNo();
366
367 PWaitAndSignal m(mutex);
368 if ((inSeqNo & 0xff) == newFrameOutSeqNo) {
369 PTRACE(5, "SeqNos\treceivedoseqno is " << newFrameOutSeqNo << " and in order");
370 inSeqNo ++;
371 return InSequence;
372 }
373
374 if ((inSeqNo & 0xff) > newFrameOutSeqNo) {
375 //WE have already seen this frame. drop it.
376 PTRACE(5, "SeqNos\treceivedoseqno is " << newFrameOutSeqNo << " We have already seen this frame");
377 return RepeatedFrame;
378 }
379
380 PTRACE(5, "SeqNos\treceivedoseqno is " << newFrameOutSeqNo << " is out of order. " << inSeqNo);
381 return SkippedFrame;
382 }
383
384
385
CopyContents(IAX2SequenceNumbers & src)386 void IAX2SequenceNumbers::CopyContents(IAX2SequenceNumbers &src)
387 {
388 PWaitAndSignal m(mutex);
389 inSeqNo = src.InSeqNo();
390 outSeqNo = src.OutSeqNo();
391 }
392
AsString() const393 PString IAX2SequenceNumbers::AsString() const
394 {
395 PWaitAndSignal m(mutex);
396 PStringStream res;
397 res << " in" << inSeqNo << " out" << outSeqNo ;
398
399 return res;
400 }
401
PrintOn(ostream & strm) const402 void IAX2SequenceNumbers::PrintOn(ostream & strm) const
403 {
404 strm << AsString();
405 }
406
InSeqNo()407 PINDEX IAX2SequenceNumbers::InSeqNo()
408 {
409 PWaitAndSignal m(mutex);
410 return inSeqNo;
411 }
412
OutSeqNo()413 PINDEX IAX2SequenceNumbers::OutSeqNo()
414 {
415 PWaitAndSignal m(mutex);
416 return outSeqNo;
417 }
418
IsFirstReplyFrame()419 PBoolean IAX2SequenceNumbers::IsFirstReplyFrame()
420 {
421 PWaitAndSignal m(mutex);
422 return (inSeqNo == 1) && (outSeqNo == 0);
423 }
424
IsSequenceNosZero()425 PBoolean IAX2SequenceNumbers::IsSequenceNosZero()
426 {
427 PWaitAndSignal m(mutex);
428 return ((inSeqNo && 0xff) == 0) && ((outSeqNo && 0xff) == 0);
429 }
430
SetInSeqNo(PINDEX newVal)431 void IAX2SequenceNumbers::SetInSeqNo(PINDEX newVal)
432 {
433 PWaitAndSignal m(mutex);
434 inSeqNo = newVal;
435 }
436
SetOutSeqNo(PINDEX newVal)437 void IAX2SequenceNumbers::SetOutSeqNo(PINDEX newVal)
438 {
439 PWaitAndSignal m(mutex);
440 outSeqNo = newVal;
441 }
442
SetInOutSeqNo(PINDEX inVal,PINDEX outVal)443 void IAX2SequenceNumbers::SetInOutSeqNo(PINDEX inVal, PINDEX outVal)
444 {
445 PWaitAndSignal m(mutex);
446
447 inSeqNo = inVal;
448 outSeqNo = outVal;
449 }
450
451 ////////////////////////////////////////////////////////////////////////////////
IAX2Encryption()452 IAX2Encryption::IAX2Encryption()
453 {
454 encryptionEnabled = PFalse;
455 }
456
457
SetEncryptionOn(PBoolean newState)458 void IAX2Encryption::SetEncryptionOn (PBoolean newState)
459 {
460 encryptionEnabled = newState;
461 PTRACE(3, "Set encryption to " << PString(encryptionEnabled ? "On" : "Off"));
462 }
463
SetEncryptionKey(PString & newKey)464 void IAX2Encryption::SetEncryptionKey(PString & newKey)
465 {
466 encryptionKey = newKey;
467 CalculateAesKeys();
468 }
469
SetChallengeKey(PString & newKey)470 void IAX2Encryption::SetChallengeKey(PString & newKey)
471 {
472 challengeKey = newKey;
473 CalculateAesKeys();
474 }
475
EncryptionKey() const476 const PString & IAX2Encryption::EncryptionKey() const
477 {
478 return encryptionKey;
479 }
480
ChallengeKey() const481 const PString & IAX2Encryption::ChallengeKey() const
482 {
483 return challengeKey;
484 }
485
IsEncrypted() const486 PBoolean IAX2Encryption::IsEncrypted() const
487 {
488 return encryptionEnabled;
489 }
490
491 #if OPAL_PTLIB_SSL_AES
AesEncryptKey()492 AES_KEY *IAX2Encryption::AesEncryptKey()
493 {
494 return &aesEncryptKey;
495 }
496
AesDecryptKey()497 AES_KEY *IAX2Encryption::AesDecryptKey()
498 {
499 return &aesDecryptKey;
500 }
501 #endif
502
CalculateAesKeys()503 void IAX2Encryption::CalculateAesKeys()
504 {
505 if (encryptionKey.IsEmpty())
506 return;
507
508 if (challengeKey.IsEmpty())
509 return;
510
511
512 #if OPAL_PTLIB_SSL_AES
513 IAX2IeMd5Result ie(*this);
514 PBYTEArray context = ie.GetDataBlock();
515
516 PTRACE(6, "Decryption\tContext has a size of " << context.GetSize());
517
518 AES_set_encrypt_key(context.GetPointer(), 128, &aesEncryptKey);
519 AES_set_decrypt_key(context.GetPointer(), 128, &aesDecryptKey);
520 #endif
521 }
522
523 #endif // OPAL_IAX2
524
525 //////////////////////////////////////////////////////////////////////////////
526
527 /* The comment below is magic for those who use emacs to edit this file.
528 * With the comment below, the tab key does auto indent to 2 spaces.
529 *
530 * Local Variables:
531 * mode:c
532 * c-basic-offset:2
533 * End:
534 */
535
536