Git Product home page Git Product logo

i2p-sam's Introduction

I2P SAM

An I2P SAM library: enabling applications to communicate through the I2P network. I2P is a fully distributed, "privacy-by-design" network.

To get I2P up and running, take a look at the project: https://github.com/diva-exchange/i2p

Use Cases

I2P is an instantly available peer-to-peer network which can be used for things like:

  • chat, social media and alike - all private and secure
  • distributed databases, aka blockchains (see https://testnet.diva.exchange as an example)
  • gaming, file sharing and ... whatever else you come up with

I2P is fully distributed, well researched and gets further developed by a competent community.

This I2P SAM library helps developers to create an I2P application quickly and hassle-free.

Get Started

npm i @diva.exchange/i2p-sam

or, lighter, without developer dependencies:

npm i --omit dev @diva.exchange/i2p-sam

Quick Start - Examples

How to Use Streams

Send an HTTP GET request to diva.i2p and output the response:

import { createStream } from '@diva.exchange/i2p-sam';

createStream({
  stream: {
    destination: 'diva.i2p'
  },
  sam: {
    host: '127.0.0.1',          # your local I2P SAM host
    portTCP: 7656               # your local I2P SAM port
  },
}).then((sam) => {
  sam.on('data', (data: Buffer) => {
    console.log('Incoming Data: ' + data.toString());
  });
  sam.send(Buffer.from('GET / HTTP/1.1\r\nHost: diva.i2p\r\n\r\n'));
});

Forward incoming streaming data to a local socket server:

import { createStream, createForward, I2pSamStream } from '@diva.exchange/i2p-sam';
import net from 'net';

(async () => {
  const serverForward = net.createServer((c) => {
    console.debug('client connected');
    c.on('end', () => {
      console.debug('client disconnected');
    });
    c.on('data', (data: Buffer) => {
      console.debug(data.toString());
      c.write(`Hello Client!\n`);
    });
  });
  serverForward.listen(20222, '127.0.0.1');

  const samForward: I2pSamStream = await createForward({
    sam: { 
      host: '127.0.0.1',      # your local I2P SAM host
      portTCP: 7656           # your local I2P SAM port
    },
    forward: {
      host: '127.0.0.1',      # your local listener, see above
      port: 20222,            # your local listener, see above
    },
  });

  const samClient: I2pSamStream = await createStream({
    sam: { 
      host: '127.0.0.1',        # your local I2P SAM host
      portTCP: 7656             # your local I2P SAM port
    },
    stream: {
      destination: samForward.getPublicKey()
    },
  });
  // event handler
  samClient.on('data', (data: Buffer) => {
    console.debug(data.toString());
  });
  // send some data to destination
  samClient.stream(Buffer.from(`Hi Server!\n`));
})();

How to Use Repliable Datagrams

Send messages from peer A to peer B through the I2P network:

import { createDatagram, toB32 } from '@diva.exchange/i2p-sam';

(async () => {
  // instantiate Peer A
  const peerA = await createDatagram({
    sam: {
      host: '127.0.0.1',          # your local I2P SAM host
      portTCP: 7656               # your local I2P SAM port
    }
  }); 
  
  // instantiate Peer B
  const peerB = await createDatagram({
    sam: {
      host: '127.0.0.1',          # your local I2P SAM host
      portTCP: 7656               # your local I2P SAM port
    },
    listen: { 
      address: '127.0.0.1',       # udp listener
      port: 20202                 # udp listener
    }
  }).on('data', (data: Buffer, from) => {
    console.debug(`Incoming Data from ${toB32(from)}: ${data.toString()}`);
  });

    
  // send 100 messages via UDP, every 500ms a message
  // IMPORTANT: UDP is not reliable. Some messages might get lost.
  const msg: string = 'Hello World';
  await new Promise((resolve) => {
    let t = 0;
    const i = setInterval(() => {
      peerA.send(peerB.getPublicKey(), Buffer.from(`${t} ${msg}`);
      if (t++ >= 100) {
        clearInterval(i);
        resolve(true);
      }
    }, 500);
  });
})();

How to Use Raw Datagrams

Send messages from peer A to peer B through the I2P network:

import { createRaw } from '@diva.exchange/i2p-sam';

(async () => {
  // instantiate Peer A
  const peerA = await createRaw({
    sam: {
      host: '127.0.0.1',            # your local I2P SAM host
      portTCP: 7656               # your local I2P SAM port
    }
  }); 
  
  // instantiate Peer B
  const peerB = await createRaw({
    sam: {
      host: '127.0.0.1',            # your local I2P SAM host
      portTCP: 7656               # your local I2P SAM port
    },
    listen: { 
      address: '127.0.0.1',       # udp listener
      port: 20202                 # udp listener
    }
  }).on('data', (data: Buffer) => {
    console.log('Incoming Data: ' + data.toString());
  });

  // send 100 messages via UDP, every 500ms a message
  // IMPORTANT: UDP is not reliable. Some messages might get lost.
  const msg: string = 'Hello Peer B - I am Peer A';
  await new Promise((resolve) => {
    let t = 0;
    const i = setInterval(() => {
      peerA.send(peerB.getPublicKey(), Buffer.from(`${t} ${msg}`);
      if (t++ >= 100) {
        clearInterval(i);
        resolve(true);
      }
    }, 500);
  });
})();

API

getPublicKey(): string

Get the public key of the local destination.

Example:

import { createDatagram } from '@diva.exchange/i2p-sam';

createDatagram({
  sam: {
    host: '127.0.0.1',          # your local I2P SAM host
    portTCP: 7656               # your local I2P SAM port
  }
}).then((sam) => console.log(sam.getPublicKey()));

getPrivateKey(): string

Get the private key of the local destination.

Example:

import { createDatagram } from '@diva.exchange/i2p-sam';

createDatagram({
  sam: {
    host: '127.0.0.1',          # your local I2P SAM host
    portTCP: 7656               # your local I2P SAM port
  }
}).then((sam) => console.log(sam.getPrivateKey()));

getKeyPair(): { public: string, private: string }

Get the public and private key of the local destination.

Example:

import { createStream } from '@diva.exchange/i2p-sam';

createStream({
  sam: {
    host: '127.0.0.1',          # your local I2P SAM host
    portTCP: 7656               # your local I2P SAM port
  },
  stream: {
    destination: 'diva.i2p'
  },
}).then((sam) => console.log(sam.getKeyPair()));

close()

Close a SAM connection.

Example:

import { createRaw } from '@diva.exchange/i2p-sam';

(async () => {
  const sam = await createRaw({
    sam: {
      host: '127.0.0.1',          # your local I2P SAM host
      portTCP: 7656               # your local I2P SAM port
    }
  });
  
  sam.close();
})();

toB32(destination: string): string

Convert a destination to a b32 address (without any extensions - just a Base32 string).

Example:

import { toB32 } from '@diva.exchange/i2p-sam';

console.log(toB32('[some base64-encoded destination]'));

createLocalDestination(c: Configuration): Promise<{ address: string, public: string, private: string }>

Create a new local destination and return its properties.

Example:

import { createLocalDestination } from '@diva.exchange/i2p-sam';

createLocalDestination({
  sam: {
    host: '127.0.0.1',          # your local I2P SAM host
    portTCP: 7656               # your local I2P SAM port
  }
}).then((obj) => console.log(obj));

lookup(c: Configuration, name: string): Promise<string>

Lookup (aka resolve) an I2P address (like diva.i2p or also a .b32.i2p address) to a destination. The destination, which is the public key, is a base64 encoded string.

Example:

import { lookup } from '@diva.exchange/i2p-sam';

lookup({
  sam: {
    host: '127.0.0.1',          # your local I2P SAM host
    portTCP: 7656               # your local I2P SAM port
  }
}, 'diva.i2p').then((dest) => console.log(dest));

stream(msg: Buffer)

Example: see the Get Started: How to Use Streams above.

send(destination: string, msg: Buffer)

Example: see Get Started: How to Use Datagrams above.

Configuration and its Defaults

type tSession = {
  id?: string;
  options?: string;
};

type tStream = {
  destination: string;
};

type tForward = {
  host: string;
  port: number;
  silent?: boolean;
};

type tListen = {
  address: string;
  port: number;
  hostForward?: string;
  portForward?: number;
};

type tSam = {
  host: string;
  portTCP: number;
  portUDP?: number;
  versionMin?: string;
  versionMax?: string;
  publicKey?: string;
  privateKey?: string;
};

export type Configuration = {
  session?: tSession;
  stream?: tStream;
  forward?: tForward;
  listen?: tListen;
  sam?: tSam;
};

type ConfigurationDefault = {
  session: tSession;
  stream: tStream;
  forward: tForward;
  listen: tListen;
  sam: tSam;
};

const DEFAULT_CONFIGURATION: ConfigurationDefault = {
  session: {
    id: '',
    options: '',
  },
  stream: {
    destination: '',
  },
  forward: {
    host: '',
    port: 0,
    silent: false,
  },
  listen: {
    address: '127.0.0.1',
    port: 0,
    hostForward: '',
    portForward: 0,
  },
  sam: {
    host: '127.0.0.1',
    portTCP: 7656,
    portUDP: 7655,
    versionMin: '',
    versionMax: '',
    publicKey: '',
    privateKey: '',
  },
};

Events

data

Incoming data.

error

Generic Error event - emitted if sockets report errors.

import { createRaw } from '@diva.exchange/i2p-sam';

(async () => {
  const sam = await createRaw({
    sam: {
      host: '127.0.0.1',          # your local I2P SAM host
      portTCP: 7656               # your local I2P SAM port
    }
  });
  sam.on('error', (error) => console.debug(error));
})();

close

Emitted if one of the involved sockets got closed.

How to Run Unit Tests

Assumptions:

  1. git, node and npm is available.
  2. docker and docker-compose is available.

Clone the source code from git git clone https://github.com/diva-exchange/i2p-sam.git and enter the folder i2p-sam.

Prepare the test environment by creating the docker container:

docker-compose -f test/sam.diva.i2p.yml up -d

Check whether the I2P test node is properly running by accessing the local console on: http://172.19.74.11:7070.

To modify the IP address of the local console, adapt the file test/sam.diva.i2p.yml.

After the docker container is running for about five minutes (reason: the I2P network needs some minutes to integrate), execute the unit tests:

npm run test

Executing the unit tests will take around 5 minutes. Reason: the communication via I2P gets tested - which is the purpose of this library.

Stop the container (and purge all data within):

docker-compose -f test/sam.diva.i2p.yml down --volumes

Linting

To lint the code, use

npm run lint

Contact the Developers

On DIVA.EXCHANGE you'll find various options to get in touch with the team.

Talk to us via Telegram https://t.me/diva_exchange_chat_de (English or German).

Donations

Your donation goes entirely to the project. Your donation makes the development of DIVA.EXCHANGE faster.

XMR: 42QLvHvkc9bahHadQfEzuJJx4ZHnGhQzBXa8C9H3c472diEvVRzevwpN7VAUpCPePCiDhehH4BAWh8kYicoSxpusMmhfwgx

BTC: 3Ebuzhsbs6DrUQuwvMu722LhD8cNfhG1gs

Awesome, thank you!

References

SAM docs: https://geti2p.net/en/docs/api/samv3

I2Pd: https://i2pd.readthedocs.io/

License

APACHE 2.0

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.