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]

name | class, % | method, % | block, % | line, %
--- | --- | --- | --- | ---
RTCPOutThread.java | 0% (0/1) | 0% (0/16) | 0% (0/867) | 0% (0/208)

### COVERAGE BREAKDOWN BY CLASS AND METHOD

name | class, % | method, % | block, % | line, %
--- | --- | --- | --- | ---
class RTCPOutThread | 0% (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)

1 | package cz.vutbr.feec.session.rtprtcp.internal;
2 |
3 | import java.net.DatagramPacket;
4 | import java.util.Enumeration;
5 |
6 | import org.apache.log4j.Logger;
7 |
8 | import cz.vutbr.feec.packets.PacketGenerateException;
9 | import cz.vutbr.feec.packets.rtcp.ByePacket;
10 | import cz.vutbr.feec.packets.rtcp.ReceiverReportPacket;
11 | import cz.vutbr.feec.packets.rtcp.ReportPacket;
12 | import cz.vutbr.feec.packets.rtcp.SenderReportPacket;
13 | import cz.vutbr.feec.packets.rtcp.ReportBlock;
14 | import cz.vutbr.feec.packets.rtcp.SDESChunk;
15 | import cz.vutbr.feec.packets.rtcp.SDESItem;
16 | import 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 |
27 | public 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