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

    Constructors
    Constructor and Description
    `FragmentedMessage(I2PAppContext ctx)`

  - ### Method Summary

    Methods
    Modifier and Type | Method and Description
    --- | ---
    `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`