March 20, 2011

Heuristic decode of RTP packets in practice

It is not possible to a distinguish RTP packet reliably without additional analysis of signaling.

Different ways are used to understand if some packet is RTP or not.
I've made investigation of the X company's IP sniffer module and the JNetPcap library.

You can find here methods used in these software. All these methods don't give a 100% exact decision.
You can find RTP header description in specification of RTP protocol.

X company's IP sniffer module

Analysis is done inside method IsValid() of RtpPacket class.
A decision is taken on base check of the three parameters: RTP version, payload type and header length.
  • The payload type is checked if it belongs to a valid range of values from 34 (H263) to 96 (DynMin).
  • The header length check is a little more complex.
    IPP calculates the RTP header length on base value the CSRC count (field CC) and padding (field P). During this step IPP supposes that a current packet is a RTP packet.
    Then it calculates the data length as a difference between the total packet length and the calculated header length - DataLen = TotalPacketLen - HeaderLen.
    After that it compares calculated data length with total packet length.
    If data length is bigger than total length then it is not RTP.
  • RTP version must be 2.

Source code:

bool RtpPacket::IsValid()
{
    //check for correct version
   if (version != 2) return false;
  
   //check for a known payload type
   if (payloadType > rtpPayloadH263 && payloadType < rtpPayloadDynMin) return false;

   if (dataLen >= totalLength) return false;

   return true;
}

 JNetPcap

Analysis is done inside function validate_rtp() of packet_protocol.cpp file (line 143 for version 1.3.b3).
The decision is taken by using more parameters. However I am not sure that probability of the recognition is higher. Let's consider the algorithm.
  • It checks the RTP version. The version must be 2 also.
  • The CSRC count check is empty. The JNetPcap check only low boundary. It must be greater than 15. But CSRC count is 4 bits field and it can't be more 15.
  • The payload check is much simpler. It also checks only low boundary. It must be greater than 25.
  • Sequence number is checked for zero.
  • SSRC is checked for zero.
  • Timestamp is checked for zero.
  • All other fields if any are also checked for zero.
  • If a packet has extension then extension length is also checked for out of bounds.

JNetPcap source code:

int validate_rtp(scan_t *scan) {
    if ((scan->buf_len - scan->offset) < sizeof(rtp_t)) {
        return INVALID;
    }
    register rtp_t *rtp = (rtp_t *)(scan->buf + scan->offset);
    if (rtp->rtp_ver != 2 ||
            rtp->rtp_cc > 15 ||
            rtp->rtp_type > 25 ||
            rtp->rtp_seq == 0 ||
            rtp->rtp_ts == 0 ||
            rtp->rtp_ssrc == 0
            ) {
                TRACE("INVALID header flad");
                CALL(debug_rtp(rtp));
                EXIT();
                return INVALID;
    }
    uint32_t *c = (uint32_t *)(rtp + 1);
    for (int i = 0; i < rtp->rtp_cc; i ++) {
        TRACE("CSRC[%d]=0x%x", i, BIG_ENDIAN32(c[i]));
        if (BIG_ENDIAN32(c[i]) == 0) {
            TRACE("INVALID CSRC entry is 0");
            EXIT();
            return INVALID;
        }
        /*
         * Check for any duplicates CSRC ids within the table. Normally there
         * can't be any duplicates.
         */
        for (int j = i + 1; j < rtp->rtp_cc; j ++) {
            if (BIG_ENDIAN32(c[i]) == BIG_ENDIAN32(c[j])) {
                TRACE("INVALID duplicates CSRC entries");
                EXIT();
                return INVALID;
            }
        }
    }
    if (rtp->rtp_ext) {
        rtpx_t * rtpx = (rtpx_t *)(
                    scan->buf +
                    scan->offset +
                    RTP_LENGTH +
                    (rtp->rtp_cc * 4));
        register int xlen = BIG_ENDIAN16(rtpx->rtpx_len) * 4;
        if ((!SCAN_IS_FRAGMENT(scan) &&
                (scan->offset + xlen > scan->wire_len))    ||
                (xlen > 1500) ) {
                    TRACE("INVALID rtpx_len > %d bytes (wire_len) in extension header",
                            scan->wire_len);
                    EXIT();
                    return INVALID;
        }
    }
    TRACE("OK");
    EXIT();
    CALL(debug_rtp(rtp));
    return RTP_ID;
}

March 2, 2011

C++/Qt vs Java

From my point of view, this article is useful for to realize possible risks.

Please find extracts from it below. The original article is attached at the end of the page.

Programmer efficiency

"Programmer-efficiency describes how efficiently (i.e. how quickly and accurately) a programmer with a given degree of experience and knowledge can implement a certain set of requirements in a particular programming language, including debugging and project setup time."

"Java has several features designed to make it more programmer-efficient. For example, unlike C++ (or C), the programmer does not have to explicitly "free" (give back) allocated memory resources to the operating system."

"Research shows that in practice, garbage collection and other Java features, do not have a major influence on the programmer-efficiency."

"In conclusion: both research and practice contradict the claim that Java programmers achieve a higher programmer-efficiency than C++ programmers."

Runtime efficiency

"Prechelt provides useful data. The amount of data he provides is huge, but he arrives at the conclusion that "a Java program must be expected to run at least 1.22 times as long as a C/C++ program".

"Note that he says at least; the average runtime of Java programs is even longer. Our own experience shows that Java programs tend to run about 2-3 times as long than their equivalent C/C++ programs for the same task."

Cross platform approaches

"It is the semi-interpreted nature of Java programs that makes the "compile once, run anywhere" approach of Java possible in the first place. Once a Java program is compiled into bytecode, it can be executed on any platform which has a JVM. In practice, this is not always the case, because of implementation differences in different JVMs, and because of the necessity to sometimes use native, non-Java code, usually written in C or C++, together with Java programs."

"But is the use of platform-independent bytecode the right approach for crossplatform applications? With a good cross-platform toolkit like Qt and good compilers on the various platforms, programmers can achieve almost the same by compiling their source code once for each platform: "write once, compile everywhere"."

"The question arises why it should be necessary to run the Java Virtual Machine in software; if a program can be implemented in software, it should also be possible to have hardware implement the same functionality."

Memory efficiency

"Java and C++ take completely different approaches to memory management. In C++, all memory management must be done explicitly by the programmer …. Java automatically de-allocates (frees) unused memory"

"Garbage collection is very convenient, but the trade offs are greater memory consumption and slower runtime speed. …. In addition to the higher memory requirements, the garbage collection process itself requires processing power … Since the garbage collector runs periodically, it can occasionally lead to Java programs "freezing" for a few seconds…..".

"The Qt toolkit takes a more efficient approach to easing the memory management task for its programmers: when an object is deleted, all dependant objects are automatically deleted too. Qt’s approach does not interfere with the programmer’s freedom to delete manually when they wish to."

"To sum up this discussion, we have found C++ to provide much better runtime- and memory-efficiency than Java, while having comparable programmer-efficiency."

Available libraries and tools

"The Java platform includes an impressive number of packages that provide hundreds of classes for all kinds of purposes, including graphical user interfaces, security, networking and other tasks. This is certainly an advantage of the Java platform. For each package available on the Java platform, there is at least one corresponding library for C++."

"However, this strength of Java is also one of its weaknesses. It becomes increasingly difficult for the individual programmer to find their way through the huge APIs."

"If Java has an advantage on the side of available libraries, C++ clearly has an advantage when it comes to available tools"

Conclusion

Both independent academic research and industrial experience demonstrate that the hype favouring Java is mostly unjustified, and that the C++/Qt combination is superior. This is mainly due to the runtime and memory efficiency problems in Java programs … and Java’s failure to deliver increased programmer efficiency. In various programming projects we have been involved in, junior-level programmers learnt Java faster, but more experienced and senior-level programmers (which are usually in charge of the application design and the implementation of the critical parts of an application) achieved better and faster results using C+.

References


Qt vs. Java: A Comparison of Qt and Java for Large- Scale, Industrial-Strength GUI Development