EMMA Coverage Report (generated Tue Dec 18 20:38:46 CET 2007)
[all classes][cz.vutbr.feec.session.rtprtcp.internal]

## COVERAGE SUMMARY FOR SOURCE FILE [RTPThreadHandler.java]

name | class, % | method, % | block, % | line, %
--- | --- | --- | --- | ---
RTPThreadHandler.java | 0% (0/1) | 0% (0/6) | 0% (0/388) | 0% (0/85)

### COVERAGE BREAKDOWN BY CLASS AND METHOD

name | class, % | method, % | block, % | line, %
--- | --- | --- | --- | ---
class RTPThreadHandler | 0% (0/1) | 0% (0/6) | 0% (0/388) | 0% (0/85)
<static initializer> |  | 0% (0/1) | 0% (0/5) | 0% (0/3)
RTPThreadHandler (Session3550, Socket, int): void |  | 0% (0/1) | 0% (0/31) | 0% (0/9)
run (): void |  | 0% (0/1) | 0% (0/162) | 0% (0/39)
sendPacket (byte [], int): int |  | 0% (0/1) | 0% (0/8) | 0% (0/2)
sendPacket (byte [], int, boolean): int |  | 0% (0/1) | 0% (0/107) | 0% (0/21)
validateRTPPacketHeader (byte []): boolean |  | 0% (0/1) | 0% (0/75) | 0% (0/11)

1 | package cz.vutbr.feec.session.rtprtcp.internal;
2 |
3 | import java.net.InetAddress;
4 | import java.net.UnknownHostException;
5 | import java.util.Random;
6 |
7 | import org.apache.log4j.Logger;
8 |
9 | import cz.vutbr.feec.packets.PacketGenerateException;
10 | import cz.vutbr.feec.packets.PacketParseException;
11 | import cz.vutbr.feec.packets.rtp.RTPPacket;
12 | import cz.vutbr.feec.session.SessionThread;
13 |
14 | import net.java.dev.jssm.Socket;
15 |
16 | /**
17 | * This class encapsulates the functionality to construct and send out RTP
18 | * Packets and also to receive RTP Packets. It provides a seperate thread to
19 | * receive and send out RTP Packets.
20 | */
21 |
22 | public class RTPThreadHandler extends SessionThread {
23 | /** The logger. */
24 | private static Logger logger = Logger.getLogger(RTPThreadHandler.class
25 | .getName());
26 |
27 | /** Multicast Socket for sending RTP. */
28 | protected Socket socket;
29 |
30 | /** The destination port. */
31 | protected int destPort;
32 |
33 | /**
34 | * Constructs a datagram, assembles it into an RTP packet and sends it out.
35 | * @param marker the marker
36 | * @param length the length
37 | * @param data Payload to be sent out as part of the RTP Packet.
38 | * @return the int
39 | */
40 | private byte[] sendBuffer = new byte[1500];
41 |
42 | /** The sequence number of rtp packet. */
43 | private long sequence_number; // 16 bits
44 |
45 | /** The RTP session. */
46 | private Session3550 session;
47 |
48 | /**
49 | * Constructor for the class. Takes in a TCP/IP Address and a port number.
50 | * It initializes a a new multicast socket according to the multicast
51 | * address and the port number given
52 | *
53 | * @param rtpPort
54 | * the rtp port
55 | * @param multicastSocket
56 | * the multicast socket
57 | * @param rtpSession
58 | * the rtp session
59 | */
60 | public RTPThreadHandler(Session3550 rtpSession, Socket multicastSocket,
61 | int rtpPort) {
62 | this.setName("RTP-in/out (R) or (S)");
63 | this.session = rtpSession;
64 | this.socket = multicastSocket;
65 |
66 | this.destPort = rtpPort;
67 | // socket.setDestinationPort(rtpPort);
68 |
69 | Random rnd = new Random(); // Use time as default seed
70 |
71 | // Start with a random sequence number
72 | sequence_number = (long) (Math.abs(rnd.nextInt()) & 0x000000FF);
73 |
74 | // Session3550.outprintln("RTP Session SSRC: "
75 | // + Long.toHexString(session.getOwnSource().getSSRC()));
76 | // Session3550.outprintln(" Starting Seq: " + sequence_number);
77 | }
78 |
79 | /**
80 | * Send packet.
81 | *
82 | * @param length
83 | * the length
84 | * @param data
85 | * the data
86 | *
87 | * @return the int
88 | * @throws PacketGenerateException
89 | */
90 | public int sendPacket(byte[] data, int length) throws PacketGenerateException {
91 | boolean marker = false;
92 | return sendPacket(data, length, marker);
93 | }
94 |
95 | public int sendPacket(byte[] data, int length, boolean marker) throws PacketGenerateException {
96 | RTPPacket packet = new RTPPacket();
97 | packet.setVersion(RTCPConstants.VERSION);
98 | packet.setPadding(RTCPConstants.PADDING);
99 | packet.setExtension(RTCPConstants.EXTENSION);
100 | int m = marker ? 1 : 0;
101 | packet.setMarker(m);
102 | packet.setPayloadtype(session.getPayloadType());
103 | packet.setSeqNum(sequence_number);
104 | packet.setTimeStamp(System.currentTimeMillis());
105 | packet.setSSRC(session.getOwnSource().getSSRC());
106 | packet.setData(data, 0, data.length);
107 | int pktLen = packet.generate(sendBuffer, 0);
108 |
109 | // invoke event for listeners
110 | session.onRTPSent(packet);
111 |
112 | sequence_number++;
113 | session.packetCount++;
114 | session.octetCount += data.length;
115 | session.getOwnSource().timeOfLastRTPSent = System.currentTimeMillis();
116 |
117 | logger.debug(" RTP_PKT_LEN:" + pktLen + " RTP_HEADER_LEN:"
118 | + " PAYLOAD_LEN:"+length);
119 | socket.sendTo(sendBuffer, pktLen , destPort);
120 |
121 | return pktLen;
122 | }
123 |
124 | /**
125 | * Starts the RTP Receiver. This method instantiates a multicast socket on
126 | * the multicast address and port specified and listens for packets on that
127 | * multicast group. When it receives a packet, it parses the packet out and
128 | * updates several session and source level statistics. It also posts an
129 | * event to the Application about the reception of an RTP Packet
130 | */
131 |
132 | public void run() {
133 | byte buf[] = new byte[1024];
134 | // DatagramPacket packet = new DatagramPacket(buf, buf.length);
135 | int packetLen;
136 | long lastTime = System.currentTimeMillis();
137 |
138 | while (!isStopped()) {
139 | packetLen = socket.receiveFrom(buf);
140 | if (packetLen == -1) {
141 | continue; // repeat - only timeout
142 | }
143 |
144 | lastTime = System.currentTimeMillis();
145 |
146 | if (validateRTPPacketHeader(buf)) {
147 |
148 | RTPPacket rtppkt = new RTPPacket();
149 | try {
150 | rtppkt.parse(buf, 0, packetLen);
151 | } catch (PacketParseException e) {
152 | logger.warn("Packet parsing failed");
153 | continue;
154 | }
155 |
156 | final int RTP_PACKET_HEADER_LENGTH = 12;
157 | final int RTP_PACKET_CSRC_LENGTH = 4 * rtppkt.getCSRCcount();
158 |
159 | // the payload is after the fixed 12 byte header
160 |
161 | // TODO: Neefektivni kod - zlepsit naroky na pamet
162 | byte payload[] = new byte[packetLen - RTP_PACKET_HEADER_LENGTH
163 | - RTP_PACKET_CSRC_LENGTH];
164 |
165 | for (int i = 0; i < payload.length; i++) {
166 | payload[i] = buf[i + RTP_PACKET_HEADER_LENGTH
167 | + RTP_PACKET_CSRC_LENGTH];
168 | // System.out.print(" "+payload[i]);
169 | }
170 |
171 | rtppkt.setData(payload, 0, payload.length);
172 |
173 | // Get the source corresponding to this SSRC
174 | Source src = session.getMemberOrCreateMember(rtppkt.getSSRC());
175 |
176 | if (rtppkt.getSSRC() != session.getOwnSource().ssrc) { // not me
177 |
178 | long curTime = System.currentTimeMillis();
179 |
180 | // store last received packet
181 | session.lastRTPPktReceived = rtppkt;
182 | src.timeOfLastRTPArrival = curTime;
183 |
184 | // actualize max timestamp seen
185 | if (src.update_seq(rtppkt.getSeqNum(), rtppkt.getTimeStamp())) {
186 |
187 | // if this is the first RTP Packet Received from
188 | // this source
189 | // then store the seq no. as its base
190 |
191 | session.onRTPReceive(rtppkt);
192 | // Source of RTP packet is not yet sender
193 | if (!src.isSender()) {
194 | src.setSender(true);
195 | // add saneder to Senders Table
196 | session.addSender(rtppkt.getSSRC(), rtppkt.getSeqNum());
197 | // call nottifier
198 | session.onNewSender(src);
199 | }
200 |
201 | // AudioPlayer2 player =
202 | // GuiFactory.getAudioPlayer();
203 | // player.play(payload, payload.length);
204 | }
205 | // else {
206 | // System.out.println("!!!!!!!!!!!!!!!!! NOT YET
207 | // VALIDATED"+src.ssrc);
208 | // }
209 | }
210 | } else {
211 | InetAddress from;
212 | try {
213 | from = InetAddress.getByAddress(socket.getRemoteAddress());
214 | logger.warn("Bad RTP Packet received From:" + from + " LEN:"
215 | + packetLen);
216 | // from = InetAddressFactory.newInetAddress(
217 | // socket.getRemoteAddress()).toString();
218 | } catch (UnknownHostException e) {
219 | // ok
220 | }
221 | }
222 | logger.debug("TIME FOR PROCESSING RTP PACKET: "
223 | + (System.currentTimeMillis() - lastTime));
224 | }
225 | }
226 |
227 | /**
228 | * Validates RTP Packet. Returns true or false corresponding to the test
229 | * results.
230 | *
231 | * @param packet
232 | * the packet
233 | *
234 | * @return True if validation was successful, False otherwise.
235 | */
236 |
237 | private boolean validateRTPPacketHeader(byte packet[]) {
238 | // +-+-+-+-+-+-+-+-+
239 | // |V=2|P|X| CC |
240 | // +-+-+-+-+-+-+-+-+
241 |
242 | if (packet.length <= 0) {
243 | logger.warn("packet.length <= 0: " + packet.length);
244 | return false;
245 | }
246 |
247 | // Version MUST be 2
248 | if (((packet[0] & 0xC0) >> 6) != 2) {
249 | // VersionValid = false;
250 | logger.warn("RTP version != 2: " + ((packet[0] & 0xC0) >> 6));
251 | return false;
252 | }
253 |
254 | // +-+-+-+-+-+-+-+-+
255 | // |M| PT |
256 | // +-+-+-+-+-+-+-+-+
257 | // 0 1 0 1 1 0 0 0
258 |
259 | // Payload Type must be the same as the session's
260 | if ((packet[1] & 0x7F) != session.getPayloadType()) {
261 | logger.warn("PAYLOAD TYPE != " + session.getPayloadType() + "("
262 | + (packet[1] & 0x7F) + ")");
263 |
264 | return false;
265 | }
266 | return true;
267 | }
268 | }

[all classes][cz.vutbr.feec.session.rtprtcp.internal]
EMMA 2.0.5312 EclEmma Fix 1 (C) Vladimir Roubtsov