Permalink
Browse files

Added some RTCP support

  • Loading branch information...
steely-glint committed Mar 26, 2018
1 parent 3a29dc5 commit 24c7d5574476667307dbd0da231ebbe5108971af
@@ -16,6 +16,7 @@
*/
package com.phono.srtplight;

import static com.phono.srtplight.SRTPProtocolImpl.getHex;
import java.net.DatagramPacket;
import java.nio.ByteBuffer;
import java.util.ArrayList;
@@ -31,6 +32,23 @@
final static int SDES = 202;
final static int BYE = 203;
final static int RTPFB = 205;
final static int PSFB = 206;
protected char pt;
protected long ssrc;

void addBody(ByteBuffer bb) {
int pad = 0;
int rc = this.getRC();
int llen = this.estimateBodyLength();
byte[] head = new byte[4];
BitUtils.copyBits(2, 2, head, 0);
BitUtils.copyBits(pad, 1, head, 2);
BitUtils.copyBits(rc, 5, head, 3);
BitUtils.copyBits(pt, 8, head, 8);
BitUtils.copyBits(llen, 16, head, 16);
bb.put(head);
bb.putInt((int) ssrc);
}

/*
0 1 2 3
@@ -69,31 +87,21 @@
| profile-specific extensions |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
static public RTCP mkRTCP(DatagramPacket pkt) throws InvalidRTCPPacketException {
static public RTCP mkRTCP(ByteBuffer bb) throws InvalidRTCPPacketException {
RTCP ret = null;

int len = pkt.getLength();
byte [] data = new byte[len];
System.arraycopy(pkt.getData(), 0, data, 0, len);
Log.debug("RTCP packet "+ SRTPProtocolImpl.getHex(data));
ByteBuffer bb = ByteBuffer.wrap(data);
int begin = bb.position();
char fh = bb.getChar();
int v = (fh & ((char) (0xc000))) >>> 14;
int p = (fh & ((char) (0x2000))) >>> 13;
int rc = (fh & ((char) (0x1f00))) >>> 8;
int pt = (char) (fh & ((char) (0x00ff)));
int lpt = (char) (fh & ((char) (0x00ff)));
int length = bb.getChar();
Log.debug("Have RTCP pkt with v=" + v + " p=" + p + " rc=" + rc + " pt=" + pt + " lenght=" + length);
Log.debug("Have RTCP pkt with v=" + v + " p=" + p + " rc=" + rc + " pt=" + lpt + " lenght=" + length);
if (v != 2) {
throw new InvalidRTCPPacketException("version must be 2");
}
int offset = (length *4);
int tail = bb.remaining() - offset;
if (tail > 0){
Log.debug("have tail bytes "+ tail);
parseTail(bb,offset,tail);
}
switch (pt) {
int offset = (length * 4);
switch (lpt) {
case SR:
ret = new SenderReport(bb, rc, length);
break;
@@ -109,23 +117,36 @@ static public RTCP mkRTCP(DatagramPacket pkt) throws InvalidRTCPPacketException
case RTPFB:
ret = new FB(bb, rc, length);
break;
case PSFB:
ret = new PSFB(bb, rc, length);
break;
default:
Log.debug("Ignoring unknown RTCP type =" + pt);
ret = new RTCP();
Log.debug("Ignoring unknown RTCP type =" + lpt);
break;
}
bb.position(begin + offset + 4);
return ret;
}

public static void main(String[] args) {
Log.setLevel(Log.ALL);
byte[] sr = {(byte) 0x80, (byte) 0xc8, (byte) 0x00, (byte) 0x06, (byte) 0x50, (byte) 0xf6, (byte) 0xb8, (byte) 0xbf, (byte) 0xdd, (byte) 0x62, (byte) 0x47, (byte) 0xcd, (byte) 0x4b, (byte) 0x43, (byte) 0x95, (byte) 0x81,
(byte) 0x27, (byte) 0x9b, (byte) 0xca, (byte) 0xef, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};
byte[] rr = {(byte) 0x81, (byte) 0xc9, (byte) 0x00, (byte) 0x07, (byte) 0xab, (byte) 0x36, (byte) 0xcd, (byte) 0x19, (byte) 0x2e, (byte) 0x0f, (byte) 0x36, (byte) 0x14, (byte) 0xa0, (byte) 0xfb, (byte) 0xf0, (byte) 0xe5, (byte) 0x5a, (byte) 0x50, (byte) 0x0b, (byte) 0xc0, (byte) 0x1a, (byte) 0xc9, (byte) 0x52, (byte) 0xbc, (byte) 0x61, (byte) 0x36, (byte) 0x57, (byte) 0xd5, (byte) 0x5f, (byte) 0x19, (byte) 0x00, (byte) 0xa4
byte[] sr = {(byte) 0x80, (byte) 0xc8, (byte) 0x00, (byte) 0x06, (byte) 0x50, (byte) 0xf6, (byte) 0xb8,
(byte) 0xbf, (byte) 0xdd, (byte) 0x62, (byte) 0x47, (byte) 0xcd, (byte) 0x4b, (byte) 0x43, (byte) 0x95, (byte) 0x81,
(byte) 0x27, (byte) 0x9b, (byte) 0xca, (byte) 0xef, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};
byte[] rr = {(byte) 0x81, (byte) 0xc9, (byte) 0x00, (byte) 0x07, (byte) 0xab, (byte) 0x36, (byte) 0xcd,
(byte) 0x19, (byte) 0x2e, (byte) 0x0f, (byte) 0x36, (byte) 0x14, (byte) 0xa0, (byte) 0xfb, (byte) 0xf0,
(byte) 0xe5, (byte) 0x5a, (byte) 0x50, (byte) 0x0b, (byte) 0xc0, (byte) 0x1a, (byte) 0xc9, (byte) 0x52,
(byte) 0xbc, (byte) 0x61, (byte) 0x36, (byte) 0x57, (byte) 0xd5, (byte) 0x5f, (byte) 0x19, (byte) 0x00, (byte) 0xa4
};
byte[] fb = {(byte) 0x8f, (byte) 0xcd, (byte) 0x00, (byte) 0x06, (byte) 0x75, (byte) 0xe8, (byte) 0x1d, (byte) 0x8f, (byte) 0x04, (byte) 0xad, (byte) 0xa0, (byte) 0xf2, (byte) 0xda, (byte) 0x59, (byte) 0x26, (byte) 0x25, (byte) 0x30, (byte) 0xee, (byte) 0x6e, (byte) 0x9f, (byte) 0x71, (byte) 0x36, (byte) 0x82, (byte) 0x61, (byte) 0xfb, (byte) 0xe4, (byte) 0x12, (byte) 0x80};
byte[] fb = {(byte) 0x8f, (byte) 0xcd, (byte) 0x00, (byte) 0x06, (byte) 0x75, (byte) 0xe8, (byte) 0x1d, (byte) 0x8f,
(byte) 0x04, (byte) 0xad, (byte) 0xa0, (byte) 0xf2, (byte) 0xda, (byte) 0x59, (byte) 0x26, (byte) 0x25, (byte) 0x30,
(byte) 0xee, (byte) 0x6e, (byte) 0x9f, (byte) 0x71, (byte) 0x36, (byte) 0x82, (byte) 0x61, (byte) 0xfb, (byte) 0xe4,
(byte) 0x12, (byte) 0x80};
byte[][] tests = {sr, rr, fb};
for (byte[] t : tests) {
DatagramPacket p = new DatagramPacket(t, t.length);
ByteBuffer p = ByteBuffer.wrap(t);
try {
RTCP r = mkRTCP(p);
if (r != null) {
@@ -138,34 +159,40 @@ public static void main(String[] args) {
irp.printStackTrace();
}
}
SenderReport sro = mkSenderReport();
sro.setSSRC(1358346431);
sro.setNTPStamp(-2494352296553245311L);
sro.setRTPStamp(664521455);
sro.setSenderPackets(0);
sro.setSenderOctets(0);
int ebl = sro.estimateBodyLength();
ByteBuffer bbo = ByteBuffer.allocate(4*(ebl+1));
sro.addBody(bbo);
byte [] pky = bbo.array();
Log.debug("sro "+sro);
Log.debug("sro "+getHex(pky));
for (int i=0;i<sr.length;i++){
if (pky[i]!= sr[i]){
Log.error("packets differ at:"+i);
}
}
}

private static void parseTail(ByteBuffer bb, int offset, int tail) {
/*
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ |
| |E| SRTCP index | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<+
| ~ SRTCP MKI (OPTIONAL) ~ |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| : authentication tag : |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
*/
int opos = bb.position();
int mkti= 0;
long authtag = 0;
bb.position(offset);
long index = bb.getInt();
boolean encryption = (index < 0);
index = (0x7fffffff & index);
if(bb.remaining() > 4){
mkti = bb.getInt();
}
if(bb.remaining() > 4){
authtag = bb.getInt();
}
Log.debug("Tail ="+tail+" index="+index+" mkti="+mkti+" authtag="+authtag+" encryption="+encryption);
//checkauth();
bb.position(opos);
public static SenderReport mkSenderReport() {
SenderReport ret = new SenderReport();
return ret;
}

int estimateBodyLength() { // this is int 32s -1
return 1;
}

public void setSSRC(long s) {
ssrc = s;
}

int getRC() {
return 0;
}

private static class SenderReport extends RTCP {
@@ -185,13 +212,54 @@ private static void parseTail(ByteBuffer bb, int offset, int tail) {
| sender's octet count |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*/
long ssrc;
long ntpstamp;
long rtpstamp;
long senderPkts;
long senderOcts;
ArrayList<ReportBlock> reports;

public void setNTPStamp(long s) {
ntpstamp = s;
}

public void setRTPStamp(long s) {
rtpstamp = s;
}

public void setSenderOctets(long s) {
senderPkts = s;
}

public void setSenderPackets(long s) {
senderOcts = s;
}

public void addReport(ReportBlock b) {
reports.add(b);
}

@Override
public void addBody(ByteBuffer bb) {
super.addBody(bb);
bb.putLong(ntpstamp);
bb.putInt((int) rtpstamp);
bb.putInt((int) senderPkts);
bb.putInt((int) senderOcts);
for (ReportBlock r : reports) {
r.addBody(bb);
}
}

@Override
int getRC() {
return reports.size();
}

@Override
int estimateBodyLength() {
return 6 + (6 * reports.size());
}

public SenderReport(ByteBuffer bb, int rc, int length) throws InvalidRTCPPacketException {
int expected = 6 + (6 * rc);
if (length != expected) {
@@ -210,6 +278,11 @@ public SenderReport(ByteBuffer bb, int rc, int length) throws InvalidRTCPPacketE
}
}

private SenderReport() {
reports = new ArrayList();
pt = SR;
}

public String toString() {
String ret = "RTCP SR: ssrc=" + ssrc + " ntpstamp=" + ntpstamp + " rtpstamp=" + rtpstamp + " senderPkts=" + senderPkts + " senderOcts=" + senderOcts;
for (ReportBlock b : reports) {
@@ -278,6 +351,9 @@ public String toString() {
}
}

public RTCP() {
}

private static class SDES extends RTCP {

public SDES(ByteBuffer bb, int rc, int length) {
@@ -294,8 +370,8 @@ public BYE(ByteBuffer bb, int rc, int length) {

long sssrc;
long mssrc;
private int fmt;
private byte[] fci;
protected int fmt;
protected byte[] fci;

/*
Figure 3:
@@ -329,6 +405,18 @@ public String toString() {
}
}

private static class PSFB extends FB {

public PSFB(ByteBuffer bb, int rc, int length) throws InvalidRTCPPacketException {
super(bb, rc, length);
}

public String toString() {
String ret = "RTCP PSFB: sssrc=" + sssrc + " mssrc=" + mssrc + " fmt=" + fmt + " fci length=" + fci.length;
return ret;
}
}

class ReportBlock {

/*
@@ -370,6 +458,10 @@ public String toString() {
return "ReportBlock for ssrc=" + ssrc + " frac=" + frac + " cumulost=" + cumulost + " highestSeqRcvd=" + highestSeqRcvd + " iaJitter=" + iaJitter + " lsr=" + lsr + " dlsr=" + dlsr;
}

private void addBody(ByteBuffer bb) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}

}

}
Oops, something went wrong.

0 comments on commit 24c7d55

Please sign in to comment.