Permalink
Browse files

added relay mode where we use and trust incomming seqnos rather than …

…using our own count.
  • Loading branch information...
steely-glint committed Oct 22, 2018
1 parent 86dd61d commit 772621eba5a32f034938a413a76ad39ef7795250
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.phono</groupId>
<artifactId>srtplight</artifactId>
<version>1.1.2</version>
<version>1.1.3</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -39,6 +39,7 @@
protected long _roc = 0; // only used for inbound we _know_ the answer for outbound.
protected char _s_l;// only used for inbound we _know_ the answer for outbound.


/* networky stuff bidriectional*/
DatagramSocket _ds;
SocketAddress _far;
@@ -69,10 +70,10 @@ public RTPProtocolImpl(int id, DatagramSocket ds, InetSocketAddress far, int typ
_csrcid = _rand.nextInt();
try {
if (_far != null) {
if (!far.getAddress().isLoopbackAddress()){
if (!far.getAddress().isLoopbackAddress()) {
_ds.connect(_far);
} // if we are talking to loopback we dont need the extra
// security of connecting.
// security of connecting.
}

_ds.setSoTimeout(100);
@@ -90,13 +91,13 @@ public void run() {
_listen = new Thread(ir);
_listen.setName(_session);
_first = true;
Log.debug("RTP session "+this.getClass().getSimpleName()+_session);
Log.debug("RTP session " + this.getClass().getSimpleName() + _session);
}

public void setSSRC(long v){
public void setSSRC(long v) {
_csrcid = v;
}

public RTPProtocolImpl(int id, String local_media_address, int local_audio_port, String remote_media_address, int remote_audio_port, int type) throws SocketException {
this(id, new DatagramSocket(local_audio_port), new InetSocketAddress(remote_media_address, remote_audio_port), type);
}
@@ -109,7 +110,7 @@ protected void irun() {
byte[] data = new byte[1500];
DatagramPacket dp = new DatagramPacket(data, data.length);
Log.debug("Max Datagram size " + data.length);
Log.debug("address is " +_ds.getLocalSocketAddress().toString());
Log.debug("address is " + _ds.getLocalSocketAddress().toString());

while (_listen != null) {
try {
@@ -120,11 +121,11 @@ protected void irun() {
dp = new DatagramPacket(data, data.length);
}
} catch (Exception x) {
Log.debug(this.getClass().getSimpleName()+" "+ x.toString());
Log.debug(this.getClass().getSimpleName() + " " + x.toString());
_lastx = x;
}
}
if (!_ds.isClosed()){
if (!_ds.isClosed()) {
_ds.close();
}
// some tidyup here....
@@ -161,6 +162,11 @@ public Exception getNClearLastX() {
}

public void sendPacket(byte[] data, long stamp, int ptype, boolean marker) throws IOException {
sendPacket(data, stamp, (char)_seqno, ptype, marker);
_seqno++;
}

public void sendPacket(byte[] data, long stamp, char seqno, int ptype, boolean marker) throws IOException {
// skip X
// skip cc
// skip M
@@ -177,8 +183,8 @@ public void sendPacket(byte[] data, long stamp, int ptype, boolean marker) throw
copyBits(1, 1, payload, 8);
}
copyBits(ptype, 7, payload, 9);
payload[2] = (byte) (_seqno >> 8);
payload[3] = (byte) _seqno;
payload[2] = (byte) (seqno >> 8);
payload[3] = (byte) seqno;
payload[4] = (byte) (stamp >> 24);
payload[5] = (byte) (stamp >> 16);
payload[6] = (byte) (stamp >> 8);
@@ -191,14 +197,14 @@ public void sendPacket(byte[] data, long stamp, int ptype, boolean marker) throw
payload[i + RTPHEAD] = data[i];
}
appendAuth(payload);
DatagramPacket p = (_far ==null)?new DatagramPacket(payload, payload.length):
new DatagramPacket(payload, payload.length, _far);
DatagramPacket p = (_far == null) ? new DatagramPacket(payload, payload.length)
: new DatagramPacket(payload, payload.length, _far);
_ds.send(p);
_seqno++;
Log.verb("sending RTP " + _ptype + " packet length " + payload.length );

Log.verb("sending RTP " + _ptype + " packet length " + payload.length);
} catch (IOException ex) {
_lastx = ex;
Log.error("Not sending RTP " + _ptype + "ex = " + ex.getMessage());
Log.error("Not sending RTP " + _ptype + "ex = " + ex.getMessage());
throw ex;
}

@@ -235,20 +241,20 @@ protected void parsePacket(DatagramPacket dp) throws IOException {
long stamp = 0;
int sync = 0;

Log.verb("got packet " +plen);
Log.verb("got packet " + plen);

if (plen < 12) {
throw new RTPPacketException("Packet too short. RTP must be >12 bytes");
}
ver = copyBits(packet, 0, 2);
pad = copyBits(packet, 2, 1);
csrcn = copyBits(packet, 4, 4);
mark = copyBits(packet,8,1);
mark = copyBits(packet, 8, 1);
ptype = copyBits(packet, 9, 7);
ByteBuffer pb = ByteBuffer.wrap(packet);

seqno = pb.getChar(2);
stamp = getUnsignedInt(pb,4);
stamp = getUnsignedInt(pb, 4);
sync = pb.getInt(8);
if (plen < (RTPHEAD + 4 * csrcn)) {
throw new RTPPacketException("Packet too short. CSRN =" + csrcn + " but packet only " + plen);
@@ -296,9 +302,9 @@ protected void parsePacket(DatagramPacket dp) throws IOException {

throw rpx;
}
deliverPayload(payload, stamp, sync, seqno,mark);
deliverPayload(payload, stamp, sync, seqno, mark);

Log.verb("got RTP " + ptype + " packet " + payload.length );
Log.verb("got RTP " + ptype + " packet " + payload.length);

}

@@ -341,7 +347,8 @@ protected void deliverPayload(byte[] payload, long stamp, int ssrc, char seqno)
_rtpds.dataPacketReceived(payload, stamp, getIndex(seqno));
}
}

void appendAuth(byte[] payload, char seqno) throws RTPPacketException {
}
void appendAuth(byte[] payload) throws RTPPacketException {
// nothing to do in rtp
}
@@ -368,15 +375,15 @@ protected void syncChanged(long sync) throws RTPPacketException {
throw new RTPPacketException("Sync changed: was " + _sync + " now " + sync);
}
}
public static long getUnsignedInt(ByteBuffer bb,int loc) {

public static long getUnsignedInt(ByteBuffer bb, int loc) {
return ((long) bb.getInt(loc) & 0xffffffffL);
}

public static void putUnsignedInt(ByteBuffer bb, long value, int loc) {
bb.putInt(loc,(int) (value & 0xffffffffL));
bb.putInt(loc, (int) (value & 0xffffffffL));
}

public void startrecv() {
_listen.start();
}
@@ -478,7 +485,7 @@ public void setDTMFPayloadType(int type) {
}

protected void deliverPayload(byte[] payload, long stamp, int sync, char seqno, int mark) {
deliverPayload(payload,stamp,sync,seqno);
deliverPayload(payload, stamp, sync, seqno);
}

protected static class RTPPacketException extends IOException {
@@ -487,4 +494,57 @@ protected void deliverPayload(byte[] payload, long stamp, int sync, char seqno,
super(mess);
}
}

public static void main(String[] args) {
// loop back test
byte data[] = new byte[1209];
SecureRandom sr = new SecureRandom();
sr.nextBytes(data);
long stamp = 0;
int id;
int type;
final DatagramPacket[] dsa = new DatagramPacket[1];
final long gstamp[] = new long[1];
final long gindex[] = new long[1];
try {
DatagramSocket ds = new DatagramSocket() {
@Override
public void send(DatagramPacket dp) throws IOException {
dsa[0] = dp;
}
};
id = sr.nextInt(Character.MAX_VALUE);
type = sr.nextInt(Byte.MAX_VALUE);
RTPProtocolImpl target = new RTPProtocolImpl(id, ds, null, type);
RTPDataSink rtpds = new RTPDataSink() {
@Override
public void dataPacketReceived(byte[] data, long stamp, long index) {
gstamp[0] = stamp;
gindex[0] = index;
}
};
target.setRTPDataSink(rtpds);
while (stamp < 0x200000000L) {
target.sendPacket(data, stamp, type);
target.parsePacket(dsa[0]);
if (gstamp[0] != stamp) {
throw new java.lang.ArithmeticException("Stamp is wrong " + gstamp[0] + " != " + stamp);
}
long xindex = stamp;
if (gindex[0] != xindex) {
throw new java.lang.ArithmeticException("Index is wrong " + gindex[0] + " != " + xindex);
}
if ((stamp % 0x1000000) == 0) {
System.out.println("did " + stamp + " tests");
}
stamp++;
}
} catch (Exception x) {
System.out.println("exception " + x.getLocalizedMessage());

x.printStackTrace();
}
System.out.println("did " + stamp + " tests");

}
}
@@ -16,9 +16,6 @@
* limitations under the License.
*
*/



import java.io.*;
import java.io.IOException;
import java.net.DatagramSocket;
@@ -30,7 +27,7 @@
import javax.crypto.Mac;

/**
* see http://www.faqs.org/rfcs/rfc3711.html
* see http://www.faqs.org/rfcs/rfc3711.html
*/
public class SRTPProtocolImpl extends RTPProtocolImpl {

@@ -110,7 +107,7 @@ public SRTPProtocolImpl(int id, String local_media_address, int local_audio_port
*
*/
/*
/*
To authenticate and decrypt an SRTP packet, the receiver SHALL do the
following:
@@ -228,19 +225,17 @@ void checkAuth(byte[] packet, int plen) throws RTPPacketException {

@Override
protected void deliverPayload(
byte[] payload, long stamp, int ssrc , char seqno) {
byte[] payload, long stamp, int ssrc, char seqno) {
try {
if (_doCrypt) {
decrypt(payload, ssrc);
}
super.deliverPayload(payload, stamp, ssrc,seqno);
super.deliverPayload(payload, stamp, ssrc, seqno);
} catch (GeneralSecurityException ex) {
Log.error("problem with decryption " + ex.getMessage());
}
}



@Override
void updateCounters(
char seqno) {
@@ -256,10 +251,11 @@ void updateCounters(

@Override
/**
* calculate the outbound auth and put it at the end of the packet
* starting at length - _tail space is already allocated.
* calculate the outbound auth and put it at the end of the packet starting
* at length - _tail space is already allocated.
*/
void appendAuth(byte[] packet ) throws RTPPacketException {
void appendAuth(byte[] packet) throws RTPPacketException {

if (_doAuth) {
try {
// strictly we might need to derive the keys here too -
@@ -270,8 +266,8 @@ void appendAuth(byte[] packet ) throws RTPPacketException {
ByteBuffer m = ByteBuffer.allocate(offs + 4);
m.put(packet, 0, offs);
int oroc = (int) (_seqno >>> 16);
if ((_seqno & 0xffff)== 0){
Log.debug("seqno = 0 outgoing roc ="+oroc);
if ((_seqno & 0xffff) == 0) {
Log.debug("seqno = 0 outgoing roc =" + oroc);
}
m.putInt(oroc);
if (Log.getLevel() > Log.DEBUG) {
@@ -295,6 +291,51 @@ void appendAuth(byte[] packet ) throws RTPPacketException {
}
}

Character oseq = null;
int roc = 0;
static final int wrapdiff = 2 << 14;
@Override
/*
variant that sets seqno itself rather than incrementing it .
which requires a small amount of guesswork
*/
public void sendPacket(byte[] data, long stamp, char seqno, int ptype, boolean marker) throws SocketException, IOException {
int n = roc;
if (oseq == null) {
oseq = seqno;
}
/* check for wrap or unwrap */
int diff = seqno - oseq;
if (diff < (-wrapdiff)) {
// huge negative diff between seqs
// assume we wrapped
roc++;
n = roc;
Log.debug(" wrapped seqno " + (int) seqno + " oseq " + (int) oseq + " diff =" + diff + " outgoing roc =" + n);

}
if (diff > wrapdiff) {
// big positive
// pre-wrap packet was out of order
n = roc - 1;
Log.debug(" unwrapped seqno " + (int) seqno + " oseq " + (int) oseq + " diff =" + diff + " outgoing roc =" + n);
}
oseq = seqno;
long low = (long) seqno;
long high = ((long) n << 16);
_seqno = low | high;
try {
if (_doCrypt) {
_scOut.deriveKeys(stamp);
encrypt(data, (int) _csrcid, _seqno);
}
super.sendPacket(data, stamp, seqno, ptype, marker);
} catch (Exception ex) {
Log.error("problem encrypting packet" + ex.getMessage());
ex.printStackTrace();
}
}

@Override
public void sendPacket(byte[] data, long stamp, int ptype, boolean marker) throws SocketException,
IOException {
@@ -382,7 +423,6 @@ public static void main(String[] args) {
s.terminate();
}


}

private void testRcvSRTP() {
@@ -409,7 +449,7 @@ private void testRcvSRTP() {

RTPDataSink sink = new RTPDataSink() {

public void dataPacketReceived(byte[] data, long stamp,long idx) {
public void dataPacketReceived(byte[] data, long stamp, long idx) {
Log.debug("got " + data.length + " bytes");
Log.debug("data =" + getHex(data));
Log.debug("Message is " + new String(data));
@@ -480,7 +520,7 @@ private void testSendSRTP() throws IOException {
// kinda don'r expect this.....
RTPDataSink sink = new RTPDataSink() {

public void dataPacketReceived(byte[] data, long stamp,long idx) {
public void dataPacketReceived(byte[] data, long stamp, long idx) {
Log.debug("got " + data.length + " bytes");
Log.debug("data =" + getHex(data));
Log.debug("Message is " + new String(data));

0 comments on commit 772621e

Please sign in to comment.