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