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