All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.pkts.streams.impl.BasicSipStream Maven / Gradle / Ivy

The newest version!
/**
 * 
 */
package io.pkts.streams.impl;

import io.pkts.PcapOutputStream;
import io.pkts.frame.PcapGlobalHeader;
import io.pkts.packet.sip.SipPacket;
import io.pkts.packet.sip.SipPacketParseException;
import io.pkts.sdp.SDP;
import io.pkts.streams.SipStream;
import io.pkts.streams.StreamId;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;

/**
 * The {@link BasicSipStream} only does some very basic analysis of the SIP
 * messages in order to determine which dialog the message belongs to. It is
 * faster and consumes less memory than the {@link DefaultSipStream} but is not
 * capable of detecting so-called derived dialogs since it (falsely) assumes it
 * can use the call-id as a unique key for each dialog.
 * 
 * Also, if multiple pcaps are merged it will not always handle the case where
 * e.g. the initial message indicating the start of the stream shows up after we
 * have already seen other messages in the stream (could happen if you merge two
 * pcaps where the first pcap contains messages that arrived later time - hence,
 * you didn't merge the pcaps in cronological order). If you need this accuracy,
 * then you should be using the {@link DefaultSipStream} instead.
 * 
 * @author [email protected]
 */
public class BasicSipStream implements SipStream {

    /**
     * This is the unique identifier of this particular {@link SipStream}.
     * Currently, this is the same
     */
    private final StreamId streamIdentifier;

    private final SimpleCallStateMachine fsm;

    private final PcapGlobalHeader globalHeader;

    /**
     * 
     */
    public BasicSipStream(final PcapGlobalHeader globalHeader, final StreamId streamIdentifier) {
        this.globalHeader = globalHeader;
        this.streamIdentifier = streamIdentifier;
        this.fsm = new SimpleCallStateMachine(this.streamIdentifier.asString());
    }

    @Override
    public void addMessage(final SipPacket message) throws SipPacketParseException {
        this.fsm.onEvent(message);
    }

    public boolean isTerminated() {
        return this.fsm.isTerminated();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List getPackets() {
        return this.fsm.getMessages();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public long getPostDialDelay() throws SipPacketParseException {
        return this.fsm.getPostDialDelay();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public long getDuration() {
        return this.fsm.getDuration();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public StreamId getStreamIdentifier() {
        return this.streamIdentifier;
    }

    @Override
    public void write(final OutputStream out) throws IOException {
        for (final SipPacket msg : this.fsm.getMessages()) {
            msg.write(out);
        }
    }

    @Override
    public CallState getCallState() {
        return this.fsm.getCallState();
    }

    @Override
    public boolean handshakeComplete() {
        return this.fsm.isHandshakeCompleted();
    }

    @Override
    public boolean reTranmitsDetected() {
        return this.fsm.reTransmitsDetected();
    }

    @Override
    public void save(final String filename) throws IOException {
        final File file = new File(filename);
        final FileOutputStream os = new FileOutputStream(file);
        final PcapOutputStream out = PcapOutputStream.create(this.globalHeader, os);
        try {
            this.write(out);
        } catch (final IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            if (out != null) {
                out.close();
            }
        }
    }

    @Override
    public void save(final OutputStream out) throws IOException {
        this.globalHeader.write(out);
        this.write(out);
    }

    @Override
    public long getTimeOfFirstPacket() {
        return this.fsm.getTimeOfFirstMessage();
    }

    @Override
    public long getTimeOfLastPacket() {
        return this.fsm.getTimeOfLastMessage();
    }

    @Override
    public SipStream createEmptyClone() {
        return new BasicSipStream(this.globalHeader, this.streamIdentifier);
    }

    @Override
    public SDP getInviteSDP() throws SipPacketParseException {
        for (final SipPacket msg : this.fsm.getMessages()) {
            if (msg.isRequest() && msg.isInvite()) {
                return getSDPorNull(msg);
            }
        }
        return null;
    }

    @Override
    public SDP get200OkSDP() throws SipPacketParseException {
        for (final SipPacket msg : this.fsm.getMessages()) {
            if (msg.isResponse() && msg.isInvite() && msg.toResponse().isSuccess()) {
                return getSDPorNull(msg);
            }
        }
        return null;
    }

    private SDP getSDPorNull(final SipPacket msg) throws SipPacketParseException {
        final Object content = msg.getContent();
        if (content instanceof SDP) {
            return (SDP) content;
        }
        return null;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy