1 /*
2  *
3  *
4  * Inter Asterisk Exchange 2
5  *
6  * A class to describe the node we are talking to.
7  *
8  * Open Phone Abstraction Library (OPAL)
9  *
10  * Copyright (c) 2005 Indranet Technologies Ltd.
11  *
12  * The contents of this file are subject to the Mozilla Public License
13  * Version 1.0 (the "License"); you may not use this file except in
14  * compliance with the License. You may obtain a copy of the License at
15  * http://www.mozilla.org/MPL/
16  *
17  * Software distributed under the License is distributed on an "AS IS"
18  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
19  * the License for the specific language governing rights and limitations
20  * under the License.
21  *
22  * The Original Code is Open Phone Abstraction Library.
23  *
24  * The Initial Developer of the Original Code is Indranet Technologies Ltd.
25  *
26  * The author of this code is Derek J Smithies
27  *
28  * $Revision: 24606 $
29  * $Author: dereksmithies $
30  * $Date: 2010-07-28 22:51:05 -0500 (Wed, 28 Jul 2010) $
31  */
32 
33 #ifndef OPAL_IAX2_REMOTE_H
34 #define OPAL_IAX2_REMOTE_H
35 
36 #ifndef _PTLIB_H
37 #include <ptlib.h>
38 #endif
39 
40 #include <opal/buildopts.h>
41 
42 #if OPAL_IAX2
43 
44 #include <ptlib/sockets.h>
45 
46 #if OPAL_PTLIB_SSL_AES
47 #include <openssl/aes.h>
48 #endif
49 
50 #ifdef P_USE_PRAGMA
51 #pragma interface
52 #endif
53 
54 class IAX2FullFrame;
55 
56 
57 /**A simple class which contains the different source and dest call
58    numbers, and the remote address + remote port */
59 class IAX2Remote : public PObject
60 {
61   PCLASSINFO(IAX2Remote, PObject);
62 
63  public:
64 
65   /**Constructor*/
66   IAX2Remote();
67 
~IAX2Remote()68   virtual ~IAX2Remote() { };
69 
70   /**Call number as used at the destination of this data frame. If we are
71      receiving this packet, it refers to our call number. */
DestCallNumber()72   PINDEX DestCallNumber() { return destCallNumber; }
73 
74   /**Call number as used at the source of this data frame. If we are
75      receiving this packet, it refers to the call number at the remote
76      host. */
SourceCallNumber()77   PINDEX SourceCallNumber() { return sourceCallNumber; }
78 
79   /**Pretty print this remote structure (address & port) to the designated stream*/
80   virtual void PrintOn(ostream & strm) const;
81 
82   /**Define which is used to indicate the call number is undefined */
83   enum {
84     callNumberUndefined = 0xffff
85   };
86 
87   /** Return the current value of the ip address used by the other end of this call */
RemoteAddress()88   PIPSocket::Address RemoteAddress() { return remoteAddress; }
89 
90   /**the connection token can be derived from the information in this
91      class. Consequently, get this class to create the connection
92      token */
93   PString BuildConnectionToken();
94 
95   /**Similar to BuildConnectionTokenId, but build it with our source call  number, not remote call number */
96   PString BuildOurConnectionToken();
97 
98   /** return the current value of the port at the other end of this call */
RemotePort()99   PINDEX   RemotePort() { return remotePort; }
100 
101   /**Copy data from supplied Remote structure to this class */
102   void Assign(IAX2Remote &);
103 
104   /**Set the remote address as used by this class */
SetRemoteAddress(PIPSocket::Address & newVal)105   void SetRemoteAddress(PIPSocket::Address &newVal) { remoteAddress = newVal; }
106 
107   /**Set the remote address as used by this class */
SetRemoteAddress(int newVal)108   void SetRemoteAddress(int newVal) { remoteAddress = newVal; }
109 
110   /**Set the remote port, as used by this class */
SetRemotePort(PINDEX newVal)111   void SetRemotePort (PINDEX newVal) { remotePort = newVal; }
112 
113   /**Set the Source Call Number, as used by this class */
SetSourceCallNumber(PINDEX newVal)114   void SetSourceCallNumber(PINDEX newVal) { sourceCallNumber = newVal; }
115 
116   /**Set the Dest Call Number, as used by this class */
117   void SetDestCallNumber(PINDEX newVal);
118 
119   /**Return true if remote port & address & destCallNumber & source
120      call number match up.  This is used when finding a Connection
121      that generated an ethernet frame which is to be transmitted*/
122   PBoolean operator == (IAX2Remote & other);
123 
124   /**Return true if remote port & address & destCallNumber==sourceCallNumber  match up.
125      This is used when finding a Connection to process an incoming ethernet frame */
126   PBoolean operator *= (IAX2Remote & other);
127 
128 
129   /**Returns true if these are are different */
130   PBoolean operator != (IAX2Remote & other);
131 
132 
133  protected:
134   /**Call number at the local computer.*/
135   PINDEX       sourceCallNumber;
136 
137   /**Call number at the remote computer.*/
138   PINDEX       destCallNumber;
139 
140   /**Ip address used by the remote endpoint*/
141   PIPSocket::Address remoteAddress;
142 
143   /**Port number used by the remote endpoint.*/
144   PINDEX               remotePort;
145 
146 };
147 
148 ////////////////////////////////////////////////////////////////////////////////
149 /**A class to store the timestamp and sequence number in a indexable
150   fashion.
151 
152   This class will be used as a key into the sorted list, which is
153   declared below  (PacketIdList).  This class is required because
154   pwlib's dictionaries requires the key to be a descendant from a PObject
155 
156   The 32 bit timestamp is left shifted by 8 bits, and the
157   result is added to the 8 bit seqno value */
158 class IAX2FrameIdValue : public PObject
159 {
160   PCLASSINFO(IAX2FrameIdValue, PObject);
161  public:
162   /**Constructor. to timestamp<<8   +  sequenceNumber*/
163   IAX2FrameIdValue (PINDEX timeStamp, PINDEX seqVal);
164 
165   /**Constructor to some value */
166   IAX2FrameIdValue (PINDEX val);
167 
168   /**Retrieve this timestamp */
169   PINDEX GetTimeStamp() const;
170 
171   /**Retrieve this sequence number.*/
172   PINDEX GetSequenceVal() const;
173 
174   /**Retrieve the bottom 32 bits.  In this call, the data is assumed
175      to be no timestamp, and sequence number could be > 255. This is
176      used for the iseqno of transmitted packets */
177   PINDEX GetPlainSequence() const;
178 
179   /**Pretty print this data to the designated stream*/
180   virtual void PrintOn(ostream & strm) const;
181 
182   /**Declare this method so that all comparisons (as used in sorted
183      lists) work. correctly*/
184   virtual Comparison Compare(const PObject & obj) const;
185 
186  protected:
187 
188   /**The combination of time and sequence number is stored in this
189      element, which is a pwlib construct of 64 bits */
190   PUInt64 value;
191 };
192 
193 ////////////////////////////////////////////////////////////////////////////////
194 
195 /**A class to store a unique identifing number, so we can keep track
196 of all frames we have sent and received. This will be sued to keep the
197 iseqno correct (for use in sent frames), and to ensure that we never
198 send two frames with the same iseqno and timestamp pair.*/
PDECLARE_SORTED_LIST(IAX2PacketIdList,IAX2FrameIdValue)199 PDECLARE_SORTED_LIST(IAX2PacketIdList, IAX2FrameIdValue)
200 #ifdef DOC_PLUS_PLUS
201 class IAX2PacketIdList : public PSortedList
202 {
203 #endif
204 
205   /**Return true if a FrameIdValue object is found in the list that
206    * matches the value in the supplied arguement*/
207   PBoolean Contains(IAX2FrameIdValue &src);
208 
209   /**Return the value at the beginning of the list. Use this value as
210      the InSeqNo of this endpoint.*/
211   PINDEX GetFirstValue();
212 
213   /**For the supplied frame, append to this list */
214   void AppendNewFrame(IAX2FullFrame &src);
215 
216   /**Pretty print this listto the designated stream*/
217   virtual void PrintOn(ostream & strm) const;
218 
219  protected:
220   /**Remove all the contiguous oldest values, which is used for
221      determining the correct iseqno.  This endpoints iseqno is
222      determined from::: iseqno is�always
223      highest_contiguously_recieved_oseq+1�
224   */
225   void RemoveOldContiguousValues();
226 };
227 
228 ////////////////////////////////////////////////////////////////////////////////
229 /**A structure to hold incoming and outgoing sequence numbers */
230 class IAX2SequenceNumbers
231 {
232  public:
233 /**An enum to describe incoming frame. The incoming frame may be on time
234    (perfect sequence numbers) repeated (we have already seen it before) or out
235    of order (a frame is skipped). */
236   enum IncomingOrder {
237     InSequence,  ///<  perfect sequence number
238     SkippedFrame, ///< there is a missing frame, a VNAK condition
239     RepeatedFrame ///< we have already seen this frame...
240   };
241 
242 
243 
244   /**Constructor, which sets the in and out sequence numbers to zero*/
IAX2SequenceNumbers()245   IAX2SequenceNumbers()
246     { ZeroAllValues();   };
247 
248   /**Destructor, which is provided as this class contains virtual methods*/
~IAX2SequenceNumbers()249   virtual ~IAX2SequenceNumbers() { }
250 
251   /**Initialise to Zero values */
252   void ZeroAllValues();
253 
254   /**Read the incoming sequence number */
255   PINDEX InSeqNo();
256 
257   /**Read the outgoing sequence number */
258   PINDEX OutSeqNo();
259 
260   /**Report true if the frame has inSeqNo and outSeqNo of 1 and 0 respectively,
261      indicating this is a reply to a new frame (could be an ack, accept frame) */
262   PBoolean IsFirstReplyFrame();
263 
264   /**Report if the sequences numbers (in and out) are both Zero. This is the case for
265      some frames (new, invalid) */
266   PBoolean IsSequenceNosZero();
267 
268   /**Assign new value to the in (or expected) seq number */
269   void SetInSeqNo(PINDEX newVal);
270 
271   /**Assign a new value to the sequence number used for outgoing frames */
272   void SetOutSeqNo(PINDEX newVal);
273 
274   /**Assign a new value to the seq.in and seq.out, which is used prior
275      to sending a frame */
276   void SetInOutSeqNo(PINDEX inVal, PINDEX outVal);
277 
278   /**Assign the sequence nos as appropropriate for when we are sending a
279    * sequence set in a ack frame */
280   void SetAckSequenceInfo(IAX2SequenceNumbers & other);
281 
282   /**Comparison operator - tests if sequence numbers are different */
283   PBoolean  operator !=(IAX2SequenceNumbers &other);
284 
285   /**Comparison operator - tests if sequence numbers are equal */
286   PBoolean operator ==(IAX2SequenceNumbers &other);
287 
288   /**Increment this sequences outSeqNo, and assign the results to the source arg */
289   void MassageSequenceForSending(IAX2FullFrame &src /*<!src will be transmitted to the remote node */
290 				 );
291 
292   /**Take the incoming frame, and increment seq nos by some multiple
293      of 256 to bring them into line with the current values. Use the
294      wrapAound member variable to do this.*/
295   void WrapAroundFrameSequence(IAX2SequenceNumbers & src);
296 
297   /** We have received a message from the remote node. Check sequence numbers
298       are ok. reply with the appropriate enum to describe if the incoming
299       frame is early, late, or on time */
300   IncomingOrder IncomingMessageInOrder
301     (IAX2FullFrame &src /*<!frame to be compared with current data base.*/  );
302 
303   /**Copy the sequence info from the source argument to this class */
304   void CopyContents(IAX2SequenceNumbers &src);
305 
306   /**Report  the contents as a string*/
307   PString AsString() const;
308 
309   /**Pretty print in and out sequence numbers  to the designated stream*/
310   virtual void PrintOn(ostream & strm) const;
311 
312   /**Report true if this sequnece info is the very first packet
313      received from a remote node, where we have initiated the call */
IsFirstReply()314   PBoolean IsFirstReply() { return (inSeqNo == 1) && (outSeqNo == 0); }
315 
316   /**Add an offset to the inSeqNo and outSeqNo variables */
317   void AddWrapAroundValue(PINDEX newOffset);
318 
319 
320  protected:
321 
322   /**An enum to contain the various defines required by this clsss */
323   enum sequenceDefines {
324     minSpacing = 3   /*!< minimum spacing in ms for the time stamp of full frames */
325   };
326 
327   /** Packet number (next incoming expected)*/
328   PINDEX inSeqNo;
329 
330   /** Packet number (outgoing) */
331   PINDEX outSeqNo;
332 
333   /**Mutex to protect access to this structrue while doing seqno changes*/
334   PMutex mutex;
335 
336   /**Last sent time stamp - ensure 3 ms gap between time stamps. */
337   PINDEX lastSentTimeStamp;
338 
339   /**Dictionary of timestamp and OutSeqNo for frames received by  this iax device */
340   IAX2PacketIdList receivedLog;
341 };
342 
343 ////////////////////////////////////////////////////////////////////////////////
344 /** A class that holds the state variables on encryption - is it on, and the two keys. */
345 class IAX2Encryption : public PObject
346 {
347   PCLASSINFO(IAX2Encryption, PObject);
348  public:
349   /**Constructor, which sets encrytpion to the default value of "OFF" */
350   IAX2Encryption();
351 
352   /**Set the flag that indicates this communication session is all encrypted.. */
353   void SetEncryptionOn (PBoolean newState = true);
354 
355   /**Set the password/key used in encryption process */
356   void SetEncryptionKey(PString & newKey);
357 
358   /**Set the challenge  used in encryption process */
359   void SetChallengeKey(PString & newKey);
360 
361   /**Get the value of the encrption key  - or password key */
362   const PString & EncryptionKey() const;
363 
364   /**Get the value of the challenge key */
365   const PString & ChallengeKey() const;
366 
367   /**Report if the encryption is enabled  (or turned on) */
368   PBoolean IsEncrypted() const;
369 
370 #if OPAL_PTLIB_SSL_AES
371   /**Get a pointer to a filled AES_KEY encrypt structure */
372   AES_KEY *AesEncryptKey();
373 
374   /**Get a pointer to a filled AES_KEY decrypt structure */
375   AES_KEY *AesDecryptKey();
376 #endif
377 
378  protected:
379   /**Do the calculation of the encrypt and decrypt AES 128 keys.
380      If neither, or only 1 of the encrypt/challenge keys are defined, do nothing */
381   void CalculateAesKeys();
382 
383   /**string to use for decryption/encryption of this frame */
384   PString encryptionKey;
385 
386   /**string to use for decryption/encryption of this frame */
387   PString challengeKey;
388 
389   /**Flag to specify if encryption is happening */
390   PBoolean encryptionEnabled;
391 
392 #if OPAL_PTLIB_SSL_AES
393   /**key to be used for AES 128 encryption */
394   AES_KEY aesEncryptKey;
395 
396   /**key to be used for AES 128 decoding */
397   AES_KEY aesDecryptKey;
398 #endif
399 };
400 
401 ////////////////////////////////////////////////////////////////////////////////
402 
403 
404 #endif // OPAL_IAX2
405 
406 #endif // OPAL_IAX2_REMOTE_H
407 
408 /* The comment below is magic for those who use emacs to edit this file.
409  * With the comment below, the tab key does auto indent to 2 spaces.
410  *
411  * Local Variables:
412  * mode:c
413  * c-basic-offset:2
414  * End:
415  */
416