OPAL  Version 3.12.9
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: 30514 $
32  * $Author: rjongbloed $
33  * $Date: 2013-09-17 11:38:19 +1000 (Tue, 17 Sep 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_referenceCount == 0 && m_idleTimer.HasExpired(); }
996 
999 
1000  protected:
1001  PDECLARE_NOTIFIER(PTimer, OpalTransport, KeepAlive);
1002 
1004  PChannel * m_channel;
1005  PThread * m_thread;
1007  PBYTEArray m_keepAliveData;
1008  PSimpleTimer m_idleTimer;
1009  PAtomicInteger m_referenceCount;
1010 };
1011 
1012 
1014 {
1015  PCLASSINFO(OpalTransportIP, OpalTransport);
1016  protected:
1022  OpalEndPoint & endpoint,
1023  PChannel * channel,
1024  PIPSocket::Address binding,
1025  WORD port
1026  );
1028 
1029  public:
1035  bool allowNAT = true
1036  ) const;
1037 
1042  virtual PBoolean SetLocalAddress(
1043  const OpalTransportAddress & address
1044  );
1045 
1048  virtual OpalTransportAddress GetRemoteAddress() const;
1049 
1055  virtual PBoolean SetRemoteAddress(
1056  const OpalTransportAddress & address
1057  );
1058 
1060 
1061  protected:
1064  virtual const PCaselessString & GetProtoPrefix() const = 0;
1065 
1066  PIPSocket::Address localAddress; // Address of the local interface
1068  PIPSocket::Address remoteAddress; // Address of the remote host
1070 };
1071 
1072 
1074 {
1075  PCLASSINFO(OpalTransportTCP, OpalTransportIP);
1076  public:
1082  OpalEndPoint & endpoint,
1083  PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
1084  WORD port = 0,
1085  PBoolean reuseAddr = false
1086  );
1088  OpalEndPoint & endpoint,
1089  PChannel * socket
1090  );
1091 
1095 
1100  virtual PBoolean IsReliable() const;
1101 
1104  virtual PBoolean IsCompatibleTransport(
1105  const OpalTransportAddress & address
1106  ) const;
1107 
1110  virtual PBoolean Connect();
1111 
1121  virtual PBoolean ReadPDU(
1122  PBYTEArray & pdu
1123  );
1124 
1130  virtual PBoolean WritePDU(
1131  const PBYTEArray & pdu
1132  );
1134 
1135 
1136  protected:
1139  virtual const PCaselessString & GetProtoPrefix() const;
1140 
1141  bool OnConnectedSocket(PTCPSocket * socket);
1142 
1144 };
1145 
1146 
1148 {
1149  PCLASSINFO(OpalTransportUDP, OpalTransportIP);
1150  public:
1156  OpalEndPoint & endpoint,
1157  PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
1158  WORD port = 0,
1159  bool reuseAddr = false,
1160  bool preOpen = false
1161  );
1162 
1166  OpalEndPoint & endpoint,
1167  const PMonitoredSocketsPtr & sockets,
1168  const PString & iface
1169  );
1170 
1174 
1177  virtual PBoolean Read(
1178  void * buffer,
1179  PINDEX length
1180  );
1182 
1187  virtual PBoolean IsReliable() const;
1188 
1191  virtual PBoolean IsCompatibleTransport(
1192  const OpalTransportAddress & address
1193  ) const;
1194 
1202  virtual PBoolean Connect();
1203 
1206  virtual PString GetInterface() const;
1207 
1214  virtual bool SetInterface(
1215  const PString & iface
1216  );
1217 
1221  bool allowNAT = true
1222  ) const;
1223 
1228  virtual PBoolean SetLocalAddress(
1229  const OpalTransportAddress & address
1230  );
1231 
1237  virtual PBoolean SetRemoteAddress(
1238  const OpalTransportAddress & address
1239  );
1240 
1252  virtual void SetPromiscuous(
1253  PromisciousModes promiscuous
1254  );
1255 
1261 
1266  virtual PString GetLastReceivedInterface() const;
1267 
1277  virtual PBoolean ReadPDU(
1278  PBYTEArray & packet
1279  );
1280 
1286  virtual PBoolean WritePDU(
1287  const PBYTEArray & pdu
1288  );
1289 
1300  virtual bool WriteConnect(
1301  const WriteConnectCallback & function
1302  );
1303 
1307  PINDEX size
1308  ) { m_bufferSize = size; }
1310 
1311  protected:
1314  virtual const PCaselessString & GetProtoPrefix() const;
1315 
1318  PBYTEArray m_preReadPacket;
1320 
1321  friend class OpalListenerUDP;
1322 };
1323 
1324 
1326 
1327 class OpalInternalTransport : public PObject
1328 {
1329  PCLASSINFO(OpalInternalTransport, PObject);
1330  public:
1331  virtual bool Parse(
1332  OpalTransportAddress & address,
1333  WORD port
1334  ) const = 0;
1335 
1336  virtual PString GetHostName(
1337  const OpalTransportAddress & address,
1338  bool includeService
1339  ) const;
1340 
1341  virtual PBoolean GetIpAndPort(
1342  const OpalTransportAddress & address,
1343  PIPSocket::Address & ip,
1344  WORD & port
1345  ) const;
1346 
1347  virtual OpalListener * CreateListener(
1348  const OpalTransportAddress & address,
1349  OpalEndPoint & endpoint,
1351  ) const = 0;
1352 
1353  virtual OpalTransport * CreateTransport(
1354  const OpalTransportAddress & address,
1355  OpalEndPoint & endpoint,
1357  ) const = 0;
1358 };
1359 
1360 
1362 
1364 {
1366  public:
1367  virtual bool Parse(
1368  OpalTransportAddress & address,
1369  WORD port
1370  ) const;
1371  virtual PString GetHostName(
1372  const OpalTransportAddress & address,
1373  bool includeService
1374  ) const;
1375  virtual PBoolean GetIpAndPort(
1376  const OpalTransportAddress & address,
1377  PIPSocket::Address & ip,
1378  WORD & port
1379  ) const;
1380 
1381  static PBoolean GetAdjustedIpAndPort(const OpalTransportAddress & address,
1382  OpalEndPoint & endpoint,
1384  PIPSocket::Address & ip,
1385  WORD & port,
1386  PBoolean & reuseAddr);
1387 };
1388 
1389 template <class ListenerType, class TransportType, unsigned AltTypeOption, class AltTypeClass>
1391 {
1392  public:
1394  const OpalTransportAddress & address,
1395  OpalEndPoint & endpoint,
1397  ) const
1398  {
1399  return new ListenerType(endpoint, address, options);
1400  }
1401 
1403  const OpalTransportAddress & address,
1404  OpalEndPoint & endpoint,
1406  ) const
1407  {
1408  PIPSocket::Address ip;
1409  WORD port;
1410  PBoolean reuseAddr;
1411  if (GetAdjustedIpAndPort(address, endpoint, options, ip, port, reuseAddr)) {
1412  if (options == AltTypeOption)
1413  return new AltTypeClass(endpoint, ip, 0, reuseAddr);
1414  else
1415  return new TransportType(endpoint, ip, 0, reuseAddr);
1416  }
1417  return NULL;
1418  }
1419 };
1420 
1423 
1424 #if OPAL_PTLIB_SSL
1425 
1426 class PSSLContext;
1427 class PSSLChannel;
1428 
1429 class OpalListenerTLS : public OpalListenerTCP
1430 {
1431  PCLASSINFO(OpalListenerTLS, OpalListenerTCP);
1432  public:
1433  OpalListenerTLS(
1434  OpalEndPoint & endpoint,
1435  PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
1436  WORD port = 0,
1437  PBoolean exclusive = true
1438  );
1439  OpalListenerTLS(
1440  OpalEndPoint & endpoint,
1441  const OpalTransportAddress & binding,
1443  );
1444 
1447  ~OpalListenerTLS();
1448 
1449  virtual PBoolean Open(const AcceptHandler & acceptHandler, ThreadMode mode = SpawnNewThreadMode);
1450  virtual OpalTransport * Accept(const PTimeInterval & timeout);
1451  virtual const PCaselessString & GetProtoPrefix() const;
1452  virtual OpalTransport * CreateTransport(
1453  const OpalTransportAddress & localAddress,
1454  const OpalTransportAddress & remoteAddress
1455  ) const;
1456 
1457  protected:
1458  PSSLContext * m_sslContext;
1459 };
1460 
1461 
1462 class OpalTransportTLS : public OpalTransportTCP
1463 {
1464  PCLASSINFO(OpalTransportTLS, OpalTransportTCP);
1465  public:
1466  OpalTransportTLS(
1467  OpalEndPoint & endpoint,
1468  PSSLChannel * ssl
1469  );
1470 
1471  OpalTransportTLS(
1472  OpalEndPoint & endpoint,
1473  PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
1474  WORD port = 0,
1475  PBoolean reuseAddr = false
1476  );
1477 
1479  ~OpalTransportTLS();
1480 
1481  // Overrides
1482  virtual PBoolean IsCompatibleTransport(const OpalTransportAddress & address) const;
1483  virtual PBoolean Connect();
1484  virtual const PCaselessString & GetProtoPrefix() const;
1485  virtual bool IsAuthenticated(const PString & domain) const;
1486 };
1487 
1489 
1490 typedef OpalTransportTLS OpalTransportTCPS; // For backward compatibility
1491 typedef OpalListenerTLS OpalListenerTCPS;
1492 
1493 
1494 #endif // OPAL_PTLIB_SSL
1495 
1496 
1497 #endif // OPAL_OPAL_TRANSPORT_H
1498 
1499 
1500 // End of File ///////////////////////////////////////////////////////////////