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 [RTCPInThread.java]

nameclass, %method, %block, %line, %
RTCPInThread.java0%   (0/1)0%   (0/10)0%   (0/719)0%   (0/143)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class RTCPInThread0%   (0/1)0%   (0/10)0%   (0/719)0%   (0/143)
<static initializer> 0%   (0/1)0%   (0/12)0%   (0/3)
RTCPInThread (SessionType, Session3550, SocketStrategy, int, String): void 0%   (0/1)0%   (0/47)0%   (0/12)
isSender (): boolean 0%   (0/1)0%   (0/8)0%   (0/1)
processAppPacket (int): int 0%   (0/1)0%   (0/18)0%   (0/4)
processByePacket (int): int 0%   (0/1)0%   (0/103)0%   (0/16)
processRR (int): int 0%   (0/1)0%   (0/19)0%   (0/4)
processRsiPacket (int): int 0%   (0/1)0%   (0/33)0%   (0/6)
processSDES (int): int 0%   (0/1)0%   (0/17)0%   (0/4)
processSR (int): int 0%   (0/1)0%   (0/19)0%   (0/4)
run (): void 0%   (0/1)0%   (0/443)0%   (0/89)

1package cz.vutbr.feec.session.rtprtcp.internal;
2 
3import java.net.DatagramPacket;
4 
5import org.apache.log4j.Logger;
6 
7import cz.vutbr.feec.packets.PacketParseException;
8import cz.vutbr.feec.packets.rsi.RSIPacket;
9import cz.vutbr.feec.packets.rtcp.AppPacket;
10import cz.vutbr.feec.packets.rtcp.ByePacket;
11import cz.vutbr.feec.packets.rtcp.ReceiverReportPacket;
12import cz.vutbr.feec.packets.rtcp.ReportPacket;
13import cz.vutbr.feec.packets.rtcp.SenderReportPacket;
14import cz.vutbr.feec.packets.rtcp.SDESPacket;
15import cz.vutbr.feec.session.SessionThread;
16 
17/**
18 * This class encapsulates the functionality to receive and parse out RTCP
19 * packets. This class provides a seperate thread to receive these RTCP Packets.
20 * Depending on the kind of RTCP packet received (e.g. SR, RR, SDES, BYE) the
21 * receiver parses them out correctly and updates several session and source
22 * level statistics. Each packet having been parsed posts an event to the
23 * application corresponding to the packet that the receiver received
24 */
25 
26public class RTCPInThread extends SessionThread {
27 
28        /** The logger. */
29        private static Logger logger = Logger.getLogger(RTCPInThread.class
30                        .getName());
31 
32        /** The socket. */
33        private SocketStrategy socket;
34 
35        /** Session to be operated with. */
36        private Session3550 session;
37 
38        // /** Counts bytes of packet (not compound). */
39        // private int offset = 0;
40 
41        private final int BUFFER_LENGTH = 1024;
42        /** The packet. */
43        private byte buffer[] = new byte[BUFFER_LENGTH];
44 
45        private final SessionType type;
46 
47        /**
48         * Constructor for sender session.
49         * 
50         * @param rtpSession
51         *            the rtp session
52         * @param rtcpPort
53         *            the rtcp port
54         * @param sock
55         *            the sock
56         */
57        public RTCPInThread(SessionType type, Session3550 rtpSession,
58                        SocketStrategy sock, int rtcpPort, String name) {
59                this.session = rtpSession;
60                this.type = type;
61                if (sock.isMulticastSocket()) {
62                        logger.debug("CREATING RTCP-IN THREAD (RECEIVER)");
63                        setName("RTCP-in(R)" + name);
64                } else {
65                        logger.debug("CREATING RTCP-IN THREAD (SENDER)");
66                        setName("RTCP-in(S)" + name);
67                }
68                this.socket = sock;
69        }
70 
71        /**
72         * Checks if is sender.
73         * 
74         * @return true, if is sender
75         */
76        private boolean isSender() {
77                return !socket.isMulticastSocket();
78        }
79 
80        /**
81         * Starts the RTCP Receiver Thread. The thread creates a new multicast
82         * socket according to the Multicast address and port provided in the
83         * constructor. Then the thread waits in idle state for the reception of a
84         * RTCP Packet. As soon as a RTCP Packet is received, the receiver first
85         * validates the RTCP Packet accoring to the following rules RTCP Header
86         * Validity Checks 1) Version should always =2 2) The payload type field of
87         * the first RTCP Packet should be SR or RR 3) The Padding Bit (P) should be
88         * zero for the first packet 4) The length fields of individual RTCP Packets
89         * must total to the overall length of the compound RTCP Packet
90         * 
91         * After the packet has been validated, it is parsed differently according
92         * to the type of packet (e.g. Sender Report, Receive Report, BYE, SDES)
93         * etc. For each packet parsed, session and source level statistics are
94         * updated and an event is posted for the application corresponding to the
95         * type of packet that was parsed.
96         */
97        public void run() {
98                // byte[] mirrorPacket = new byte[72];
99                // #################################################################
100 
101                DatagramPacket header;
102                header = new DatagramPacket(buffer, buffer.length);
103 
104                int offset = 0;
105                // #################################################################
106                // LISTEN FOR PACKETS
107                while (!isStopped()) {
108                        int recvLen;
109                        recvLen = socket.receiveFrom(header);
110 
111                        // every 500 miliseconds will be thrown this excpetion
112                        // to checked if thread has not been stoped
113                        if (recvLen == -1) {
114                                // So timeout expired
115                                continue;
116                        }
117                        logger.info("RTCP packet received. MC:"
118                                        + socket.isMulticastSocket() + " PORT:"
119                                        + socket.getBindedPort());
120                        /*******************************************************************
121                         * RTCP Header Validity Checks 1) Version should always =2 2) The
122                         * payload type field of the first RTCP Packet should be SR or RR 3)
123                         * The Padding Bit (P) should be zero for the first packet 4) The
124                         * length fields of individual RTCP Packets must total to the
125                         * overall length of the compound RTCP Packet
126                         ******************************************************************/
127 
128                        // RTCP Header Validity Check 2
129                        int payLoadType = (int) (buffer[1] & 0xff);
130                        if ((payLoadType != RTCPConstants.RTCP_SR)
131                                        & (payLoadType != RTCPConstants.RTCP_RR)) {
132                                // RTCP Header Validity Check 3
133                                if ((((buffer[0] & 0xff) >> 5) & 0x01) != 0) {
134                                        logger.warn("RTCP Header Check Fail :"
135                                                        + " First Padding bit not zero\n");
136                                }
137                        }
138 
139                        // Since a RTCP Packet may contain many types of RTCP Packets
140                        // Keep parsing the packets until the no. of bytes parsed =
141                        // total no of bytes read
142                        int totalBytesRead = 0;
143                        offset = 0;
144 
145                        // read SSRC from first SSRC or CSRC packet
146                        long SSRC = ((buffer[4] & 0xff) << 24) | ((buffer[5] & 0xff) << 16)
147                                        | ((buffer[6] & 0xff) << 8) | (buffer[7] & 0xff);
148 
149                        if (SSRC == session.getSSRC()) {
150                                // own packet - so skip its processing
151                                continue;
152                        }
153 
154                        int i = -1;
155                        boolean errorEccured = false;
156                        while (totalBytesRead < recvLen && !errorEccured) {
157                                // RTCP Header Validity Check 1
158                                i++;
159                                byte version = (byte) ((buffer[offset] & 0xff) >> 6);
160                                int pt = ((buffer[offset + 1] & 0xff));
161                                if (version != 0x02) {
162                                        logger.warn("RTCP Header Check Fail :" + " version:"
163                                                        + version + " pt:" + pt + " SSRC:" + SSRC + " MC:"
164                                                        + socket.isMulticastSocket() + " binded:"
165                                                        + socket.getBindedPort() + "." + "i:" + i);
166                                        break;
167 
168                                }
169 
170                                // Check the length of this particular packet
171                                // int length = (short) ((packet[bytesRead + 2] << 8) |
172                                // (packet[bytesRead + 3] & 0xff));
173 
174                                // Check the Payload type of this packet
175                                if (pt < 200) {
176                                        logger.warn("RTCP Header Check Fail :" + " Wrong PT :" + pt
177                                                        + " SSRC:" + SSRC + " MC:"
178                                                        + socket.isMulticastSocket() + " binded:"
179                                                        + socket.getBindedPort() + ".");
180                                        break;
181                                }
182 
183                                try {
184                                        if (pt == RTCPConstants.RTCP_SR) {
185                                                logger.debug("Sender Report (part:" + i
186                                                                + " of compound packet)");
187                                                offset += processSR(offset);
188                                        } else if (pt == RTCPConstants.RTCP_RR) {
189                                                logger.debug("Receiver Report (part:" + i
190                                                                + " of compound packet)");
191                                                offset += processRR(offset);
192                                        } else if (pt == RTCPConstants.RTCP_SDES) {
193                                                logger
194                                                                .debug("SDES (part:" + i
195                                                                                + " of compound packet)");
196                                                offset += processSDES(offset);
197                                        } else if (pt == RTCPConstants.RTCP_BYE) {
198                                                logger.debug("BYE (part:" + i + " of compound packet)");
199                                                offset += processByePacket(offset);
200                                        } else if (pt == RTCPConstants.RTCP_APP) {
201                                                logger.debug("APP (part:" + i + " of compound packet)");
202                                                offset += processAppPacket(offset);
203                                        } else if (pt == RTCPConstants.RTCP_RSI) {
204                                                logger.debug("RSI (part:" + i + " of compound packet)");
205                                                offset += processRsiPacket(offset);
206                                        } else {
207                                                logger.warn("Unknown packet received.");
208                                                break;
209                                        }
210                                } catch (PacketParseException e) {
211                                        logger.warn("Parsing of packet failed:" + e);
212                                        if (logger.isDebugEnabled()) {
213                                                e.printStackTrace();
214                                        }
215                                        errorEccured = true;
216                                }
217 
218                                // length reperesents 32-bit blocks + 32-bit header
219                                // length needs to be computed in octets RFC 3550, ch 6.3
220 
221                                totalBytesRead = offset;
222                        }
223 
224                        // Update avg RTCP size
225                        logger.debug(" ## R ## " + totalBytesRead);
226                        session.updateAvgPktLength(totalBytesRead);
227 
228                        // RTCP Header Validity Check 4
229                        if (totalBytesRead < recvLen) {
230                                // not yet whole compound packet processed
231 
232                                logger
233                                                .info("TotalBytesRead: "
234                                                                + totalBytesRead
235                                                                + " Header.getLength"
236                                                                + recvLen
237                                                                + "(2) RTCP Header Check Fail : "
238                                                                + "Bytes Read do not Match Total Packet Length TotalRead:"
239                                                                + totalBytesRead + " Header:"
240                                                                + header.getLength() + "\n");
241                                continue;
242                        } else {
243                                // mirror the received RTCP compound packet to the multicast
244                                // group
245                                if (totalBytesRead == recvLen) {
246                                        if (isSender()) {
247                                                session.mirrorPacketToMcastGroup(buffer, recvLen);
248                                                logger.debug("Mirroring -> multicast, port:"
249                                                                + session.getMirrorPacketDestPort());
250                                        }
251                                } else {
252                                        logger.warn("Received packet length does not match.");
253                                        break;
254                                }
255                        }
256                }
257        }
258 
259        /**
260         * Process SDES.
261         * 
262         * @throws PacketParseException
263         */
264        private int processSDES(int offset) throws PacketParseException {
265                SDESPacket sdes = new SDESPacket();
266                int len = sdes.parse(buffer, offset, BUFFER_LENGTH);
267 
268                session.onSDESReceive(sdes);
269 
270                return len;
271        }
272 
273        /**
274         * Process bye packet.
275         * 
276         * @throws PacketParseException
277         */
278        private int processByePacket(int offset) throws PacketParseException {
279                ByePacket bye = new ByePacket();
280                int len = bye.parse(buffer, offset, BUFFER_LENGTH);
281                session.onBYEReceive(bye);
282 
283                final int max = bye.getSSRCCount();
284 
285                // for every SSRC/CSRC received
286                for (int i = 0; i < max; i++) {
287                        // remove member from all lists
288                        Source src = session.getMemberOrInvalid(bye.getSSRC(i));
289                        assert src != null : "BYE odhlasuje clena ktery neni v session obsazen";
290                        session.removeMember(src.ssrc);
291 
292                        // TODO: se odesila ByePacket a prichazi Bye od jinych, musi pribyvat members !!!
293                        
294                        // according rfc 3550, ch 6.3.4
295                        session.tn = session.tc
296                                        + ((double) session.members / (double) session.pmembers)
297                                        * (session.tn - session.tc);
298                        session.tp = session.tc
299                                        - ((double) session.members / (double) session.pmembers)
300                                        * (session.tc - session.tp);
301                        session.pmembers = session.members;
302                }
303                return len;
304        }
305 
306        /**
307         * Process app packet.
308         * @throws PacketParseException 
309         */
310        private int processAppPacket(int offset) throws PacketParseException {
311                AppPacket pkt = new AppPacket();
312                int len = pkt.parse(buffer, offset, buffer.length);
313                
314                logger.warn("Warning parsing Application packet is not supported.");
315                
316                return len;
317        }
318 
319        /**
320         * Process app packet.
321         */
322        private int processRsiPacket(int offset) {
323                assert !type.equals(SessionType.RECEIVER) : "Receiver nesmi prijimat RSI pakety";
324 
325                RSIPacket rsi = new RSIPacket();
326                try {
327                        offset += rsi.parse(buffer, 0, offset);
328                        session.onRSIReceive(rsi);
329                } catch (PacketParseException e) {
330                        // it is ok
331                }
332                return offset;
333        }
334 
335        /**
336         * Process SR.
337         * 
338         * @throws PacketParseException
339         */
340        private int processSR(int offset) throws PacketParseException {
341                SenderReportPacket sr = new SenderReportPacket();
342                offset += sr.parse(buffer, offset, BUFFER_LENGTH);
343 
344                session.onSRReceive(sr);
345 
346                if (ConfigDebug.RTCP_RECEIVER_SR) {
347                        System.out.println("### R ###" + sr);
348                }
349                return offset;
350        }
351 
352        /**
353         * Process RR.
354         * 
355         * @throws PacketParseException
356         */
357        private int processRR(int offset) throws PacketParseException {
358                ReportPacket rr = new ReceiverReportPacket();
359                offset += rr.parse(buffer, offset, BUFFER_LENGTH);
360 
361                session.onRRReceive(rr);
362 
363                if (ConfigDebug.RTCP_RECEIVER_SR) {
364                        System.out.println("### R ###" + rr);
365                }
366                return offset;
367        }
368}

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