00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 #ifndef __OPAL_RTP_H
00223 #define __OPAL_RTP_H
00224
00225 #ifdef P_USE_PRAGMA
00226 #pragma interface
00227 #endif
00228
00229
00230 #include <ptlib/sockets.h>
00231
00232 class RTP_JitterBuffer;
00233
00234 #ifdef P_STUN
00235 class PSTUNClient;
00236 #endif
00237
00239
00240
00241
00242 #if P_HAS_QOS
00243
00244 class RTP_QOS : public PObject
00245 {
00246 PCLASSINFO(RTP_QOS,PObject);
00247 public:
00248 PQoS dataQoS;
00249 PQoS ctrlQoS;
00250 };
00251
00252 #else
00253
00254 class RTP_QOS;
00255
00256 #endif
00257
00259
00260
00263 class RTP_DataFrame : public PBYTEArray
00264 {
00265 PCLASSINFO(RTP_DataFrame, PBYTEArray);
00266
00267 public:
00268 RTP_DataFrame(PINDEX payloadSize = 2048);
00269
00270 enum {
00271 ProtocolVersion = 2,
00272 MinHeaderSize = 12
00273 };
00274
00275 enum PayloadTypes {
00276 PCMU,
00277 FS1016,
00278 G721,
00279 G726 = G721,
00280 GSM,
00281 G7231,
00282 DVI4_8k,
00283 DVI4_16k,
00284 LPC,
00285 PCMA,
00286 G722,
00287 L16_Stereo,
00288 L16_Mono,
00289 G723,
00290 CN,
00291 MPA,
00292 G728,
00293 DVI4_11k,
00294 DVI4_22k,
00295 G729,
00296 Cisco_CN,
00297
00298 CelB = 25,
00299 JPEG,
00300 H261 = 31,
00301 MPV,
00302 MP2T,
00303 H263,
00304
00305 LastKnownPayloadType,
00306
00307 DynamicBase = 96,
00308 MaxPayloadType = 127,
00309 IllegalPayloadType
00310 };
00311
00312 unsigned GetVersion() const { return (theArray[0]>>6)&3; }
00313
00314 BOOL GetExtension() const { return (theArray[0]&0x10) != 0; }
00315 void SetExtension(BOOL ext);
00316
00317 BOOL GetMarker() const { return (theArray[1]&0x80) != 0; }
00318 void SetMarker(BOOL m);
00319
00320 PayloadTypes GetPayloadType() const { return (PayloadTypes)(theArray[1]&0x7f); }
00321 void SetPayloadType(PayloadTypes t);
00322
00323 WORD GetSequenceNumber() const { return *(PUInt16b *)&theArray[2]; }
00324 void SetSequenceNumber(WORD n) { *(PUInt16b *)&theArray[2] = n; }
00325
00326 DWORD GetTimestamp() const { return *(PUInt32b *)&theArray[4]; }
00327 void SetTimestamp(DWORD t) { *(PUInt32b *)&theArray[4] = t; }
00328
00329 DWORD GetSyncSource() const { return *(PUInt32b *)&theArray[8]; }
00330 void SetSyncSource(DWORD s) { *(PUInt32b *)&theArray[8] = s; }
00331
00332 PINDEX GetContribSrcCount() const { return theArray[0]&0xf; }
00333 DWORD GetContribSource(PINDEX idx) const;
00334 void SetContribSource(PINDEX idx, DWORD src);
00335
00336 PINDEX GetHeaderSize() const;
00337
00338 int GetExtensionType() const;
00339 void SetExtensionType(int type);
00340 PINDEX GetExtensionSize() const;
00341 BOOL SetExtensionSize(PINDEX sz);
00342 BYTE * GetExtensionPtr() const;
00343
00344 PINDEX GetPayloadSize() const { return payloadSize; }
00345 BOOL SetPayloadSize(PINDEX sz);
00346 BYTE * GetPayloadPtr() const { return (BYTE *)(theArray+GetHeaderSize()); }
00347
00348 protected:
00349 PINDEX payloadSize;
00350
00351 #if PTRACING
00352 friend ostream & operator<<(ostream & o, PayloadTypes t);
00353 #endif
00354 };
00355
00356 PLIST(RTP_DataFrameList, RTP_DataFrame);
00357
00358
00361 class RTP_ControlFrame : public PBYTEArray
00362 {
00363 PCLASSINFO(RTP_ControlFrame, PBYTEArray);
00364
00365 public:
00366 RTP_ControlFrame(PINDEX compoundSize = 2048);
00367
00368 unsigned GetVersion() const { return (BYTE)theArray[compoundOffset]>>6; }
00369
00370 unsigned GetCount() const { return (BYTE)theArray[compoundOffset]&0x1f; }
00371 void SetCount(unsigned count);
00372
00373 enum PayloadTypes {
00374 e_SenderReport = 200,
00375 e_ReceiverReport,
00376 e_SourceDescription,
00377 e_Goodbye,
00378 e_ApplDefined
00379 };
00380
00381 unsigned GetPayloadType() const { return (BYTE)theArray[compoundOffset+1]; }
00382 void SetPayloadType(unsigned t);
00383
00384 PINDEX GetPayloadSize() const { return 4*(*(PUInt16b *)&theArray[compoundOffset+2]); }
00385 void SetPayloadSize(PINDEX sz);
00386
00387 BYTE * GetPayloadPtr() const { return (BYTE *)(theArray+compoundOffset+4); }
00388
00389 BOOL ReadNextCompound();
00390 BOOL WriteNextCompound();
00391
00392 PINDEX GetCompoundSize() const { return compoundSize; }
00393
00394 #pragma pack(1)
00395 struct ReceiverReport {
00396 PUInt32b ssrc;
00397 BYTE fraction;
00398 BYTE lost[3];
00399 PUInt32b last_seq;
00400 PUInt32b jitter;
00401 PUInt32b lsr;
00402 PUInt32b dlsr;
00403
00404 unsigned GetLostPackets() const { return (lost[0]<<16U)+(lost[1]<<8U)+lost[2]; }
00405 void SetLostPackets(unsigned lost);
00406 };
00407
00408 struct SenderReport {
00409 PUInt32b ssrc;
00410 PUInt32b ntp_sec;
00411 PUInt32b ntp_frac;
00412 PUInt32b rtp_ts;
00413 PUInt32b psent;
00414 PUInt32b osent;
00415 };
00416
00417 enum DescriptionTypes {
00418 e_END,
00419 e_CNAME,
00420 e_NAME,
00421 e_EMAIL,
00422 e_PHONE,
00423 e_LOC,
00424 e_TOOL,
00425 e_NOTE,
00426 e_PRIV,
00427 NumDescriptionTypes
00428 };
00429
00430 struct SourceDescription {
00431 PUInt32b src;
00432 struct Item {
00433 BYTE type;
00434 BYTE length;
00435 char data[1];
00436
00437 const Item * GetNextItem() const { return (const Item *)((char *)this + length + 2); }
00438 Item * GetNextItem() { return (Item *)((char *)this + length + 2); }
00439 } item[1];
00440 };
00441
00442 SourceDescription & AddSourceDescription(
00443 DWORD src
00444 );
00445
00446 SourceDescription::Item & AddSourceDescriptionItem(
00447 SourceDescription & sdes,
00448 unsigned type,
00449 const PString & data
00450 );
00451 #pragma pack()
00452
00453 protected:
00454 PINDEX compoundOffset;
00455 PINDEX compoundSize;
00456 };
00457
00458
00459 class RTP_Session;
00460
00465 class RTP_UserData : public PObject
00466 {
00467 PCLASSINFO(RTP_UserData, PObject);
00468
00469 public:
00476 virtual void OnTxStatistics(
00477 const RTP_Session & session
00478 ) const;
00479
00486 virtual void OnRxStatistics(
00487 const RTP_Session & session
00488 ) const;
00489 };
00490
00491
00494 class RTP_Session : public PObject
00495 {
00496 PCLASSINFO(RTP_Session, PObject);
00497
00498 public:
00499 enum {
00500 DefaultAudioSessionID = 1,
00501 DefaultVideoSessionID = 2,
00502 DefaultFaxSessionID = 3
00503 };
00504
00509 RTP_Session(
00510 unsigned id,
00511 RTP_UserData * userData = NULL
00512 );
00513
00517 ~RTP_Session();
00519
00531 void SetJitterBufferSize(
00532 unsigned minJitterDelay,
00533 unsigned maxJitterDelay,
00534 PINDEX stackSize = 30000
00535 );
00536
00542 unsigned GetJitterBufferSize() const;
00543
00545 virtual BOOL ModifyQOS(RTP_QOS * )
00546 { return FALSE; }
00547
00553 BOOL ReadBufferedData(
00554 DWORD timestamp,
00555 RTP_DataFrame & frame
00556 );
00557
00563 virtual BOOL ReadData(
00564 RTP_DataFrame & frame
00565 ) = 0;
00566
00569 virtual BOOL WriteData(
00570 RTP_DataFrame & frame
00571 ) = 0;
00572
00575 virtual BOOL WriteControl(
00576 RTP_ControlFrame & frame
00577 ) = 0;
00578
00581 virtual BOOL SendReport();
00582
00585 virtual void Close(
00586 BOOL reading
00587 ) = 0;
00588
00591 virtual PString GetLocalHostName() = 0;
00593
00596 enum SendReceiveStatus {
00597 e_ProcessPacket,
00598 e_IgnorePacket,
00599 e_AbortTransport
00600 };
00601 virtual SendReceiveStatus OnSendData(RTP_DataFrame & frame);
00602 virtual SendReceiveStatus OnReceiveData(const RTP_DataFrame & frame);
00603 virtual SendReceiveStatus OnReceiveControl(RTP_ControlFrame & frame);
00604
00605 class ReceiverReport : public PObject {
00606 PCLASSINFO(ReceiverReport, PObject);
00607 public:
00608 void PrintOn(ostream &) const;
00609
00610 DWORD sourceIdentifier;
00611 DWORD fractionLost;
00612 DWORD totalLost;
00613 DWORD lastSequenceNumber;
00614 DWORD jitter;
00615 PTimeInterval lastTimestamp;
00616 PTimeInterval delay;
00617 };
00618 PARRAY(ReceiverReportArray, ReceiverReport);
00619
00620 class SenderReport : public PObject {
00621 PCLASSINFO(SenderReport, PObject);
00622 public:
00623 void PrintOn(ostream &) const;
00624
00625 DWORD sourceIdentifier;
00626 PTime realTimestamp;
00627 DWORD rtpTimestamp;
00628 DWORD packetsSent;
00629 DWORD octetsSent;
00630 };
00631 virtual void OnRxSenderReport(const SenderReport & sender,
00632 const ReceiverReportArray & reports);
00633 virtual void OnRxReceiverReport(DWORD src,
00634 const ReceiverReportArray & reports);
00635
00636 class SourceDescription : public PObject {
00637 PCLASSINFO(SourceDescription, PObject);
00638 public:
00639 SourceDescription(DWORD src) { sourceIdentifier = src; }
00640 void PrintOn(ostream &) const;
00641
00642 DWORD sourceIdentifier;
00643 POrdinalToString items;
00644 };
00645 PARRAY(SourceDescriptionArray, SourceDescription);
00646 virtual void OnRxSourceDescription(const SourceDescriptionArray & descriptions);
00647
00648 virtual void OnRxGoodbye(const PDWORDArray & sources,
00649 const PString & reason);
00650
00651 virtual void OnRxApplDefined(const PString & type, unsigned subtype, DWORD src,
00652 const BYTE * data, PINDEX size);
00654
00659 unsigned GetSessionID() const { return sessionID; }
00660
00663 PString GetCanonicalName() const;
00664
00667 void SetCanonicalName(const PString & name);
00668
00671 PString GetToolName() const;
00672
00675 void SetToolName(const PString & name);
00676
00679 RTP_UserData * GetUserData() const { return userData; }
00680
00683 void SetUserData(
00684 RTP_UserData * data
00685 );
00686
00689 DWORD GetSyncSourceOut() const { return syncSourceOut; }
00690
00693 void IncrementReference() { referenceCount++; }
00694
00697 BOOL DecrementReference() { return --referenceCount == 0; }
00698
00701 BOOL WillIgnoreOtherSources() const { return ignoreOtherSources; }
00702
00705 void SetIgnoreOtherSources(
00706 BOOL ignore
00707 ) { ignoreOtherSources = ignore; }
00708
00711 BOOL WillIgnoreOutOfOrderPackets() const { return ignoreOutOfOrderPackets; }
00712
00715 void SetIgnoreOutOfOrderPackets(
00716 BOOL ignore
00717 ) { ignoreOutOfOrderPackets = ignore; }
00718
00721 const PTimeInterval & GetReportTimeInterval() { return reportTimeInterval; }
00722
00725 void SetReportTimeInterval(
00726 const PTimeInterval & interval
00727 ) { reportTimeInterval = interval; }
00728
00731 unsigned GetTxStatisticsInterval() { return txStatisticsInterval; }
00732
00735 void SetTxStatisticsInterval(
00736 unsigned packets
00737 );
00738
00741 unsigned GetRxStatisticsInterval() { return rxStatisticsInterval; }
00742
00745 void SetRxStatisticsInterval(
00746 unsigned packets
00747 );
00748
00751 DWORD GetPacketsSent() const { return packetsSent; }
00752
00755 DWORD GetOctetsSent() const { return octetsSent; }
00756
00759 DWORD GetPacketsReceived() const { return packetsReceived; }
00760
00763 DWORD GetOctetsReceived() const { return octetsReceived; }
00764
00767 DWORD GetPacketsLost() const { return packetsLost; }
00768
00771 DWORD GetPacketsOutOfOrder() const { return packetsOutOfOrder; }
00772
00775 DWORD GetPacketsTooLate() const;
00776
00781 DWORD GetAverageSendTime() const { return averageSendTime; }
00782
00787 DWORD GetMaximumSendTime() const { return maximumSendTime; }
00788
00793 DWORD GetMinimumSendTime() const { return minimumSendTime; }
00794
00799 DWORD GetAverageReceiveTime() const { return averageReceiveTime; }
00800
00805 DWORD GetMaximumReceiveTime() const { return maximumReceiveTime; }
00806
00811 DWORD GetMinimumReceiveTime() const { return minimumReceiveTime; }
00812
00817 DWORD GetAvgJitterTime() const { return jitterLevel>>7; }
00818
00822 DWORD GetMaxJitterTime() const { return maximumJitterLevel>>7; }
00823
00827 PTime GetFirstDataReceivedTime() const { return firstDataReceivedTime; }
00829
00830 protected:
00831 void AddReceiverReport(RTP_ControlFrame::ReceiverReport & receiver);
00832
00833 unsigned sessionID;
00834 PString canonicalName;
00835 PString toolName;
00836 unsigned referenceCount;
00837 RTP_UserData * userData;
00838
00839 #ifndef NO_H323_AUDIO_CODECS
00840 RTP_JitterBuffer * jitter;
00841 #endif
00842
00843 BOOL ignoreOtherSources;
00844 BOOL ignoreOutOfOrderPackets;
00845 DWORD syncSourceOut;
00846 DWORD syncSourceIn;
00847 PTimeInterval reportTimeInterval;
00848 unsigned txStatisticsInterval;
00849 unsigned rxStatisticsInterval;
00850 WORD lastSentSequenceNumber;
00851 WORD expectedSequenceNumber;
00852 DWORD lastSentTimestamp;
00853 PTimeInterval lastSentPacketTime;
00854 PTimeInterval lastReceivedPacketTime;
00855 WORD lastRRSequenceNumber;
00856 PINDEX consecutiveOutOfOrderPackets;
00857
00858
00859 DWORD packetsSent;
00860 DWORD octetsSent;
00861 DWORD packetsReceived;
00862 DWORD octetsReceived;
00863 DWORD packetsLost;
00864 DWORD packetsOutOfOrder;
00865 DWORD averageSendTime;
00866 DWORD maximumSendTime;
00867 DWORD minimumSendTime;
00868 DWORD averageReceiveTime;
00869 DWORD maximumReceiveTime;
00870 DWORD minimumReceiveTime;
00871 DWORD jitterLevel;
00872 DWORD maximumJitterLevel;
00873
00874 unsigned txStatisticsCount;
00875 unsigned rxStatisticsCount;
00876
00877 DWORD averageSendTimeAccum;
00878 DWORD maximumSendTimeAccum;
00879 DWORD minimumSendTimeAccum;
00880 DWORD averageReceiveTimeAccum;
00881 DWORD maximumReceiveTimeAccum;
00882 DWORD minimumReceiveTimeAccum;
00883 DWORD packetsLostSinceLastRR;
00884 DWORD lastTransitTime;
00885 PTime firstDataReceivedTime;
00886
00887 PMutex reportMutex;
00888 PTimer reportTimer;
00889 };
00890
00891
00894 class RTP_SessionManager : public PObject
00895 {
00896 PCLASSINFO(RTP_SessionManager, PObject);
00897
00898 public:
00903 RTP_SessionManager();
00904 RTP_SessionManager(const RTP_SessionManager & sm);
00905 RTP_SessionManager & operator=(const RTP_SessionManager & sm);
00907
00908
00922 RTP_Session * UseSession(
00923 unsigned sessionID
00924 );
00925
00932 void AddSession(
00933 RTP_Session * session
00934 );
00935
00939 void ReleaseSession(
00940 unsigned sessionID
00941 );
00942
00947 RTP_Session * GetSession(
00948 unsigned sessionID
00949 ) const;
00950
00967 RTP_Session * First();
00968
00975 RTP_Session * Next();
00976
00984 void Exit();
00986
00987
00988 protected:
00989 PDICTIONARY(SessionDict, POrdinalKey, RTP_Session);
00990 SessionDict sessions;
00991 PMutex mutex;
00992 PINDEX enumerationIndex;
00993 };
00994
00995
00996
00999 class RTP_UDP : public RTP_Session
01000 {
01001 PCLASSINFO(RTP_UDP, RTP_Session);
01002
01003 public:
01008 RTP_UDP(
01009 unsigned id,
01010 BOOL remoteIsNat = FALSE
01011 );
01012
01014 ~RTP_UDP();
01016
01024 virtual BOOL ReadData(RTP_DataFrame & frame);
01025
01028 virtual BOOL WriteData(RTP_DataFrame & frame);
01029
01032 virtual BOOL WriteControl(RTP_ControlFrame & frame);
01033
01036 virtual void Close(
01037 BOOL reading
01038 );
01039
01042 virtual PString GetLocalHostName();
01044
01049 virtual BOOL ModifyQOS(RTP_QOS * rtpqos);
01050
01053 virtual void EnableGQoS();
01054
01055 #if P_HAS_QOS
01056
01058 PQoS & GetQOS();
01059 #endif
01060
01061
01066 BOOL Open(
01067 PIPSocket::Address localAddress,
01068 WORD portBase,
01069 WORD portMax,
01070 BYTE ipTypeOfService,
01071 #ifdef P_STUN
01072 PSTUNClient * stun = NULL,
01073 #else
01074 void * = NULL,
01075 #endif
01076 RTP_QOS * rtpqos = NULL
01077 );
01079
01082 void Reopen(BOOL isReading);
01084
01089 PIPSocket::Address GetLocalAddress() const { return localAddress; }
01090
01093 void SetLocalAddress(
01094 const PIPSocket::Address & addr
01095 ) { localAddress = addr; }
01096
01099 PIPSocket::Address GetRemoteAddress() const { return remoteAddress; }
01100
01103 WORD GetLocalDataPort() const { return localDataPort; }
01104
01107 WORD GetLocalControlPort() const { return localControlPort; }
01108
01111 WORD GetRemoteDataPort() const { return remoteDataPort; }
01112
01115 WORD GetRemoteControlPort() const { return remoteControlPort; }
01116
01119 PUDPSocket & GetDataSocket() { return *dataSocket; }
01120
01123 PUDPSocket & GetControlSocket() { return *controlSocket; }
01124
01127 BOOL SetRemoteSocketInfo(
01128 PIPSocket::Address address,
01129 WORD port,
01130 BOOL isDataPort
01131 );
01132
01135 void ApplyQOS(
01136 const PIPSocket::Address & addr
01137 );
01139
01140 protected:
01141 SendReceiveStatus ReadDataPDU(RTP_DataFrame & frame);
01142 SendReceiveStatus ReadControlPDU();
01143 SendReceiveStatus ReadDataOrControlPDU(
01144 PUDPSocket & socket,
01145 PBYTEArray & frame,
01146 BOOL fromDataChannel
01147 );
01148
01149 PIPSocket::Address localAddress;
01150 WORD localDataPort;
01151 WORD localControlPort;
01152
01153 PIPSocket::Address remoteAddress;
01154 WORD remoteDataPort;
01155 WORD remoteControlPort;
01156
01157 PIPSocket::Address remoteTransmitAddress;
01158
01159 BOOL shutdownRead;
01160 BOOL shutdownWrite;
01161
01162 PUDPSocket * dataSocket;
01163 PUDPSocket * controlSocket;
01164
01165 BOOL appliedQOS;
01166 BOOL enableGQOS;
01167
01168 BOOL remoteIsNAT;
01169 };
01170
01171
01172 #endif // __OPAL_RTP_H
01173
01174