## net.i2p.router.tunnel
Class FragmentedMessage

    java.lang.Object
      net.i2p.router.tunnel.FragmentedMessage

    public class FragmentedMessage

extends Object

Gather fragments of I2NPMessages at a tunnel endpoint, making them available for reading when complete. Warning - this is all unsynchronized here - receivers must implement synchronization

Constructor Summary
`FragmentedMessage(I2PAppContext ctx)`

Method Summary
`void` `failed()`
`int` `getCompleteSize()`
`(package private) SimpleTimer.TimedEvent` `getExpireEvent()` used in the fragment handler so we can cancel the expire event on success
`int` `getFragmentCount()`
`long` `getLifetime()` how long has this fragmented message been alive?
`long` `getMessageId()`
`boolean` `getReleased()`
`long` `getReleasedAfter()`
`Hash` `getTargetRouter()`
`TunnelId` `getTargetTunnel()`
`boolean` `isComplete()` have we received all of the fragments?
`boolean` `receive(long messageId, byte[] payload, int offset, int length, boolean isLast, Hash toRouter, TunnelId toTunnel)` Receive the first fragment and related metadata.
`boolean` `receive(long messageId, int fragmentNum, byte[] payload, int offset, int length, boolean isLast)` Receive a followup fragment, though one of these may arrive at the endpoint prior to the fragment # 0.
`(package private) void` `setExpireEvent(SimpleTimer.TimedEvent evt)`
`byte[]` `toByteArray()`

`String`

`toString()`
public InputStream getInputStream() { return new FragmentInputStream(); } private class FragmentInputStream extends InputStream { private int _fragment; private int _offset; public FragmentInputStream() { _fragment = 0; _offset = 0; } public int read() throws IOException { while (true) { ByteArray ba = _fragments[_fragment]; if (ba == null) return -1; if (_offset >= ba.getValid()) { _fragment++; _offset = 0; } else { byte rv = ba.getData()[ba.getOffset()+_offset]; _offset++; return rv; } } } }

`void` `writeComplete(byte[] target, int offset)`
`void` `writeComplete(OutputStream out)`

Methods inherited from class java.lang.Object
`clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait`

Constructor Detail

### FragmentedMessage

    public FragmentedMessage(I2PAppContext ctx)

Method Detail

### receive

    public boolean receive(long messageId,
                           int fragmentNum,
                           byte[] payload,
                           int offset,
                           int length,
                           boolean isLast)

  Receive a followup fragment, though one of these may arrive at the endpoint prior to the fragment # 0.

  Parameters:
    `messageId` - what messageId is this fragment a part of
    `fragmentNum` - sequence number within the message (must be greater than 1)
    `payload` - data for the fragment
    `offset` - index into the payload where the fragment data starts (past headers/etc)
    `length` - how much past the offset should we snag?
    `isLast` - is this the last fragment in the message?

### receive

    public boolean receive(long messageId,
                           byte[] payload,
                           int offset,
                           int length,
                           boolean isLast,
                           Hash toRouter,
                           TunnelId toTunnel)

  Receive the first fragment and related metadata. This may not be the first one to arrive at the endpoint however.

  Parameters:
    `messageId` - what messageId is this fragment a part of
    `payload` - data for the fragment
    `offset` - index into the payload where the fragment data starts (past headers/etc)
    `length` - how much past the offset should we snag?
    `isLast` - is this the last fragment in the message?
    `toRouter` - what router is this destined for (may be null)
    `toTunnel` - what tunnel is this destined for (may be null)

### getMessageId

    public long getMessageId()

### getTargetRouter

    public Hash getTargetRouter()

### getTargetTunnel

    public TunnelId getTargetTunnel()

### getFragmentCount

    public int getFragmentCount()

### getExpireEvent

    SimpleTimer.TimedEvent getExpireEvent()

  used in the fragment handler so we can cancel the expire event on success

### setExpireEvent

    void setExpireEvent(SimpleTimer.TimedEvent evt)

### isComplete

    public boolean isComplete()

  have we received all of the fragments?

### getCompleteSize

    public int getCompleteSize()

### getLifetime

    public long getLifetime()

  how long has this fragmented message been alive?

### getReleased

    public boolean getReleased()

### writeComplete

    public void writeComplete(OutputStream out)
                       throws IOException

  Throws:
    `IOException`

### writeComplete

    public void writeComplete(byte[] target,
                              int offset)

### toByteArray

    public byte[] toByteArray()

### getReleasedAfter

    public long getReleasedAfter()

### failed

    public void failed()

### toString

    public String toString()

  public InputStream getInputStream() { return new FragmentInputStream(); } private class FragmentInputStream extends InputStream { private int _fragment; private int _offset; public FragmentInputStream() { _fragment = 0; _offset = 0; } public int read() throws IOException { while (true) { ByteArray ba = _fragments[_fragment]; if (ba == null) return -1; if (_offset >= ba.getValid()) { _fragment++; _offset = 0; } else { byte rv = ba.getData()[ba.getOffset()+_offset]; _offset++; return rv; } } } }

  Overrides:
    `toString` in class `Object`