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

nameclass, %method, %block, %line, %
RTCPOutThread.java0%   (0/1)0%   (0/16)0%   (0/867)0%   (0/208)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class RTCPOutThread0%   (0/1)0%   (0/16)0%   (0/867)0%   (0/208)
<static initializer> 0%   (0/1)0%   (0/5)0%   (0/3)
AssembleRTCPReceptionReportBlock (Source): ReportBlock 0%   (0/1)0%   (0/35)0%   (0/9)
AssembleRTCPSourceDescriptionPacket (byte [], int): int 0%   (0/1)0%   (0/238)0%   (0/52)
RTCPOutThread (SessionType, Session3550, SocketStrategy, int, String): void 0%   (0/1)0%   (0/35)0%   (0/9)
assembleRTCPReportBlocks (ReportPacket): int 0%   (0/1)0%   (0/54)0%   (0/15)
delayRTCPSending (double): boolean 0%   (0/1)0%   (0/45)0%   (0/15)
fillBufferByePacket (String, byte [], int): int 0%   (0/1)0%   (0/22)0%   (0/5)
generateRTCPPacket (SessionType, byte [], int): int 0%   (0/1)0%   (0/49)0%   (0/10)
generateReceiverReportPacket (byte [], int): int 0%   (0/1)0%   (0/37)0%   (0/9)
generateSenderReportPacket (byte [], int): int 0%   (0/1)0%   (0/70)0%   (0/14)
getDestRtcpPort (): int 0%   (0/1)0%   (0/3)0%   (0/1)
onExpire (): void 0%   (0/1)0%   (0/189)0%   (0/43)
run (): void 0%   (0/1)0%   (0/30)0%   (0/9)
schedule (double): void 0%   (0/1)0%   (0/14)0%   (0/4)
sendPacket (byte [], int): int 0%   (0/1)0%   (0/37)0%   (0/8)
stopRTCPSender (): void 0%   (0/1)0%   (0/4)0%   (0/2)

1package cz.vutbr.feec.session.rtprtcp.internal;
2 
3import java.net.DatagramPacket;
4import java.util.Enumeration;
5 
6import org.apache.log4j.Logger;
7 
8import cz.vutbr.feec.packets.PacketGenerateException;
9import cz.vutbr.feec.packets.rtcp.ByePacket;
10import cz.vutbr.feec.packets.rtcp.ReceiverReportPacket;
11import cz.vutbr.feec.packets.rtcp.ReportPacket;
12import cz.vutbr.feec.packets.rtcp.SenderReportPacket;
13import cz.vutbr.feec.packets.rtcp.ReportBlock;
14import cz.vutbr.feec.packets.rtcp.SDESChunk;
15import cz.vutbr.feec.packets.rtcp.SDESItem;
16import cz.vutbr.feec.packets.rtcp.SDESPacket;
17 
18/**
19 * This class encapsulates the functionality to construct and send out an RTCP
20 * Packet. This class provides a separate thread to send out RTCP Packets. The
21 * thread is put to sleep for a specified amount of time ( as calculated using
22 * various RTCP parameters and reception feedback). When the thread moves out of
23 * the blocked (or sleep) state, it determines what kind of a RTCP Packets needs
24 * to be send out , constructs the appropriate RTCP packets and sends them
25 */
26 
27public class RTCPOutThread extends Thread {
28 
29        /** The scheduled time. */
30        private double scheduledTime = -1;
31 
32        /** The terminate. */
33        private boolean terminate;
34 
35        /** The logger. */
36        private static Logger logger = Logger.getLogger(RTCPOutThread.class
37                        .getName());
38 
39        /** Multicast Port for RTCP Packets destination. */
40        private int destRtcpPort;
41 
42        /**
43         * Multicast Socket for sending RTCP
44         */
45        // RtcpSenderSocket m_RTCPSenderSocket;
46        /**
47         * Flag used to determine when to terminate after sending a BYE
48         */
49 
50        /** The socket. */
51        private SocketStrategy socket;
52 
53        /** session using this thread. */
54        private Session3550 session;
55 
56        /** The member type. */
57        private final SessionType type;
58 
59        /**
60         * The Constructor. This thread is used by sender and receiver and its
61         * functionality is to construct and send RTCP packets.
62         * 
63         * @param rtpSession
64         *            the rtp session
65         * @param socket
66         *            the socket
67         * @param rtcpPort
68         *            the rtcp port
69         */
70        public RTCPOutThread(SessionType type, Session3550 rtpSession,
71                        SocketStrategy socket, int rtcpPort, String name) {
72                this.type = type;
73                this.destRtcpPort = rtcpPort;
74                this.session = rtpSession;
75                this.socket = socket;
76                setName("RTCP-out(" + type + "):" + name);
77        }
78 
79        /**
80         * Initializes the thread by creating a multicast socket on a specified
81         * address and a port It manages the thread initialization and blocking of
82         * the thread (i.e putting it to sleep for a specified amount of time) This
83         * function also implements the BYE backoff algorithm with Option B. The BYE
84         * Backoff Algorithm is used in order to avoid a flood of BYE packets when
85         * many users leave the system
86         * 
87         * Note : if a client has never sent an RTP or RTCP Packet, it will not send
88         * a BYE Packet when it leaves the group. For More Information : See the
89         * Flowchart
90         */
91 
92        public synchronized void stopRTCPSender() {
93                terminate = true;
94        }
95 
96        /**
97         * Starts RTCP thread.
98         */
99        public void run() {
100                // flag terminates the endless while loop
101                terminate = false;
102 
103                scheduledTime = session.computeInterval();
104                while (!session.isByeSent()) {
105 
106                        // If inturrepted during this sleep time, continue with execution
107                        boolean allTimeConsumed = delayRTCPSending(scheduledTime);
108 
109                        if (!allTimeConsumed) {
110                                logger.info("Requested bye packet.");
111                                // Sleep was interrupted, this only occurs if thread
112                                // was terminated to indicate a request to send a BYE packet
113                                session.setByeRequested(true);
114                        }
115 
116                        // See if it is the right time to send a RTCP packet or reschedule
117                        onExpire();
118                }
119        }
120 
121        /**
122         * Provides a wrapper around java sleep to handle exceptions in case when
123         * session wants to quit. Returns 0 is sleep was interrupted and 1 if all
124         * the sleep time was consumed.
125         * 
126         * @param miliSeconds
127         *            No. of miliseconds to sleep
128         * 
129         * @return 0 if interrupted, 1 if the sleep progressed normally (all time
130         *         consumed)
131         */
132 
133        private boolean delayRTCPSending(double miliSeconds) {
134                if (ConfigDebug.RTCP_GENERATOR_TIMER2) {
135                        System.out.println("### REQUESTED SLEEP: " + miliSeconds);
136                }
137                double startWaitingTime = System.currentTimeMillis();
138                for (;;) {
139                        boolean expired = true;
140                        try {
141                                if (ConfigDebug.RTCP_GENERATOR_TIMER2) {
142                                        System.out.println("### SLEEP:           "
143                                                        + ConfigDebug.toString(miliSeconds) + " mSec");
144                                }
145                                Thread.sleep((long) miliSeconds);
146                                double timeElapsed = ((double) System.currentTimeMillis())
147                                                - startWaitingTime;
148                                if (ConfigDebug.RTCP_GENERATOR_TIMER2) {
149                                        System.out.println("### WAKEUP AFTER:    "
150                                                        + ConfigDebug.toString(timeElapsed));
151                                }
152                        } catch (InterruptedException e) {
153                                double timeElapsed = ((double) System.currentTimeMillis())
154                                                - startWaitingTime;
155                                if (ConfigDebug.RTCP_GENERATOR_TIMER2) {
156                                        System.out.println("### SLEEP INTERUPTED:"
157                                                        + ConfigDebug.toString(timeElapsed) + " mSec");
158                                }
159                                // interupted, not expired
160                                expired = false;
161                        }
162                        if (expired) {
163                                break;
164                        }
165                }
166                double timeElapsed = ((double) System.currentTimeMillis())
167                                - startWaitingTime;
168                        logger.debug("### SLEEP FINISHED   "
169                                        + ConfigDebug.toString(timeElapsed / 1000) + " sec");
170                return true; // all the time consumed
171        }
172 
173        /**
174         * Top Level Function to assemble a compound RTCP Packet. This function
175         * determines what kind of RTCP Packet needs to be created and sent out. If
176         * this source is a sender (ie. generating RTP Packets), then a Sender
177         * Report (SR) is sent out otherwise a Receiver Report (RR) is sent out. An
178         * SDES Packet is appended to the SR or RR PAcket. If a BYE was requested by
179         * the application , a BYE PAcket is sent out.
180         * 
181         * @return length of generated packet
182         * @throws PacketGenerateException
183         */
184 
185        private int generateRTCPPacket(SessionType type, byte[] buffer, int offset)
186                        throws PacketGenerateException {
187 
188                // Determine if the packet is SR or RR
189                //
190                // Generate an SR packet if I am an active sender and did send an
191                // RTP packet since last time I sent an RTCP packet.
192                //
193                // if ( (rtpSession.isActiveSender() ) && (
194                // rtpSession.TimeOfLastRTCPSent < rtpSession.TimeOfLastRTPSent ) )
195                int length = 0;
196                if (type.equals(SessionType.SENDER)) {
197                        length = generateSenderReportPacket(buffer, offset);
198                } else if (type.equals(SessionType.RECEIVER)) {
199                        length = generateReceiverReportPacket(buffer, offset);
200                } else if (type.equals(SessionType.FEEDBACK_TARGET)) {
201 
202                }
203 
204                // Append an SDES packet
205                AssembleRTCPSourceDescriptionPacket(buffer, offset + length);
206 
207                // Append a BYE packet if necessary
208                if (session.isByeRequested()) {
209                        length += fillBufferByePacket("Quitting", buffer, offset + length);
210                }
211                return length;
212        }
213 
214        /***************************************************************************
215         * 
216         * Functions to assemble RTCP packet components.
217         * 
218         **************************************************************************/
219 
220        /**
221         * Creates a Sender Report RTCP Packet.
222         * 
223         * @return The Sender Report Packet.
224         * @throws PacketGenerateException
225         */
226 
227        private int generateSenderReportPacket(byte[] result, int offset)
228                        throws PacketGenerateException {
229                SenderReportPacket sr = new SenderReportPacket();
230                sr.setVersion(RTCPConstants.VERSION);
231                // 
232                // rc - generated automatically according to count of RBlocks
233                sr.setPadding(RTCPConstants.PADDING);
234                // payload = const 200
235                sr.setSSRC(session.getSSRC());
236                // ??? sr.setLength() - generated automaticaly
237 
238                sr.setNTP_timestamp_MSW(System.currentTimeMillis() >> 32);
239                sr.setNTP_timestamp_LSW(System.currentTimeMillis() & 0xFFFFFFFFL);
240                sr.setRTP_timestamp((long) session.tc + session.getRandomOffset());
241                sr.setSenderPacketCount(session.packetCount);
242                sr.setSenderOctetCount(session.octetCount);
243 
244                int RepBlockcount = assembleRTCPReportBlocks(sr);
245                // length = header(1) + SenderInfo(4)+ReportBlockCount*6
246                sr.setLength(1 + 5 + RepBlockcount * 6);
247 
248                session.onSRSent(sr);
249                int length = sr.generate(result, offset);
250 
251                return length;
252        }
253 
254        /**
255         * Creates the Reception reports by determining which source need to be
256         * included and makes calls to AssembleRTCPReceptionReportBlock function to
257         * generate the individual blocks. The function returns the fixed length
258         * RTCP Sender Info ( 5*32 bits or 20 bytes ).
259         * 
260         * @param report
261         *            the sr
262         * 
263         * @return The RTCP Reception Report Blocks
264         */
265 
266        private synchronized int assembleRTCPReportBlocks(ReportPacket report) {
267                // ######## RBlock #########
268                Enumeration<Source> sendersCollection = session.getSendersTable();
269                // Iterate through all the sources and generate packets for those
270                // that are active senders.
271                int count = 0;
272 
273                while (sendersCollection.hasMoreElements()) {
274 
275                        Source s = (Source) sendersCollection.nextElement();
276                        if (session.getSSRC() != s.ssrc) {
277                                if (count == 32) {
278                                        count--;
279                                        // TODO : Add logic for more than 31 Recption Reports - AN
280                                        System.err.println("Protocol is not designed yet to use "
281                                                        + " more then 31 senders");
282                                        break;
283                                }
284 
285                                if ((s.timeOfLastRTPArrival > session.getOwnSource().timeOfLastRTCPSent)
286                                                && (s.getSSRC() != session.getSSRC())) {
287                                        ReportBlock rb = AssembleRTCPReceptionReportBlock(s);
288                                        report.addReportBlock(rb);
289                                        count++;
290                                }
291                        }
292                }
293                return count;
294        }
295 
296        /**
297         * Creates a Receiver Report RTCP Packet.
298         * 
299         * @return byte[] The Receiver Report Packet
300         * @throws PacketGenerateException
301         */
302        private int generateReceiverReportPacket(byte[] buffer, int offset)
303                        throws PacketGenerateException {
304                ReportPacket rr = new ReceiverReportPacket();
305                rr.setVersion(RTCPConstants.VERSION);
306                // 
307                // rc - generated automatically according to count of RBlocks
308                rr.setPadding(RTCPConstants.PADDING);
309                // payload = const 200
310                rr.setSSRC(session.getSSRC());
311                // ??? sr.setLength() - generated automaticaly
312 
313                int noOfBlocks = assembleRTCPReportBlocks(rr);
314                // header(1)+ReportBlock*6
315                rr.setLength(1 + 6 * noOfBlocks);
316 
317                session.onRRSent(rr);
318                int length = rr.generate(buffer, offset);
319 
320                return length;
321        }
322 
323        /**
324         * Creates an Source Description SDES RTCP Packet.
325         * 
326         * @return length of generated packet.
327         * @throws PacketGenerateException
328         */
329 
330        private int AssembleRTCPSourceDescriptionPacket(byte[] buffer, int offset)
331                        throws PacketGenerateException {
332                /*
333                 * following figure from draft-ietf-avt-rtp-new-00.txt 0 1 2 3 0 1 2 3 4
334                 * 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
335                 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
336                 * |V=2|P| SC | PT=SDES=202 | length | header
337                 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ |
338                 * SSRC/CSRC_1 | chunk
339                 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1 |
340                 * SDES items | | ... |
341                 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ |
342                 * SSRC/CSRC_2 | chunk
343                 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2 |
344                 * SDES items | | ... |
345                 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
346                 */
347 
348                SDESPacket sp = new SDESPacket();
349                SDESChunk chunk = new SDESChunk();
350                chunk.setSSRC_CSRC(session.getOwnSource().getSSRC());
351 
352                // ###### CNAME #####
353                SDESItem item = new SDESItem();
354                item.setType(SDESItem.CNAME);
355                item.setText(session.getOwnSource().CNAME);
356 
357                chunk.addItem(item);
358 
359                if (session.getOwnSource().NAME != null
360                                && !session.getOwnSource().NAME.equals("")) {
361                        item = new SDESItem();
362                        item.setType(SDESItem.NAME);
363                        item.setText(session.getOwnSource().NAME);
364                        chunk.addItem(item);
365                }
366 
367                if (session.getOwnSource().EMAIL != null
368                                && !session.getOwnSource().EMAIL.equals("")) {
369                        item = new SDESItem();
370                        item.setType(SDESItem.EMAIL);
371                        item.setText(session.getOwnSource().EMAIL);
372                        chunk.addItem(item);
373                }
374 
375                if (session.getOwnSource().PHONE != null
376                                && !session.getOwnSource().PHONE.equals("")) {
377                        item = new SDESItem();
378                        item.setType(SDESItem.PHONE);
379                        item.setText(session.getOwnSource().PHONE);
380                        chunk.addItem(item);
381                }
382 
383                if (session.getOwnSource().LOC != null
384                                && !session.getOwnSource().LOC.equals("")) {
385                        item = new SDESItem();
386                        item.setType(SDESItem.LOC);
387                        item.setText(session.getOwnSource().LOC);
388                        chunk.addItem(item);
389                }
390 
391                if (session.getOwnSource().TOOL != null
392                                && !session.getOwnSource().TOOL.equals("")) {
393                        item = new SDESItem();
394                        item.setType(SDESItem.TOOL);
395                        item.setText(session.getOwnSource().TOOL);
396                        chunk.addItem(item);
397                }
398 
399                if (session.getOwnSource().NOTE != null
400                                && !session.getOwnSource().NOTE.equals("")) {
401                        item = new SDESItem();
402                        item.setType(SDESItem.NOTE);
403                        item.setText(session.getOwnSource().NOTE);
404                        chunk.addItem(item);
405                }
406 
407                if (session.getOwnSource().PRIV != null
408                                && !session.getOwnSource().PRIV.equals("")) {
409                        throw new RuntimeException(
410                                        "SDES PRIV packet has not been implemented yet WWW: "
411                                                        + session.getOwnSource().PRIV);
412 
413                        // item.setType(SDESItem.PRIV);
414                        // item.setText(rtpSession.getOwnSource().PRIV);
415                        // item.setSSRC(rtpSession.getOwnSource().getSSRC());
416                        //                        
417                        // chunk.addItem(item);
418                }
419                sp.addChunk(chunk);
420                session.onSDESSent(sp);
421                int length = sp.generate(buffer, offset);
422 
423                return length;
424        }
425 
426        /**
427         * Constructs a fixed length RTCP Reception. Report block ( 6*32 bits or 24
428         * bytes ) for a particular source.
429         * 
430         * @param RTPSource
431         *            the RTP source
432         * 
433         * @return The RTCP Reception Report Block
434         */
435 
436        private synchronized ReportBlock AssembleRTCPReceptionReportBlock(
437                        Source RTPSource) {
438                /*
439                 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ |
440                 * SSRC_1 (SSRC of first source) | report
441                 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
442                 * block | fraction lost | cumulative number of packets lost | 1
443                 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
444                 * extended highest sequence number received |
445                 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
446                 * interarrival jitter |
447                 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
448                 * last SR (LSR) |
449                 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
450                 * delay since last SR (DLSR) |
451                 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
452                 * 
453                 */
454 
455                ReportBlock rb = new ReportBlock();
456                rb.setSSRC(RTPSource.getSSRC());
457                rb.setFractionLost(RTPSource.getFraction());
458                rb.setCumulativeNumofPackLost(RTPSource.getLost());
459                rb.setExHIseqNumRec(RTPSource.getLast_seq());
460                rb.setInterArrJitter(RTPSource.getJitter());
461                rb.setLSR(RTPSource.getLsr());
462                rb.setDLSR((long) RTPSource.DLSR);
463 
464                // Update all the statistics associated with this source
465 
466                return rb;
467        }
468 
469        /**
470         * Constructs a "BYE" packet (PT=BYE=203).
471         * 
472         * @param reasonsForLeaving
473         *            the Reasons for leaving
474         * 
475         * @return The BYE Packet .
476         * @throws PacketGenerateException
477         */
478        private int fillBufferByePacket(String reasonsForLeaving, byte[] buffer,
479                        int offset) throws PacketGenerateException {
480                ByePacket bye = new ByePacket();
481                bye.addSSRC(session.getSSRC());
482                bye.setReasonText(reasonsForLeaving);
483                session.onBYESent(bye);
484                return bye.generate(buffer, offset);
485        }
486 
487        /**
488         * Sends the byte array RTCP packet. Zero return is error condition
489         * 
490         * @param buffer
491         *            the packet
492         * 
493         * @return 1 for success, 0 for failure.
494         */
495 
496        protected int sendPacket(byte buffer[], int length) {
497 
498                session.getOwnSource().timeOfLastRTCPSent = System
499                                .currentTimeMillis();
500                DatagramPacket DGram = new DatagramPacket(buffer, length, null,
501                                0);
502 
503                logger.info("SEND RTCP packet MC:" + socket.isMulticastSocket()
504                                + ",PORT:" + destRtcpPort);
505 
506                this.socket.send(DGram, destRtcpPort);
507                return 1;
508        }
509 
510        private byte[] expireBuffer = new byte[1500];
511 
512        /**
513         * On expire.
514         */
515        private void onExpire()
516        /*
517         * event e, int members, int senders, double rtcp_bw, int we_sent, double
518         * *avg_rtcp_size, int *initial, time_tp tc, time_tp *tp, int *pmembers)
519         */
520        {
521                // refresh informations about expiration of members
522                session.refresh();
523                /*
524                 * This function is responsible for deciding whether to send an RTCP
525                 * report or BYE packet now, or to reschedule transmission. It is also
526                 * responsible for updating the pmembers, initial, tp, and avg_rtcp_size
527                 * state variables. This function should be called upon expiration of
528                 * the event timer used by Schedule().
529                 */
530                final double tc = System.currentTimeMillis();
531                double t; /* Interval */
532                double tn; /* Next transmit time */
533 
534                /*
535                 * In the case of a BYE, we use "timer reconsideration" to reschedule
536                 * the transmission of the BYE if necessary
537                 */
538                if (session.isByeRequested()) {
539                        
540                        // TODO: Pokud je mene nez 50 prvku, tak neuvazovat 
541                        
542                        int length = 100;
543                        try {
544                                length = generateRTCPPacket(this.type, expireBuffer, 0);
545                                sendPacket(expireBuffer, length);
546                                logger.debug("BYE sent");
547                                session.setByeSent(true);
548                        } catch (PacketGenerateException e) {
549                                logger.error("Failed to generate packet");
550                                e.printStackTrace();
551                                System.exit(-1);
552                        }
553 
554                        session.prepareForByeTransmit(length);
555                        t = session.computeInterval();
556                        session.onSchedule(t, session);
557                        
558                        tn = session.tc + t;
559                        // TODO - nepracuje spravne 
560                        // 6.3.7 Transmitting a BYE Packet - rfc3550.txt
561                        logger.debug("tn <= tc: "+(tn <= tc)+" DIFF:"+(tn - tc));
562                        if (tn <= tc) {
563                                // send SR or RR packet
564                                stopRTCPSender(); // bye requested
565                                logger.info("Bye requested - stopping RTCP SENDER");
566                        } else {
567                                // naplanuje odeslani RTCP packetu v case tn
568                                schedule(tn - System.currentTimeMillis());
569                        }
570                } else {
571                        t = session.computeInterval();
572                        session.onSchedule(t, session);
573 
574                        tn = session.tp + t;
575                        if (tn <= tc) {
576                                // assembling could causes:
577                                // - onRRSent();
578                                // - onSRSent();
579                                // - onSDESSent();
580                                // - onByeSent();
581                                int length = 0;
582                                try {
583                                        length = generateRTCPPacket(this.type,
584                                                        expireBuffer, 0);
585                                        sendPacket(expireBuffer, length);
586                                        logger.debug("RTCP Interval  - sending RTCP packet, len:"
587                                                        + length + " + IP & UDP header");
588                                } catch (PacketGenerateException e) {
589                                        logger.error("Failed to send generate packet");
590                                        e.printStackTrace();
591                                        System.exit(-1);
592                                }
593 
594                                // send SR or RR packet
595                                session.updateAvgPktLength(length);
596                                session.tp = tc;
597 
598                                /*
599                                 * We must redraw the interval. Don't reuse the one computed
600                                 * above, since its not actually distributed the same, as we are
601                                 * conditioned on it being small enough to cause a packet to be
602                                 * sent
603                                 */
604 
605                                t = session.computeInterval();
606                                // naplanuje odeslani RTCP packetu v case t+tc
607                                schedule(t);
608                                session.initial = false;
609                        } else {
610                                // naplanuje odeslani packetu v case tn
611                                schedule(tn - System.currentTimeMillis());
612                        }
613                        session.pmembers = session.getMembersCount();
614                }
615        }
616 
617        /**
618         * Schedules expiration time for RTCP sending.
619         * 
620         * @param timeDelay
621         *            delay in milisec
622         */
623        protected synchronized void schedule(double timeDelay) {
624                scheduledTime = (long) timeDelay;
625 
626                if (scheduledTime < 0) {
627                        scheduledTime = 0;
628                }
629        }
630 
631        /**
632         * Gets the dest rtcp port.
633         * 
634         * @return the dest rtcp port
635         */
636        public int getDestRtcpPort() {
637                return destRtcpPort;
638        }
639}

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