OPAL  Version 3.10.4
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: 26231 $
32  * $Author: rjongbloed $
33  * $Date: 2011-07-19 21:23:34 -0500 (Tue, 19 Jul 2011) $
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 
57 
149 class OpalTransportAddress : public PCaselessString
150 {
151  PCLASSINFO(OpalTransportAddress, PCaselessString);
152  public:
157  const char * address,
158  WORD port = 0,
159  const char * proto = NULL
160  );
162  const PString & address,
163  WORD port = 0,
164  const char * proto = NULL
165  );
167  const PIPSocket::Address & ip,
168  WORD port,
169  const char * proto = NULL
170  );
172 
180  PBoolean IsEquivalent(
181  const OpalTransportAddress & address,
182  bool wildcards = false
183  ) const;
184 
187  PBoolean IsCompatible(
188  const OpalTransportAddress & address
189  ) const;
190 
193  PCaselessString GetProto(bool withDollar = false) const { return Left(Find('$')+(withDollar?1:0)); }
194 
198  PBoolean GetIpAddress(PIPSocket::Address & ip) const;
199 
203  PBoolean GetIpAndPort(PIPSocket::Address & ip, WORD & port) const;
204  PBoolean GetIpAndPort(PIPSocketAddressAndPort & ipPort) const;
205 
209  virtual PString GetHostName() const;
210 
211  enum BindOptions {
219  };
220 
253  OpalEndPoint & endpoint,
254  BindOptions option
255  ) const;
256 
284  virtual OpalTransport * CreateTransport(
285  OpalEndPoint & endpoint,
286  BindOptions option = HostOnly
287  ) const;
289 
290 
291  protected:
293  WORD port,
294  const char * proto
295  );
296 
298 };
299 
300 
302  public:
304  const OpalTransportAddress & address
305  ) { AppendAddress(address); }
307  const PStringArray & array
308  ) { AppendStringCollection(array); }
310  const PStringList & list
311  ) { AppendStringCollection(list); }
313  const PSortedStringList & list
314  ) { AppendStringCollection(list); }
315 
316  void AppendString(
317  const char * address
318  );
319  void AppendString(
320  const PString & address
321  );
322  void AppendAddress(
323  const OpalTransportAddress & address
324  );
325 
326  protected:
328  const PCollection & coll
329  );
330 };
331 
332 
333 
334 
336 
349 class OpalListener : public PObject
350 {
351  PCLASSINFO(OpalListener, PObject);
352  public:
357  OpalListener(
359  );
361 
366  void PrintOn(
367  ostream & strm
368  ) const;
370 
373  enum ThreadMode {
377  };
378 
393  virtual PBoolean Open(
394  const PNotifier & acceptHandler,
396  ) = 0;
397 
400  virtual PBoolean IsOpen() = 0;
401 
404  virtual void Close() = 0;
405 
408  virtual OpalTransport * Accept(
409  const PTimeInterval & timeout
410  ) = 0;
411 
414  virtual OpalTransport * CreateTransport(
415  const OpalTransportAddress & localAddress,
416  const OpalTransportAddress & remoteAddress
417  ) const = 0;
418 
425  const OpalTransportAddress & remoteAddress = OpalTransportAddress()
426  ) const = 0;
427 
430  void CloseWait();
431 
437 
438 
439  protected:
448  PDECLARE_NOTIFIER(PThread, OpalListener, ListenForConnections);
449  PBoolean StartThread(
450  const PNotifier & acceptHandler,
451  ThreadMode mode
452  );
453 
455  PThread * thread;
456  PNotifier acceptHandler;
458 };
459 
460 
461 PLIST(OpalListenerList, OpalListener);
462 
463 
465 {
466  PCLASSINFO(OpalListenerIP, OpalListener);
467  public:
473  OpalEndPoint & endpoint,
474  PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
475  WORD port = 0,
476  PBoolean exclusive = true
477  );
479  OpalEndPoint & endpoint,
480  const OpalTransportAddress & binding,
482  );
484 
493  const OpalTransportAddress & remoteAddress = OpalTransportAddress()
494  ) const;
496 
499  WORD GetListenerPort() const { return listenerPort; }
500 
501  virtual const char * GetProtoPrefix() const = 0;
503 
504 
505  protected:
506  PIPSocket::Address localAddress;
509 };
510 
511 
513 {
514  PCLASSINFO(OpalListenerTCP, OpalListenerIP);
515  public:
521  OpalEndPoint & endpoint,
522  PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
523  WORD port = 0,
524  PBoolean exclusive = true
525  );
527  OpalEndPoint & endpoint,
528  const OpalTransportAddress & binding,
530  );
531 
536 
559  virtual PBoolean Open(
560  const PNotifier & acceptHandler,
562  );
563 
566  virtual PBoolean IsOpen();
567 
570  virtual void Close();
571 
574  virtual OpalTransport * Accept(
575  const PTimeInterval & timeout
576  );
577 
580  virtual OpalTransport * CreateTransport(
582  const OpalTransportAddress & remoteAddress
583  ) const;
585 
586 
587  protected:
588  virtual const char * GetProtoPrefix() const;
589 
590  PTCPSocket listener;
591 };
592 
593 
595 {
596  PCLASSINFO(OpalListenerUDP, OpalListenerIP);
597  public:
603  OpalEndPoint & endpoint,
604  PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
605  WORD port = 0,
606  PBoolean exclusive = true
607  );
609  OpalEndPoint & endpoint,
610  const OpalTransportAddress & binding,
612  );
613 
618 
641  virtual PBoolean Open(
642  const PNotifier & acceptHandler,
644  );
645 
648  virtual PBoolean IsOpen();
649 
652  virtual void Close();
653 
656  virtual OpalTransport * Accept(
657  const PTimeInterval & timeout
658  );
659 
662  virtual OpalTransport * CreateTransport(
664  const OpalTransportAddress & remoteAddress
665  ) const;
666 
673  const OpalTransportAddress & remoteAddress = OpalTransportAddress()
674  ) const;
676 
682  PINDEX size
683  ) { m_bufferSize = size; }
685 
686 
687  protected:
688  virtual const char * GetProtoPrefix() const;
689 
690  PMonitoredSocketsPtr listenerBundle;
691  PINDEX m_bufferSize;
692 };
693 
694 
696 
701 class OpalTransport : public PIndirectChannel
702 {
703  PCLASSINFO(OpalTransport, PIndirectChannel);
704  public:
709  OpalTransport(OpalEndPoint & endpoint);
710 
713  ~OpalTransport();
715 
720  void PrintOn(
721  ostream & strm
722  ) const;
724 
729  virtual PBoolean IsReliable() const = 0;
730 
737  virtual PString GetInterface() const;
738 
745  virtual bool SetInterface(
746  const PString & iface
747  );
748 
752  bool allowNAT = true
753  ) const = 0;
754 
759  virtual PBoolean SetLocalAddress(
760  const OpalTransportAddress & address
761  ) = 0;
762 
765  virtual OpalTransportAddress GetRemoteAddress() const = 0;
766 
772  virtual PBoolean SetRemoteAddress(
773  const OpalTransportAddress & address
774  ) = 0;
775 
778  virtual PBoolean Connect() = 0;
779 
782  PBoolean ConnectTo(
783  const OpalTransportAddress & address
784  ) { return SetRemoteAddress(address) && Connect(); }
785 
788  virtual PBoolean Close();
789 
792  void CloseWait();
793 
798 
801  virtual PBoolean IsCompatibleTransport(
802  const OpalTransportAddress & address
803  ) const = 0;
804 
811  };
812 
823  virtual void SetPromiscuous(
824  PromisciousModes promiscuous
825  );
826 
832 
837  virtual PString GetLastReceivedInterface() const;
838 
848  virtual PBoolean ReadPDU(
849  PBYTEArray & packet
850  ) = 0;
851 
857  virtual PBoolean WritePDU(
858  const PBYTEArray & pdu
859  ) = 0;
860 
861  typedef PBoolean (*WriteConnectCallback)(OpalTransport & transport, void * userData);
862 
875  virtual PBoolean WriteConnect(
876  WriteConnectCallback function,
877  void * userData
878  );
879 
882  virtual void AttachThread(
883  PThread * thread
884  );
885 
888  virtual PBoolean IsRunning() const;
890 
891  OpalEndPoint & GetEndPoint() const { return endpoint; }
892 
895  virtual const char * GetProtoPrefix() const = 0;
896 
897  PMutex & GetWriteMutex() { return m_writeMutex; }
898 
899  protected:
901  PThread * thread;
902  PMutex m_writeMutex;
903 };
904 
905 
907 {
908  PCLASSINFO(OpalTransportIP, OpalTransport);
909  public:
915  OpalEndPoint & endpoint,
916  PIPSocket::Address binding,
917  WORD port
918  );
920 
926  bool allowNAT = true
927  ) const;
928 
933  virtual PBoolean SetLocalAddress(
934  const OpalTransportAddress & address
935  );
936 
939  virtual OpalTransportAddress GetRemoteAddress() const;
940 
946  virtual PBoolean SetRemoteAddress(
947  const OpalTransportAddress & address
948  );
949 
951 
952  protected:
955  virtual const char * GetProtoPrefix() const = 0;
956 
957  PIPSocket::Address localAddress; // Address of the local interface
958  WORD localPort;
959  PIPSocket::Address remoteAddress; // Address of the remote host
961 };
962 
963 
965 {
966  PCLASSINFO(OpalTransportTCP, OpalTransportIP);
967  public:
973  OpalEndPoint & endpoint,
974  PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
975  WORD port = 0,
976  PBoolean reuseAddr = false
977  );
979  OpalEndPoint & endpoint,
980  PTCPSocket * socket
981  );
982 
986 
991  virtual PBoolean IsReliable() const;
992 
995  virtual PBoolean IsCompatibleTransport(
996  const OpalTransportAddress & address
997  ) const;
998 
1001  virtual PBoolean Connect();
1002 
1012  virtual PBoolean ReadPDU(
1013  PBYTEArray & pdu
1014  );
1015 
1021  virtual PBoolean WritePDU(
1022  const PBYTEArray & pdu
1023  );
1025 
1026 
1027  protected:
1030  virtual const char * GetProtoPrefix() const;
1031 
1041  virtual PBoolean OnOpen();
1042 
1043 
1045 };
1046 
1047 
1049 {
1050  PCLASSINFO(OpalTransportUDP, OpalTransportIP);
1051  public:
1057  OpalEndPoint & endpoint,
1058  PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
1059  WORD port = 0,
1060  bool reuseAddr = false,
1061  bool preOpen = false
1062  );
1063 
1067  OpalEndPoint & endpoint,
1068  const PMonitoredSocketsPtr & sockets,
1069  const PString & iface
1070  );
1071 
1075 
1078  virtual PBoolean Read(
1079  void * buffer,
1080  PINDEX length
1081  );
1083 
1088  virtual PBoolean IsReliable() const;
1089 
1092  virtual PBoolean IsCompatibleTransport(
1093  const OpalTransportAddress & address
1094  ) const;
1095 
1103  virtual PBoolean Connect();
1104 
1107  virtual PString GetInterface() const;
1108 
1115  virtual bool SetInterface(
1116  const PString & iface
1117  );
1118 
1122  bool allowNAT = true
1123  ) const;
1124 
1129  virtual PBoolean SetLocalAddress(
1130  const OpalTransportAddress & address
1131  );
1132 
1138  virtual PBoolean SetRemoteAddress(
1139  const OpalTransportAddress & address
1140  );
1141 
1153  virtual void SetPromiscuous(
1154  PromisciousModes promiscuous
1155  );
1156 
1162 
1167  virtual PString GetLastReceivedInterface() const;
1168 
1178  virtual PBoolean ReadPDU(
1179  PBYTEArray & packet
1180  );
1181 
1187  virtual PBoolean WritePDU(
1188  const PBYTEArray & pdu
1189  );
1190 
1201  virtual PBoolean WriteConnect(
1202  WriteConnectCallback function,
1203  void * userData
1204  );
1205 
1209  PINDEX size
1210  ) { m_bufferSize = size; }
1212 
1213  protected:
1216  virtual const char * GetProtoPrefix() const;
1217 
1220  PBYTEArray m_preReadPacket;
1222 
1223  friend class OpalListenerUDP;
1224 };
1225 
1226 
1228 
1229 class OpalInternalTransport : public PObject
1230 {
1231  PCLASSINFO(OpalInternalTransport, PObject);
1232  public:
1233  virtual PString GetHostName(
1234  const OpalTransportAddress & address
1235  ) const;
1236 
1237  virtual PBoolean GetIpAndPort(
1238  const OpalTransportAddress & address,
1239  PIPSocket::Address & ip,
1240  WORD & port
1241  ) const;
1242 
1243  virtual OpalListener * CreateListener(
1244  const OpalTransportAddress & address,
1245  OpalEndPoint & endpoint,
1247  ) const = 0;
1248 
1249  virtual OpalTransport * CreateTransport(
1250  const OpalTransportAddress & address,
1251  OpalEndPoint & endpoint,
1253  ) const = 0;
1254 };
1255 
1256 
1258 
1260 {
1262  public:
1263  virtual PString GetHostName(
1264  const OpalTransportAddress & address
1265  ) const;
1266  virtual PBoolean GetIpAndPort(
1267  const OpalTransportAddress & address,
1268  PIPSocket::Address & ip,
1269  WORD & port
1270  ) const;
1271 
1272  static PBoolean GetAdjustedIpAndPort(const OpalTransportAddress & address,
1273  OpalEndPoint & endpoint,
1275  PIPSocket::Address & ip,
1276  WORD & port,
1277  PBoolean & reuseAddr);
1278 };
1279 
1280 template <class ListenerType, class TransportType, unsigned AltTypeOption, class AltTypeClass>
1282 {
1283  public:
1285  const OpalTransportAddress & address,
1286  OpalEndPoint & endpoint,
1288  ) const
1289  {
1290  return new ListenerType(endpoint, address, options);
1291  }
1292 
1294  const OpalTransportAddress & address,
1295  OpalEndPoint & endpoint,
1297  ) const
1298  {
1299  PIPSocket::Address ip;
1300  WORD port;
1301  PBoolean reuseAddr;
1302  if (GetAdjustedIpAndPort(address, endpoint, options, ip, port, reuseAddr)) {
1303  if (options == AltTypeOption)
1304  return new AltTypeClass(endpoint, ip, 0, reuseAddr);
1305  else
1306  return new TransportType(endpoint, ip, 0, reuseAddr);
1307  }
1308  return NULL;
1309  }
1310 };
1311 
1314 
1315 #if OPAL_PTLIB_SSL
1316 
1317 class PSSLContext;
1318 
1319 class OpalListenerTCPS : public OpalListenerTCP
1320 {
1321  PCLASSINFO(OpalListenerTCPS, OpalListenerTCP);
1322  public:
1323  OpalListenerTCPS(
1324  OpalEndPoint & endpoint,
1325  PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
1326  WORD port = 0,
1327  PBoolean exclusive = true
1328  );
1329  OpalListenerTCPS(
1330  OpalEndPoint & endpoint,
1331  const OpalTransportAddress & binding,
1333  );
1334 
1337  ~OpalListenerTCPS();
1338 
1339  OpalTransport * Accept(const PTimeInterval & timeout);
1340  const char * GetProtoPrefix() const;
1341 
1342  protected:
1343  void Construct();
1344 
1345  PSSLContext * sslContext;
1346 };
1347 
1348 class OpalTransportTCPS : public OpalTransportTCP
1349 {
1350  PCLASSINFO(OpalTransportTCPS, OpalTransportTCP);
1351  public:
1352  OpalTransportTCPS(
1353  OpalEndPoint & endpoint,
1354  PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
1355  WORD port = 0,
1356  PBoolean reuseAddr = false
1357  );
1358  OpalTransportTCPS(
1359  OpalEndPoint & endpoint,
1360  PTCPSocket * socket
1361  );
1362 
1364  ~OpalTransportTCPS();
1365 
1366  PBoolean IsCompatibleTransport(const OpalTransportAddress & address) const;
1367  PBoolean Connect();
1368  PBoolean OnOpen();
1369  const char * GetProtoPrefix() const;
1370 
1371  protected:
1372  PSSLContext * sslContext;
1373 };
1374 
1376 
1377 
1378 #endif // OPAL_PTLIB_SSL
1379 
1380 
1381 #endif // OPAL_OPAL_TRANSPORT_H
1382 
1383 
1384 // End of File ///////////////////////////////////////////////////////////////