OPAL  Version 3.12.5
transports.h
Go to the documentation of this file.
1 /*
2  * transport.h
3  *
4  * Transport declarations
5  *
6  * Open Phone Abstraction Library (OPAL)
7  * Formally known as the Open H323 project.
8  *
9  * Copyright (c) 2001 Equivalence Pty. Ltd.
10  * Portions Copyright (C) 2006 by Post Increment
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 Equivalence Pty. Ltd.
25  *
26  * Contributor(s): Post Increment
27  * Portions of this code were written with the assistance of funding from
28  * US Joint Forces Command Joint Concept Development & Experimentation (J9)
29  * http://www.jfcom.mil/about/abt_j9.htm
30  *
31  * $Revision: 30053 $
32  * $Author: rjongbloed $
33  * $Date: 2013-06-25 20:09:05 -0500 (Tue, 25 Jun 2013) $
34  */
35 
36 #ifndef OPAL_OPAL_TRANSPORT_H
37 #define OPAL_OPAL_TRANSPORT_H
38 
39 #ifdef P_USE_PRAGMA
40 #pragma interface
41 #endif
42 
43 #include <opal/buildopts.h>
44 
45 #include <ptlib/sockets.h>
46 #include <ptclib/psockbun.h>
47 
48 
49 class OpalManager;
50 class OpalEndPoint;
51 class OpalListener;
52 class OpalTransport;
54 
55 typedef PSafePtr<OpalTransport> OpalTransportPtr;
56 
57 
59 
154 class OpalTransportAddress : public PCaselessString
155 {
156  PCLASSINFO(OpalTransportAddress, PCaselessString);
157  public:
158  static const PCaselessString & IpPrefix();
159  static const PCaselessString & UdpPrefix();
160  static const PCaselessString & TcpPrefix();
161 #if OPAL_PTLIB_SSL
162  static const PCaselessString & TlsPrefix();
163 #endif
164 
169  const char * address,
170  WORD port = 0,
171  const char * proto = NULL
172  );
174  const PString & address,
175  WORD port = 0,
176  const char * proto = NULL
177  );
179  const PIPSocket::Address & ip,
180  WORD port,
181  const char * proto = NULL
182  );
183 
185  virtual PObject * Clone() const { return new OpalTransportAddress(*this); }
187 
195  PBoolean IsEquivalent(
196  const OpalTransportAddress & address,
197  bool wildcards = false
198  ) const;
199 
202  PBoolean IsCompatible(
203  const OpalTransportAddress & address
204  ) const;
205 
208  PCaselessString GetProtoPrefix() const { return Left(Find('$')+1); }
209 
210  // For backward compatibility
211  PCaselessString GetProto(bool withDollar = false) const { return Left(Find('$')+(withDollar?1:0)); }
212 
216  PBoolean GetIpAddress(PIPSocket::Address & ip) const;
217 
221  PBoolean GetIpAndPort(PIPSocket::Address & ip, WORD & port) const;
222  PBoolean GetIpAndPort(PIPSocketAddressAndPort & ipPort) const;
223 
227  virtual PString GetHostName(
228  bool includeService = false
229  ) const;
230 
231  enum BindOptions {
239  };
240 
273  OpalEndPoint & endpoint,
274  BindOptions option
275  ) const;
276 
304  virtual OpalTransport * CreateTransport(
305  OpalEndPoint & endpoint,
306  BindOptions option = HostOnly
307  ) const;
309 
310 
311  protected:
313  WORD port,
314  const char * proto
315  );
316 
318 };
319 
320 
321 class OpalTransportAddressArray : public PArray<OpalTransportAddress>
322 {
323  typedef PArray<OpalTransportAddress> ParentClass;
324  PCLASSINFO(OpalTransportAddressArray, ParentClass);
325 
326  protected:
328  : ParentClass(dummy, c) { }
329 
330  public:
331  OpalTransportAddressArray(PINDEX initialSize = 0)
332  : ParentClass(initialSize) { }
334  const OpalTransportAddress & address
335  ) { AppendAddress(address); }
337  const PStringArray & array
338  ) { AppendStringCollection(array); }
340  const PStringList & list
341  ) { AppendStringCollection(list); }
343  const PSortedStringList & list
344  ) { AppendStringCollection(list); }
345 
346  void AppendString(
347  const char * address
348  );
349  void AppendString(
350  const PString & address
351  );
352  void AppendAddress(
353  const OpalTransportAddress & address
354  );
355 
356  virtual PObject * Clone() const
357  {
358  return new OpalTransportAddressArray(0, this);
359  }
360 
361  protected:
363  const PCollection & coll
364  );
365 };
366 
367 
368 
369 
371 
384 class OpalListener : public PObject
385 {
386  PCLASSINFO(OpalListener, PObject);
387  public:
392  OpalListener(
394  );
396 
401  void PrintOn(
402  ostream & strm
403  ) const;
405 
408  enum ThreadMode {
412  };
413 
414  typedef PNotifierTemplate<const OpalTransportPtr &> AcceptHandler;
415  #define PDECLARE_AcceptHandlerNotifier(cls, fn) PDECLARE_NOTIFIER2(OpalListener, cls, fn, const OpalTransportPtr &)
416 
417 
432  virtual bool Open(
433  const AcceptHandler & acceptHandler,
435  );
436 
439  virtual bool IsOpen() const = 0;
440 
443  virtual void Close() = 0;
444 
447  virtual OpalTransport * Accept(
448  const PTimeInterval & timeout
449  ) = 0;
450 
453  virtual OpalTransport * CreateTransport(
454  const OpalTransportAddress & localAddress,
455  const OpalTransportAddress & remoteAddress
456  ) const = 0;
457 
464  const OpalTransportAddress & remoteAddress = OpalTransportAddress()
465  ) const = 0;
466 
469  void CloseWait();
470 
476 
477 
478  protected:
487  void ListenForConnections();
488  void TransportThreadMain(OpalTransportPtr transport);
489 
491  PThread * thread;
494 };
495 
496 
497 PLIST(OpalListenerList, OpalListener);
498 
499 
501 {
502  PCLASSINFO(OpalListenerIP, OpalListener);
503  public:
509  OpalEndPoint & endpoint,
510  PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
511  WORD port = 0,
512  PBoolean exclusive = true
513  );
515  OpalEndPoint & endpoint,
516  const OpalTransportAddress & binding,
518  );
520 
529  const OpalTransportAddress & remoteAddress = OpalTransportAddress()
530  ) const;
532 
535  WORD GetListenerPort() const { return listenerPort; }
536 
537  virtual const PCaselessString & GetProtoPrefix() const = 0;
539 
540 
541  protected:
542  bool CanCreateTransport(
544  const OpalTransportAddress & remoteAddress
545  ) const;
546 
547  PIPSocket::Address localAddress;
550 };
551 
552 
554 {
555  PCLASSINFO(OpalListenerTCP, OpalListenerIP);
556  public:
562  OpalEndPoint & endpoint,
563  PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
564  WORD port = 0,
565  PBoolean exclusive = true
566  );
568  OpalEndPoint & endpoint,
569  const OpalTransportAddress & binding,
571  );
572 
577 
600  virtual bool Open(
601  const AcceptHandler & acceptHandler,
603  );
604 
607  virtual bool IsOpen() const;
608 
611  virtual void Close();
612 
615  virtual OpalTransport * Accept(
616  const PTimeInterval & timeout
617  );
618 
621  virtual OpalTransport * CreateTransport(
623  const OpalTransportAddress & remoteAddress
624  ) const;
626 
627 
628  protected:
629  virtual const PCaselessString & GetProtoPrefix() const;
630 
631  PTCPSocket listener;
632 };
633 
634 
636 {
637  PCLASSINFO(OpalListenerUDP, OpalListenerIP);
638  public:
644  OpalEndPoint & endpoint,
645  PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
646  WORD port = 0,
647  PBoolean exclusive = true
648  );
650  OpalEndPoint & endpoint,
651  const OpalTransportAddress & binding,
653  );
654 
659 
682  virtual bool Open(
683  const AcceptHandler & acceptHandler,
685  );
686 
689  virtual bool IsOpen() const;
690 
693  virtual void Close();
694 
697  virtual OpalTransport * Accept(
698  const PTimeInterval & timeout
699  );
700 
703  virtual OpalTransport * CreateTransport(
705  const OpalTransportAddress & remoteAddress
706  ) const;
707 
714  const OpalTransportAddress & remoteAddress = OpalTransportAddress()
715  ) const;
717 
723  PINDEX size
724  ) { m_bufferSize = size; }
726 
727 
728  protected:
729  virtual const PCaselessString & GetProtoPrefix() const;
730 
731  PMonitoredSocketsPtr listenerBundle;
732  PINDEX m_bufferSize;
733 };
734 
735 
737 
742 class OpalTransport : public PSafeObject
743 {
744  PCLASSINFO(OpalTransport, PSafeObject);
745  protected:
750  OpalTransport(OpalEndPoint & endpoint, PChannel * channel);
751 
752  public:
755  ~OpalTransport();
757 
762  void PrintOn(
763  ostream & strm
764  ) const;
765 
780  virtual PBoolean Write(
781  const void * buf,
782  PINDEX len
783  );
785 
790  virtual PBoolean IsReliable() const = 0;
791 
795  virtual bool IsAuthenticated(
796  const PString & /*domain*/
797  ) const { return true; }
798 
805  virtual PString GetInterface() const;
806 
813  virtual bool SetInterface(
814  const PString & iface
815  );
816 
820  bool allowNAT = true
821  ) const = 0;
822 
827  virtual PBoolean SetLocalAddress(
828  const OpalTransportAddress & address
829  ) = 0;
830 
833  virtual OpalTransportAddress GetRemoteAddress() const = 0;
834 
840  virtual PBoolean SetRemoteAddress(
841  const OpalTransportAddress & address
842  ) = 0;
843 
846  virtual PBoolean Connect() = 0;
847 
850  PBoolean ConnectTo(
851  const OpalTransportAddress & address
852  ) { return SetRemoteAddress(address) && Connect(); }
853 
856  virtual PBoolean Close();
857 
860  void CloseWait();
861 
866 
869  virtual PBoolean IsCompatibleTransport(
870  const OpalTransportAddress & address
871  ) const = 0;
872 
879  };
880 
891  virtual void SetPromiscuous(
892  PromisciousModes promiscuous
893  );
894 
900 
905  virtual PString GetLastReceivedInterface() const;
906 
916  virtual PBoolean ReadPDU(
917  PBYTEArray & packet
918  ) = 0;
919 
925  virtual PBoolean WritePDU(
926  const PBYTEArray & pdu
927  ) = 0;
928 
929  typedef PNotifierTemplate<bool &> WriteConnectCallback;
930  #define PDECLARE_WriteConnectCallback(cls, fn) PDECLARE_NOTIFIER2(OpalTransport, cls, fn, bool &)
931 
944  virtual bool WriteConnect(
945  const WriteConnectCallback & function
946  );
947 
952  void SetKeepAlive(
953  const PTimeInterval & timeout,
954  const PBYTEArray & data
955  );
956 
959  virtual void AttachThread(
960  PThread * thread
961  );
962 
965  virtual PBoolean IsRunning() const;
967 
968  OpalEndPoint & GetEndPoint() const { return endpoint; }
969 
972  virtual const PCaselessString & GetProtoPrefix() const = 0;
973 
974  bool IsOpen() const
975  { return m_channel != NULL && m_channel->IsOpen(); }
976 
977  bool IsGood() const
978  { return IsOpen() && !m_channel->bad() && !m_channel->eof(); }
979 
980  PChannel::Errors GetErrorCode(PChannel::ErrorGroup group = PChannel::NumErrorGroups) const
981  { return m_channel != NULL ? m_channel->GetErrorCode(group) : PChannel::NotOpen; }
982 
983  PString GetErrorText(PChannel::ErrorGroup group = PChannel::NumErrorGroups) const
984  { return m_channel != NULL ? m_channel->GetErrorText(group) : PString::Empty(); }
985 
986  int GetErrorNumber(PChannel::ErrorGroup group = PChannel::NumErrorGroups) const
987  { return m_channel != NULL ? m_channel->GetErrorNumber(group) : -1; }
988 
989  void SetReadTimeout(const PTimeInterval & t)
990  { if (m_channel != NULL) m_channel->SetReadTimeout(t); }
991 
992  PChannel * GetChannel() const { return m_channel; }
993  void SetChannel(PChannel * chan) { m_channel = chan; }
994 
995  bool IsIdle() const { return m_idleTimer.HasExpired(); }
996 
997  protected:
998  PDECLARE_NOTIFIER(PTimer, OpalTransport, KeepAlive);
999 
1001  PChannel * m_channel;
1002  PThread * m_thread;
1004  PBYTEArray m_keepAliveData;
1005  PSimpleTimer m_idleTimer;
1006 };
1007 
1008 
1010 {
1011  PCLASSINFO(OpalTransportIP, OpalTransport);
1012  protected:
1018  OpalEndPoint & endpoint,
1019  PChannel * channel,
1020  PIPSocket::Address binding,
1021  WORD port
1022  );
1024 
1025  public:
1031  bool allowNAT = true
1032  ) const;
1033 
1038  virtual PBoolean SetLocalAddress(
1039  const OpalTransportAddress & address
1040  );
1041 
1044  virtual OpalTransportAddress GetRemoteAddress() const;
1045 
1051  virtual PBoolean SetRemoteAddress(
1052  const OpalTransportAddress & address
1053  );
1054 
1056 
1057  protected:
1060  virtual const PCaselessString & GetProtoPrefix() const = 0;
1061 
1062  PIPSocket::Address localAddress; // Address of the local interface
1064  PIPSocket::Address remoteAddress; // Address of the remote host
1066 };
1067 
1068 
1070 {
1071  PCLASSINFO(OpalTransportTCP, OpalTransportIP);
1072  public:
1078  OpalEndPoint & endpoint,
1079  PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
1080  WORD port = 0,
1081  PBoolean reuseAddr = false
1082  );
1084  OpalEndPoint & endpoint,
1085  PChannel * socket
1086  );
1087 
1091 
1096  virtual PBoolean IsReliable() const;
1097 
1100  virtual PBoolean IsCompatibleTransport(
1101  const OpalTransportAddress & address
1102  ) const;
1103 
1106  virtual PBoolean Connect();
1107 
1117  virtual PBoolean ReadPDU(
1118  PBYTEArray & pdu
1119  );
1120 
1126  virtual PBoolean WritePDU(
1127  const PBYTEArray & pdu
1128  );
1130 
1131 
1132  protected:
1135  virtual const PCaselessString & GetProtoPrefix() const;
1136 
1137  bool OnConnectedSocket(PTCPSocket * socket);
1138 
1140 };
1141 
1142 
1144 {
1145  PCLASSINFO(OpalTransportUDP, OpalTransportIP);
1146  public:
1152  OpalEndPoint & endpoint,
1153  PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
1154  WORD port = 0,
1155  bool reuseAddr = false,
1156  bool preOpen = false
1157  );
1158 
1162  OpalEndPoint & endpoint,
1163  const PMonitoredSocketsPtr & sockets,
1164  const PString & iface
1165  );
1166 
1170 
1173  virtual PBoolean Read(
1174  void * buffer,
1175  PINDEX length
1176  );
1178 
1183  virtual PBoolean IsReliable() const;
1184 
1187  virtual PBoolean IsCompatibleTransport(
1188  const OpalTransportAddress & address
1189  ) const;
1190 
1198  virtual PBoolean Connect();
1199 
1202  virtual PString GetInterface() const;
1203 
1210  virtual bool SetInterface(
1211  const PString & iface
1212  );
1213 
1217  bool allowNAT = true
1218  ) const;
1219 
1224  virtual PBoolean SetLocalAddress(
1225  const OpalTransportAddress & address
1226  );
1227 
1233  virtual PBoolean SetRemoteAddress(
1234  const OpalTransportAddress & address
1235  );
1236 
1248  virtual void SetPromiscuous(
1249  PromisciousModes promiscuous
1250  );
1251 
1257 
1262  virtual PString GetLastReceivedInterface() const;
1263 
1273  virtual PBoolean ReadPDU(
1274  PBYTEArray & packet
1275  );
1276 
1282  virtual PBoolean WritePDU(
1283  const PBYTEArray & pdu
1284  );
1285 
1296  virtual bool WriteConnect(
1297  const WriteConnectCallback & function
1298  );
1299 
1303  PINDEX size
1304  ) { m_bufferSize = size; }
1306 
1307  protected:
1310  virtual const PCaselessString & GetProtoPrefix() const;
1311 
1314  PBYTEArray m_preReadPacket;
1316 
1317  friend class OpalListenerUDP;
1318 };
1319 
1320 
1322 
1323 class OpalInternalTransport : public PObject
1324 {
1325  PCLASSINFO(OpalInternalTransport, PObject);
1326  public:
1327  virtual bool Parse(
1328  OpalTransportAddress & address,
1329  WORD port
1330  ) const = 0;
1331 
1332  virtual PString GetHostName(
1333  const OpalTransportAddress & address,
1334  bool includeService
1335  ) const;
1336 
1337  virtual PBoolean GetIpAndPort(
1338  const OpalTransportAddress & address,
1339  PIPSocket::Address & ip,
1340  WORD & port
1341  ) const;
1342 
1343  virtual OpalListener * CreateListener(
1344  const OpalTransportAddress & address,
1345  OpalEndPoint & endpoint,
1347  ) const = 0;
1348 
1349  virtual OpalTransport * CreateTransport(
1350  const OpalTransportAddress & address,
1351  OpalEndPoint & endpoint,
1353  ) const = 0;
1354 };
1355 
1356 
1358 
1360 {
1362  public:
1363  virtual bool Parse(
1364  OpalTransportAddress & address,
1365  WORD port
1366  ) const;
1367  virtual PString GetHostName(
1368  const OpalTransportAddress & address,
1369  bool includeService
1370  ) const;
1371  virtual PBoolean GetIpAndPort(
1372  const OpalTransportAddress & address,
1373  PIPSocket::Address & ip,
1374  WORD & port
1375  ) const;
1376 
1377  static PBoolean GetAdjustedIpAndPort(const OpalTransportAddress & address,
1378  OpalEndPoint & endpoint,
1380  PIPSocket::Address & ip,
1381  WORD & port,
1382  PBoolean & reuseAddr);
1383 };
1384 
1385 template <class ListenerType, class TransportType, unsigned AltTypeOption, class AltTypeClass>
1387 {
1388  public:
1390  const OpalTransportAddress & address,
1391  OpalEndPoint & endpoint,
1393  ) const
1394  {
1395  return new ListenerType(endpoint, address, options);
1396  }
1397 
1399  const OpalTransportAddress & address,
1400  OpalEndPoint & endpoint,
1402  ) const
1403  {
1404  PIPSocket::Address ip;
1405  WORD port;
1406  PBoolean reuseAddr;
1407  if (GetAdjustedIpAndPort(address, endpoint, options, ip, port, reuseAddr)) {
1408  if (options == AltTypeOption)
1409  return new AltTypeClass(endpoint, ip, 0, reuseAddr);
1410  else
1411  return new TransportType(endpoint, ip, 0, reuseAddr);
1412  }
1413  return NULL;
1414  }
1415 };
1416 
1419 
1420 #if OPAL_PTLIB_SSL
1421 
1422 class PSSLContext;
1423 class PSSLChannel;
1424 
1425 class OpalListenerTLS : public OpalListenerTCP
1426 {
1427  PCLASSINFO(OpalListenerTLS, OpalListenerTCP);
1428  public:
1429  OpalListenerTLS(
1430  OpalEndPoint & endpoint,
1431  PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
1432  WORD port = 0,
1433  PBoolean exclusive = true
1434  );
1435  OpalListenerTLS(
1436  OpalEndPoint & endpoint,
1437  const OpalTransportAddress & binding,
1439  );
1440 
1443  ~OpalListenerTLS();
1444 
1445  virtual PBoolean Open(const AcceptHandler & acceptHandler, ThreadMode mode = SpawnNewThreadMode);
1446  virtual OpalTransport * Accept(const PTimeInterval & timeout);
1447  virtual const PCaselessString & GetProtoPrefix() const;
1448  virtual OpalTransport * CreateTransport(
1449  const OpalTransportAddress & localAddress,
1450  const OpalTransportAddress & remoteAddress
1451  ) const;
1452 
1453  protected:
1454  PSSLContext * m_sslContext;
1455 };
1456 
1457 
1458 class OpalTransportTLS : public OpalTransportTCP
1459 {
1460  PCLASSINFO(OpalTransportTLS, OpalTransportTCP);
1461  public:
1462  OpalTransportTLS(
1463  OpalEndPoint & endpoint,
1464  PSSLChannel * ssl
1465  );
1466 
1467  OpalTransportTLS(
1468  OpalEndPoint & endpoint,
1469  PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
1470  WORD port = 0,
1471  PBoolean reuseAddr = false
1472  );
1473 
1475  ~OpalTransportTLS();
1476 
1477  // Overrides
1478  virtual PBoolean IsCompatibleTransport(const OpalTransportAddress & address) const;
1479  virtual PBoolean Connect();
1480  virtual const PCaselessString & GetProtoPrefix() const;
1481  virtual bool IsAuthenticated(const PString & domain) const;
1482 };
1483 
1485 
1486 typedef OpalTransportTLS OpalTransportTCPS; // For backward compatibility
1487 typedef OpalListenerTLS OpalListenerTCPS;
1488 
1489 
1490 #endif // OPAL_PTLIB_SSL
1491 
1492 
1493 #endif // OPAL_OPAL_TRANSPORT_H
1494 
1495 
1496 // End of File ///////////////////////////////////////////////////////////////