it;
25 | it = context.audioFrom.iterator();
26 | while (it.hasNext()) {
27 | AudioData data = it.next();
28 | data.close();
29 | LocalMetrics metrics = new LocalMetrics(context, data);
30 | metrics.setPacketLoss(data.getLossRate());
31 | metrics.setDelay(data.getJitter());
32 | VQSessionReport report = new VQSessionReport(metrics);
33 | CollectorStack.instance.sendMessage(report.toString());
34 | }
35 | it = context.audioTo.iterator();
36 | while (it.hasNext()) {
37 | AudioData data = it.next();
38 | data.close();
39 | LocalMetrics metrics = new LocalMetrics(context, data);
40 | metrics.setPacketLoss(data.getLossRate());
41 | metrics.setDelay(data.getJitter());
42 | VQSessionReport report = new VQSessionReport(metrics);
43 | CollectorStack.instance.sendMessage(report.toString());
44 | }
45 | return StateTerminated.instance;
46 | case Message.INVITE:
47 | case Message.ACK:
48 | logger.warn("Unexpected message in terminating: " + message);
49 | break;
50 | case Message.BYE:
51 | break;
52 | case Message.RTP_PACKET:
53 | processRtpPacket(context, (RtpPacket)message);
54 | break;
55 | }
56 | return this;
57 | }
58 | }
--------------------------------------------------------------------------------
/src/com/tt/reaper/filter/FilterExecute.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.filter;
2 |
3 | import org.apache.log4j.Logger;
4 |
5 | import com.tt.reaper.Configuration;
6 |
7 | public class FilterExecute extends Thread {
8 | private static Logger logger = Logger.getLogger(FilterExecute.class);
9 | public static final FilterExecute instance = new FilterExecute();
10 | private String command;
11 | private boolean running = false;
12 |
13 | private FilterExecute() {
14 | }
15 |
16 | public synchronized void init() {
17 | command = new Configuration().getCommand();
18 | if (command == null) {
19 | logger.error("Filter command not configured");
20 | }
21 | if (running == false)
22 | start();
23 | running = true;
24 | }
25 |
26 | public void run() {
27 | try {
28 | logger.info("Running filter: " + command);
29 | Process p = Runtime.getRuntime().exec(command);
30 | p.waitFor();
31 | logger.warn("Filter exited with return value: " + p.exitValue());
32 | } catch (Exception e) {
33 | logger.error("Error running filter: ", e);
34 | }
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/http/WebHandler.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.http;
2 |
3 | import java.io.IOException;
4 | import java.io.OutputStream;
5 |
6 | import com.sun.net.httpserver.HttpExchange;
7 | import com.sun.net.httpserver.HttpHandler;
8 | import com.tt.reaper.call.CallManager;
9 | import com.tt.reaper.message.DataRequest;
10 | import com.tt.reaper.message.DataResponse;
11 | import com.tt.reaper.message.Message;
12 | import com.tt.reaper.message.MessageQueue;
13 |
14 | public class WebHandler implements HttpHandler {
15 |
16 | @Override
17 | public void handle(HttpExchange xchange) throws IOException {
18 | String body = "Active CallsActive Calls
";
19 | body += "";
20 | MessageQueue queue = new MessageQueue();
21 | CallManager.instance.send(new DataRequest(queue));
22 | Message response = queue.getBlocking();
23 | if (response instanceof DataResponse)
24 | {
25 | body += ((DataResponse)response).data.replaceAll("<", "<").replaceAll(">", ">");
26 | }
27 | body += "
";
28 | xchange.sendResponseHeaders(200, body.length());
29 | OutputStream outputStream = xchange.getResponseBody();
30 | outputStream.write(body.getBytes());
31 | outputStream.close();
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/http/WebServer.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.http;
2 |
3 | import java.net.InetSocketAddress;
4 |
5 | import org.apache.log4j.Logger;
6 |
7 | import com.sun.net.httpserver.HttpServer;
8 | import com.tt.reaper.call.CallContext;
9 |
10 | public class WebServer {
11 | protected static Logger logger = Logger.getLogger(CallContext.class);
12 | public static WebServer instance = new WebServer();
13 | private HttpServer server;
14 |
15 | private WebServer()
16 | {
17 |
18 | }
19 |
20 | public void init()
21 | {
22 | try {
23 | server = HttpServer.create(new InetSocketAddress("127.0.0.1", 8060), 10);
24 | server.createContext("/", new WebHandler());
25 | server.start();
26 | }
27 | catch (Exception e)
28 | {
29 | logger.error("Error starting web server");
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/message/AckMessage.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.message;
2 |
3 | import javax.sip.message.Request;
4 |
5 | public class AckMessage extends RequestMessage {
6 | public AckMessage(Request request) {
7 | super(Message.ACK, request);
8 | }
9 | }
--------------------------------------------------------------------------------
/src/com/tt/reaper/message/ByeMessage.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.message;
2 |
3 | import javax.sip.message.Request;
4 |
5 | public class ByeMessage extends RequestMessage {
6 | public ByeMessage(Request request) {
7 | super(Message.BYE, request);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/message/CancelMessage.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.message;
2 |
3 | import javax.sip.message.Request;
4 |
5 | public class CancelMessage extends RequestMessage {
6 | public CancelMessage(Request request) {
7 | super(Message.CANCEL, request);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/message/DataRequest.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.message;
2 |
3 | public class DataRequest extends Message {
4 | public MessageQueue queue;
5 |
6 | public DataRequest(MessageQueue queue) {
7 | super(Message.DATA_REQUEST);
8 | this.queue = queue;
9 | }
10 | }
--------------------------------------------------------------------------------
/src/com/tt/reaper/message/DataResponse.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.message;
2 |
3 | public class DataResponse extends Message {
4 | public String data;
5 |
6 | public DataResponse(String data) {
7 | super(Message.DATA_REQUEST);
8 | this.data = data;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/message/ErrorMessage.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.message;
2 |
3 | import javax.sip.message.Response;
4 |
5 | public class ErrorMessage extends ResponseMessage {
6 | private ErrorMessage(Response response)
7 | {
8 | super(Message.FAILURE, response);
9 | }
10 |
11 | static SipMessage create(Response response)
12 | {
13 | if (response.getStatusCode() >= 300) {
14 | return new ErrorMessage(response);
15 | }
16 | return null;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/message/InviteMessage.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.message;
2 |
3 | import javax.sip.message.Request;
4 |
5 | public class InviteMessage extends RequestMessage {
6 | public InviteMessage()
7 | {
8 | super(Message.INVITE, Request.INVITE, getNewCallId());
9 | status = init();
10 | }
11 |
12 | public InviteMessage(Request request) {
13 | super(Message.INVITE, request);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/message/Message.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.message;
2 |
3 | import org.apache.log4j.Logger;
4 |
5 | public abstract class Message {
6 | protected static Logger logger = Logger.getLogger(Message.class);
7 | public static final int PROVISIONAL = 180;
8 | public static final int SUCCESS = 200;
9 | public static final int FAILURE = 400;
10 | public static final int ACK = 1;
11 | public static final int BYE = 2;
12 | public static final int INVITE = 3;
13 | public static final int PUBLISH = 4;
14 | public static final int NOTIFY = 5;
15 | public static final int CANCEL = 6;
16 | public static final int DATA_RESPONSE = 996;
17 | public static final int DATA_REQUEST = 997;
18 | public static final int RTP_PACKET = 998;
19 | public static final int DATA_PACKET = 999;
20 |
21 | private int type;
22 |
23 | protected Message(int type)
24 | {
25 | this.type = type;
26 | }
27 |
28 | public final int getType()
29 | {
30 | return type;
31 | }
32 | }
--------------------------------------------------------------------------------
/src/com/tt/reaper/message/MessageFactory.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.message;
2 |
3 | import javax.sip.message.Request;
4 | import javax.sip.message.Response;
5 |
6 | public class MessageFactory {
7 | public SipMessage create(Request request)
8 | {
9 | String eventName = request.getMethod();
10 |
11 | if (Request.ACK.equals(eventName))
12 | {
13 | return new AckMessage(request);
14 | }
15 | if (Request.BYE.equals(eventName))
16 | {
17 | return new ByeMessage(request);
18 | }
19 | if (Request.CANCEL.equals(eventName))
20 | {
21 | return new CancelMessage(request);
22 | }
23 | if (Request.INFO.equals(eventName))
24 | {
25 | return null;
26 | }
27 | if (Request.INVITE.equals(eventName))
28 | {
29 | return new InviteMessage(request);
30 | }
31 | if (Request.MESSAGE.equals(eventName))
32 | {
33 | return null;
34 | }
35 | if (Request.NOTIFY.equals(eventName))
36 | {
37 | return new NotifyMessage(request);
38 | }
39 | if (Request.OPTIONS.equals(eventName))
40 | {
41 | return null;
42 | }
43 | if (Request.PRACK.equals(eventName))
44 | {
45 | return null;
46 | }
47 | if (Request.PUBLISH.equals(eventName))
48 | {
49 | return new PublishMessage(request);
50 | }
51 | if (Request.REFER.equals(eventName))
52 | {
53 | return null;
54 | }
55 | if (Request.REGISTER.equals(eventName))
56 | {
57 | return null;
58 | }
59 | if (Request.SUBSCRIBE.equals(eventName))
60 | {
61 | return null;
62 | }
63 | if (Request.UPDATE.equals(eventName))
64 | {
65 | return null;
66 | }
67 |
68 | return null;
69 | }
70 |
71 | public SipMessage create(Response response)
72 | {
73 | SipMessage message;
74 | if ((message = SuccessMessage.create(response)) != null)
75 | return message;
76 | if ((message = ProvisionalMessage.create(response)) != null)
77 | return message;
78 | if ((message = ErrorMessage.create(response)) != null)
79 | return message;
80 | return null;
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/message/MessageQueue.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.message;
2 |
3 | import java.util.Collections;
4 | import java.util.LinkedList;
5 | import java.util.List;
6 |
7 | import org.apache.log4j.Logger;
8 |
9 | public class MessageQueue
10 | {
11 | private static Logger logger = Logger.getLogger(MessageQueue.class);
12 | protected List queue;
13 |
14 | public MessageQueue()
15 | {
16 | queue = Collections.synchronizedList(new LinkedList());
17 | }
18 |
19 | public Message getBlocking()
20 | {
21 | try
22 | {
23 | synchronized (queue)
24 | {
25 | while (queue.isEmpty())
26 | queue.wait();
27 | return (Message) queue.remove(0);
28 | }
29 | }
30 | catch (Exception e) {
31 | logger.error("Error with queue: ", e);
32 | }
33 | return null;
34 | }
35 |
36 | public Message get()
37 | {
38 | try
39 | {
40 | return (Message) queue.remove(0);
41 | }
42 | catch (Exception e) {}
43 | return null;
44 | }
45 |
46 | public void add(Message e)
47 | {
48 | synchronized (queue)
49 | {
50 | queue.add(e);
51 | queue.notify();
52 | }
53 | }
54 | }
--------------------------------------------------------------------------------
/src/com/tt/reaper/message/NotifyMessage.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.message;
2 |
3 | import javax.sip.header.ContentTypeHeader;
4 | import javax.sip.message.Request;
5 |
6 | public class NotifyMessage extends RequestMessage {
7 | public NotifyMessage(Request request) {
8 | super(Message.NOTIFY, request);
9 | }
10 |
11 | public NotifyMessage(String data)
12 | {
13 | super(SipMessage.NOTIFY, Request.NOTIFY, getNewCallId());
14 | init(data);
15 | }
16 |
17 | private boolean init(String data)
18 | {
19 | if (super.init() == false)
20 | return false;
21 | try {
22 | ContentTypeHeader contentTypeHeader;
23 | contentTypeHeader = headerFactory
24 | .createContentTypeHeader("application", "text/plain");
25 | request.setContent(data, contentTypeHeader);
26 | return true;
27 | }
28 | catch (Exception e)
29 | {
30 | logger.error("Error adding content: ", e);
31 | }
32 | return false;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/message/ProvisionalMessage.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.message;
2 |
3 | import javax.sip.message.Response;
4 |
5 | public class ProvisionalMessage extends ResponseMessage {
6 | private ProvisionalMessage(Response response)
7 | {
8 | super(SipMessage.PROVISIONAL, response);
9 | }
10 |
11 | static SipMessage create(Response response)
12 | {
13 | if (response.getStatusCode() < 200) {
14 | return new ProvisionalMessage(response);
15 | }
16 | return null;
17 | }
18 | }
--------------------------------------------------------------------------------
/src/com/tt/reaper/message/PublishMessage.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.message;
2 |
3 | import javax.sip.header.ContentTypeHeader;
4 | import javax.sip.message.Request;
5 |
6 | public class PublishMessage extends RequestMessage {
7 |
8 | public PublishMessage(String data)
9 | {
10 | super(SipMessage.PUBLISH, Request.PUBLISH, getNewCallId());
11 | status = init(data);
12 | }
13 |
14 | public PublishMessage(Request request) {
15 | super(SipMessage.PUBLISH, request);
16 | status = true;
17 | }
18 |
19 | private boolean init(String data)
20 | {
21 | if (super.init() == false)
22 | return false;
23 | try {
24 | ContentTypeHeader contentTypeHeader;
25 | contentTypeHeader = headerFactory
26 | .createContentTypeHeader("application", "vq-rtcpxr");
27 | request.setContent(data, contentTypeHeader);
28 | return true;
29 | }
30 | catch (Exception e)
31 | {
32 | logger.error("Error adding content: ", e);
33 | }
34 | return false;
35 | }
36 |
37 | public boolean getStatus() {
38 | return status;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/message/RequestMessage.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.message;
2 |
3 | import gov.nist.javax.sip.message.SIPMessage;
4 |
5 | import java.util.ArrayList;
6 |
7 | import javax.sip.address.Address;
8 | import javax.sip.address.SipURI;
9 | import javax.sip.header.CSeqHeader;
10 | import javax.sip.header.CallIdHeader;
11 | import javax.sip.header.ContactHeader;
12 | import javax.sip.header.FromHeader;
13 | import javax.sip.header.MaxForwardsHeader;
14 | import javax.sip.header.ToHeader;
15 | import javax.sip.header.ViaHeader;
16 | import javax.sip.message.Request;
17 |
18 | public class RequestMessage extends SipMessage {
19 | protected boolean status = false;
20 | Request request;
21 | String message;
22 | CallIdHeader callIdHeader;
23 |
24 | RequestMessage(int type, String message, CallIdHeader callIdHeader)
25 | {
26 | super(type);
27 | this.message = message;
28 | this.callIdHeader = callIdHeader;
29 | }
30 |
31 | RequestMessage(int type, Request request)
32 | {
33 | super(type);
34 | this.request = request;
35 | }
36 |
37 | boolean init()
38 | {
39 | try {
40 | SipURI from = addressFactory.createSipURI(getFromUsername(), getFromHost()
41 | + ":" + getFromPort());
42 | Address fromNameAddress = addressFactory.createAddress(from);
43 | fromNameAddress.setDisplayName(getFromUsername());
44 | FromHeader fromHeader = headerFactory.createFromHeader(fromNameAddress,
45 | getSoftwareVersion());
46 |
47 | SipURI toAddress = addressFactory.createSipURI(getToUsername(), getToHost()
48 | + ":" + getToPort());
49 | Address toNameAddress = addressFactory.createAddress(toAddress);
50 | toNameAddress.setDisplayName(getToUsername());
51 | ToHeader toHeader = headerFactory.createToHeader(toNameAddress, null);
52 |
53 | SipURI requestURI = addressFactory.createSipURI(getToUsername(), getToHost()
54 | + ":" + getToPort());
55 | requestURI.setTransportParam("udp");
56 |
57 | ArrayList viaHeaders = new ArrayList();
58 | ViaHeader viaHeader = headerFactory.createViaHeader(getFromHost(),
59 | getFromPort(), "udp", null);
60 | viaHeaders.add(viaHeader);
61 |
62 | CSeqHeader cSeqHeader = headerFactory.createCSeqHeader(1L, message);
63 |
64 | MaxForwardsHeader maxForwards = headerFactory
65 | .createMaxForwardsHeader(70);
66 | request = messageFactory.createRequest(requestURI,
67 | message, callIdHeader, cSeqHeader, fromHeader,
68 | toHeader, viaHeaders, maxForwards);
69 |
70 | SipURI contactURI = addressFactory.createSipURI(getFromUsername(),
71 | getFromHost());
72 | contactURI.setPort(getFromPort());
73 | Address contactAddress = addressFactory.createAddress(contactURI);
74 | contactAddress.setDisplayName(getFromUsername());
75 | ContactHeader contactHeader = headerFactory
76 | .createContactHeader(contactAddress);
77 | request.addHeader(contactHeader);
78 | }
79 | catch (Exception e)
80 | {
81 | logger.error("Error initializing stack: ", e);
82 | return false;
83 | }
84 | return true;
85 | }
86 |
87 | public final Request getRequest() {
88 | return request;
89 | }
90 |
91 | public final String getFrom()
92 | {
93 | FromHeader header = (FromHeader) request.getHeader(FromHeader.NAME);
94 | if (header == null)
95 | return "null";
96 | return header.getAddress().toString();
97 | }
98 |
99 | public final String getTo()
100 | {
101 | ToHeader header = (ToHeader) request.getHeader(ToHeader.NAME);
102 | if (header == null)
103 | return "null";
104 | return header.getAddress().toString();
105 | }
106 |
107 | public final String getCallId()
108 | {
109 | CallIdHeader header = (CallIdHeader) request.getHeader(CallIdHeader.NAME);
110 | if (header == null)
111 | return "null";
112 | return header.getCallId();
113 | }
114 |
115 | public final SIPMessage getMessage() {
116 | return (SIPMessage)request;
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/message/ResponseMessage.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.message;
2 |
3 | import gov.nist.javax.sip.message.SIPMessage;
4 | import gov.nist.javax.sip.message.SIPResponse;
5 |
6 | import javax.sip.header.CallIdHeader;
7 | import javax.sip.header.ToHeader;
8 | import javax.sip.message.Request;
9 | import javax.sip.message.Response;
10 |
11 | public class ResponseMessage extends SipMessage {
12 | protected Response response;
13 | private Request request;
14 |
15 | protected ResponseMessage(int type, Response response)
16 | {
17 | super(type);
18 | this.response = response;
19 | }
20 |
21 | public ResponseMessage(Request request) {
22 | super(Message.SUCCESS);
23 | try {
24 | this.request = request;
25 | response = messageFactory.createResponse(200, request);
26 | ToHeader toHeader = (ToHeader)response.getHeader(ToHeader.NAME);
27 | toHeader.setTag("888");
28 | } catch (Exception e) {
29 | e.printStackTrace();
30 | }
31 | }
32 |
33 | public ResponseMessage(int type) {
34 | super(type);
35 | response = new SIPResponse();
36 | }
37 |
38 | public Response getResponse() {
39 | return response;
40 | }
41 |
42 | public Request getRequest() {
43 | return request;
44 | }
45 |
46 | public final String getCallId()
47 | {
48 | CallIdHeader header = (CallIdHeader) response.getHeader(CallIdHeader.NAME);
49 | if (header == null)
50 | return "null";
51 | return header.getCallId();
52 | }
53 |
54 | public final SIPMessage getMessage() {
55 | return (SIPMessage)response;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/message/RtpPacket.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.message;
2 |
3 |
4 | public class RtpPacket extends Message {
5 | private String sourceMacAddress;
6 | private String sourceIPAddress;
7 | private int sourcePort;
8 | private String destinationMacAddress;
9 | private String destinationIPAddress;
10 | private int destinationPort;
11 | private int sequenceNumber;
12 | private int timeStamp;
13 | private int arrival;
14 |
15 | public RtpPacket(String value) {
16 | super(Message.RTP_PACKET);
17 | String[] fields = value.split(";");
18 | if (fields.length < 9) {
19 | logger.error("Failed to parse content");
20 | return;
21 | }
22 | sourceMacAddress = fields[0];
23 | sourceIPAddress = fields[1];
24 | sourcePort = Integer.parseInt(fields[2]);
25 | destinationMacAddress = fields[3];
26 | destinationIPAddress = fields[4];
27 | destinationPort = Integer.parseInt(fields[5]);
28 | sequenceNumber = Integer.parseInt(fields[6]) & 0xFFFF;
29 | timeStamp = Integer.parseInt(fields[7]);
30 | arrival = Integer.parseInt(fields[8]);
31 | }
32 |
33 | public String getSource() {
34 | return sourceIPAddress + ":" + sourcePort;
35 | }
36 |
37 | public String getDestination() {
38 | return destinationIPAddress + ":" + destinationPort;
39 | }
40 |
41 | public String toString() {
42 | return "RtpPacket(" + getSource() + "," + getDestination() + ")";
43 | }
44 |
45 | public String getSourceMac() {
46 | return sourceMacAddress;
47 | }
48 |
49 | public String getDestinationMac() {
50 | return destinationMacAddress;
51 | }
52 |
53 | public int getSequenceNumber() {
54 | return sequenceNumber;
55 | }
56 |
57 | public int getTimeStamp() {
58 | return timeStamp;
59 | }
60 |
61 | public int getArrival() {
62 | return arrival;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/message/SipMessage.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.message;
2 |
3 | import gov.nist.javax.sdp.MediaDescriptionImpl;
4 | import gov.nist.javax.sdp.fields.AttributeField;
5 | import gov.nist.javax.sdp.fields.MediaField;
6 | import gov.nist.javax.sip.message.SIPMessage;
7 |
8 | import java.util.ArrayList;
9 | import java.util.Iterator;
10 | import java.util.Vector;
11 |
12 | import javax.sdp.SdpFactory;
13 | import javax.sdp.SessionDescription;
14 | import javax.sip.SipFactory;
15 | import javax.sip.address.AddressFactory;
16 | import javax.sip.header.CallIdHeader;
17 | import javax.sip.header.ContentTypeHeader;
18 | import javax.sip.header.HeaderFactory;
19 | import javax.sip.message.MessageFactory;
20 |
21 | import com.tt.reaper.Configuration;
22 | import com.tt.reaper.call.AudioData;
23 | import com.tt.reaper.sip.CollectorStack;
24 |
25 | public abstract class SipMessage extends Message {
26 | protected static AddressFactory addressFactory;
27 | protected static HeaderFactory headerFactory;
28 | protected static MessageFactory messageFactory;
29 | protected static SdpFactory sdpFactory;
30 | private static int fromPort;
31 | private static String fromHost;
32 | private static String fromUsername;
33 | private static String toHost;
34 | private static String toPort;
35 | private static String toUsername;
36 | private static String softwareVersion;
37 |
38 | protected SipMessage(int type)
39 | {
40 | super(type);
41 | }
42 |
43 | public static boolean initFactory(SipFactory sipFactory, Configuration configuration)
44 | {
45 | try {
46 | headerFactory = sipFactory.createHeaderFactory();
47 | addressFactory = sipFactory.createAddressFactory();
48 | messageFactory = sipFactory.createMessageFactory();
49 | sdpFactory = SdpFactory.getInstance();
50 | fromPort = configuration.getWritePort();
51 | fromHost = configuration.getWriteInterface();
52 | fromUsername = configuration.getWriteUsername();
53 | toHost = configuration.getCollectorHost();
54 | toPort = "" + configuration.getCollectorPort();
55 | toUsername = configuration.getCollectorUsername();
56 | softwareVersion = configuration.getSoftwareVersion();
57 | return true;
58 | }
59 | catch (Exception e)
60 | {
61 | logger.error("Error initializing stack: ", e);
62 | }
63 | return false;
64 | }
65 |
66 | void setSdp(String sdpContent) {
67 | try {
68 | ContentTypeHeader contentTypeHeader;
69 | contentTypeHeader = headerFactory
70 | .createContentTypeHeader("application", "sdp");
71 | getMessage().setContent(sdpContent, contentTypeHeader);
72 | }
73 | catch (Exception e)
74 | {
75 | e.printStackTrace();
76 | }
77 | }
78 |
79 | protected static CallIdHeader getNewCallId() {
80 | return CollectorStack.instance.getNewCallId();
81 | }
82 |
83 | protected final int getFromPort() {
84 | return fromPort;
85 | }
86 |
87 | protected final String getFromHost() {
88 | return fromHost;
89 | }
90 |
91 | protected final String getFromUsername() {
92 | return fromUsername;
93 | }
94 |
95 | protected final String getToHost() {
96 | return toHost;
97 | }
98 |
99 | protected final String getToPort() {
100 | return toPort;
101 | }
102 |
103 | protected final String getToUsername() {
104 | return toUsername;
105 | }
106 |
107 | protected final String getSoftwareVersion() {
108 | return softwareVersion;
109 | }
110 |
111 | public abstract String getCallId();
112 | public abstract SIPMessage getMessage();
113 |
114 | @SuppressWarnings("unchecked")
115 | public final ArrayList getAudioData()
116 | {
117 | if (getMessage().getRawContent() == null)
118 | return null;
119 | ArrayList list = new ArrayList();
120 | String content = new String(getMessage().getRawContent());
121 | logger.debug("content=<" + content + ">");
122 | try {
123 | SessionDescription sdp = sdpFactory.createSessionDescription(content);
124 | String ipAddy = sdp.getConnection().getAddress();
125 | Vector descriptors = (Vector)sdp.getMediaDescriptions(true);
126 | Iterator it = descriptors.iterator();
127 | while (it.hasNext()) {
128 | MediaDescriptionImpl mediaDescription = it.next();
129 | MediaField field = mediaDescription.getMediaField();
130 | if (field == null) {
131 | logger.warn("Missing media field");
132 | continue;
133 | }
134 | AudioData audio = new AudioData();
135 | audio.ipAddy = ipAddy;
136 | audio.rtpPort = field.getPort();
137 | Vector formats = field.getFormats();
138 | if (formats == null) {
139 | list.add(audio);
140 | continue;
141 | }
142 | if (formats.size() < 1) {
143 | list.add(audio);
144 | continue;
145 | }
146 | audio.payloadType = (String) field.getFormats().get(0);
147 |
148 | Vector attributes = mediaDescription.getAttributeFields();
149 | if (attributes == null) {
150 | list.add(audio);
151 | continue;
152 | }
153 | Iterator ait = attributes.iterator();
154 | while (ait.hasNext()) {
155 | Object objay = ait.next();
156 | if (! (objay instanceof AttributeField))
157 | continue;
158 | AttributeField afield = (AttributeField)objay;
159 | if (! "rtpmap".equals(afield.getName()))
160 | continue;
161 | String [] parsed = afield.getValue().split("[ /]");
162 | if (parsed.length < 3)
163 | continue;
164 | if (! parsed[0].equals(audio.payloadType))
165 | continue;
166 | audio.payloadDescription = parsed[1];
167 | audio.sampleRate = parsed[2];
168 | }
169 | list.add(audio);
170 | logger.info(getCallId() + " audio=" + audio.toString());
171 | }
172 | return list;
173 | } catch (Exception e) {
174 | e.printStackTrace();
175 | }
176 | return list;
177 | }
178 | }
179 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/message/SuccessMessage.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.message;
2 |
3 | import javax.sip.message.Response;
4 |
5 | public class SuccessMessage extends ResponseMessage {
6 | private SuccessMessage(Response response)
7 | {
8 | super(Message.SUCCESS, response);
9 | }
10 |
11 | static SipMessage create(Response response)
12 | {
13 | int status = response.getStatusCode();
14 | if ((status >= 200) && (status < 300)) {
15 | return new SuccessMessage(response);
16 | }
17 | return null;
18 | }
19 |
20 | public Response getResponse()
21 | {
22 | return response;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/rtcp/DataPacket.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.rtcp;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Iterator;
5 |
6 | import com.tt.reaper.message.Message;
7 |
8 | public class DataPacket extends Message {
9 | private String sourceMacAddress;
10 | private String sourceIPAddress;
11 | private int sourcePort;
12 | private String destinationMacAddress;
13 | private String destinationIPAddress;
14 | private int destinationPort;
15 | private ArrayList list = new ArrayList();
16 |
17 | public DataPacket(byte[] content) {
18 | super(Message.DATA_PACKET);
19 | if (content == null)
20 | return;
21 | String header = new String(content);
22 | String[] fields = header.split(";");
23 | if (fields.length < 6) {
24 | logger.error("Failed to parse content");
25 | return;
26 | }
27 | sourceMacAddress = fields[0];
28 | sourceIPAddress = fields[1];
29 | sourcePort = Integer.parseInt(fields[2]);
30 | destinationMacAddress = fields[3];
31 | destinationIPAddress = fields[4];
32 | destinationPort = Integer.parseInt(fields[5]);
33 |
34 | String encodedData = fields[6];
35 | byte[] rtcpPacket = new byte[encodedData.length()/2];
36 | int index = 0;
37 | for (int j=0; j getIterator() {
72 | return list.iterator();
73 | }
74 |
75 | public String getSource() {
76 | return sourceIPAddress + ":" + sourcePort;
77 | }
78 |
79 | public String getDestination() {
80 | return destinationIPAddress + ":" + destinationPort;
81 | }
82 |
83 | public String toString() {
84 | return "DataPacket(" + getSource() + "," + getDestination() + ")";
85 | }
86 |
87 | public String getSourceMac() {
88 | return sourceMacAddress;
89 | }
90 |
91 | public String getDestinationMac() {
92 | return destinationMacAddress;
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/rtcp/ExtendedReportBlock.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.rtcp;
2 |
3 | public class ExtendedReportBlock {
4 | public static final int LOSS_RLE = 1;
5 | public static final int DUPLICATE_RLE = 2;
6 | public static final int PACKET_RECEIPT_TIMES = 3;
7 | public static final int RECEIVER_REFERENCE_TIME = 4;
8 | public static final int DLRR = 5;
9 | public static final int STATISTICS_SUMMARY = 6;
10 | public static final int VOIP_METRICS = 7;
11 | public static final int HEADER_LENGTH = 4;
12 |
13 | protected byte [] data;
14 | protected int offset;
15 |
16 | public ExtendedReportBlock(byte[] data, int offset) {
17 | this.data = data;
18 | this.offset = offset;
19 | }
20 |
21 | static int probeBlockType(byte[] data, int offset) {
22 | return (data[offset + 0] & 0xFF);
23 | }
24 |
25 | public int getBlockType()
26 | {
27 | return data[offset + 0] & 0xFF;
28 | }
29 |
30 | public int getTypeSpecific()
31 | {
32 | return data[offset + 1] & 0xFF;
33 | }
34 |
35 | public int getBlockLength()
36 | {
37 | return (RtcpPacket.getInt(data, offset) & 0xFFFF) * 4;
38 | }
39 |
40 | public int getLength() {
41 | return getBlockLength() + HEADER_LENGTH;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/rtcp/ReportBlock.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.rtcp;
2 |
3 | public class ReportBlock {
4 | private byte [] data;
5 | private int start;
6 |
7 | public ReportBlock(byte [] data, int start)
8 | {
9 | this.data = data;
10 | this.start = start;
11 | }
12 |
13 | public int getSSRC() {
14 | return RtcpPacket.getInt(data, start + 0);
15 | }
16 |
17 | public int getFractionLost() {
18 | return data[start + 4];
19 | }
20 |
21 | public int getCumulativeLost() {
22 | return (RtcpPacket.getInt(data, start + 4) & 0xFFFFFF);
23 | }
24 |
25 | public int getExtendedHighestSequenceReceived() {
26 | return RtcpPacket.getInt(data, start + 8);
27 | }
28 |
29 | public int getJitter()
30 | {
31 | return RtcpPacket.getInt(data, start + 12);
32 | }
33 |
34 | public int getLastReport() {
35 | return RtcpPacket.getInt(data, start + 16);
36 | }
37 |
38 | public int getDelaySinceLastReport() {
39 | return RtcpPacket.getInt(data, start + 20);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/rtcp/RtcpExtendedReport.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.rtcp;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Iterator;
5 |
6 | public class RtcpExtendedReport extends RtcpPacket {
7 | private static final int HEADER_LENGTH = 8;
8 | private ArrayList list = new ArrayList();
9 |
10 | public RtcpExtendedReport(byte[] data, int offset) {
11 | super(data, offset);
12 | int start = offset + HEADER_LENGTH;
13 | int end = offset + getLength();
14 | while (start < end) {
15 | ExtendedReportBlock block = null;
16 | switch (ExtendedReportBlock.probeBlockType(data, start)) {
17 | case ExtendedReportBlock.VOIP_METRICS:
18 | block = new VoipMetricsExtendedReportBlock(data, start);
19 | list.add((VoipMetricsExtendedReportBlock) block);
20 | break;
21 | default:
22 | logger.info("Ignoring RTCP-XR: " + ExtendedReportBlock.probeBlockType(data, start));
23 | block = new ExtendedReportBlock(data, start);
24 | break;
25 | }
26 | start += block.getLength();
27 | }
28 | }
29 |
30 | public int getSSRC()
31 | {
32 | return getInt(data, offset + 4);
33 | }
34 |
35 | public Iterator getIterator() {
36 | return list.iterator();
37 | }
38 | }
--------------------------------------------------------------------------------
/src/com/tt/reaper/rtcp/RtcpPacket.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.rtcp;
2 |
3 | import org.apache.log4j.Logger;
4 |
5 | public class RtcpPacket {
6 | protected static Logger logger = Logger.getLogger(RtcpPacket.class);
7 | public static final int HEADER_SIZE = 8;
8 | public static final int SENDER_INFO_SIZE = 20;
9 | public static final int REPORT_SIZE = 24;
10 | public static final int TYPE_SENDER_REPORT = 0xC8;
11 | public static final int TYPE_RECEIVER_REPORT = 0xC9;
12 | public static final int TYPE_SOURCE_DESCRIPTION = 0xCA;
13 | public static final int TYPE_GOODBYE = 0xCB;
14 | public static final int TYPE_APPLICATION_DEFINED = 0xCC;
15 | public static final int TYPE_EXTENDED_REPORT = 0xCF;
16 |
17 | protected byte[] data;
18 | protected int offset;
19 |
20 | RtcpPacket(byte[] data, int offset) {
21 | this.data = data;
22 | this.offset = offset;
23 | }
24 |
25 | static int probePacketType(byte[] data, int offset) {
26 | return (data[offset + 1] & 0xFF);
27 | }
28 |
29 | static int getInt(byte[] data, int offset) {
30 | long value;
31 | value = data[offset++] & 0xFF;
32 | value <<= 8;
33 | value |= data[offset++] & 0xFF;
34 | value <<= 8;
35 | value |= data[offset++] & 0xFF;
36 | value <<= 8;
37 | value |= data[offset++] & 0xFF;
38 | return (int)value;
39 | }
40 |
41 | public int getVersion() {
42 | return (data[offset + 0] >> 6) & 0x03;
43 | }
44 |
45 | public int getCount() {
46 | return (data[offset + 0] & 0x1F);
47 | }
48 |
49 | public int getPacketType() {
50 | return (data[offset + 1] & 0xFF);
51 | }
52 |
53 | public int getLength()
54 | {
55 | return (((data[offset + 2] << 8) | data[offset + 3]) + 1) * 4;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/rtcp/RtcpReceiverReport.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.rtcp;
2 |
3 | public class RtcpReceiverReport extends RtcpPacket {
4 |
5 | public RtcpReceiverReport(byte[] data, int offset) {
6 | super(data, offset);
7 | }
8 |
9 | public int getSSRC()
10 | {
11 | return getInt(data, offset + 4);
12 | }
13 |
14 | public ReportBlock getReport(int number)
15 | {
16 | return new ReportBlock(data, ((offset + HEADER_SIZE) + (number * REPORT_SIZE)));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/rtcp/RtcpSenderReport.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.rtcp;
2 |
3 |
4 | public class RtcpSenderReport extends RtcpPacket {
5 |
6 | public RtcpSenderReport(byte[] data, int offset) {
7 | super(data, offset);
8 | }
9 |
10 | public int getSSRC()
11 | {
12 | return getInt(data, offset + 4);
13 | }
14 |
15 | public long getTimeStamp() {
16 | int start = offset + 8;
17 | long value;
18 | value = data[start++] & 0xFF;
19 | value <<= 8;
20 | value |= data[start++] & 0xFF;
21 | value <<= 8;
22 | value |= data[start++] & 0xFF;
23 | value <<= 8;
24 | value |= data[start++] & 0xFF;
25 | value <<= 8;
26 | value |= data[start++] & 0xFF;
27 | value <<= 8;
28 | value |= data[start++] & 0xFF;
29 | value <<= 8;
30 | value |= data[start++] & 0xFF;
31 | value <<= 8;
32 | value |= data[start++] & 0xFF;
33 | return value;
34 | }
35 |
36 | public int getRTPTimeStamp()
37 | {
38 | return getInt(data, offset + 16);
39 | }
40 |
41 | public int getSenderPacketCount()
42 | {
43 | return getInt(data, offset + 20);
44 | }
45 |
46 | public int getSenderOctetCount()
47 | {
48 | return getInt(data, offset + 24);
49 | }
50 |
51 | public ReportBlock getReport(int number)
52 | {
53 | return new ReportBlock(data, ((offset + HEADER_SIZE + SENDER_INFO_SIZE) + (number * REPORT_SIZE)));
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/rtcp/RtcpSourceDescription.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.rtcp;
2 |
3 | public class RtcpSourceDescription extends RtcpPacket {
4 |
5 | public RtcpSourceDescription(byte[] data, int offset) {
6 | super(data, offset);
7 | }
8 | }
--------------------------------------------------------------------------------
/src/com/tt/reaper/rtcp/VoipMetricsExtendedReportBlock.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.rtcp;
2 |
3 | public class VoipMetricsExtendedReportBlock extends ExtendedReportBlock {
4 |
5 | public VoipMetricsExtendedReportBlock(byte[] data, int offset) {
6 | super(data, offset);
7 | }
8 |
9 | public double getLossRate()
10 | {
11 | return ((double)(data[offset + 8] & 0xFF)) / 256.0;
12 | }
13 |
14 | public double getDiscardRate()
15 | {
16 | return ((double)(data[offset + 9] & 0xFF)) / 256.0;
17 | }
18 |
19 | public double getBurstDensity()
20 | {
21 | return ((double)(data[offset + 10] & 0xFF)) / 256.0;
22 | }
23 |
24 | public double getGapDensity()
25 | {
26 | return ((double)(data[offset + 11] & 0xFF)) / 256.0;
27 | }
28 |
29 | public int getBurstDuration()
30 | {
31 | return ((RtcpPacket.getInt(data, offset + 12) >> 16) & 0xFFFF);
32 | }
33 |
34 | public int getGapDuration()
35 | {
36 | return (RtcpPacket.getInt(data, offset + 12) & 0xFFFF);
37 | }
38 |
39 | public int getRoundTripDelay()
40 | {
41 | return ((RtcpPacket.getInt(data, offset + 16) >> 16) & 0xFFFF);
42 | }
43 |
44 | public int getEndSystemDelay()
45 | {
46 | return (RtcpPacket.getInt(data, offset + 16) & 0xFFFF);
47 | }
48 |
49 | public int getSignalLevel()
50 | {
51 | return data[offset + 20];
52 | }
53 |
54 | public int getNoiseLevel()
55 | {
56 | return data[offset + 21];
57 | }
58 |
59 | public int getResidualEchoReturnLoss()
60 | {
61 | return data[offset + 22] & 0xFF;
62 | }
63 |
64 | public int getGmin()
65 | {
66 | return data[offset + 23] & 0xFF;
67 | }
68 |
69 | public int getRFactor()
70 | {
71 | return data[offset + 24] & 0xFF;
72 | }
73 |
74 | public int getExtRFactor()
75 | {
76 | return data[offset + 25] & 0xFF;
77 | }
78 |
79 | public double getMOSLQ()
80 | {
81 | return ((double)(data[offset + 26] & 0xFF)) / 10.0;
82 | }
83 |
84 | public double getMOSCQ()
85 | {
86 | return ((double)(data[offset + 27] & 0xFF)) / 10.0;
87 | }
88 |
89 | private int getRxConfig()
90 | {
91 | return data[offset + 28] & 0xFF;
92 | }
93 |
94 | public int getPacketLossConcealment()
95 | {
96 | return (getRxConfig() >> 6) & 0x03;
97 | }
98 |
99 | public int getJitterBufferAdaptive()
100 | {
101 | return (getRxConfig() >> 4) & 0x03;
102 | }
103 |
104 | public int getJitterBufferRate()
105 | {
106 | return getRxConfig() & 0x0F;
107 | }
108 |
109 | public int getJitterBufferNominal()
110 | {
111 | return (RtcpPacket.getInt(data, offset + 28) & 0xFFFF);
112 | }
113 |
114 | public int getJitterBufferMaximum()
115 | {
116 | return ((RtcpPacket.getInt(data, offset + 32) >> 16) & 0xFFFF);
117 | }
118 |
119 | public int getJitterBufferAbsMaximum()
120 | {
121 | return (RtcpPacket.getInt(data, offset + 32) & 0xFFFF);
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/sip/CollectorListener.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.sip;
2 |
3 | import javax.sip.DialogTerminatedEvent;
4 | import javax.sip.IOExceptionEvent;
5 | import javax.sip.RequestEvent;
6 | import javax.sip.ResponseEvent;
7 | import javax.sip.SipListener;
8 | import javax.sip.TimeoutEvent;
9 | import javax.sip.TransactionTerminatedEvent;
10 |
11 | import org.apache.log4j.Logger;
12 |
13 | import com.tt.reaper.CollectorManager;
14 | import com.tt.reaper.message.MessageFactory;
15 | import com.tt.reaper.message.SipMessage;
16 |
17 | class CollectorListener implements SipListener {
18 | private static Logger logger = Logger.getLogger(CollectorListener.class);
19 | private MessageFactory factory = new MessageFactory();
20 |
21 | CollectorListener() {
22 | }
23 |
24 | @Override
25 | public void processDialogTerminated(DialogTerminatedEvent evt) {
26 | logger.info("processDialogTerminated");
27 | }
28 |
29 | @Override
30 | public void processIOException(IOExceptionEvent evt) {
31 | logger.info("processIOException");
32 | }
33 |
34 | @Override
35 | public void processRequest(RequestEvent evt) {
36 | SipMessage message = factory.create(evt.getRequest());
37 | CollectorManager.instance.send(message);
38 | }
39 |
40 | @Override
41 | public void processResponse(ResponseEvent evt) {
42 | SipMessage message = factory.create(evt.getResponse());
43 | CollectorManager.instance.send(message);
44 | }
45 |
46 | @Override
47 | public void processTimeout(TimeoutEvent evt) {
48 | logger.info("processTimeout");
49 | }
50 |
51 | @Override
52 | public void processTransactionTerminated(TransactionTerminatedEvent evt) {
53 | logger.info("processTransactionTerminated");
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/sip/CollectorStack.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.sip;
2 |
3 | import javax.sip.ListeningPoint;
4 | import javax.sip.ServerTransaction;
5 | import javax.sip.SipFactory;
6 | import javax.sip.SipProvider;
7 | import javax.sip.SipStack;
8 | import javax.sip.header.CallIdHeader;
9 |
10 | import org.apache.log4j.Logger;
11 |
12 | import com.tt.reaper.Configuration;
13 | import com.tt.reaper.message.PublishMessage;
14 | import com.tt.reaper.message.RequestMessage;
15 | import com.tt.reaper.message.ResponseMessage;
16 |
17 | public class CollectorStack {
18 | private static final String STACK_NAME = "CollectorStack";
19 | private static Logger logger = Logger.getLogger(CollectorStack.class);
20 | public static CollectorStack instance = new CollectorStack();
21 | private SipProvider collectorProvider;
22 | private static boolean initialized = false;
23 | public String lastSendData;
24 |
25 | private CollectorStack()
26 | {
27 | }
28 |
29 | public synchronized boolean init()
30 | {
31 | if (initialized == true)
32 | return true;
33 | initialized = true;
34 | logger.info("Starting the collector stack...");
35 | try {
36 | SipStack sipStack;
37 | Configuration configuration;
38 | configuration = new Configuration();
39 | configuration.setStackName(STACK_NAME);
40 | SipFactory.getInstance().setPathName("gov.nist");
41 | sipStack = SipFactory.getInstance().createSipStack(configuration);
42 | RequestMessage.initFactory(SipFactory.getInstance(), configuration);
43 | ListeningPoint reaperUdp = sipStack.createListeningPoint(configuration.getWriteInterface(), configuration.getWritePort(), "udp");
44 | collectorProvider = sipStack.createSipProvider(reaperUdp);
45 | collectorProvider.addSipListener(new CollectorListener());
46 | collectorProvider.setAutomaticDialogSupportEnabled(false);
47 | logger.info("Collector SIP stack initialized successfully");
48 | }
49 | catch (Exception e)
50 | {
51 | logger.error("Error initializing stack: ", e);
52 | return false;
53 | }
54 | return true;
55 | }
56 |
57 | public boolean sendResponse(ResponseMessage response) {
58 | try {
59 | ServerTransaction st = collectorProvider.getNewServerTransaction(response.getRequest());
60 | st.sendResponse(response.getResponse());
61 | }
62 | catch (Exception e) {
63 | logger.error("Error sending response: ", e);
64 | }
65 | return true;
66 | }
67 |
68 | public boolean sendMessage(String data) {
69 | lastSendData = data;
70 | try {
71 | PublishMessage publish = new PublishMessage(data);
72 | collectorProvider.sendRequest(publish.getRequest());
73 | }
74 | catch (Exception e)
75 | {
76 | logger.error("Error sending message: ", e);
77 | return false;
78 | }
79 | return true;
80 | }
81 |
82 | public CallIdHeader getNewCallId() {
83 | logger.info("Get new call id: " + collectorProvider);
84 | return collectorProvider.getNewCallId();
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/sip/ReaperListener.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.sip;
2 |
3 | import javax.sip.DialogTerminatedEvent;
4 | import javax.sip.IOExceptionEvent;
5 | import javax.sip.RequestEvent;
6 | import javax.sip.ResponseEvent;
7 | import javax.sip.SipListener;
8 | import javax.sip.TimeoutEvent;
9 | import javax.sip.TransactionTerminatedEvent;
10 |
11 | import org.apache.log4j.Logger;
12 |
13 | import com.tt.reaper.call.CallManager;
14 | import com.tt.reaper.message.MessageFactory;
15 | import com.tt.reaper.message.SipMessage;
16 |
17 | class ReaperListener implements SipListener {
18 | private static Logger logger = Logger.getLogger(ReaperListener.class);
19 | private MessageFactory factory = new MessageFactory();
20 |
21 | ReaperListener()
22 | {
23 | }
24 |
25 | @Override
26 | public void processDialogTerminated(DialogTerminatedEvent evt) {
27 | logger.info("processDialogTerminated");
28 | }
29 |
30 | @Override
31 | public void processIOException(IOExceptionEvent evt) {
32 | logger.info("processIOException");
33 | }
34 |
35 | @Override
36 | public void processRequest(RequestEvent evt) {
37 | logger.debug("ReaperListener processRequest():" + evt.getRequest().getMethod());
38 | SipMessage message = factory.create(evt.getRequest());
39 | if (message != null)
40 | CallManager.instance.send(message);
41 | }
42 |
43 | @Override
44 | public void processResponse(ResponseEvent evt) {
45 | logger.debug("ReaperListener processRequest():" + evt.getResponse().getStatusCode());
46 | SipMessage message = factory.create(evt.getResponse());
47 | if (message != null)
48 | CallManager.instance.send(message);
49 | }
50 |
51 | @Override
52 | public void processTimeout(TimeoutEvent evt) {
53 | logger.info("processTimeout");
54 | }
55 |
56 | @Override
57 | public void processTransactionTerminated(TransactionTerminatedEvent evt) {
58 | logger.info("processTransactionTerminated");
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/sip/ReaperStack.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.sip;
2 |
3 | import javax.sip.ListeningPoint;
4 | import javax.sip.SipFactory;
5 | import javax.sip.SipProvider;
6 | import javax.sip.SipStack;
7 |
8 | import org.apache.log4j.Logger;
9 |
10 | import com.tt.reaper.Configuration;
11 | import com.tt.reaper.message.RequestMessage;
12 |
13 | public class ReaperStack {
14 | private static final String STACK_NAME = "ReaperStack";
15 | private static Logger logger = Logger.getLogger(ReaperStack.class);
16 | public static ReaperStack instance = new ReaperStack();
17 | private SipProvider reaperProvider;
18 | private static boolean initialized = false;
19 |
20 | private ReaperStack()
21 | {
22 | }
23 |
24 | public synchronized boolean init()
25 | {
26 | if (initialized == true)
27 | return true;
28 | initialized = true;
29 | logger.info("Starting the reaper stack...");
30 | try {
31 | SipStack sipStack;
32 | Configuration configuration;
33 | configuration = new Configuration();
34 | configuration.setStackName(STACK_NAME);
35 | SipFactory.getInstance().setPathName("gov.nist");
36 | sipStack = SipFactory.getInstance().createSipStack(configuration);
37 | RequestMessage.initFactory(SipFactory.getInstance(), configuration);
38 | ListeningPoint reaperTcp = sipStack.createListeningPoint("127.0.0.1", configuration.getReadPort(), "tcp");
39 | reaperProvider = sipStack.createSipProvider(reaperTcp);
40 | reaperProvider.addSipListener(new ReaperListener());
41 | reaperProvider.setAutomaticDialogSupportEnabled(false);
42 | logger.info("Reaper SIP stack initialized successfully");
43 | }
44 | catch (Exception e)
45 | {
46 | logger.error("Error initializing stack: ", e);
47 | return false;
48 | }
49 | return true;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/vq/LocalMetrics.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.vq;
2 |
3 | import com.tt.reaper.call.AudioData;
4 | import com.tt.reaper.call.CallContext;
5 |
6 | public class LocalMetrics extends Metrics {
7 | private static final String NAME = "LocalMetrics";
8 |
9 | LocalMetrics()
10 | {
11 | super(NAME);
12 | }
13 |
14 | public LocalMetrics(CallContext context, AudioData data) {
15 | super(NAME, context, data);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/vq/Metrics.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.vq;
2 |
3 | import java.text.SimpleDateFormat;
4 | import java.util.Date;
5 | import java.util.TimeZone;
6 |
7 | import com.tt.reaper.call.AudioData;
8 | import com.tt.reaper.call.CallContext;
9 | import com.tt.reaper.rtcp.ReportBlock;
10 | import com.tt.reaper.rtcp.VoipMetricsExtendedReportBlock;
11 |
12 | public class Metrics {
13 | String metrics;
14 |
15 | protected Metrics(String name)
16 | {
17 | metrics = name + ":\r\n";
18 | }
19 |
20 | protected Metrics(String name, CallContext context, AudioData data) {
21 | metrics = name + ":\r\n";
22 | if (data.from) {
23 | context.endTime = new Date();
24 | setSessionDescription(data.payloadType, data.payloadDescription, data.sampleRate);
25 | setTimeStamps(context.startTime, context.endTime);
26 | setCallID(context.callId);
27 | setFromID(context.from);
28 | setToID(context.to);
29 | setOrigID(context.from);
30 | setLocalAddr(context.from);
31 | setLocalMac(context.fromMac);
32 | setRemoteAddr(context.to);
33 | setRemoteMac(context.toMac);
34 | }
35 | else {
36 | if (context.endTime == null)
37 | context.endTime = new Date();
38 | setSessionDescription(data.payloadType, data.payloadDescription, data.sampleRate);
39 | setTimeStamps(context.startTime, context.endTime);
40 | setCallID(context.callId);
41 | setFromID(context.from);
42 | setToID(context.to);
43 | setOrigID(context.from);
44 | setLocalAddr(context.to);
45 | setLocalMac(context.toMac);
46 | setRemoteAddr(context.from);
47 | setRemoteMac(context.fromMac);
48 | }
49 | }
50 | public static String formatDate(Date date) {
51 | SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'");
52 | dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
53 | return dateFormat.format(date);
54 | }
55 |
56 | public void setSessionDescription(String type, String description, String sample) {
57 | if ((type == null) && (description == null) && (sample == null))
58 | return;
59 | metrics += "SessionDesc:";
60 | if (type != null)
61 | metrics += "PT=" + type;
62 | if (description != null)
63 | metrics += " PD=" + description;
64 | if (sample != null)
65 | metrics += " SR="+ sample;
66 | metrics += "\r\n";
67 | }
68 |
69 | public void setTimeStamps(Date startTime, Date endTime) {
70 | metrics += "Timestamps:START=" + formatDate(startTime) + " STOP=" + formatDate(endTime) + "\r\n";
71 | }
72 |
73 | public void setCallID(String value)
74 | {
75 | if (value == null)
76 | return;
77 | metrics += "CallID:" + value + "\r\n";
78 | }
79 |
80 | public void setFromID(String value)
81 | {
82 | if (value == null)
83 | return;
84 | metrics += "FromID:" + value + "\r\n";
85 | }
86 |
87 | public void setToID(String value)
88 | {
89 | if (value == null)
90 | return;
91 | metrics += "ToID:" + value + "\r\n";
92 | }
93 |
94 | public void setOrigID(String value)
95 | {
96 | if (value == null)
97 | return;
98 | metrics += "OrigID:" + value + "\r\n";
99 | }
100 |
101 | public void setLocalAddr(String value)
102 | {
103 | if (value == null)
104 | return;
105 | metrics += "LocalAddr:" + value + "\r\n";
106 | }
107 |
108 | public void setLocalMac(String value) {
109 | if (value == null)
110 | return;
111 | metrics += "LocalMAC:" + value + "\r\n";
112 | }
113 |
114 | public void setRemoteAddr(String value)
115 | {
116 | if (value == null)
117 | return;
118 | metrics += "RemoteAddr:" + value + "\r\n";
119 | }
120 |
121 | public void setRemoteMac(String value) {
122 | if (value == null)
123 | return;
124 | metrics += "RemoteMAC:" + value + "\r\n";
125 | }
126 |
127 | private String addAttribute(String result, String name, int value)
128 | {
129 | if (! result.isEmpty())
130 | result += " ";
131 | result += name + "=" + value;
132 | return result;
133 | }
134 |
135 | private String addAttribute(String result, String name, double value)
136 | {
137 | if (! result.isEmpty())
138 | result += " ";
139 | result += name + String.format("=%.1f", value);
140 | return result;
141 | }
142 |
143 | public void setJitterBuffer(int adaptive, int rate, int nominal, int max, int absMax) {
144 | metrics += String.format("JitterBuffer:JBA=%d JBR=%d JBN=%d JBM=%d JBX=%d\r\n", adaptive, rate, nominal, max, absMax);
145 | }
146 |
147 | public void setPacketLoss(double lossRate, double discardRate)
148 | {
149 | metrics += String.format("PacketLoss:NLR=%.1f JDR=%.1f\r\n", lossRate, discardRate);
150 | }
151 |
152 | public void setPacketLoss(double lossRate)
153 | {
154 | metrics += String.format("PacketLoss:NLR=%.1f\r\n", lossRate);
155 | }
156 |
157 | public void setBurstGapLoss(double burstDensity, int burstDuration, double gapDensity, int gapDuration, int gmin)
158 | {
159 | metrics += String.format("BurstGapLoss:BLD=%.1f BD=%d GLD=%.1f GD=%d GMIN=%d\r\n", burstDensity, burstDuration, gapDensity, gapDuration, gmin);
160 | }
161 |
162 | public void setDelay(int roundTrip, int endSystem, int symmOneWay, int interarrivalJitter, int meanAbsJitter)
163 | {
164 | metrics += String.format("Delay:RTD=%d ESD=%d SOWD=%d IAJ=%d MAJ=%d\r\n", roundTrip, endSystem, symmOneWay, interarrivalJitter, meanAbsJitter);
165 | }
166 |
167 | public void setDelay(int interarrivalJitter)
168 | {
169 | metrics += String.format("Delay:IAJ=%d\r\n", interarrivalJitter);
170 | }
171 |
172 | public void setDelay(int roundTrip, int endSystem)
173 | {
174 | metrics += String.format("Delay:RTD=%d ESD=%d\r\n", roundTrip, endSystem);
175 | }
176 |
177 | public void setSignal(int signal, int noise, int rerl) {
178 | metrics += String.format("Signal:SL=%d NL=%d RERL=%d\r\n", signal, noise, rerl);
179 | }
180 |
181 | public void setQualityEst(int rlq, int rcq, int extri, double moslq, double moscq, boolean usedP564) {
182 | metrics += String.format("QualityEst:RLQ=%d RCQ=%d EXTRI=%d MOSLQ=%.1f MOSCQ=%.1f QoEEstAlg=%s\r\n", rlq, rcq, extri, moslq, moscq, (usedP564?"P.564":"other"));
183 | }
184 |
185 | public void setQualityEst(int rcq, int extri, double moslq, double moscq) {
186 | String result = new String();
187 | if ((rcq < 127) && (rcq >= 0))
188 | result = addAttribute(result, "RCQ", rcq);
189 | if ((extri < 127) && (extri >= 0))
190 | result = addAttribute(result, "EXTRI", extri);
191 | if ((moslq <= 5.0) && (moslq > 0))
192 | result = addAttribute(result, "MOSLQ", moslq);
193 | if ((moscq <= 5.0) && (moscq > 0))
194 | result = addAttribute(result, "MOSCQ", moscq);
195 | if (! result.isEmpty())
196 | metrics += "QualityEst:" + result + "\r\n";
197 | }
198 |
199 | public void setMetrics(VoipMetricsExtendedReportBlock b)
200 | {
201 | setJitterBuffer(b.getJitterBufferAdaptive(), b.getJitterBufferRate(), b.getJitterBufferNominal(), b.getJitterBufferMaximum(), b.getJitterBufferAbsMaximum());
202 | setPacketLoss(b.getLossRate(), b.getDiscardRate());
203 | setBurstGapLoss(b.getBurstDensity(), b.getBurstDuration(), b.getGapDensity(), b.getGapDuration(), b.getGmin());
204 | setDelay(b.getRoundTripDelay(), b.getEndSystemDelay());
205 | setSignal(b.getSignalLevel(), b.getNoiseLevel(), b.getResidualEchoReturnLoss());
206 | setQualityEst(b.getRFactor(), b.getExtRFactor(), b.getMOSLQ(), b.getMOSCQ());
207 | }
208 |
209 |
210 | public void setMetrics(ReportBlock report) {
211 | report.getCumulativeLost();
212 | setPacketLoss(report.getFractionLost());
213 | setDelay(report.getJitter());
214 | }
215 |
216 | public String toString()
217 | {
218 | return metrics;
219 | }
220 | }
221 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/vq/RemoteMetrics.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.vq;
2 |
3 | import com.tt.reaper.call.AudioData;
4 | import com.tt.reaper.call.CallContext;
5 |
6 | public class RemoteMetrics extends Metrics {
7 | private static final String NAME = "RemoteMetrics";
8 |
9 | RemoteMetrics()
10 | {
11 | super(NAME);
12 | }
13 |
14 | public RemoteMetrics(CallContext context, AudioData data) {
15 | super(NAME, context, data);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/vq/VQIntervalReport.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.vq;
2 |
3 | public class VQIntervalReport extends VQReportEvent {
4 | private static final String HEADER = "VQIntervalReport\r\n";
5 |
6 | public VQIntervalReport(LocalMetrics localMetrics) {
7 | super(HEADER, localMetrics);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/vq/VQReportEvent.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.vq;
2 |
3 |
4 | class VQReportEvent {
5 | String header;
6 | private LocalMetrics localMetrics;
7 | private RemoteMetrics remoteMetrics;
8 |
9 | protected VQReportEvent(String header, LocalMetrics localMetrics) {
10 | this.header = header;
11 | this.localMetrics = localMetrics;
12 | }
13 |
14 | public void setRemoteMetrics(RemoteMetrics remoteMetrics) {
15 | this.remoteMetrics = remoteMetrics;
16 | }
17 |
18 | public String toString()
19 | {
20 | String message = header;
21 | message += localMetrics;
22 | if (remoteMetrics != null)
23 | message += remoteMetrics;
24 | return message;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/com/tt/reaper/vq/VQSessionReport.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.vq;
2 |
3 | public class VQSessionReport extends VQReportEvent {
4 | private static final String HEADER = "VQSessionReport : CallTerm\r\n";
5 |
6 | public VQSessionReport(LocalMetrics localMetrics) {
7 | super(HEADER, localMetrics);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/tcmpdump/README:
--------------------------------------------------------------------------------
1 | This patched version of tcpdump was built with 4.1.1. Download tcpdump-4.1.1
2 | and cd to the main source directory. Apply the patch file:
3 |
4 | patch -p1 -i patch.txt
5 |
6 |
--------------------------------------------------------------------------------
/tcmpdump/patch.txt:
--------------------------------------------------------------------------------
1 | diff -Naur tcpdump-4.1.1/Makefile.in tcpdump-reaper/Makefile.in
2 | --- tcpdump-4.1.1/Makefile.in 2010-11-16 07:43:33.000000000 -0700
3 | +++ tcpdump-reaper/Makefile.in 2010-11-16 08:11:21.000000000 -0700
4 | @@ -90,6 +90,7 @@
5 | print-symantec.c print-syslog.c print-tcp.c print-telnet.c print-tftp.c \
6 | print-timed.c print-token.c print-udld.c print-udp.c print-usb.c \
7 | print-vjc.c print-vqp.c print-vrrp.c print-vtp.c print-forces.c \
8 | + reaper.c \
9 | print-wb.c print-zephyr.c signature.c setsignal.c tcpdump.c util.c
10 |
11 | LIBNETDISSECT_SRC=print-isakmp.c
12 | diff -Naur tcpdump-4.1.1/print-ether.c tcpdump-reaper/print-ether.c
13 | --- tcpdump-4.1.1/print-ether.c 2010-11-16 07:43:33.000000000 -0700
14 | +++ tcpdump-reaper/print-ether.c 2010-11-16 08:16:30.000000000 -0700
15 | @@ -38,6 +38,7 @@
16 | #include "ethertype.h"
17 |
18 | #include "ether.h"
19 | +#include "reaper.h"
20 |
21 | const struct tok ethertype_values[] = {
22 | { ETHERTYPE_IP, "IPv4" },
23 | @@ -94,6 +95,8 @@
24 | (void)printf("%s > %s",
25 | etheraddr_string(ESRC(ep)),
26 | etheraddr_string(EDST(ep)));
27 | + reaper_set_source_mac(etheraddr_string(ESRC(ep)));
28 | + reaper_set_destination_mac(etheraddr_string(EDST(ep)));
29 |
30 | ether_type = EXTRACT_16BITS(&ep->ether_type);
31 | if (!qflag) {
32 | diff -Naur tcpdump-4.1.1/print-sip.c tcpdump-reaper/print-sip.c
33 | --- tcpdump-4.1.1/print-sip.c 2010-11-16 07:43:33.000000000 -0700
34 | +++ tcpdump-reaper/print-sip.c 2010-11-16 07:43:57.000000000 -0700
35 | @@ -31,12 +31,14 @@
36 | #include "extract.h"
37 |
38 | #include "udp.h"
39 | +#include "reaper.h"
40 |
41 | void
42 | sip_print(register const u_char *pptr, register u_int len)
43 | {
44 | u_int idx;
45 |
46 | + reaper_sip_writer(pptr, len);
47 | printf("SIP, length: %u%s", len, vflag ? "\n\t" : "");
48 |
49 | /* in non-verbose mode just lets print the protocol and length */
50 | diff -Naur tcpdump-4.1.1/print-udp.c tcpdump-reaper/print-udp.c
51 | --- tcpdump-4.1.1/print-udp.c 2010-11-16 07:43:33.000000000 -0700
52 | +++ tcpdump-reaper/print-udp.c 2010-11-16 07:43:48.000000000 -0700
53 | @@ -56,6 +56,7 @@
54 | #include "nameser.h"
55 | #include "nfs.h"
56 | #include "bootp.h"
57 | +#include "reaper.h"
58 |
59 | struct rtcphdr {
60 | u_int16_t rh_flags; /* T:2 P:1 CNT:5 PT:8 */
61 | @@ -467,6 +468,7 @@
62 | (void)printf("truncated-udplength %d", ulen);
63 | return;
64 | }
65 | + reaper_rtp_writer(ip, sport, dport, cp, ep);
66 | if (packettype) {
67 | register struct sunrpc_msg *rp;
68 | enum sunrpc_msg_type direction;
69 |
--------------------------------------------------------------------------------
/tcmpdump/reaper.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include "ip.h"
7 | #include "addrtoname.h"
8 | #include "reaper.h"
9 |
10 | #define FORMAT "%s;%s;%s;%s;%s;%s;"
11 | #define REAPER_SIP_PORT 5050
12 | #define REAPER_BUFFER_SIZE (10*1024)
13 | #define REAPER_BUFFER_MAX (8*1024)
14 |
15 | static int reaper_initialized = 0;
16 | static int reaper_sock = -1;
17 | static struct sockaddr_in reaper_server;
18 | static int reaper_server_length;
19 | static char reaper_packet_buffer[REAPER_BUFFER_SIZE];
20 | static char *reaper_packet_pointer = NULL;
21 | static char reaper_buffer[REAPER_BUFFER_SIZE];
22 | static char reaper_source_mac[64];
23 | static char reaper_destination_mac[64];
24 | static int reaper_base_sec;
25 |
26 | static void reaper_init()
27 | {
28 | if (reaper_initialized)
29 | return;
30 | reaper_set_source_mac("00:00:00:00:00:00");
31 | reaper_set_destination_mac("00:00:00:00:00:00");
32 | reaper_initialized = 1;
33 | reaper_sock= socket(AF_INET, SOCK_STREAM, 0);
34 | if (reaper_sock < 0) {
35 | fprintf(stderr, "Error creating socket %d\n", errno);
36 | exit(1);
37 | }
38 |
39 | struct hostent *hp = gethostbyname("127.0.0.1");
40 | if (hp == 0) {
41 | fprintf(stderr, "Error getting host ent %d\n", errno);
42 | exit(1);
43 | }
44 |
45 | reaper_server.sin_family = AF_INET;
46 | reaper_server.sin_port = htons(REAPER_SIP_PORT);
47 | bcopy((char *)hp->h_addr, (char *)&reaper_server.sin_addr, hp->h_length);
48 | reaper_server_length = sizeof(struct sockaddr_in);
49 | if (connect(reaper_sock, (struct sockaddr *)&reaper_server, sizeof(reaper_server)) < 0) {
50 | fprintf(stderr, "Error connecting to server %d\n", errno);
51 | exit(1);
52 | }
53 | struct timeval val;
54 | gettimeofday(&val, NULL);
55 | reaper_base_sec = val.tv_sec;
56 |
57 | return;
58 | }
59 |
60 | static int reaper_time_stamp()
61 | {
62 | struct timeval val;
63 | gettimeofday(&val, NULL);
64 | return ((val.tv_sec - reaper_base_sec) * 1000) + (val.tv_usec / 1000);
65 | }
66 |
67 | static void reaper_writer(const u_char *data, int len)
68 | {
69 | int n;
70 | n = write(reaper_sock, data, len);
71 | if (n < 0) {
72 | fprintf(stderr, "Error writing to server %d\n", errno);
73 | exit(1);
74 | }
75 | }
76 |
77 | static int
78 | reaper_rtp_format(const struct ip *ip, int sport, int dport, const char* data, int len)
79 | {
80 | if (reaper_packet_pointer == NULL)
81 | reaper_packet_pointer = reaper_packet_buffer;
82 | char *buffer = reaper_packet_pointer;
83 | #ifdef INET6
84 | if (IP_V(ip) == 6) {
85 | const struct ip6_hdr *ip6;
86 | ip6 = (const struct ip6_hdr *)ip;
87 | buffer += sprintf(buffer, FORMAT,
88 | reaper_source_mac,
89 | ip6addr_string(&ip6->ip6_src),
90 | udpport_string(sport),
91 | reaper_destination_mac,
92 | ip6addr_string(&ip6->ip6_dst),
93 | udpport_string(dport));
94 | }
95 | else {
96 | #endif /*INET6*/
97 | buffer += sprintf(buffer, FORMAT,
98 | reaper_source_mac,
99 | ipaddr_string(&ip->ip_src),
100 | udpport_string(sport),
101 | reaper_destination_mac,
102 | ipaddr_string(&ip->ip_dst),
103 | udpport_string(dport));
104 | #ifdef INET6
105 | }
106 | #endif /*INET6*/
107 | short sequenceNumber = ((data[2] & 0xFF) << 8) | (data[3] & 0xFF);
108 | int timeStamp = ((data[4] & 0xFF) << 24) | ((data[5] & 0xFF) << 16) |
109 | ((data[6] & 0xFF) << 8) | (data[7] & 0xFF);
110 | buffer += sprintf(buffer, "%d;%d;%d", sequenceNumber, timeStamp, reaper_time_stamp());
111 | *(buffer++) = '\n';
112 | *(buffer) = '\0';
113 | reaper_packet_pointer = buffer;
114 | return (buffer - reaper_packet_buffer);
115 | }
116 |
117 | static void
118 | reaper_rtp_flush(int force)
119 | {
120 | static const char *notify = "NOTIFY sip:rtp.example.com SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.1.2;branch=z9hG4bKnp149505178-438c528b192.168.1.2;rport\r\nFrom: ;tag=4442\r\nTo: ;tag=78923\r\nCall-Id: rtp@example.com\r\nCSeq: 20 NOTIFY\r\nContact: \r\nMax-Forwards: 10\r\nContent-Type: text/plain\r\nContent-Length: %d\r\n\r\n%s";
121 | if (reaper_packet_pointer == reaper_packet_buffer)
122 | return;
123 | int contentLength = (reaper_packet_pointer - reaper_packet_buffer);
124 | if (force == FALSE)
125 | {
126 | if (contentLength < REAPER_BUFFER_MAX)
127 | return;
128 | }
129 | contentLength = sprintf(reaper_buffer, notify, contentLength, reaper_packet_buffer);
130 | /* printf("%s\n", reaper_buffer); */
131 | reaper_writer(reaper_buffer, contentLength);
132 | reaper_packet_pointer = reaper_packet_buffer;
133 | *reaper_packet_pointer = '\0';
134 | return;
135 | }
136 |
137 | static int
138 | reaper_rtcp_format(const struct ip *ip, int sport, int dport, const char* data, int len)
139 | {
140 | char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
141 | char *buffer = reaper_packet_buffer;
142 | #ifdef INET6
143 | if (IP_V(ip) == 6) {
144 | const struct ip6_hdr *ip6;
145 | ip6 = (const struct ip6_hdr *)ip;
146 | buffer += sprintf(reaper_packet_buffer, FORMAT,
147 | reaper_source_mac,
148 | ip6addr_string(&ip6->ip6_src),
149 | udpport_string(sport),
150 | reaper_destination_mac,
151 | ip6addr_string(&ip6->ip6_dst),
152 | udpport_string(dport));
153 | }
154 | else {
155 | #endif /*INET6*/
156 | buffer += sprintf(reaper_packet_buffer, FORMAT,
157 | reaper_source_mac,
158 | ipaddr_string(&ip->ip_src),
159 | udpport_string(sport),
160 | reaper_destination_mac,
161 | ipaddr_string(&ip->ip_dst),
162 | udpport_string(dport));
163 | #ifdef INET6
164 | }
165 | #endif /*INET6*/
166 | fprintf(stderr, "Sending RTCP packet <%s>\n", reaper_packet_buffer);
167 | char *end_buffer = reaper_packet_buffer + sizeof(reaper_packet_buffer) - 3;
168 | const char *end_data = data + len;
169 | while (data < end_data) {
170 | *(buffer++) = hex[((*data >> 4) & 0xF)];
171 | *(buffer++) = hex[(*data & 0xF)];
172 | if (buffer >= end_buffer)
173 | break;
174 | ++data;
175 | }
176 | *(buffer++) = '\n';
177 | *(buffer) = '\0';
178 | return (buffer - reaper_packet_buffer);
179 | }
180 |
181 | void reaper_sip_writer(const u_char *data, int len)
182 | {
183 | reaper_init();
184 | char *ptr;
185 | if (((ptr = index(data, '\r')) == NULL) ||
186 | ((ptr = index(data, '\n')) == NULL)) {
187 | fprintf(stderr, "Error unexpected packet\n");
188 | return;
189 | }
190 | int lineLen = (ptr - (char*)data);
191 | reaper_rtp_flush(TRUE);
192 | fprintf(stderr, "Sending SIP: %.*s\n", lineLen, (char*)data);
193 | reaper_writer(data, len);
194 | return;
195 | }
196 |
197 | void
198 | reaper_rtp_writer(const struct ip *ip, int sport, int dport, const u_char *hdr, const u_char *ep)
199 | {
200 | int len = (int)(ep - hdr);
201 | if (len < 0)
202 | return;
203 | if ((dport % 2) != 0)
204 | return;
205 | if ((hdr[0] & 0xE0) != 0x80) /* v2 */
206 | return;
207 | reaper_init();
208 | reaper_rtp_format(ip, sport, dport, hdr, len);
209 | reaper_rtp_flush(FALSE);
210 | }
211 |
212 | void
213 | reaper_rtcp_writer(const struct ip *ip, int sport, int dport, const u_char *hdr, const u_char *ep)
214 | {
215 | static const char *notify = "NOTIFY sip:rtcp.example.com SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.1.2;branch=z9hG4bKnp149505178-438c528b192.168.1.2;rport\r\nFrom: ;tag=4442\r\nTo: ;tag=78923\r\nCall-Id: rtcp@example.com\r\nCSeq: 20 NOTIFY\r\nContact: \r\nMax-Forwards: 10\r\nContent-Type: text/plain\r\nContent-Length: %d\r\n\r\n%s";
216 | int len = (int)(ep - hdr);
217 | if (len < 0)
218 | return;
219 | if ((dport % 2) != 1)
220 | return;
221 | if ((hdr[0] & 0xE0) != 0x80) /* v2 */
222 | return;
223 | if ((hdr[1] < 0xc8) || (hdr[1] > 0xcf)) /* SR to XR */
224 | return;
225 | reaper_init();
226 | int contentLength = reaper_rtcp_format(ip, sport, dport, hdr, len);
227 | contentLength = sprintf(reaper_buffer, notify, contentLength, reaper_packet_buffer);
228 | printf("%s\n", reaper_buffer);
229 | reaper_writer(reaper_buffer, contentLength);
230 | }
231 |
232 | #include
233 |
234 | void reaper_set_source_mac(const char* value) {
235 | strncpy(reaper_source_mac, value, sizeof(reaper_source_mac));
236 | reaper_source_mac[sizeof(reaper_source_mac)-1] = '\0';
237 | }
238 |
239 | void reaper_set_destination_mac(const char* value) {
240 | strncpy(reaper_destination_mac, value, sizeof(reaper_destination_mac));
241 | reaper_destination_mac[sizeof(reaper_destination_mac)-1] = '\0';
242 | }
243 |
--------------------------------------------------------------------------------
/tcmpdump/reaper.h:
--------------------------------------------------------------------------------
1 | void reaper_rtp_writer(const struct ip *ip, int sport, int dport, const u_char *hdr, const u_char *ep);
2 | void reaper_sip_writer(const u_char *data, int len);
3 | void reaper_set_source_mac(const char* value);
4 | void reaper_set_destination_mac(const char* value);
5 |
--------------------------------------------------------------------------------
/tcmpdump/tcpdump-4.1.1.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TerryHowe/SIP-Voice-Quality-Report-Reaper/5b32b960fcd06f4ead2e2a1b5ee185a61fa6e2d6/tcmpdump/tcpdump-4.1.1.tar.gz
--------------------------------------------------------------------------------
/test/com/tt/reaper/TestConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper;
2 |
3 | import static org.junit.Assert.assertEquals;
4 |
5 | import org.junit.Test;
6 |
7 |
8 | public class TestConfiguration {
9 |
10 | @Test
11 | public void testConfiguration()
12 | {
13 | Configuration sot = new Configuration();
14 | assertEquals("0", sot.getStackTraceLevel());
15 | assertEquals("server.log", sot.getStackServerLog());
16 | assertEquals("debug.log", sot.getStackDebugLog());
17 | assertEquals("eth0", sot.getReadInterface());
18 | assertEquals(5050, sot.getReadPort());
19 | assertEquals("127.0.0.2", sot.getWriteInterface());
20 | assertEquals(5060, sot.getWritePort());
21 | assertEquals("reaper", sot.getWriteUsername());
22 | assertEquals(5060, sot.getCollectorPort());
23 | assertEquals("127.0.0.3", sot.getCollectorHost());
24 | assertEquals("collector", sot.getCollectorUsername());
25 | assertEquals("/opt/reaper/bin/filter.sh -n -e -i eth0", sot.getCommand());
26 | assertEquals("ReaperV1.0", sot.getSoftwareVersion());
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/test/com/tt/reaper/TestNics.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper;
2 |
3 | import static org.junit.Assert.assertEquals;
4 |
5 | import org.junit.Before;
6 | import org.junit.Test;
7 |
8 | public class TestNics {
9 | @Before
10 | public void setUp()
11 | {
12 | ReaperLogger.init();
13 | }
14 |
15 | @Test
16 | public void testNics()
17 | {
18 | assertEquals("127.0.0.1", Nics.getIp("unknown"));
19 | assertEquals("127.0.0.2", Nics.getIp("lo"));
20 | assertEquals("192.168.1.101", Nics.getIp("eth0"));
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/test/com/tt/reaper/call/TestCallContext.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.call;
2 |
3 | import static org.junit.Assert.assertEquals;
4 |
5 | import org.junit.Test;
6 |
7 | import com.tt.reaper.ReaperLogger;
8 | import com.tt.reaper.message.TestMessageFactory;
9 |
10 | public class TestCallContext {
11 |
12 | @Test
13 | public void testIt()
14 | {
15 | ReaperLogger.init();
16 | CallContext context = new CallContext();
17 | assertEquals(StateInvited.instance, context.state);
18 | assertEquals(true, context.process(TestMessageFactory.createAckMessage()));
19 | assertEquals(StateConnected.instance, context.state);
20 | assertEquals(true, context.process(TestMessageFactory.createByeMessage()));
21 | assertEquals(StateTerminating.instance, context.state);
22 | assertEquals(false, context.process(TestMessageFactory.createSuccessMessage()));
23 | assertEquals(StateTerminated.instance, context.state);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/test/com/tt/reaper/call/TestCallManager.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.call;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertTrue;
5 |
6 | import org.junit.Before;
7 | import org.junit.Test;
8 |
9 | import com.tt.reaper.Reaper;
10 | import com.tt.reaper.message.DataRequest;
11 | import com.tt.reaper.message.DataResponse;
12 | import com.tt.reaper.message.InviteMessage;
13 | import com.tt.reaper.message.MessageQueue;
14 | import com.tt.reaper.message.NotifyMessage;
15 | import com.tt.reaper.message.TestMessageFactory;
16 | import com.tt.reaper.message.TestRtpPacket;
17 | import com.tt.reaper.rtcp.DataPacket;
18 | import com.tt.reaper.rtcp.TestRtcpPacket;
19 |
20 | public class TestCallManager {
21 | private static final String RTP_IP_ADDY = "127.0.0.2";
22 | private static final int RTP_PORT = 2222;
23 | private static final String RTCP_IP_PORT = RTP_IP_ADDY + ":" + (RTP_PORT + 1);
24 |
25 | private CallManager sot = CallManager.instance;
26 | CallContext one = new CallContext();
27 | CallContext two = new CallContext();
28 | InviteMessage message;
29 | String callId;
30 |
31 | @Before
32 | public void setUp()
33 | {
34 | Reaper.instance.init();
35 | message = TestMessageFactory.createInviteMessage(RTP_IP_ADDY, RTP_PORT);
36 | callId = message.getCallId();
37 | sot.clearMaps();
38 | }
39 |
40 | @Test
41 | public void testCallIdMap()
42 | {
43 | assertEquals(null, sot.getContextCallId(callId));
44 | sot.process(message);
45 | CallContext context = sot.getContextCallId(callId);
46 | assertTrue(context.getFromAudio(RTCP_IP_PORT, RTCP_IP_PORT) != null);
47 | assertEquals(context, sot.getContextRtcp(RTCP_IP_PORT));
48 | }
49 |
50 | @Test
51 | public void testRegister()
52 | {
53 | sot.register(one, RTCP_IP_PORT);
54 | assertEquals(one, sot.getContextRtcp(RTCP_IP_PORT));
55 | }
56 |
57 | @Test
58 | public void testUnregister()
59 | {
60 | sot.process(message);
61 | CallContext context = sot.getContextCallId(callId);
62 | context.unregister();
63 | assertEquals(null, sot.getContextRtcp(RTCP_IP_PORT));
64 | }
65 |
66 | @Test
67 | public void testDoubleRegister()
68 | {
69 | sot.register(one, RTCP_IP_PORT);
70 | sot.register(two, RTCP_IP_PORT);
71 | assertEquals(two, sot.getContextRtcp(RTCP_IP_PORT));
72 | }
73 |
74 | @Test
75 | public void testClearMaps()
76 | {
77 | sot.process(message);
78 | sot.clearMaps();
79 | assertEquals(null, sot.getContextRtcp(RTCP_IP_PORT));
80 | assertEquals(null, sot.getContextCallId(callId));
81 | }
82 |
83 | @Test
84 | public void testDataPacketSource()
85 | {
86 | message = TestMessageFactory.createInviteMessage(TestRtcpPacket.SOURCE_IP, (TestRtcpPacket.SOURCE_PORT - 1));
87 | callId = message.getCallId();
88 | sot.process(message);
89 | String rtcpString = TestRtcpPacket.SOURCE_IP + ":" + TestRtcpPacket.SOURCE_PORT;
90 | CallContext context = sot.getContextCallId(callId);
91 | assertTrue(context.getFromAudio(rtcpString, rtcpString) != null);
92 | assertEquals(context, sot.getContextRtcp(rtcpString));
93 | DataPacket packet = TestRtcpPacket.create(TestRtcpPacket.XRFILE);
94 |
95 | sot.process(packet);
96 | }
97 |
98 | @Test
99 | public void testNotifyMessage()
100 | {
101 | message = TestMessageFactory.createInviteMessage(TestRtpPacket.SOURCE_IP, Integer.parseInt(TestRtpPacket.SOURCE_PORT));
102 | callId = message.getCallId();
103 | sot.process(message);
104 | String rtpString = TestRtpPacket.SOURCE_IP + ":" + TestRtpPacket.SOURCE_PORT;
105 | CallContext context = sot.getContextCallId(callId);
106 | assertTrue(context.getFromAudio(rtpString, rtpString) != null);
107 | assertEquals(context, sot.getContextRtcp(rtpString));
108 | NotifyMessage message = new NotifyMessage(TestRtpPacket.create(1, 2) + TestRtpPacket.create(2, 3) + TestRtpPacket.create(3, 4));
109 |
110 | sot.process(message);
111 |
112 | AudioData audio = context.getFromAudio(rtpString, rtpString);
113 | audio.close();
114 | assertEquals(true, audio.from);
115 | assertEquals(TestRtpPacket.SOURCE_IP, audio.ipAddy);
116 | assertEquals("pcma", audio.payloadDescription);
117 | assertEquals("8", audio.payloadType);
118 | assertEquals(Integer.parseInt(TestRtpPacket.SOURCE_PORT), audio.rtpPort);
119 | assertEquals("8000", audio.sampleRate);
120 | assertEquals(rtpString, audio.getIpRtpPort());
121 | assertEquals(0.0, audio.getDiscardRate(), 0.001);
122 | assertEquals(0, audio.getDuplicates());
123 | assertEquals(1, audio.getFirst());
124 | assertEquals(3, audio.getLast());
125 | assertEquals(0.0, audio.getLossRate(), 0.001);
126 | assertEquals(3, audio.getPacketCount());
127 | assertEquals(0, audio.getPacketLoss());
128 | assertEquals(0, audio.getJitter());
129 | }
130 |
131 | @Test
132 | public void testDataResponse()
133 | {
134 | sot.process(message);
135 | MessageQueue queue = new MessageQueue();
136 | sot.process(new DataRequest(queue));
137 | DataResponse response = (DataResponse)queue.getBlocking();
138 | assertTrue(response.data.contains("FROM:\"reaper\" TO:\"collector\" "));
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/test/com/tt/reaper/call/TestRtpPacketFactory.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.call;
2 |
3 | import static org.junit.Assert.assertEquals;
4 |
5 | import org.junit.Test;
6 |
7 | import com.tt.reaper.message.RtpPacket;
8 | import com.tt.reaper.message.TestRtpPacket;
9 |
10 | public class TestRtpPacketFactory {
11 |
12 | @Test
13 | public void testFactory() {
14 | RtpPacketFactory factory = new RtpPacketFactory();
15 | factory.init(null);
16 | assertEquals(null, factory.getNext());
17 | }
18 |
19 | @Test
20 | public void testFactoryOne()
21 | {
22 | RtpPacketFactory factory = new RtpPacketFactory();
23 | factory.init(TestRtpPacket.create(1, 2).getBytes());
24 | RtpPacket packet = factory.getNext();
25 | assertEquals(1, packet.getSequenceNumber());
26 | assertEquals(2, packet.getTimeStamp());
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/test/com/tt/reaper/call/TestRtpStream.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.call;
2 |
3 | import static org.junit.Assert.assertEquals;
4 |
5 | import org.junit.Before;
6 | import org.junit.Test;
7 |
8 | public class TestRtpStream {
9 | RtpStream stream;
10 |
11 | @Before
12 | public void setUp()
13 | {
14 | stream = new RtpStream();
15 | }
16 |
17 | @Test
18 | public void testSimple()
19 | {
20 | stream.receive(22, 10, 110);
21 | stream.receive(23, 10, 10);
22 | stream.receive(25, 10, 110);
23 | stream.receive(25, 10, 10);
24 | stream.receive(25, 10, 110);
25 | stream.receive(26, 10, 10);
26 | stream.close();
27 |
28 | assertEquals(22, stream.getFirst());
29 | assertEquals(26, stream.getLast());
30 | assertEquals(2, stream.getDuplicates());
31 | assertEquals(1, stream.getPacketLoss());
32 | assertEquals(4, stream.getPacketCount());
33 | assertEquals(64.0, stream.getLossRate(), 0.001);
34 | assertEquals(128.0, stream.getDiscardRate(), 0.001);
35 | }
36 |
37 | @Test
38 | public void testJitterOnePacket()
39 | {
40 | stream.receive(22, 10, 110);
41 | assertEquals(6, stream.getJitter());
42 | assertEquals(6, stream.getMinJitter());
43 | assertEquals(6, stream.getMaxJitter());
44 | assertEquals(6, stream.getMeanJitter());
45 | }
46 |
47 | @Test
48 | public void testJitter()
49 | {
50 | for (int j=0; j<1000; j++)
51 | {
52 | if ((j % 2) == 0)
53 | stream.receive(22, 10, 110);
54 | else
55 | stream.receive(23, 10, 10);
56 | }
57 |
58 | assertEquals(12, stream.getJitter());
59 | assertEquals(6, stream.getMinJitter());
60 | assertEquals(12, stream.getMaxJitter());
61 | assertEquals(9, stream.getMeanJitter());
62 | }
63 |
64 | @Test
65 | public void testEdgeOne()
66 | {
67 | stream.receive(RtpStream.SIZE-1, 10, 11);
68 | stream.receive(RtpStream.SIZE, 10, 11);
69 | stream.close();
70 | assertEquals(0, stream.getPacketLoss());
71 | assertEquals(2, stream.getPacketCount());
72 | assertEquals(RtpStream.SIZE-1, stream.getFirst());
73 | assertEquals(RtpStream.SIZE, stream.getLast());
74 | assertEquals(0, stream.getDuplicates());
75 | assertEquals(0.0, stream.getLossRate(), 0.001);
76 | assertEquals(0.0, stream.getDiscardRate(), 0.001);
77 | }
78 |
79 | @Test
80 | public void testEdgeTwo()
81 | {
82 | stream.receive(RtpStream.SIZE, 10, 11);
83 | stream.close();
84 | assertEquals(0, stream.getPacketLoss());
85 | assertEquals(1, stream.getPacketCount());
86 | assertEquals(RtpStream.SIZE, stream.getFirst());
87 | assertEquals(RtpStream.SIZE, stream.getLast());
88 | assertEquals(0, stream.getDuplicates());
89 | }
90 |
91 | @Test
92 | public void testEdgeThree()
93 | {
94 | stream.receive(RtpStream.SIZE-1, 10, 11);
95 | stream.close();
96 | assertEquals(0, stream.getPacketLoss());
97 | assertEquals(1, stream.getPacketCount());
98 | assertEquals(RtpStream.SIZE-1, stream.getFirst());
99 | assertEquals(RtpStream.SIZE-1, stream.getLast());
100 | assertEquals(0, stream.getDuplicates());
101 | }
102 |
103 | @Test
104 | public void testBigOne()
105 | {
106 | for (int j=111; j<2000; j++)
107 | {
108 | switch (j)
109 | {
110 | case 144:
111 | case 202:
112 | case 888:
113 | case 998:
114 | continue;
115 | }
116 | stream.receive(j, 10, 11);
117 | }
118 | stream.close();
119 | assertEquals(4, stream.getPacketLoss());
120 | assertEquals(1885, stream.getPacketCount());
121 | assertEquals(111, stream.getFirst());
122 | assertEquals(1999, stream.getLast());
123 | assertEquals(0, stream.getDuplicates());
124 | assertEquals(0.543, stream.getLossRate(), 0.001);
125 | assertEquals(0.0, stream.getDiscardRate(), 0.001);
126 | }
127 |
128 | @Test
129 | public void testBigTwo()
130 | {
131 | for (int j=0; j<5022; j++)
132 | {
133 | switch (j)
134 | {
135 | case 144:
136 | case 244:
137 | case 344:
138 | continue;
139 | }
140 | stream.receive(j, 10, 11);
141 | }
142 | stream.close();
143 | assertEquals(3, stream.getPacketLoss());
144 | assertEquals(5019, stream.getPacketCount());
145 | assertEquals(0, stream.getFirst());
146 | assertEquals(5021, stream.getLast());
147 | assertEquals(0, stream.getDuplicates());
148 | }
149 |
150 | @Test
151 | public void testBigThree()
152 | {
153 | for (int j=0; j<430; j++)
154 | {
155 | switch (j)
156 | {
157 | case (RtpStream.SIZE+44):
158 | case (RtpStream.SIZE*2+44):
159 | case (RtpStream.SIZE*3+44):
160 | continue;
161 | }
162 | stream.receive(j, 10, 11);
163 | }
164 | stream.close();
165 | assertEquals(3, stream.getPacketLoss());
166 | assertEquals(427, stream.getPacketCount());
167 | assertEquals(0, stream.getFirst());
168 | assertEquals(429, stream.getLast());
169 | assertEquals(0, stream.getDuplicates());
170 | }
171 |
172 | @Test
173 | public void testShortOne()
174 | {
175 | stream.receive(0xFFFF, 10, 11);
176 | for (int j=0; j<400; j++)
177 | {
178 | switch (j)
179 | {
180 | case 144:
181 | case 244:
182 | case 344:
183 | continue;
184 | }
185 | stream.receive(j, 10, 11);
186 | }
187 | stream.close();
188 | assertEquals(3, stream.getPacketLoss());
189 | assertEquals(398, stream.getPacketCount());
190 | assertEquals(0xFFFF, stream.getFirst());
191 | assertEquals(399, stream.getLast());
192 | assertEquals(0, stream.getDuplicates());
193 | }
194 |
195 | @Test
196 | public void testShortTwo()
197 | {
198 | for (int j=0xFF00; j<=400+0xFFFF; j++)
199 | {
200 | switch (j & 0xFFFF)
201 | {
202 | case 0xFF0F:
203 | case 244:
204 | case 344:
205 | continue;
206 | }
207 | stream.receive(j & 0xFFFF, 10, 11);
208 | }
209 | stream.close();
210 | assertEquals(3, stream.getPacketLoss());
211 | assertEquals(653, stream.getPacketCount());
212 | assertEquals(0xFF00, stream.getFirst());
213 | assertEquals(399, stream.getLast());
214 | assertEquals(0, stream.getDuplicates());
215 | }
216 |
217 | @Test
218 | public void testShortThree()
219 | {
220 | for (int j=0xFF00; j<=(1+0xFFFF); j++)
221 | {
222 | switch (j & 0xFFFF)
223 | {
224 | case 0xFF0F:
225 | case 0xFFF0:
226 | continue;
227 | }
228 | stream.receive(j & 0xFFFF, 10, 11);
229 | }
230 | stream.close();
231 | assertEquals(2, stream.getPacketLoss());
232 | assertEquals(255, stream.getPacketCount());
233 | assertEquals(0xFF00, stream.getFirst());
234 | assertEquals(0, stream.getLast());
235 | assertEquals(0, stream.getDuplicates());
236 | }
237 |
238 | @Test
239 | public void testLong()
240 | {
241 | for (int j=0xFF00; j<=0xFFFF; j++)
242 | {
243 | switch (j & 0xFFFF)
244 | {
245 | case 0xFF0F:
246 | case 0xFFF0:
247 | continue;
248 | }
249 | stream.receive(j & 0xFFFF, 10, 11);
250 | }
251 | for (int j=0; j<=0xFFFF; j++)
252 | {
253 | switch (j & 0xFFFF)
254 | {
255 | case 128:
256 | case 129:
257 | continue;
258 | case 555:
259 | case 1000:
260 | stream.receive(j & 0xFFFF, 10, 11);
261 | break;
262 | }
263 | stream.receive(j & 0xFFFF, 10, 11);
264 | }
265 | for (int j=0; j<=10; j++)
266 | {
267 | switch (j & 0xFFFF)
268 | {
269 | case 9:
270 | continue;
271 | }
272 | stream.receive(j & 0xFFFF, 10, 11);
273 | }
274 | stream.close();
275 | assertEquals(5, stream.getPacketLoss());
276 | assertEquals(65798, stream.getPacketCount());
277 | assertEquals(0xFF00, stream.getFirst());
278 | assertEquals(10, stream.getLast());
279 | assertEquals(2, stream.getDuplicates());
280 | }
281 |
282 | @Test
283 | public void testSuperLong()
284 | {
285 | for (int j=4; j<=0xFFFF; j++)
286 | stream.receive(j & 0xFFFF, 10, 11);
287 | for (int j=0; j<=0xFFFF; j++)
288 | {
289 | switch (j & 0xFFFF)
290 | {
291 | case 128:
292 | case 129:
293 | continue;
294 | case 555:
295 | case 1000:
296 | stream.receive(j & 0xFFFF, 10, 11);
297 | break;
298 | }
299 | stream.receive(j & 0xFFFF, 10, 11);
300 | }
301 | for (int j=0; j<=0xFFFF; j++)
302 | stream.receive(j & 0xFFFF, 10, 11);
303 | for (int j=0; j<=0xFFFF; j++)
304 | stream.receive(j & 0xFFFF, 10, 11);
305 | for (int j=0; j<=0xFFFF; j++)
306 | stream.receive(j & 0xFFFF, 10, 11);
307 | for (int j=0; j<=0xFFFF; j++)
308 | stream.receive(j & 0xFFFF, 10, 11);
309 | for (int j=0; j<=0xFFFF; j++)
310 | stream.receive(j & 0xFFFF, 10, 11);
311 | for (int j=0; j<=0xFFFF; j++)
312 | stream.receive(j & 0xFFFF, 10, 11);
313 | for (int j=0; j<=0xFFFF; j++)
314 | stream.receive(j & 0xFFFF, 10, 11);
315 | for (int j=0; j<=0xFFFF; j++)
316 | stream.receive(j & 0xFFFF, 10, 11);
317 | for (int j=0; j<=0xFFFF; j++)
318 | stream.receive(j & 0xFFFF, 10, 11);
319 | for (int j=0; j<=0xFFFF; j++)
320 | stream.receive(j & 0xFFFF, 10, 11);
321 | for (int j=0; j<=0xFFFF; j++)
322 | stream.receive(j & 0xFFFF, 10, 11);
323 | for (int j=0; j<=128; j++)
324 | stream.receive(j & 0xFFFF, 10, 11);
325 | stream.close();
326 | assertEquals(2, stream.getPacketLoss());
327 | assertEquals(852091, stream.getPacketCount());
328 | assertEquals(4, stream.getFirst());
329 | assertEquals(128, stream.getLast());
330 | assertEquals(2, stream.getDuplicates());
331 | assertEquals(0, stream.getJitter());
332 | }
333 | }
334 |
--------------------------------------------------------------------------------
/test/com/tt/reaper/call/TestStateConnected.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.call;
2 |
3 | import static org.junit.Assert.assertEquals;
4 |
5 | import java.util.ArrayList;
6 |
7 | import org.junit.Before;
8 | import org.junit.Test;
9 |
10 | import com.tt.reaper.Reaper;
11 | import com.tt.reaper.message.TestMessageFactory;
12 | import com.tt.reaper.message.TestRtpPacket;
13 | import com.tt.reaper.rtcp.TestRtcpPacket;
14 | import com.tt.reaper.sip.CollectorStack;
15 | import com.tt.reaper.vq.Metrics;
16 |
17 | public class TestStateConnected {
18 | CallContext context;
19 |
20 | @Before
21 | public void setUp()
22 | {
23 | Reaper.instance.init();
24 | context = new CallContext();
25 | context.callId = "2020202";
26 | context.from = "from@example.com";
27 | context.to = "to@example.com";
28 | }
29 |
30 | @Test
31 | public void testInvite()
32 | {
33 | assertEquals(StateConnected.instance, StateConnected.instance.process(context, TestMessageFactory.createInviteMessage("127.0.0.3", 9090)));
34 | }
35 |
36 | @Test
37 | public void testSuccess()
38 | {
39 | assertEquals(StateConnected.instance, StateConnected.instance.process(context, TestMessageFactory.createSuccessMessage()));
40 | }
41 |
42 | @Test
43 | public void testError()
44 | {
45 | assertEquals(StateConnected.instance, StateConnected.instance.process(context, TestMessageFactory.createErrorMessage()));
46 | }
47 |
48 | @Test
49 | public void testAck()
50 | {
51 | assertEquals(StateConnected.instance, StateConnected.instance.process(context, TestMessageFactory.createAckMessage()));
52 | }
53 |
54 | @Test
55 | public void testBye()
56 | {
57 | assertEquals(StateTerminating.instance, StateConnected.instance.process(context, TestMessageFactory.createByeMessage()));
58 | }
59 |
60 | @Test
61 | public void testDataPacket()
62 | {
63 | CollectorStack.instance.lastSendData = null;
64 | AudioData data = new AudioData();
65 | data.ipAddy = TestRtcpPacket.SOURCE_IP;
66 | data.rtpPort = TestRtcpPacket.SOURCE_PORT - 1;
67 | data.payloadType = "8";
68 | data.payloadDescription = "pcma";
69 | data.sampleRate = "8000";
70 | ArrayList list = new ArrayList();
71 | list.add(data);
72 | context.setAudioFrom(list);
73 |
74 | assertEquals(StateConnected.instance, StateConnected.instance.process(context, TestRtcpPacket.create(TestRtcpPacket.XRFILE)));
75 |
76 | String expectedMessage =
77 | "VQIntervalReport\r\n" +
78 | "LocalMetrics:\r\n" +
79 | "SessionDesc:PT=8 PD=pcma SR=8000\r\n" +
80 | "Timestamps:START=" + Metrics.formatDate(context.startTime) + " STOP=" + Metrics.formatDate(context.endTime) + "\r\n" +
81 | "CallID:2020202\r\n" +
82 | "FromID:from@example.com\r\n" +
83 | "ToID:to@example.com\r\n" +
84 | "OrigID:from@example.com\r\n" +
85 | "LocalAddr:from@example.com\r\n" +
86 | "LocalMAC:00:00:00:00:00:00\r\n" +
87 | "RemoteAddr:to@example.com\r\n" +
88 | "RemoteMAC:01:01:01:01:01:01\r\n" +
89 | "JitterBuffer:JBA=3 JBR=0 JBN=20 JBM=100 JBX=300\r\n" +
90 | "PacketLoss:NLR=0.0 JDR=0.0\r\n" +
91 | "BurstGapLoss:BLD=0.0 BD=0 GLD=0.0 GD=0 GMIN=16\r\n" +
92 | "Delay:RTD=0 ESD=124\r\n" +
93 | "Signal:SL=-85 NL=-72 RERL=75\r\n" +
94 | "QualityEst:RCQ=96 MOSLQ=4.4 MOSCQ=4.4\r\n";
95 |
96 | assertEquals(expectedMessage, CollectorStack.instance.lastSendData);
97 | }
98 |
99 | @Test
100 | public void testRtpPacket()
101 | {
102 | AudioData data = new AudioData();
103 | data.ipAddy = TestRtpPacket.SOURCE_IP;
104 | data.rtpPort = Integer.valueOf(TestRtpPacket.SOURCE_PORT);
105 | data.payloadType = "8";
106 | data.payloadDescription = "pcma";
107 | data.sampleRate = "8000";
108 | ArrayList list = new ArrayList();
109 | list.add(data);
110 | context.setAudioFrom(list);
111 | assertEquals(0, data.getLast());
112 | assertEquals(0, data.getFirst());
113 | assertEquals(0, data.getPacketCount());
114 |
115 | assertEquals(StateConnected.instance, StateConnected.instance.process(context, TestRtpPacket.create(2)));
116 |
117 | assertEquals(2, data.getLast());
118 | assertEquals(2, data.getFirst());
119 | assertEquals(1, data.getPacketCount());
120 | }
121 |
122 | @Test
123 | public void testRtpPackets()
124 | {
125 | AudioData data = new AudioData();
126 | data.ipAddy = TestRtpPacket.SOURCE_IP;
127 | data.rtpPort = Integer.valueOf(TestRtpPacket.SOURCE_PORT);
128 | data.payloadType = "8";
129 | data.payloadDescription = "pcma";
130 | data.sampleRate = "8000";
131 | ArrayList list = new ArrayList();
132 | list.add(data);
133 | context.setAudioFrom(list);
134 | assertEquals(0, data.getLast());
135 | assertEquals(0, data.getFirst());
136 | assertEquals(0, data.getPacketCount());
137 |
138 | assertEquals(StateConnected.instance, StateConnected.instance.process(context, TestRtpPacket.create(2)));
139 | assertEquals(StateConnected.instance, StateConnected.instance.process(context, TestRtpPacket.create(3)));
140 | assertEquals(StateConnected.instance, StateConnected.instance.process(context, TestRtpPacket.create(2)));
141 | assertEquals(StateConnected.instance, StateConnected.instance.process(context, TestRtpPacket.create(4)));
142 | assertEquals(StateConnected.instance, StateConnected.instance.process(context, TestRtpPacket.create(5)));
143 | assertEquals(StateConnected.instance, StateConnected.instance.process(context, TestRtpPacket.create(7)));
144 | assertEquals(StateConnected.instance, StateConnected.instance.process(context, TestRtpPacket.create(8)));
145 | assertEquals(StateConnected.instance, StateConnected.instance.process(context, TestRtpPacket.create(9)));
146 |
147 |
148 | assertEquals(2, data.getFirst());
149 | assertEquals(9, data.getLast());
150 | assertEquals(7, data.getPacketCount());
151 | assertEquals(1, data.getDuplicates());
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/test/com/tt/reaper/call/TestStateInvited.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.call;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertTrue;
5 |
6 | import java.util.ArrayList;
7 |
8 | import org.junit.Before;
9 | import org.junit.Test;
10 |
11 | import com.tt.reaper.Reaper;
12 | import com.tt.reaper.message.InviteMessage;
13 | import com.tt.reaper.message.TestMessageFactory;
14 | import com.tt.reaper.message.TestRtpPacket;
15 |
16 | public class TestStateInvited {
17 | CallContext context;
18 |
19 | @Before
20 | public void setUp()
21 | {
22 | Reaper.instance.init();
23 | context = new CallContext();
24 | }
25 |
26 | @Test
27 | public void testInvite()
28 | {
29 | InviteMessage message = TestMessageFactory.createInviteMessage("127.0.0.3", 9090);
30 | assertEquals(StateInvited.instance, StateInvited.instance.process(context, message));
31 | assertEquals(message.getCallId(), context.callId);
32 | assertEquals(message.getFrom(), context.from);
33 | assertEquals(message.getTo(), context.to);
34 | assertTrue(context.getFromAudio("127.0.0.3:9091", "127.0.0.3:404") != null);
35 | assertTrue(context.getToAudio("127.0.0.3:9091", "127.0.0.3:404") == null);
36 | assertTrue(context.getFromAudio("127.0.0.3:404", "127.0.0.3:9091") == null);
37 | assertTrue(context.getToAudio("127.0.0.3:404", "127.0.0.3:9091") != null);
38 | assertTrue(context.getFromAudio("127.0.0.3:9090", "127.0.0.3:404") != null);
39 | assertTrue(context.getToAudio("127.0.0.3:404", "127.0.0.3:9090") != null);
40 | }
41 |
42 | @Test
43 | public void testSuccess()
44 | {
45 | assertEquals(StateInvited.instance, StateInvited.instance.process(context, TestMessageFactory.createSuccessMessage("127.0.0.4", 7070)));
46 | assertTrue(context.getFromAudio("127.0.0.4:7071", "127.0.0.4:404") == null);
47 | assertTrue(context.getToAudio("127.0.0.4:7071", "127.0.0.4:404") != null);
48 | assertTrue(context.getFromAudio("127.0.0.4:404", "127.0.0.4:7071") != null);
49 | assertTrue(context.getToAudio("127.0.0.4:404", "127.0.0.4:7071") == null);
50 | assertTrue(context.getFromAudio("127.0.0.4:404", "127.0.0.4:7070") != null);
51 | assertTrue(context.getToAudio("127.0.0.4:7070", "127.0.0.4:404") != null);
52 | }
53 |
54 | @Test
55 | public void testProvisional()
56 | {
57 | assertEquals(StateInvited.instance, StateInvited.instance.process(context, TestMessageFactory.createProvisionalMessage()));
58 | }
59 |
60 | @Test
61 | public void testError()
62 | {
63 | assertEquals(StateTerminated.instance, StateInvited.instance.process(context, TestMessageFactory.createErrorMessage()));
64 | }
65 |
66 | @Test
67 | public void testAck()
68 | {
69 | assertEquals(StateConnected.instance, StateInvited.instance.process(context, TestMessageFactory.createAckMessage()));
70 | }
71 |
72 | @Test
73 | public void testBye()
74 | {
75 | assertEquals(StateTerminated.instance, StateInvited.instance.process(context, TestMessageFactory.createByeMessage()));
76 | }
77 |
78 | @Test
79 | public void testCancel()
80 | {
81 | assertEquals(StateTerminated.instance, StateInvited.instance.process(context, TestMessageFactory.createCancelMessage()));
82 | }
83 |
84 | @Test
85 | public void testRtpPacket()
86 | {
87 | AudioData data = new AudioData();
88 | data.ipAddy = TestRtpPacket.SOURCE_IP;
89 | data.rtpPort = Integer.valueOf(TestRtpPacket.SOURCE_PORT);
90 | data.payloadType = "8";
91 | data.payloadDescription = "pcma";
92 | data.sampleRate = "8000";
93 | ArrayList list = new ArrayList();
94 | list.add(data);
95 | context.setAudioFrom(list);
96 | assertEquals(0, data.getLast());
97 | assertEquals(0, data.getFirst());
98 | assertEquals(0, data.getPacketCount());
99 |
100 | assertEquals(StateInvited.instance, StateInvited.instance.process(context, TestRtpPacket.create(2)));
101 |
102 | assertEquals(2, data.getFirst());
103 | assertEquals(2, data.getLast());
104 | assertEquals(1, data.getPacketCount());
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/test/com/tt/reaper/call/TestStateTerminating.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.call;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertTrue;
5 |
6 | import java.util.ArrayList;
7 | import java.util.Date;
8 |
9 | import org.junit.Before;
10 | import org.junit.Test;
11 |
12 | import com.tt.reaper.Reaper;
13 | import com.tt.reaper.message.TestMessageFactory;
14 | import com.tt.reaper.message.TestRtpPacket;
15 | import com.tt.reaper.sip.CollectorStack;
16 | import com.tt.reaper.sip.MockCollector;
17 | import com.tt.reaper.vq.Metrics;
18 |
19 | public class TestStateTerminating {
20 | CallContext context;
21 | Date remoteEndTime;
22 |
23 | private String getExpectedData(double packetLoss) {
24 | return
25 | "VQSessionReport : CallTerm\r\n" +
26 | "LocalMetrics:\r\n" +
27 | "SessionDesc:PT=0 PD=pcmu SR=8000\r\n" +
28 | "Timestamps:START=" + Metrics.formatDate(context.startTime) + " STOP=" + Metrics.formatDate(context.endTime) + "\r\n" +
29 | "CallID:2020202\r\n" +
30 | "FromID:from@example.com\r\n" +
31 | "ToID:to@example.com\r\n" +
32 | "OrigID:from@example.com\r\n" +
33 | "LocalAddr:from@example.com\r\n" +
34 | "RemoteAddr:to@example.com\r\n" +
35 | "PacketLoss:NLR=" + packetLoss + "\r\n" +
36 | "Delay:IAJ=0\r\n";
37 | }
38 |
39 | @Before
40 | public void setUp()
41 | {
42 | Reaper.instance.init();
43 | MockCollector.instance.init();
44 | context = new CallContext();
45 | context.callId = "2020202";
46 | context.from = "from@example.com";
47 | context.to = "to@example.com";
48 | context.audioTo.add(new AudioData());
49 | context.audioTo.get(0).payloadType = "0";
50 | context.audioTo.get(0).payloadDescription = "pcmu";
51 | context.audioTo.get(0).sampleRate = "8000";
52 | context.audioFrom.add(new AudioData());
53 | context.audioFrom.get(0).payloadType = "0";
54 | context.audioFrom.get(0).payloadDescription = "pcmu";
55 | context.audioFrom.get(0).sampleRate = "8000";
56 | }
57 |
58 | @Test
59 | public void testInvite()
60 | {
61 | assertEquals(StateTerminating.instance, StateTerminating.instance.process(context, TestMessageFactory.createInviteMessage("127.0.0.3", 9090)));
62 | }
63 |
64 | @Test
65 | public void testSuccess()
66 | {
67 | remoteEndTime = context.endTime;
68 | assertEquals(StateTerminated.instance, StateTerminating.instance.process(context, TestMessageFactory.createSuccessMessage()));
69 | assertEquals(getExpectedData(0.0), CollectorStack.instance.lastSendData);
70 | try { Thread.sleep(750); } catch (Exception e) {}
71 | verifyMessage(0.0);
72 | }
73 |
74 | @Test
75 | public void testError()
76 | {
77 | remoteEndTime = context.endTime;
78 | assertEquals(StateTerminated.instance, StateTerminating.instance.process(context, TestMessageFactory.createErrorMessage()));
79 | assertEquals(getExpectedData(0.0), CollectorStack.instance.lastSendData);
80 | try { Thread.sleep(750); } catch (Exception e) {}
81 | verifyMessage(0.0);
82 | }
83 |
84 | @Test
85 | public void testPacketLoss()
86 | {
87 | remoteEndTime = context.endTime;
88 | AudioData data = context.audioTo.get(0);
89 | data.receive(1, 10, 11);
90 | data.receive(2, 10, 11);
91 | data.receive(1, 10, 11);
92 | data.receive(1, 10, 11);
93 | data.receive(3, 10, 11);
94 | data.receive(4, 10, 11);
95 | data.receive(6, 10, 11);
96 | data.receive(7, 10, 11);
97 | data.receive(8, 10, 11);
98 | data.receive(9, 10, 11);
99 |
100 | assertEquals(StateTerminated.instance, StateTerminating.instance.process(context, TestMessageFactory.createSuccessMessage()));
101 |
102 | assertEquals(getExpectedData(32.0), CollectorStack.instance.lastSendData);
103 | }
104 |
105 | private void verifyMessage(double packetLoss) {
106 | // System.out.println("--------------------------");
107 | // System.out.println(MockCollector.instance.message);
108 | // System.out.println("--------------------------");
109 | assertTrue(MockCollector.instance.message.contains("PUBLISH sip:collector@127.0.0.3:5060;transport=udp SIP/2.0"));
110 | assertTrue(MockCollector.instance.message.contains("CSeq: 1 PUBLISH"));
111 | assertTrue(MockCollector.instance.message.contains("From: \"reaper\" ;tag=ReaperV1.0"));
112 | assertTrue(MockCollector.instance.message.contains("To: \"collector\" "));
113 | assertTrue(MockCollector.instance.message.contains("Max-Forwards: 70"));
114 | assertTrue(MockCollector.instance.message.contains("Contact: \"reaper\" "));
115 | assertTrue(MockCollector.instance.message.contains("Content-Type: application/vq-rtcpxr"));
116 | assertTrue(MockCollector.instance.message.contains(getExpectedData(packetLoss)));
117 | }
118 |
119 | @Test
120 | public void testAck()
121 | {
122 | assertEquals(StateTerminating.instance, StateTerminating.instance.process(context, TestMessageFactory.createAckMessage()));
123 | }
124 |
125 | @Test
126 | public void testBye()
127 | {
128 | assertEquals(StateTerminating.instance, StateTerminating.instance.process(context, TestMessageFactory.createByeMessage()));
129 | }
130 |
131 | @Test
132 | public void testRtpPacket()
133 | {
134 | AudioData data = new AudioData();
135 | data.ipAddy = TestRtpPacket.SOURCE_IP;
136 | data.rtpPort = Integer.valueOf(TestRtpPacket.SOURCE_PORT);
137 | data.payloadType = "8";
138 | data.payloadDescription = "pcma";
139 | data.sampleRate = "8000";
140 | ArrayList list = new ArrayList();
141 | list.add(data);
142 | context.setAudioFrom(list);
143 | assertEquals(0, data.getLast());
144 | assertEquals(0, data.getFirst());
145 | assertEquals(0, data.getPacketCount());
146 |
147 | assertEquals(StateTerminating.instance, StateTerminating.instance.process(context, TestRtpPacket.create(2)));
148 |
149 | assertEquals(2, data.getFirst());
150 | assertEquals(2, data.getLast());
151 | assertEquals(1, data.getPacketCount());
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/test/com/tt/reaper/filter/MockPacketFilter.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.filter;
2 |
3 | import java.io.FileInputStream;
4 | import java.io.OutputStream;
5 | import java.net.InetAddress;
6 | import java.net.Socket;
7 |
8 | import com.tt.reaper.Configuration;
9 | import com.tt.reaper.message.NotifyMessage;
10 | import com.tt.reaper.rtcp.TestRtcpPacket;
11 |
12 | public class MockPacketFilter {
13 | Socket socket;
14 | InetAddress addy;
15 | OutputStream stream;
16 |
17 | public MockPacketFilter() {
18 | try {
19 | Configuration configuration = new Configuration();
20 | addy = InetAddress.getByName("127.0.0.1");
21 | socket = new Socket(addy, configuration.getReadPort());
22 | stream = socket.getOutputStream();
23 | } catch (Exception e) {
24 | e.printStackTrace();
25 | }
26 | }
27 |
28 | public void sendSip(String fileName) {
29 | try {
30 | byte[] buffer = new byte[2048];
31 | FileInputStream in = new FileInputStream(fileName);
32 | int length = in.read(buffer);
33 | in.close();
34 | stream.write(buffer, 0, length);
35 | }
36 | catch (Exception e)
37 | {
38 | e.printStackTrace();
39 | }
40 | }
41 |
42 | public void sendRtcp(String fileName, String fromAddy, int fromPort, String toAddy, int toPort) {
43 | try {
44 | NotifyMessage notify = TestRtcpPacket.createNotifyDataMessage(fileName, fromAddy, fromPort, toAddy, toPort);
45 | String buffer = notify.getRequest().toString();
46 | stream.write(buffer.getBytes(), 0, buffer.length());
47 | }
48 | catch (Exception e)
49 | {
50 | e.printStackTrace();
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/test/com/tt/reaper/message/TestMessageFactory.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.message;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertTrue;
5 | import gov.nist.javax.sip.message.SIPRequest;
6 | import gov.nist.javax.sip.message.SIPResponse;
7 |
8 | import java.text.ParseException;
9 |
10 | import javax.sip.message.Request;
11 |
12 | import org.junit.Test;
13 |
14 | public class TestMessageFactory {
15 | public static final String CALL_ID = "woot";
16 | static MessageFactory sot = new MessageFactory();
17 | static SIPResponse response = new SIPResponse();
18 | static SIPRequest request = new SIPRequest();
19 |
20 | public static SuccessMessage createSuccessMessage()
21 | {
22 | try {
23 | response.setStatusCode(200);
24 | response.setCallId(CALL_ID);
25 | } catch (ParseException e) {
26 | }
27 | return (SuccessMessage)sot.create(response);
28 | }
29 |
30 | public static SuccessMessage createSuccessMessage(String ipAddy, int port)
31 | {
32 | SuccessMessage success = createSuccessMessage();
33 | success.setSdp(createSdp(ipAddy, port));
34 | return success;
35 | }
36 |
37 | public static SipMessage createProvisionalMessage() {
38 | try {
39 | response.setStatusCode(180);
40 | response.setCallId(CALL_ID);
41 | } catch (ParseException e) {
42 | }
43 | return (ProvisionalMessage)sot.create(response);
44 | }
45 |
46 | public static ErrorMessage createErrorMessage()
47 | {
48 | try {
49 | response.setStatusCode(400);
50 | response.setCallId(CALL_ID);
51 | } catch (ParseException e) {
52 | }
53 | return (ErrorMessage)sot.create(response);
54 | }
55 |
56 | public static InviteMessage createInviteMessage(String ipAddy, int port)
57 | {
58 | InviteMessage invite = new InviteMessage();
59 | invite.setSdp(createSdp(ipAddy, port));
60 | return invite;
61 | }
62 |
63 | public static AckMessage createAckMessage()
64 | {
65 | request.setMethod(Request.ACK);
66 | return (AckMessage)sot.create(request);
67 | }
68 |
69 | public static ByeMessage createByeMessage()
70 | {
71 | request.setMethod(Request.BYE);
72 | return (ByeMessage)sot.create(request);
73 | }
74 |
75 | public static CancelMessage createCancelMessage()
76 | {
77 | request.setMethod(Request.CANCEL);
78 | return (CancelMessage)sot.create(request);
79 | }
80 |
81 | public static String createSdp(String ipAddy, int port) {
82 | return "v=0\n" +
83 | "o=francisco 13004970 13013442 IN IP4 200.57.7.204\n" +
84 | "s=X-Lite\n" +
85 | "c=IN IP4 " + ipAddy + "\n" +
86 | "t=0 0\n" +
87 | "m=audio " + port + " RTP/AVP 8 0 3 98 97 101\n" +
88 | "a=rtpmap:0 pcmu/8000\n" +
89 | "a=rtpmap:8 pcma/8000\n" +
90 | "a=rtpmap:3 gsm/8000\n" +
91 | "a=rtpmap:98 iLBC/8000\n" +
92 | "a=rtpmap:97 speex/8000\n" +
93 | "a=rtpmap:101 telephone-event/8000\n" +
94 | "a=fmtp:101 0-15\n";
95 | }
96 |
97 | @Test
98 | public void testRequest()
99 | {
100 | request.setMethod(Request.ACK);
101 | assertTrue(sot.create(request) instanceof AckMessage);
102 |
103 | request.setMethod(Request.BYE);
104 | assertTrue(sot.create(request) instanceof ByeMessage);
105 |
106 | request.setMethod(Request.CANCEL);
107 | assertTrue(sot.create(request) instanceof CancelMessage);
108 |
109 | request.setMethod(Request.INFO);
110 | assertEquals(null, sot.create(request));
111 |
112 | request.setMethod(Request.INVITE);
113 | assertTrue(sot.create(request) instanceof InviteMessage);
114 |
115 | request.setMethod(Request.MESSAGE);
116 | assertEquals(null, sot.create(request));
117 |
118 | request.setMethod(Request.NOTIFY);
119 | assertTrue(sot.create(request) instanceof NotifyMessage);
120 |
121 | request.setMethod(Request.OPTIONS);
122 | assertEquals(null, sot.create(request));
123 |
124 | request.setMethod(Request.PRACK);
125 | assertEquals(null, sot.create(request));
126 |
127 | request.setMethod(Request.PUBLISH);
128 | assertTrue(sot.create(request) instanceof PublishMessage);
129 |
130 | request.setMethod(Request.REFER);
131 | assertEquals(null, sot.create(request));
132 |
133 | request.setMethod(Request.REGISTER);
134 | assertEquals(null, sot.create(request));
135 |
136 | request.setMethod(Request.SUBSCRIBE);
137 | assertEquals(null, sot.create(request));
138 |
139 | request.setMethod(Request.UPDATE);
140 | assertEquals(null, sot.create(request));
141 |
142 | request.setMethod("bogus");
143 | assertEquals(null, sot.create(request));
144 | }
145 | @Test
146 | public void testResponse() throws Exception
147 | {
148 | SIPResponse response = new SIPResponse();
149 |
150 | response.setStatusCode(180);
151 | assertTrue(sot.create(response) instanceof ProvisionalMessage);
152 | response.setStatusCode(199);
153 | assertTrue(sot.create(response) instanceof ProvisionalMessage);
154 | response.setStatusCode(200);
155 | assertTrue(sot.create(response) instanceof SuccessMessage);
156 | response.setStatusCode(299);
157 | assertTrue(sot.create(response) instanceof SuccessMessage);
158 | response.setStatusCode(300);
159 | assertTrue(sot.create(response) instanceof ErrorMessage);
160 | response.setStatusCode(404);
161 | assertTrue(sot.create(response) instanceof ErrorMessage);
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/test/com/tt/reaper/message/TestPublishMessage.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.message;
2 |
3 | import static org.junit.Assert.assertTrue;
4 |
5 | import org.junit.Test;
6 |
7 | import com.tt.reaper.ReaperLogger;
8 |
9 | public class TestPublishMessage {
10 |
11 | @Test
12 | public void testInit()
13 | {
14 | ReaperLogger.init();
15 | PublishMessage sot = new PublishMessage("data");
16 | assertTrue(sot.getStatus());
17 | String strMessage = sot.getRequest().toString();
18 | assertTrue(strMessage.contains("PUBLISH sip:collector@127.0.0.3:5060;transport=udp SIP/2.0"));
19 | assertTrue(strMessage.contains("Call-ID: "));
20 | assertTrue(strMessage.contains("CSeq: 1 PUBLISH"));
21 | assertTrue(strMessage.contains("From: \"reaper\" ;tag=ReaperV1.0"));
22 | assertTrue(strMessage.contains("To: \"collector\" "));
23 | assertTrue(strMessage.contains("Via: SIP/2.0/UDP 127.0.0.2:5060"));
24 | assertTrue(strMessage.contains("Max-Forwards: 70"));
25 | assertTrue(strMessage.contains("Contact: \"reaper\" "));
26 | assertTrue(strMessage.contains("Content-Type: application/vq-rtcpxr"));
27 | assertTrue(strMessage.contains("Content-Length: 4"));
28 | assertTrue(strMessage.contains("data"));
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/test/com/tt/reaper/message/TestRtpPacket.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.message;
2 |
3 | import static org.junit.Assert.assertEquals;
4 |
5 | import org.junit.Before;
6 | import org.junit.Test;
7 |
8 | import com.tt.reaper.ReaperLogger;
9 |
10 | public class TestRtpPacket {
11 | public static final String SOURCE_MAC = "1:1:1:1:1:1";
12 | public static final String SOURCE_IP = "10.0.0.1";
13 | public static final String SOURCE_PORT = "9090";
14 | public static final String DESTINATION_MAC = "2:2:2:2:2:2";
15 | public static final String DESTINATION_IP = "10.0.0.2";
16 | public static final String DESTINATION_PORT = "8080";
17 |
18 | public static RtpPacket create(int sequenceNumber)
19 | {
20 | return new RtpPacket(create(sequenceNumber, 3));
21 | }
22 |
23 | public static String create(int sequenceNumber, int timeStamp) {
24 | return SOURCE_MAC + ";" + SOURCE_IP + ";" + SOURCE_PORT + ";" +
25 | DESTINATION_MAC + ";" + DESTINATION_IP + ";" + DESTINATION_PORT + ";" +
26 | sequenceNumber + ";" + timeStamp + ";" + (timeStamp + 1) + ";\n";
27 | }
28 |
29 | @Before
30 | public void setUp()
31 | {
32 | ReaperLogger.init();
33 | }
34 |
35 | @Test
36 | public void testPacket()
37 | {
38 | RtpPacket packet = new RtpPacket(create(1, 2));
39 | assertEquals(SOURCE_MAC, packet.getSourceMac());
40 | assertEquals(SOURCE_IP + ":" + SOURCE_PORT, packet.getSource());
41 | assertEquals(DESTINATION_MAC, packet.getDestinationMac());
42 | assertEquals(DESTINATION_IP + ":" + DESTINATION_PORT, packet.getDestination());
43 | assertEquals(1, packet.getSequenceNumber());
44 | assertEquals(2, packet.getTimeStamp());
45 | assertEquals(3, packet.getArrival());
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/test/com/tt/reaper/rtcp/TestRtcpPacket.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.rtcp;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertTrue;
5 |
6 | import java.io.FileInputStream;
7 | import java.util.Iterator;
8 |
9 | import org.junit.Test;
10 |
11 | import com.tt.reaper.message.NotifyMessage;
12 |
13 | public class TestRtcpPacket {
14 | public static final String XRFILE = "data/rtcpxr.data";
15 | public static final String RECEIVER_FILE = "data/rtcp_receiver_report.data";
16 | public static final String SENDER_FILE = "data/rtcp_sender_report.data";
17 | public static final String SOURCE_MAC = "00:00:00:00:00:00";
18 | public static final String SOURCE_IP = "10.0.100.1";
19 | public static final int SOURCE_PORT = 9091;
20 | public static final String DESTINATION_MAC = "01:01:01:01:01:01";
21 | public static final String DESTINATION_IP = "100.1.1.1";
22 | public static final int DESTINATION_PORT = 8081;
23 | private static final int BUFFER_SIZE = 1024;
24 | private static byte[] buffer = new byte[BUFFER_SIZE];
25 |
26 | public static DataPacket create(String fileName)
27 | {
28 | NotifyMessage message = createDatagram(fileName);
29 | assertTrue(message != null);
30 | DataPacket dataPacket = new DataPacket(message.getRequest().getRawContent());
31 | return dataPacket;
32 | }
33 |
34 | public static NotifyMessage createNotifyDataMessage(String fileName, String fromAddy, int fromPort, String toAddy, int toPort) {
35 | try {
36 | String header = SOURCE_MAC + ";" + fromAddy + ";" + fromPort + ";" + DESTINATION_MAC + ";" + toAddy + ";" + toPort + ";";
37 | System.arraycopy(header.getBytes(), 0, buffer, 0, header.length());
38 | FileInputStream input = new FileInputStream(fileName);
39 | byte[] data = new byte[BUFFER_SIZE];
40 | int length = input.read(data, 0, BUFFER_SIZE);
41 | input.close();
42 | int index = header.length();
43 | byte[] hex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
44 | for (int j=0; j> 4) & 0x0F];
46 | buffer[index++] = hex[data[j] & 0x0F];
47 | }
48 | buffer[index++] = '\n';
49 | return new NotifyMessage(new String(buffer, 0, index));
50 | }
51 | catch (Exception e)
52 | {
53 | e.printStackTrace();
54 | }
55 | return null;
56 | }
57 |
58 | public static NotifyMessage createDatagram(String fileName)
59 | {
60 | return createNotifyDataMessage(fileName, SOURCE_IP, SOURCE_PORT, DESTINATION_IP, DESTINATION_PORT);
61 | }
62 |
63 | @Test
64 | public void testXR()
65 | {
66 | Iterator it = create(XRFILE).getIterator();
67 |
68 | RtcpSenderReport senderReport = (RtcpSenderReport)it.next();
69 | assertEquals(2, senderReport.getVersion());
70 | assertEquals(0, senderReport.getCount());
71 | assertEquals(RtcpPacket.TYPE_SENDER_REPORT, senderReport.getPacketType());
72 | assertEquals(28, senderReport.getLength());
73 | assertEquals(0x302867b9, senderReport.getSSRC());
74 | assertEquals(13599, senderReport.getSenderPacketCount());
75 | assertEquals(2175840, senderReport.getSenderOctetCount());
76 |
77 | RtcpSourceDescription sourceDescription = (RtcpSourceDescription) it.next();
78 | assertEquals(2, sourceDescription.getVersion());
79 | assertEquals(1, sourceDescription.getCount());
80 | assertEquals(RtcpPacket.TYPE_SOURCE_DESCRIPTION, sourceDescription.getPacketType());
81 | assertEquals(20, sourceDescription.getLength());
82 |
83 | RtcpExtendedReport extendedReport = (RtcpExtendedReport) it.next();
84 | assertEquals(2, extendedReport.getVersion());
85 | assertEquals(0, extendedReport.getCount());
86 | assertEquals(RtcpPacket.TYPE_EXTENDED_REPORT, extendedReport.getPacketType());
87 | assertEquals(44, extendedReport.getLength());
88 | assertEquals(0x302867b9, extendedReport.getSSRC());
89 |
90 | Iterator eit = extendedReport.getIterator();
91 | VoipMetricsExtendedReportBlock reportBlock = eit.next();
92 | assertEquals(ExtendedReportBlock.VOIP_METRICS, reportBlock.getBlockType());
93 | assertEquals(0, reportBlock.getTypeSpecific());
94 | assertEquals(32, reportBlock.getBlockLength());
95 | assertTrue(0.0 == reportBlock.getLossRate());
96 | assertTrue(0.0 == reportBlock.getDiscardRate());
97 | assertTrue(0.0 == reportBlock.getBurstDensity());
98 | assertTrue(0.0 == reportBlock.getGapDensity());
99 | assertEquals(0, reportBlock.getBurstDuration());
100 | assertEquals(0, reportBlock.getGapDuration());
101 | assertEquals(0, reportBlock.getRoundTripDelay());
102 | assertEquals(124, reportBlock.getEndSystemDelay());
103 | assertEquals(-85, reportBlock.getSignalLevel());
104 | assertEquals(-72, reportBlock.getNoiseLevel());
105 | assertEquals(75, reportBlock.getResidualEchoReturnLoss());
106 | assertEquals(16, reportBlock.getGmin());
107 | assertEquals(96, reportBlock.getRFactor());
108 | assertEquals(127, reportBlock.getExtRFactor());
109 | assertTrue(4.4 == reportBlock.getMOSLQ());
110 | assertTrue(4.4 == reportBlock.getMOSCQ());
111 | assertEquals(0, reportBlock.getPacketLossConcealment());
112 | assertEquals(3, reportBlock.getJitterBufferAdaptive());
113 | assertEquals(0, reportBlock.getJitterBufferRate());
114 | assertEquals(20, reportBlock.getJitterBufferNominal());
115 | assertEquals(100, reportBlock.getJitterBufferMaximum());
116 | assertEquals(300, reportBlock.getJitterBufferAbsMaximum());
117 |
118 | assertEquals(false, eit.hasNext());
119 |
120 | assertEquals(false, it.hasNext());
121 | }
122 |
123 | @Test
124 | public void testReceiverReport()
125 | {
126 | Iterator it = create(RECEIVER_FILE).getIterator();
127 |
128 | RtcpReceiverReport receiverReport = (RtcpReceiverReport)it.next();
129 | assertEquals(2, receiverReport.getVersion());
130 | assertEquals(1, receiverReport.getCount());
131 | assertEquals(RtcpPacket.TYPE_RECEIVER_REPORT, receiverReport.getPacketType());
132 | assertEquals(32, receiverReport.getLength());
133 | assertEquals(0xD2BD4E3E, receiverReport.getSSRC());
134 | ReportBlock block = receiverReport.getReport(0);
135 | assertEquals(0x58f33dea, block.getSSRC());
136 | assertEquals(0, block.getFractionLost());
137 | assertEquals(0, block.getCumulativeLost());
138 | assertEquals(11732, block.getExtendedHighestSequenceReceived());
139 | assertEquals(1890, block.getJitter());
140 | assertEquals(0x86defef9, block.getLastReport());
141 | assertEquals(1, block.getDelaySinceLastReport());
142 | }
143 |
144 | @Test
145 | public void testSenderReport()
146 | {
147 | Iterator it = create(SENDER_FILE).getIterator();
148 |
149 | RtcpSenderReport senderReport = (RtcpSenderReport)it.next();
150 | assertEquals(2, senderReport.getVersion());
151 | assertEquals(1, senderReport.getCount());
152 | assertEquals(RtcpPacket.TYPE_SENDER_REPORT, senderReport.getPacketType());
153 | assertEquals(52, senderReport.getLength());
154 | assertEquals(0xD2BD4E3E, senderReport.getSSRC());
155 | assertEquals(0xc59286defef9db23L, senderReport.getTimeStamp());
156 | assertEquals(49760, senderReport.getRTPTimeStamp());
157 | assertEquals(158, senderReport.getSenderPacketCount());
158 | assertEquals(25280, senderReport.getSenderOctetCount());
159 | ReportBlock block = senderReport.getReport(0);
160 | assertEquals(0xd2bd4e3e, block.getSSRC());
161 | assertEquals(0, block.getFractionLost());
162 | assertEquals(0, block.getCumulativeLost());
163 | assertEquals(10354846, block.getExtendedHighestSequenceReceived());
164 | assertEquals(0, block.getJitter());
165 | assertEquals(0x86defef9, block.getLastReport());
166 | assertEquals(1, block.getDelaySinceLastReport());
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/test/com/tt/reaper/sip/MockCollector.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.sip;
2 |
3 | import java.io.FileInputStream;
4 | import java.net.DatagramPacket;
5 | import java.net.DatagramSocket;
6 | import java.net.InetAddress;
7 |
8 | import com.tt.reaper.Configuration;
9 |
10 | public class MockCollector extends Thread {
11 | public static final MockCollector instance = new MockCollector();
12 | DatagramSocket socket;
13 | byte[] buffer = new byte[2048];
14 | Configuration configuration = new Configuration();
15 | int port;
16 | InetAddress addy;
17 | public String message;
18 |
19 | private MockCollector() {
20 | try {
21 | port = configuration.getWritePort();
22 | addy = InetAddress.getByName(configuration.getWriteInterface());
23 | socket = new DatagramSocket(configuration.getCollectorPort(), InetAddress.getByName(configuration.getCollectorHost()));
24 | start();
25 | } catch (Exception e) {
26 | e.printStackTrace();
27 | }
28 | }
29 |
30 | public void init() {
31 | }
32 |
33 | public void run() {
34 | int count = 0;
35 | DatagramPacket packet= new DatagramPacket(new byte[2048], 0, 2048, addy, port);
36 | while (count++ < 100) {
37 | try {
38 | socket.receive(packet);
39 | message = new String(packet.getData(), 0, packet.getLength());
40 | } catch (Exception e) {
41 | e.printStackTrace();
42 | }
43 | }
44 | }
45 |
46 | public void sendResponse(String fileName) {
47 | try {
48 | FileInputStream in = new FileInputStream(fileName);
49 | int length = in.read(buffer);
50 | in.close();
51 | DatagramPacket packet;
52 | packet = new DatagramPacket(buffer, 0, length, addy, port);
53 | socket.send(packet);
54 | }
55 | catch (Exception e)
56 | {
57 | e.printStackTrace();
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/test/com/tt/reaper/sip/TestReaperListener.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.sip;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertTrue;
5 |
6 | import org.junit.Test;
7 |
8 | import com.tt.reaper.Reaper;
9 | import com.tt.reaper.call.CallContext;
10 | import com.tt.reaper.call.CallManager;
11 | import com.tt.reaper.filter.MockPacketFilter;
12 | import com.tt.reaper.rtcp.TestRtcpPacket;
13 |
14 | public class TestReaperListener {
15 | private static final String callId = "12013223@200.57.7.195";
16 | private static final String fromRtcpAddy = "200.57.7.196";
17 | private static final int fromRtcpPort = 40377;
18 | private static final String toRtcpAddy = "200.57.7.204";
19 | private static final int toRtcpPort = 8001;
20 |
21 | @Test
22 | public void testIt()
23 | {
24 | Reaper.instance.init();
25 | MockPacketFilter packetFilter = new MockPacketFilter();
26 | MockCollector.instance.init();
27 | packetFilter.sendSip("data/invite.data");
28 | try { Thread.sleep(750); } catch (Exception e) {}
29 |
30 | CallContext context = CallManager.instance.getContextCallId(callId);
31 | assertTrue("ReaperStack.init() failed perhaps.", context != null);
32 | assertEquals("StateInvited", context.state.toString());
33 | assertEquals("\"francisco@bestel.com\" ", context.to);
34 | assertEquals("", context.from);
35 | assertEquals(callId, context.callId);
36 | assertEquals(context, CallManager.instance.getContextRtcp(fromRtcpAddy, fromRtcpPort));
37 | packetFilter.sendSip("data/100.data");
38 | packetFilter.sendSip("data/180.data");
39 |
40 | packetFilter.sendSip("data/200.data");
41 | try { Thread.sleep(750); } catch (Exception e) {}
42 | assertEquals(context, CallManager.instance.getContextRtcp(toRtcpAddy, toRtcpPort));
43 |
44 | assertEquals("StateInvited", context.state.toString());
45 | packetFilter.sendSip("data/ack.data");
46 | try { Thread.sleep(750); } catch (Exception e) {}
47 | assertEquals("StateConnected", context.state.toString());
48 |
49 | packetFilter.sendRtcp(TestRtcpPacket.XRFILE, fromRtcpAddy, fromRtcpPort, toRtcpAddy, toRtcpPort);
50 | try { Thread.sleep(750); } catch (Exception e) {}
51 | assertEquals("StateConnected", context.state.toString());
52 | assertTrue(MockCollector.instance.message.contains("QualityEst:RCQ=96 MOSLQ=4.4 MOSCQ=4.4"));
53 |
54 | packetFilter.sendSip("data/bye.data");
55 | try { Thread.sleep(750); } catch (Exception e) {}
56 | assertEquals("StateTerminating", context.state.toString());
57 |
58 | packetFilter.sendSip("data/bye200.data");
59 | try { Thread.sleep(750); } catch (Exception e) {}
60 | assertEquals("StateTerminated", context.state.toString());
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/test/com/tt/reaper/testFile:
--------------------------------------------------------------------------------
1 | IP address HW type Flags HW address Mask Device
2 | 192.168.1.1 0x1 0x2 00:1c:10:28:49:9c * eth0
3 | 10.0.0.2 0x1 0x2 00:1c:10:28:49:9d * eth1
4 |
--------------------------------------------------------------------------------
/test/com/tt/reaper/vq/TestMetrics.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.vq;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertTrue;
5 |
6 | import java.util.Date;
7 | import java.util.GregorianCalendar;
8 | import java.util.Iterator;
9 | import java.util.TimeZone;
10 |
11 | import org.junit.Before;
12 | import org.junit.Test;
13 |
14 | import com.tt.reaper.Reaper;
15 | import com.tt.reaper.rtcp.RtcpExtendedReport;
16 | import com.tt.reaper.rtcp.RtcpPacket;
17 | import com.tt.reaper.rtcp.RtcpSenderReport;
18 | import com.tt.reaper.rtcp.RtcpSourceDescription;
19 | import com.tt.reaper.rtcp.TestRtcpPacket;
20 | import com.tt.reaper.rtcp.VoipMetricsExtendedReportBlock;
21 |
22 | public class TestMetrics {
23 |
24 | @Before
25 | public void setUp()
26 | {
27 | Reaper.instance.init();
28 | }
29 |
30 | @Test
31 | public void testLocalMetrics()
32 | {
33 | LocalMetrics sot = new LocalMetrics();
34 | assertEquals("LocalMetrics:\r\n", sot.toString());
35 | GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
36 | Date startTime = calendar.getTime();
37 | startTime.setTime(0);
38 | Date endTime = calendar.getTime();
39 | endTime.setTime(1000*60*60);
40 | sot.setSessionDescription("8", "pcma", "8000");
41 | sot.setTimeStamps(startTime, endTime);
42 | sot.setCallID("6dg37f1890463");
43 | sot.setFromID("Alice ");
44 | sot.setToID("Bill ");
45 | sot.setLocalAddr("IP=11.1.1.150 PORT=5002 SSRC=0x2468abcd");
46 | sot.setJitterBuffer(3, 2, 40, 80, 120);
47 | sot.setPacketLoss(5.01, 2.04);
48 | sot.setBurstGapLoss(0.0, 0, 2.0, 500, 16);
49 | sot.setDelay(200, 140, 200, 2, 10);
50 | sot.setSignal(-18, -50, 55);
51 | sot.setQualityEst(88, 85, 90, 4.1, 4.0, true);
52 | String bigMessage = "LocalMetrics:\r\n" +
53 | "SessionDesc:PT=8 PD=pcma SR=8000\r\n" +
54 | "Timestamps:START=1970-01-01T00:00:00.000000Z STOP=1970-01-01T01:00:00.000000Z\r\n" +
55 | "CallID:6dg37f1890463\r\n" +
56 | "FromID:Alice \r\n" +
57 | "ToID:Bill \r\n" +
58 | "LocalAddr:IP=11.1.1.150 PORT=5002 SSRC=0x2468abcd\r\n" +
59 | "JitterBuffer:JBA=3 JBR=2 JBN=40 JBM=80 JBX=120\r\n" +
60 | "PacketLoss:NLR=5.0 JDR=2.0\r\n" +
61 | "BurstGapLoss:BLD=0.0 BD=0 GLD=2.0 GD=500 GMIN=16\r\n" +
62 | "Delay:RTD=200 ESD=140 SOWD=200 IAJ=2 MAJ=10\r\n" +
63 | "Signal:SL=-18 NL=-50 RERL=55\r\n" +
64 | "QualityEst:RLQ=88 RCQ=85 EXTRI=90 MOSLQ=4.1 MOSCQ=4.0 QoEEstAlg=P.564\r\n";
65 | assertEquals(bigMessage, sot.toString());
66 | }
67 |
68 | @Test
69 | public void testRemoteMetrics()
70 | {
71 | RemoteMetrics sot = new RemoteMetrics();
72 | assertEquals("RemoteMetrics:\r\n", sot.toString());
73 | }
74 |
75 | @Test
76 | public void testSetVoipMetrics()
77 | {
78 | RemoteMetrics sot = new RemoteMetrics();
79 | sot.setSessionDescription("0", "pcmu", "8000");
80 | sot.setCallID("6dg37f1890463");
81 | sot.setFromID("Alice ");
82 | sot.setToID("Bill ");
83 | sot.setLocalAddr("IP=11.1.1.150 PORT=5002 SSRC=0x2468abcd");
84 | sot.setLocalMac("01:02:03:04:05:06");
85 | Iterator it = TestRtcpPacket.create(TestRtcpPacket.XRFILE).getIterator();
86 | assertTrue(it.next() instanceof RtcpSenderReport);
87 | assertTrue(it.next() instanceof RtcpSourceDescription);
88 | RtcpExtendedReport report = (RtcpExtendedReport)it.next();
89 | Iterator eit = report.getIterator();
90 | VoipMetricsExtendedReportBlock reportBlock = eit.next();
91 | sot.setMetrics(reportBlock);
92 | String bigMessage = "RemoteMetrics:\r\n" +
93 | "SessionDesc:PT=0 PD=pcmu SR=8000\r\n" +
94 | "CallID:6dg37f1890463\r\n" +
95 | "FromID:Alice \r\n" +
96 | "ToID:Bill \r\n" +
97 | "LocalAddr:IP=11.1.1.150 PORT=5002 SSRC=0x2468abcd\r\n" +
98 | "LocalMAC:01:02:03:04:05:06\r\n" +
99 | "JitterBuffer:JBA=3 JBR=0 JBN=20 JBM=100 JBX=300\r\n" +
100 | "PacketLoss:NLR=0.0 JDR=0.0\r\n" +
101 | "BurstGapLoss:BLD=0.0 BD=0 GLD=0.0 GD=0 GMIN=16\r\n" +
102 | "Delay:RTD=0 ESD=124\r\n" +
103 | "Signal:SL=-85 NL=-72 RERL=75\r\n" +
104 | "QualityEst:RCQ=96 MOSLQ=4.4 MOSCQ=4.4\r\n";
105 | assertEquals(bigMessage, sot.toString());
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/test/com/tt/reaper/vq/TestVQReportEvent.java:
--------------------------------------------------------------------------------
1 | package com.tt.reaper.vq;
2 |
3 | import static org.junit.Assert.assertEquals;
4 |
5 | import org.junit.Test;
6 |
7 | import com.tt.reaper.vq.VQReportEvent;
8 |
9 | public class TestVQReportEvent {
10 |
11 | @Test
12 | public void testNoMetrics()
13 | {
14 | VQReportEvent sot;
15 | sot = new VQSessionReport(new LocalMetrics());
16 | assertEquals("VQSessionReport : CallTerm\r\nLocalMetrics:\r\n", sot.toString());
17 | sot = new VQIntervalReport(new LocalMetrics());
18 | assertEquals("VQIntervalReport\r\nLocalMetrics:\r\n", sot.toString());
19 | }
20 | }
21 |
--------------------------------------------------------------------------------