Giter Club home page Giter Club logo

pkts's Introduction

pkts.io

pkts.io is a pure java library for reading and writing pcaps. It's primary purpose is to manipulate/analyze existing pcaps, allowing you to build various tools around pcaps.

For full documentation, please see aboutsip.com


--- Old stuff that needs to be moved ---

There may be situations where you need to post process pcap files but the existing pcap libraries doesn't do the job for one reason or another. E.g., most of them are using libpcap under the hood and can therefore be challenging to get working across platforms.

However, if you do need more abilities that just reading you should check out the following libraries:

In fact, you should check them out anyway :-)

Details to be moved into javadoc...

Framers take raw data and only examines just enough of it in order to find the boundaries of the message and frame it. The result of this operation is a Frame.

A Frame contains raw data but has examined some of the information in the frame in order to be able to make decisions such as what payload it contains etc. A Frame can be asked to fully parse its data in order to produce a Packet.

A Packet is a parsed frame and has usually partially examined all the data within the frame to find all the necessary information about that particular protocol packet. However, everything in yajpcap is done lazily so even though the first pass of the data didn't find any obvious errors, there still can be some. If you really need to find out if all the data within the package is correct, you can call Packet.verify() which forces the packet to check everything and complain if it finds any errors.

How To

This section describes how to e.g. add a new protocol framer and how to test that it is working.

How to add a new protocol

  1. Define a new Protocol in the Protocol enum.
  2. Create a new Framer and add it into the appropriate package.
  3. Add a new Frame for the new protocol.
  4. Define and implement a new Packet, which is what we ultimately want.
  5. Register your new Framer with the FramerManager.
  6. Done...

Define new Protocol

Create a new Framer

Every protocol, no matter how simple it is, needs a Framer. The job of the framer is just to frame the entire message for that particular protocol. The framer is not supposed to do any extensive validation of the content, it should only concentrate on finding the boundaries of the data and that's it. The framer needs to be as fast as possible so feel free to make a lot of assumptions of the data. If it so happens that the data is corrupt in some way, that will later be detected when the content is parsed into a packet.

So, create a new protocol framer and add it to the corresponding framer layer. E.g., the most common thing to do is probably to create a new io.sipstack.application.application layer framer such as one for HTTP or RTP etc. In this case, that Framer (let's call is RTPFramer) should live in the package com.aboutsip.yajpcap.framer.layer7. Note, there is a helper interface in each different layer (such as Layer7Framer) that you probably want to extend.

Example: adding RTP

RTP (real-time transport protocol) is a simple protocol for transporting e.g. audio. We will use this protocol as an example of how to add a new protocol to yajpcap. RTP is defined in RFC3550.

Define a new Protocol

We are simply going to add the RTP enum into com.aboutsip.yajpcap.protocol.Protocol like so:

ICMP("icmp"), IGMP("igmp"), TCP("tcp"), UDP("udp"), SCTP("sctp"), SIP("sip"), SDP("sdp"), ETHERNET_II("eth"), SLL("sll"), IPv4( "ip"), PCAP("pcap"), RTP("rtp"), UNKNOWN("unknown");

Create a new Framer

Let's create a new RTPFramer and add it to the com.aboutsip.yajpcap.framer.layer7. We could implement the Framer interface directly but there is a helper interface for each layer that makes things a little more useful so let's implement the Layer7Framer instead.

package com.aboutsip.yajpcap.framer.layer7;

public final class RTPFramer implements Layer7Framer {

    private final FramerManager framerManager;

    public RTPFramer(final FramerManager framerManager) {
        this.framerManager = framerManager;
    }

    @Override
    public Protocol getProtocol() {
        return Protocol.RTP;
    }

    @Override
    public boolean accept(final Buffer data) throws IOException {
        return false;
    }

    @Override
    public Layer7Frame frame(final Layer4Frame parent, final Buffer buffer) throws IOException {
        return null;
    }
}

The above code is our skeleton for creating the new RTPFramer. I already implemented the getProtocol() method since it is so simple. Also, the constructor is taking a FramerManager, which we will be using later on so you probably want to include this one as well in your framer. The next steps are to implement the accept and frame methods.

Implementing the accept-method.

The purpose of the accept method is to check whether the supplied buffer could be an RTP frame or not. The trick here is to look ahead just as much as we need to figure out whether it is a good chance of this data being of the prefered type or not. In our case, the preferred type is of course RTP. Depending on the protocol you are adding, this can be easier said than done. E.g., in the case of HTTP you may look three bytes a head and see if those bytes either are "GET", "PUT", "DEL" (for delete) or "POS" (for post) and if so, then we will return true and hope that this indeed is an HTTP frame. Of course, there is a chance that these three bytes may just accidently are "GET" and then we will falsly report true. At the same time though, we cannot go over too much either since the entire yajpcap library would be so slow it would be useless. Hence, it is up to you to decide how much look ahead you need to do in order to be fairly confident that your packet is what you are looking for.

So, back to RTP. Unfortunately, there is no real good test to make sure that the data indeed is an RTP packet. Appendix 2 in RFC3550 describes one way of doing it but you really need a sequence of packets in order to be able to determine if this indeed is a RTP packet or not. The best is to analyze the session negotiation but here we are just looking at a single packet so can't do that. Therefore, we will only do what we can which isn't much. First, the size of the headers is always at least 12 bytes so let's verify that we have that. Also, the version of the RTP packet is most commonly 2 and you will find that in the first byte of the message. If both of these things are true then we return true.

public boolean accept(final Buffer data) throws IOException {

    if (data.readableBytes() < 12) {
        data.markReaderIndex();
        final Buffer b = data.readBytes(12);
        if (b.capacity() < 12) {
            return false;
        }
        data.resetReaderIndex();
    }

    final byte b = data.getByte(0);
    return ((b & 0xC0) >> 6) == 0x02;
}

Remember, this is a very basic check that is very likely to incorrectly claim that a packet is an RTP packet even though it is not.

Implementing the frame-method.

pkts's People

Contributors

aboutsip avatar ajansson76 avatar cbarrete avatar chenzhangg avatar dependabot[bot] avatar epall avatar giacobenin avatar gpolitis avatar joesaby avatar jonasborjesson avatar jonbo372 avatar joschi avatar kelnos avatar lucasec avatar mz0 avatar neonbunny avatar nragon avatar radonsky avatar teerapap avatar terje2001 avatar zeeshanasghar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pkts's Issues

is pkts support gprs [gb,gi,gn] protocol well?

hello,i'm deving a project about write pcap file by origin mysql table data, it's maybe need create a frame, and set frameNumber, srcIp,destIp,srcPort,destPort and so on into the object. After setting data, output those info into a pcap file.
I wonder if the pkts support gb,gi,gn protocol and write info into pcap file, thanks a lot!

IPv6 Support

This would be a really big issue for anyone wanting to use this in production as IPv6 is becoming more widespread.

For all packets, getProtocol() returns 'pcap'

Hi, this could be some kind of stupid mistake on my part, I'm fairly new to pcap stuff, so I hesitate to file an issue, but as far as I can tell I'm doing everything correctly.

I used Wireshark (Version 2.6.4 (v2.6.4-0-g29d48ec8)) to capture some UDP packets and saved them as "Wireshark/tcpdump/... - pcap". When I tried to read them using pkts, all of the packets return 'pcap' from getProtocol(). Loading them in tcpdump shows them as UDP packets.

Code, sample pcap file, and some screenshots, attached below.

AppPkts2.java.txt

jmavsim_px4_commander_startup2.pcap.gz

screen shot 2018-11-27 at 8 40 04 pm

screen shot 2018-11-27 at 8 42 12 pm

screen shot 2018-11-27 at 8 43 19 pm

Length is larger than buffer. Request=1226842144, capacity=262144

Exception in thread "main" java.lang.IllegalArgumentException: Length is larger than buffer. Request=1226842144, capacity=262144
at io.pkts.buffer.BoundedInputStreamBuffer.internalReadBytes(BoundedInputStreamBuffer.java:171)
at io.pkts.buffer.BoundedInputStreamBuffer.readBytes(BoundedInputStreamBuffer.java:131)
at io.pkts.framer.PcapFramer.frame(PcapFramer.java:66)
at io.pkts.Pcap.loop(Pcap.java:79)
at io.pkts.examples.streams.StreamsExample001.main(StreamsExample001.java:77)

what can I do ?

java.lang.NegativeArraySizeException

Hello,
we are using your library to parse a pcap file (which is correctly read by wireshark ) and get packet information of it.

But, when reading the second packet, the header of that packet is not placed correctly in the bytes stream, and gives error:

java.lang.NegativeArraySizeException
    at io.pkts.buffer.BoundedInputStreamBuffer.readBytes(BoundedInputStreamBuffer.java:145)
    at io.pkts.framer.PcapFramer.frame(PcapFramer.java:66)
...

Can this be avoided in any way?

I attach the 3000 first bytes of the pcap, so that you can analize it
http://www.frojasg1.com/small.pcap

I am new with your library, and I do not know if I am doing something badly.

I will be looking forward your answer.

kind regards,
Fran.

Unreadable output

The following code together with a pcap file created with tcpdump on an android emulator produces unreadable output. Opening the file with wireshark works fine.

File creation:

%ANDROID_SDK_ROOT%\emulator\emulator.exe -avd emulator1 -tcpdump out.pcap

Java-Code:

public void analyseCapFile(File pcapFile) {
        try {
            Pcap pcap = Pcap.openStream(pcapFile);
            pcap.loop(new PacketHandler() {
                @Override
                public boolean nextPacket(Packet packet) throws IOException {
                    if (packet.hasProtocol(Protocol.TCP)) {
                        System.out.println(packet.getPacket(Protocol.TCP).getPayload());
                    }
                    return true;
                }
            });
            pcap.close();
            Files.deleteIfExists(pcapFile.toPath());
        } catch (IOException e) {
            e.printStackTrace();
        }
}

Output example:

null
null
�-���Ž� POM(��n^o{����ʔq��[�&�$ �����5\3AM�^��_��<��Zw!(Ql�]��}��;������Q���0��(m��i8R����U�'G<j���e�XDT�}vYw��ҽ�+'�����ޘ���������<iץ0����r�C�}�l!������\���->(����֪G�c�LY�f�u���fU+*Ŧ���6VR-���� ٷ�Tpo����@-������+�8Ȭ\��;V �ݨѕ�� �g��q)�gp������d�1g�F���̩�l��T)�"d�|���M�/�H�lH��L��$��G������7�����q����F[�����Hw}/�% ��t��c�4ל�<L����M:%,�jz�� ��_��i������.�d3q�G2����r��Z�C;�<�ǺFl��u��)-����O�������D�Ik�[�j5=J����i@^��)Ǖ���z�VMoDR:$��cV����Q�-v����Jn�Ҩd\�b{>/�������3zS:'�T��2C�z��6��3,����S۩��
e˟U_�t?�Wv�U/H�-e�*�gs��oN} �����Eȍ��J��
����;x��X��UX�p�X��o�n�� �6"o�+�U�7������/#��8>���������Ď_���f�Ɉl�|��y�o������� ���j���/T�0�ː�u.��c���c��U�s��ۇ.y �� {E�%Wg��+ �����1�����am(����%^o��h��C��}���C��m��⵸����l�"΍0�[���6��+И9R��Q������$���v�xPZ������s
x�B+ǥ��O����Ƥ������M"H��K�4���& �[ȝY�O:�
�X��W�o�� =�5�By�l������D_���Z�&+�2����&#���6�D4�q��ɹ�Ik����+� ��q� 69����R��k�����6
�5_�c=�/����Z{�8�Z���@v ����r2��[�1�2О
�:�B���}�;�?X͋P�gA/zc$9��!��4�<��3dU,��Z/ڸ����

Missing method to specify the arrival time when creating Packets from scratch.

When writing data packets (read from another source, timestamped) into a PCAP file, it would be be nice to be able to set the arrival time to the time of that packet. And NOT the current system time.

In other words, I'm looking for a new method TransportPacketFactory.create(...,long arrivalTime) where I can explicitly specify the time of that packet. My processing time, is not the same as the packet's reception time.

Fast SIP header search

Hi,

For fast header indexing on SIP message shouldn't we use, for instance, LinkedHashMap or simply HashMap, on ImmutableSipMessage?
I have a use case where I only want some headers depending on user input.

Thanks,
Nuno

Buffer.equals - implement a more efficient version

Currently, the Buffer.equals will copy the underlying byte buffer and perform a Arrays.equal on them, which is simple enough but may not be very efficient if done frequently. Monitor this and if proven to be too slow/resource intense then just implement an Arrays.equals ourselves.

Java 9 module support ?

I'm not able to use the pkts-*.jar (buffer, core, sdp, sip, streams) inside a java 9/10/11 module project. It seems pkts have split packages. (JPMS modules do not allow split packages.)

This is the error I'm getting when building the project:
error: the unnamed module reads package io.pkts.packet.sip from both pkts.core and pkts.sip
error: the unnamed module reads package io.pkts.packet.sip.impl from both pkts.core and pkts.sip
error: module jsr305 reads package io.pkts.packet.sip from both pkts.core and pkts.sip
error: module jsr305 reads package io.pkts.packet.sip.impl from both pkts.core and pkts.sip
error: module error.prone.annotations reads package io.pkts.packet.sip from both pkts.core and pkts.sip
error: module error.prone.annotations reads package io.pkts.packet.sip.impl from both pkts.core and pkts.sip
error: module j2objc.annotations reads package io.pkts.packet.sip from both pkts.core and pkts.sip
error: module j2objc.annotations reads package io.pkts.packet.sip.impl from both pkts.core and pkts.sip
error: module animal.sniffer.annotations reads package io.pkts.packet.sip from both pkts.core and pkts.sip
error: module animal.sniffer.annotations reads package io.pkts.packet.sip.impl from both pkts.core and pkts.sip
error: module pkts.core reads package io.pkts.packet.sip from both pkts.core and pkts.sip
error: module pkts.core reads package io.pkts.packet.sip.impl from both pkts.core and pkts.sip
error: module pkts.sip reads package io.pkts.packet.sip from both pkts.core and pkts.sip
error: module pkts.sip reads package io.pkts.packet.sip.impl from both pkts.core and pkts.sip
error: module pkts.sdp reads package io.pkts.packet.sip from both pkts.core and pkts.sip
error: module pkts.sdp reads package io.pkts.packet.sip.impl from both pkts.core and pkts.sip
error: module pkts.buffers reads package io.pkts.packet.sip from both pkts.core and pkts.sip
error: module pkts.buffers reads package io.pkts.packet.sip.impl from both pkts.core and pkts.sip
error: module jain.sip.ri reads package io.pkts.packet.sip from both pkts.core and pkts.sip
error: module jain.sip.ri reads package io.pkts.packet.sip.impl from both pkts.core and pkts.sip
error: module guava reads package io.pkts.packet.sip from both pkts.core and pkts.sip
error: module guava reads package io.pkts.packet.sip.impl from both pkts.core and pkts.sip
error: module pkts.streams reads package io.pkts.packet.sip from both pkts.core and pkts.sip
error: module pkts.streams reads package io.pkts.packet.sip.impl from both pkts.core and pkts.sip

Do you have any solution for this? (Besides trying to merge all your jars in one).

Thank you,
Jay

Via header output does not enclose IPv6 host address with brackets

According to RFC3261, IPv6 address in host part of the Via header must be enclosed with brackets ('[' and ']')

Observed:
Via: SIP/2.0/UDP 2001:0db8:85a3:0042:1000:8a2e:0370:7334:5088;branch=hello

Expected:
Via: SIP/2.0/UDP [2001:0db8:85a3:0042:1000:8a2e:0370:7334]:5088;branch=hello

PCAPNG files: java.lang.IllegalArgumentException: Unknown header type

I have several PCAP files created using recent TCPDUMP on Linux. They start with the following bytes:

0a 0d 0d 0a 7c 00 00 00 4d 3c 2b 1a

The code in PcapGlobalHeader.parse doesn't seem to account for the first 8 bytes and looks for the byte order magic rightaway.
According to this page: https://www.winpcap.org/ntar/draft/PCAP-DumpFileFormat.html#sectionshb
the first 8 bytes are "Block Type = 0x0A0D0D0A" and "Block Total Length" respectively.

Only then comes the "Byte-Order Magic" bytes -- these are handled in the PcapGlobalHeader.parse method, but none of the expected formats seems to fit the actual bytes in my stream.

So even if I remove the first 8 bytes from the stream before passing it to Pcap.openStream, I still get
java.lang.IllegalArgumentException: Unknown header type.

This is using the 3.0.10 version.
My PCAP files open in wireshark GUI without problems.
So this seems like a pretty big gap in the current implementation. Or am I missing something?

SipMessageBuilder - How to replace existing `To:` header

Problem:
I want to replace existing To: header. How to do that? It seems the SipMessageBuilder has not method to do it because this withHeader(..) method adds the input as a new header. The message output results in double To: header.

public SipMessage.Builder<T> withToHeader(final ToHeader to) {

Example code:

SipMessage.Builder<SipResponse> builder = invite.createResponse(180).withReasonPhrase("Ringing");
ToHeader toHeader = invite.getToHeader();
if (toHeader.getTag() == null) {
    toHeader = toHeader.copy().withDefaultTag().build();
    builder.withToHeader(toHeader);
}
SipResponse res = builder.build();

Thanks

IndexOutOfBoundException when reading dumps bigger than 2 GB

When I open a Pcap file which is bigger than 2GB with Pcap.openstream, and loop through the packages, after a while I get an IndexOutOfboundExecption if the readed size has reached 2GB:

java.lang.IndexOutOfBoundsException
at java.io.SequenceInputStream.read(SequenceInputStream.java:202)
at io.pkts.buffer.BoundedInputStreamBuffer.readFromStream(BoundedInputStreamBuffer.java:203)
at io.pkts.buffer.BoundedInputStreamBuffer.internalReadBytes(BoundedInputStreamBuffer.java:139)
at io.pkts.buffer.BoundedInputStreamBuffer.readBytes(BoundedInputStreamBuffer.java:93)
at io.pkts.framer.PcapFramer.frame(PcapFramer.java:52)
at io.pkts.Pcap.loop(Pcap.java:77)
at com.hdsnetz.sip.Application.parse(Application.java:186)
at com.hdsnetz.sip.Application.main(Application.java:34)

SIP URI parser does not support IPv6 address

SipParser throws an exception when parsing SIP Contact header with IPv6 address in the SIP URI.

The header
Contact: <sip:user1@[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:34808;transport=TCP;ob>;expires=891

This exception is thrown

io.pkts.packet.sip.SipParseException: The SIP URI does not specify a valid host. Error encountered after 10 characters.
        at io.pkts.packet.sip.address.SipURI.frame(SipURI.java:242)
        at io.pkts.packet.sip.address.URI.frame(URI.java:74)
        at io.pkts.packet.sip.address.Address.frame(Address.java:152)
        at io.pkts.packet.sip.header.AddressParametersHeader.frame(AddressParametersHeader.java:43)
        at io.pkts.packet.sip.header.ContactHeader.frame(ContactHeader.java:60)
        at io.pkts.packet.sip.impl.SipParser.lambda$static$2(SipParser.java:206)
        at io.pkts.packet.sip.header.impl.SipHeaderImpl.ensure(SipHeaderImpl.java:75)
        at io.pkts.packet.sip.impl.SipParser.frame(SipParser.java:2185)
        ... 14 more
Caused by: io.pkts.packet.sip.SipParseException: The SIP URI does not specify a valid host. Error encountered after 6 characters.
        at io.pkts.packet.sip.impl.SipUserHostInfo$Parser.parse(SipUserHostInfo.java:184)
        at io.pkts.packet.sip.impl.SipUserHostInfo$Parser.access$100(SipUserHostInfo.java:89)
        at io.pkts.packet.sip.impl.SipUserHostInfo.frame(SipUserHostInfo.java:44)
        at io.pkts.packet.sip.impl.SipParser.consumeUserInfoHostPort(SipParser.java:1199)
        at io.pkts.packet.sip.address.SipURI.frame(SipURI.java:238)
        ... 24 more

Force usage of Quotes

I had some difficult times with old routers due to not usage of Quotes <> on SIP Addresses (At least by default).

Routes that do some kind of SIP parsing sometimes route the Sip message, sometimes they silent discard it.

To fix this, I inserted a "forceQuotes" variable to allow me controlling it, but I'm clearly doing the wrong way.
What is a proper way to configure this parameter in a class wide manner?

        public Address build() throws SipParseException {
            ...
            final Boolean forceQuotes = true;*
            final boolean yesAngleQuoteIt = yesDisplayName || uriBuilder.hasParameters() || forceQuotes;
            ...
            }

Thanks!

getContentTypeHeader

Original aboutsip/sipstack#4

[stormning]
After using sipMessage.getContentTypeHeader() ,
then use sipMessage.toBuffer().toString()
I found the contentTypeHeader value is missing

[stormning]
io.pkts.packet.sip.header.impl.ContentTypeHeaderImpl#transferValue
only transfer params to dst.
I modified it as below , and resolved the problem
@OverRide
protected void transferValue(Buffer dst) {
getValue().getBytes(0, dst);
super.transferValue(dst);
}

Infinite loop on Sip Parser

I'm having an infinite loop problem. Seems that the parser is trying to consume LWS or SWS.

It's kind rare to happen, I'm not sure if it's a mal formed SIP message, but the thread seems to enter in a loop.

Could you guys please take a look?

"atf_wrk-3" #16 daemon prio=5 os_prio=0 tid=0x00007fc5004dd000 nid=0x408 runnable [0x00007fc4e830c000] java.lang.Thread.State: RUNNABLE at java.lang.Throwable.fillInStackTrace(Native Method) at java.lang.Throwable.fillInStackTrace(Throwable.java:783) - locked <0x00000000dcddddd0> (a io.pkts.packet.sip.SipParseException) at java.lang.Throwable.<init>(Throwable.java:265) at java.lang.Exception.<init>(Exception.java:66) at java.lang.RuntimeException.<init>(RuntimeException.java:62) at io.pkts.packet.sip.SipException.<init>(SipException.java:24) at io.pkts.packet.sip.SipParseException.<init>(SipParseException.java:18) at io.pkts.packet.sip.impl.SipParser.consumeLWS(SipParser.java:1678) at io.pkts.packet.sip.impl.SipParser.consumeSWS(SipParser.java:730) at io.pkts.packet.sip.impl.SipParser.consumeSeparator(SipParser.java:960) at io.pkts.packet.sip.impl.SipParser.consumeSEMI(SipParser.java:861) at io.pkts.packet.sip.header.impl.ParametersSupport.consumeUntil(ParametersSupport.java:127) at io.pkts.packet.sip.header.impl.ParametersSupport.getParameter(ParametersSupport.java:101) at io.pkts.packet.sip.header.impl.ParametersImpl.getParameter(ParametersImpl.java:37) at io.pkts.packet.sip.header.impl.FromHeaderImpl.getTag(FromHeaderImpl.java:32) at com.dazsoft.discador.DialerFunctions.checkMinimumFields(DialerFunctions.java:288)

package io.pkts.packet.sip two times existent

Hi,

I had an issue with packets including the keyword "NOTIFY". Even though it was not a SIP packet, the function SipParser.couldBeSipMessage() caused an exception in SipInitalLine.parse(). The exception occured in a catch method (line 99) which calls method SipParseException.getErrorOffset(). The exception was "NoSuchMethodError" ... and I wondered why, because the method is existent in repository pkts-sip in class io.pkts.packet.sip.SipParseExtension.
After a while I found the reason for this exception, my project, it's a springboot project, includes the pkts-core and pkts-sip repository, because I primary want to parse pcap data for SIP messages. And I found package io.pkts.packt.sip in both repositories....
I guess that the package in pkts-core is old and discontinued isn't it ?

Buffer.equals - decide exactly what is considered to be equal

Currently, if two Buffers that originally were equal but one of them has read a few more bytes, then the two buffers are no longer considered equal but perhaps they should be? I.e., should the individual reader indices be taken into consideration when doing an equals operation?

MACAddress mix up in MacPacket

Hi there,

found another issue, the MAC address is mixed up. The source is destination and vice versa.
It's just a mix up in the order, the second mac is source and the first is destination. The change has to be done in MACPacket in functions getSourceMacAddress, getDestinationMacAddress and setMacAddress.

Source is 6 bytes from 6th
Destination is 6 bytes from 1st

SipMessage.clone() return bad format

SipMessage.clone() should be

INVITE sip:[email protected] SIP/2.0
Via: SIP/2.0/UDP 192.168.3.100:9000;branch=z9hG4bK.IQzUOQipR;rport
From: sip:[email protected];tag=3jx~hFRKz
To: sip:[email protected]
CSeq: 20 INVITE
Call-ID: 9e4hraVLt0
Max-Forwards: 70
Supported: outbound
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO, UPDATE
Content-Type: application/sdp
Content-Length: 518
Contact: sip:[email protected]:9000;+sip.instance="urn:uuid:b05bcba3-cd74-42b4-b1be-052ee0740fd2"
User-Agent: Linphone/3.8.1 (belle-sip/1.4.0)

v=0
o=600 286 2032 IN IP4 192.168.3.100
s=Talk
c=IN IP4 192.168.3.100
t=0 0

but i got

INVITE sip:[email protected] SIP/2.0
Via: SIP/2.0/UDP 192.168.3.100:9000;branch=z9hG4bK.IQzUOQipR;rport
From: sip:[email protected];tag=3jx~hFRKz
To: sip:[email protected]
CSeq: 20 INVITE
Call-ID: 9e4hraVLt0
Max-Forwards: 70
Supported: outbound
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO, UPDATE
Content-Type: application/sdp
Content-Length: 518
Contact: sip:[email protected]:9000;+sip.instance="urn:uuid:b05bcba3-cd74-42b4-b1be-052ee0740fd2"
User-Agent: Linphone/3.8.1 (belle-sip/1.4.0)
v=0
o=600 286 2032 IN IP4 192.168.3.100
s=Talk
c=IN IP4 192.168.3.100
t=0 0

it should have an empty line below User-Agent

Thoughts about SipParseExceptions (regarding issue #38 and #39)

Hello,

I'am not sure if someone still care about this project or not, but just in case, here're my thoughts:

I've posted issue 38 and 39 in the assumption that these maybe are errors. I found out it was errors, but errors caused by not correct header field values which are not corresponding to their specifaction. In my opinion this is not a task for a package parser like pkts. Because to throw Exceptions means that the package never occurs in application and even the Exception handling seems not to be correct, never throw an Execption out to the logs/stderr or another Exception will be thrown caused by a strange problem with the condtructor function of the class SipParseException.
I'am not saying that these informations wouldn't be useful they would, if they could be stored in another way, attached somehow to the packet.
If these format errors still throwing exceptions this library could not be used for analyzing SIP traffic for example, or just give the application layer a chnace to say to the counterpart that there is something wrong with the header field X.
I thought about a way to store these informations from defined exceptions somehow on the package, but in most cases where the exception will be thrown, there is no connection to the packet, only the buffer or a part of the package buffer ....
I would appreciate your ideas in that case. Otherwise I would propose that all format errors has just to be commented out, so that ALL SIP packages get into the application layer. Would you guys agree, I would make a fork and a pull request.

Move to ImmutableBuffers everywhere

Move to using ImmutableBuffer everywhere and then we can get rid of IOExceptions and stuff. This will be a slight API change though so will have to do that in a 4.0 version or something...

The values of Allow-Events (rfc3265) is being parsed as separate headers

In general, a header may allow for multiple header-values to be merged onto a single line separated by a comma. However, there are several headers in SIP that doesn't allow for this and Allow-Events is one of them. See RFC3265 section 7.4:

Allow-Events =  ( "Allow-Events" / "u" ) HCOLON event-type
                   *(COMMA event-type)

Meaning that Allow-Events has one or more event-types separated by a COMMA, which then effectively means that Allow-Events: one, two, three is actually a single header and not three headers merged into one.

uknown ether type

I used a wireless trace packet of .pcap format got this expection "uknown ether type"

Refactor the Buffer package

Refactor Buffer package. Have better support for the most commonly used type, which is a direct byte[] array type of Buffer. Also, create better support and structure for ReadOnlyBuffer and ImmutableBuffers.

  • New structure for buffers. May have Buffer, followed by StreamingBuffer and DirectBuffer, and variants of those for ReadOnly and perhaps even Immutable. This to better support the protocol packages that makes use of the immutable concept (the SIP & soon the Diameter implementation does this)
  • Clean-up some of the checked exceptions, such as IOException when reading, getting etc. It is just annoying since most of the times the buffer you may be using is a backed by a byte-array so there is no way you can have an IOException being thrown in the first place anyway... yet another early mistake of mine!
  • Ensure that all operations on e.g. a ReadOnlyBuffer will return the same so we don't have to cast all the freaking time. E.g. slice currently returns a Buffer so even though you do that operation on a ReadOnlyBuffer you will get back a Buffer that you have to cast. Annoying as s@#$

Allow: ACK, CANCEL, BYE ... parsed as VIA header

Found in Release Version 3.0.2

Replicate with:

		StringBuilder sb = new StringBuilder();
		sb.append("INVITE sip:[email protected] SIP/2.0\n");
		sb.append("Via: SIP/2.0/UDP 192.168.1.201:2048;branch=z9hG4bK-16gcnwrd28r3;rport\n");
		sb.append("From: \"Alice\" <sip:[email protected]>;tag=te94a023hw\n");
		sb.append("To: <sip:[email protected]>\n");
		sb.append("Call-ID: 313438313130343734353532333433-xehwxtcark7e\n");
		sb.append("CSeq: 1 INVITE\n");
		sb.append("Max-Forwards: 70\n");
		sb.append("User-Agent: snom300/8.7.5.17\n");
		sb.append("Contact: <sip:[email protected]:2048;line=8lif2g5m>;reg-id=1\n");
		sb.append("X-Serialnumber: 00041325476C\n");
		sb.append("P-Key-Flags: keys=\"3\"\n");
		sb.append("Accept: application/sdp\n");
		sb.append("Allow: INVITE, ACK, CANCEL, BYE, REFER, OPTIONS, NOTIFY, SUBSCRIBE, PRACK, MESSAGE, INFO, UPDATE\n");
		sb.append("Allow-Events: talk, hold, refer, call-info\n");
		sb.append("Supported: timer, 100rel, replaces, from-change\n");
		sb.append("Session-Expires: 3600\n");
		sb.append("Min-SE: 90\n");
		sb.append("Content-Type: application/sdp\n");
		sb.append("Content-Length: 403");
		sb.append("v=0\n");
		sb.append("o=root 722847273 722847273 IN IP4 192.168.1.201\n");
		sb.append("s=call\n");
		sb.append("c=IN IP4 192.168.1.201\n");
		sb.append("t=0 0\n");
		sb.append("m=audio 61856 RTP/AVP 9 0 8 3 99 112 18 101\n");
		sb.append("a=rtpmap:9 G722/8000\n");
		sb.append("a=rtpmap:0 PCMU/8000\n");
		sb.append("a=rtpmap:8 PCMA/8000\n");
		sb.append("a=rtpmap:3 GSM/8000\n");
		sb.append("a=rtpmap:99 G726-32/8000\n");
		sb.append("a=rtpmap:112 AAL2-G726-32/8000\n");
		sb.append("a=rtpmap:18 G729/8000\n");
		sb.append("a=fmtp:18 annexb=no\n");
		sb.append("a=rtpmap:101 telephone-event/8000\n");
		sb.append("a=fmtp:101 0-15\n");
		sb.append("a=ptime:20\n");
		sb.append("a=sendrecv\n");

		SipMessage msg = SipMessage.frame(sb.toString());
		
		System.out.println(msg.getViaHeaders());

InputStreamBuffer seems to be vestigial

It appears that io.pkts.buffer.InputStreamBuffer has been replaced by io.pkts.buffer.BoundedInputStreamBuffer in all usage. Given how similar the two classes are, does it make sense to delete the vestigial io.pkts.buffer.InputStreamBuffer? If not, can we extract a superclass to reduce duplication?

I ask because I'm poking around with why my code is slow, and it turns out that Buffer.readBytes(int) calls are forwarded all the way down to a low-level Channel that's really inefficient for short reads, so I want to find some place to buffer a few KB.

about the "<>" in the from header

pkts-sip version:1.0.5
code
FromHeader from = FromHeader.with().user("bob").host("example.com").build();
output
From: <sip:[email protected]>;tag=33d3a418

pkts-sip version:3.0.10
code
FromHeader from = FromHeader.builder().withUser("bob").withHost("example.com").build();
output
From: sip:[email protected];tag=live

I have a question,Why does output by version 3.0.10 have no "<>"
to header has the same problem
thanks a lot!!!

Via header fails to parse IPv6 with zero compression

Problem statement

The exception is thrown when it parses a Via header containing an IPv6 which is zero-compressed as it expects a full form IPv6 with certain number of colon(:).

Input

Via: SIP/2.0/TLS [2001:213:ab56::8]:12345;received=2001:213:ab56::8;rport=12345;branch=xxxxxx;alias

Exception

 io.pkts.packet.sip.SipParseException: Found 5 which seems odd. Expecting 0, 1,
 7 or 8 colons in the Via-host:port portion. Please check your traffic
       at io.pkts.packet.sip.impl.SipParser.consumeVia(SipParser.java:1394)
       at io.pkts.packet.sip.header.ViaHeader$Builder.<init>(ViaHeader.java:301)
       at io.pkts.packet.sip.header.ViaHeader.frame(ViaHeader.java:210)
       at io.pkts.packet.sip.impl.SipParser.lambda$static$17(SipParser.java:241)
       at io.pkts.packet.sip.header.impl.SipHeaderImpl.ensure(SipHeaderImpl.java:75)
       at io.pkts.packet.sip.impl.ImmutableSipMessage.getViaHeaders(ImmutableSipMessage.java:184)
       at io.pkts.packet.sip.impl.ImmutableSipRequest.createResponse(ImmutableSipRequest.java:72)
       at io.pkts.packet.sip.SipMessage.createResponse(SipMessage.java:110)

Consider default keyword for static interface methods.

IntelliJ barks at this code (static method may be invoked on containing interface class only). It seems to compile fine.

        SipRequest invite = SipRequest.invite(getRequestUri())
            .from(FromHeader.frame(Buffers.wrap("sip:" + getFrom())))
            .to(ToHeader.frame(Buffers.wrap(getRequestUri())))
            .via(via)
            .build();

I wonder if situations where you have that static frame() method if that should use the Java 8 default keyword for interface methods.

https://github.com/aboutsip/pkts/blob/master/pkts-sip/src/main/java/io/pkts/packet/sip/header/SipHeader.java#L88

For a 407/401 scenario, the state of the call is left at REJECTED

For a normal authentication flow, the SipStream is calculating the state of the call wrong. At the time it gets the 401/407 response it will move the state of the call over to REJECTED (should probably be un-authenticated instead) but if we get an INVITE that actually goes through ok then the state is still left at REJECTED. Suggestion: new state "UNAUTHORIZED" and the state machine allows for transitioning from this state back to whatever we have for the initial INVITE

NoSuchMethodError when parsing SUBSCRIBE packet

Hi there,

i've found an issue when parsing a trace which includes the packet which is included in the attached pcap file. It's a SUBSCRIBE. The exception stack trace looked like this:

Exception in thread "main" java.lang.NoSuchMethodError: io.pkts.packet.sip.SipParseException: method (Ljava/lang/String;)V not found
at io.pkts.packet.sip.header.ViaHeader$Builder.build(ViaHeader.java:500)
at io.pkts.packet.sip.header.ViaHeader.frame(ViaHeader.java:195)
at io.pkts.packet.sip.impl.SipParser.lambda$static$17(SipParser.java:220)
at io.pkts.packet.sip.impl.SipParser$$Lambda$18/1823923917.apply(Unknown Source)
at io.pkts.packet.sip.header.impl.SipHeaderImpl.ensure(SipHeaderImpl.java:75)
at io.pkts.packet.sip.impl.SipParser.frame2(SipParser.java:2088)
at io.pkts.packet.sip.impl.SipParser.frame(SipParser.java:1993)
at io.pkts.framer.SIPFramer.frame(SIPFramer.java:47)
at io.pkts.packet.impl.TransportPacketImpl.getNextPacket(TransportPacketImpl.java:233)
at io.pkts.packet.impl.AbstractPacket.getPacket(AbstractPacket.java:142)
at io.pkts.packet.impl.AbstractPacket.getPacket(AbstractPacket.java:151)
at io.pkts.packet.impl.AbstractPacket.getPacket(AbstractPacket.java:151)
at io.pkts.packet.impl.AbstractPacket.getPacket(AbstractPacket.java:151)
at io.pkts.packet.impl.AbstractPacket.hasProtocol(AbstractPacket.java:114)
at com.hdsnetz.sip.Application$1.nextPacket(Application.java:35)
at io.pkts.Pcap.loop(Pcap.java:83)
at com.hdsnetz.sip.Application.walk(Application.java:32)
at com.hdsnetz.sip.Application.main(Application.java:24)

The code I used was this:

private static void walk(){
try {
final Pcap pcap = Pcap.openStream("/home/thaeger/src/powerdebug/traces/1-04-0000000844/1-04-0000000844 (2)/2016-05-03_09-25-58/test.pcap");

        pcap.loop(new PacketHandler() {
            @Override
            public boolean nextPacket(Packet packet) throws IOException {
                if (packet.hasProtocol(Protocol.SIP)) {
                    //SipPacket p = (SipPacket) packet.getPacket(Protocol.SIP);
                    System.out.println(packet.getArrivalTime());
                }
                return true;
            }
        });
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

Any ideas ?
test.pcap.zip

sip://foo.bar.com is not a legal sip-uri

'/' is allowed in the user portion. However, in the example below, there is no user-portion since a user-portion MUST be followed by a "@" and in the below case it isn't, which means that the entire thing is a host-portion and in a host-portion, '/', is an illegal character...

final SipURI uri = SipURI.frame("sip://foo.bar.com");

REGISTER without FromUser will not be recognized as SIP paket

Hi,

I know, a REGISTER without FromUser doesn't make much sense, but to track down SIP issues it would be nice if such packet either be recognized as SIP paket, buit it doesn't.

Try to parse attached pcap which contains one register without FromUser.

Wireshark shows this paket too, without any problem ;-)

test.pcap.zip

How to create a Packet without parent?

Hi, I'm working. Sorry to distrub again.
I wanna create a PcapOutputStream instance and invoke it's write method to write a packet into which is a Ipv4 packet.
When I try to init a packet, the Packet constructor request me to pass a parent packet instance as Argument, but I don't know where is the parent packet can init and the parent packet don't need pass a parent packet argument.
Because I want to create a new pcap file by PcapOutputStream, but I don't know if there's a factory or defaultImpl way to init a parent packet or a create packet correct way, Could you offer a example like unit test code? Thanks!

IllegalArgumentException: Unknown header type

Hi,

I tried to read pcap file by this code:

#!/usr/bin/env groovy

@Grab('io.pkts:pkts-core:3.+')

import io.pkts.Pcap

Pcap pcap = Pcap.openStream('/tmp/icmp.pcap')

and got error:

Caught: java.lang.IllegalArgumentException: Unknown header type
java.lang.IllegalArgumentException: Unknown header type
        at io.pkts.frame.PcapGlobalHeader.parse(PcapGlobalHeader.java:207)
        at io.pkts.Pcap.openStream(Pcap.java:123)
        at io.pkts.Pcap.openStream(Pcap.java:152)
        at io.pkts.Pcap.openStream(Pcap.java:163)
        at io.pkts.Pcap$openStream.call(Unknown Source)
        at icmp.run(icmp.groovy:7)

File is valid:

$ tshark -r /tmp/icmp.pcap 
    1   0.000000    127.0.0.1 → 127.0.0.1    ICMP 98 Echo (ping) request  id=0x55be, seq=1/256, ttl=64
    2   0.000013    127.0.0.1 → 127.0.0.1    ICMP 98 Echo (ping) reply    id=0x55be, seq=1/256, ttl=64 (request in 1)

So, why I can't read it?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.