618 lines
28 KiB
HTML
618 lines
28 KiB
HTML
{% extends "global/layout.html" %}
|
|
{% block title %}{{ _('Application Development') }}{% endblock %}
|
|
{% block lastupdated %}{% trans %}May 2013{% endtrans %}{% endblock %}
|
|
{% block accuratefor %}0.9.6{% endblock %}
|
|
{% block content %}
|
|
<h1>{{ _('Application Development Guide') }}</h1>
|
|
|
|
<h2>{{ _('Contents') }}</h2>
|
|
<ul>
|
|
<li><a href="#why">{{ _('Why write I2P-specific code?') }}</a></li>
|
|
<li><a href="#concepts">{{ _('Important concepts') }}</a></li>
|
|
<li><a href="#options">{{ _('Development options') }}</a></li>
|
|
<li><a href="#start"><b>{{ _('Start developing - a simple guide') }}</b></a></li>
|
|
</ul>
|
|
|
|
<h2 id="why">{{ _('Why write I2P-specific code?') }}</h2>
|
|
|
|
<p>{% trans i2ptunnel=site_url('docs/api/i2ptunnel') -%}
|
|
There are multiple ways to use applications in I2P.
|
|
Using <a href="{{ i2ptunnel }}">I2PTunnel</a>,
|
|
you can use regular applications without needing to program explicit I2P support.
|
|
This is very effective for client-server scenario's,
|
|
where you need to connect to a single website.
|
|
You can simply create a tunnel using I2PTunnel to connect to that website, as shown in <a href="#tunnel.serverclient">Figure 1</a>.
|
|
{%- endtrans %}</p>
|
|
<p>{% trans -%}
|
|
If your application is distributed, it will require connections to a large amount of peers.
|
|
Using I2PTunnel, you will need to create a new tunnel for each peer you want to contact,
|
|
as shown in <a href="#tunnel.peertopeer">Figure 2</a>.
|
|
This process can of course be automated, but running a lot of I2PTunnel instances creates a large amount of overhead.
|
|
In addition, with many protocols you will need to force everyone to
|
|
use the same set of ports for all peers - e.g. if you want to reliably run DCC
|
|
chat, everyone needs to agree that port 10001 is Alice, port 10002 is Bob, port
|
|
10003 is Charlie, and so on, since the protocol includes TCP/IP specific information
|
|
(host and port).
|
|
{%- endtrans %}</p>
|
|
<p>{% trans -%}
|
|
General network applications often send a lot of additional data that could be used to identify users.
|
|
Hostnames, port numbers, time zones, character sets, etc. are often sent without informing the user.
|
|
As such, designing the network protocol specifically with anonymity in mind
|
|
can avoid compromising user identities.
|
|
{%- endtrans %}</p>
|
|
<p>{% trans -%}
|
|
There are also efficiency considerations to review when determining how to
|
|
interact on top of I2P. The streaming library and things built on top of it
|
|
operate with handshakes similar to TCP, while the core I2P protocols (I2NP and I2CP)
|
|
are strictly message based (like UDP or in some instances raw IP). The important
|
|
distinction is that with I2P, communication is operating over a long fat network -
|
|
each end to end message will have nontrivial latencies, but may contain payloads
|
|
of up to several KB. An application that needs a simple request and response can get rid
|
|
of any state and drop the latency incurred by the startup and teardown handshakes
|
|
by using (best effort) datagrams without having to worry about MTU detection or
|
|
fragmentation of messages.
|
|
{%- endtrans %}</p>
|
|
|
|
<div class="box" id="tunnel.serverclient" style="text-align:center">
|
|
<img src="{{ url_for('static', filename='images/i2ptunnel_serverclient.png') }}" alt="{{ _('Creating a server-client connection using I2PTunnel only requires creating a single tunnel.') }}" title="{{ _('Creating a server-client connection using I2PTunnel only requires creating a single tunnel.') }}" />
|
|
<br /><br />
|
|
{{ _('Figure 1:') }} {{ _('Creating a server-client connection using I2PTunnel only requires creating a single tunnel.') }}
|
|
</div>
|
|
<br/>
|
|
|
|
<div class="box" id="tunnel.peertopeer" style="text-align:center">
|
|
<img src="{{ url_for('static', filename='images/i2ptunnel_peertopeer.png') }}" alt="{{ _('Setting up connections for a peer-to-peer applications requires a very large amount of tunnels.') }}" title="{{ _('Setting up connections for a peer-to-peer applications requires a very large amount of tunnels.') }}" />
|
|
<br /><br />
|
|
{{ _('Figure 2:') }} {{ _('Setting up connections for a peer-to-peer applications requires a very large amount of tunnels.') }}
|
|
</div>
|
|
<br/>
|
|
|
|
{% trans -%}
|
|
In summary, a number of reasons to write I2P-specific code:
|
|
{%- endtrans %}
|
|
<ul>
|
|
<li>{% trans -%}
|
|
Creating a large amount of I2PTunnel instances consumes a non-trivial amount of resources,
|
|
which is problematic for distributed applications (a new tunnel is required for each peer).
|
|
{%- endtrans %}</li>
|
|
<li>{% trans -%}
|
|
General network protocols often send a lot of additional data that can be used to identify users.
|
|
Programming specifically for I2P allows the creation of a network protocol
|
|
that does not leak such information, keeping users anonymous and secure.
|
|
{%- endtrans %}</li>
|
|
<li>{% trans -%}
|
|
Network protocols designed for use on the regular internet can be inefficient
|
|
on I2P, which is a network with a much higher latency.
|
|
{%- endtrans %}</li>
|
|
</ul>
|
|
|
|
|
|
<p>{% trans plugins=site_url('docs/plugins') -%}
|
|
I2P supports a standard <a href="{{ plugins }}">plugins interface</a> for developers
|
|
so that applications may be easily integrated and distributed.
|
|
{%- endtrans %}</p>
|
|
|
|
|
|
<p>{% trans -%}
|
|
Applications written in Java and accessible/runnable
|
|
using an HTML interface via the standard webapps/app.war
|
|
may be considered for inclusion in the i2p distribution.
|
|
{%- endtrans %}</p>
|
|
|
|
<h2 id="concepts">{{ _('Important concepts') }}</h2>
|
|
|
|
<p>{% trans -%}
|
|
There are a few changes that require adjusting to when using I2P:
|
|
{%- endtrans %}</p>
|
|
|
|
<h3>{{ _('Destination ~= host+port') }}</h3>
|
|
|
|
<p>{% trans -%}
|
|
An application running on I2P sends messages from and receives messages to a
|
|
unique cryptographically secure end point - a "destination". In TCP or UDP
|
|
terms, a destination could (largely) be considered the equivalent of a hostname
|
|
plus port number pair, though there are a few differences.
|
|
{%- endtrans %}</p>
|
|
|
|
<ul>
|
|
<li>{% trans -%}
|
|
An I2P destination itself is a cryptographic construct - all data sent to one is
|
|
encrypted as if there were universal deployment of IPsec with the (anonymized)
|
|
location of the end point signed as if there were universal deployment of DNSSEC.
|
|
{%- endtrans %}</li>
|
|
<li>{% trans -%}
|
|
I2P destinations are mobile identifiers - they can be moved from one I2P router
|
|
to another (or it can even "multihome" - operate on multiple routers at
|
|
once). This is quite different from the TCP or UDP world where a single end point (port)
|
|
must stay on a single host.
|
|
{%- endtrans %}</li>
|
|
<li>
|
|
<p>{% trans -%}
|
|
I2P destinations are ugly and large - behind the scenes, they contain a 2048 bit ElGamal
|
|
public key for encryption, a 1024 bit DSA public key for signing, and a variable size
|
|
certificate, which may contain proof of work or blinded data.
|
|
{%- endtrans %}</p>
|
|
<p>{% trans naming=site_url('docs/naming') -%}
|
|
There are existing ways to refer to these large and ugly destinations by short
|
|
and pretty names (e.g. "irc.duck.i2p"), but those techniques do not guarantee
|
|
globally uniqueness (since they're stored locally in a database on each person's machine)
|
|
and the current mechanism is not especially scalable nor secure (updates to the host list are
|
|
managed using "subscriptions" to naming services).
|
|
There may be some secure, human readable, scalable, and globally
|
|
unique, naming system some day, but applications shouldn't depend upon it being in place,
|
|
since there are those who don't think such a beast is possible.
|
|
<a href="{{ naming }}">Further information on the naming system</a> is available.
|
|
{%- endtrans %}</p>
|
|
</li>
|
|
</ul>
|
|
|
|
<p>{% trans datagrams=site_url('docs/api/datagrams') -%}
|
|
While most applications do not need to distinguish protocols and ports,
|
|
I2P <em>does</em> support them. Complex applications may specify a protocol,
|
|
from port, and to port, on a per-message basis, to multiplex traffic on
|
|
a single destination.
|
|
See the <a href="{{ datagrams }}">datagram page</a> for details.
|
|
Simple applications operate by listening for "all protocols" on "all ports" of a destination.
|
|
{%- endtrans %}</p>
|
|
|
|
<h3>{{ _('Anonymity and confidentiality') }}</h3>
|
|
|
|
<p>{% trans -%}
|
|
I2P has transparent end to end encryption
|
|
and authentication for all data passed over the network - if Bob sends to Alice's destination,
|
|
only Alice's destination can receive it, and if Bob is using the datagrams or streaming
|
|
library, Alice knows for certain that Bob's destination is the one who sent the data.
|
|
{%- endtrans %}</p>
|
|
|
|
<p>{% trans -%}
|
|
Of course, I2P transparently anonymizes the
|
|
data sent between Alice and Bob, but it does nothing to anonymize the content of what they
|
|
send. For instance, if Alice sends Bob a form with her full name, government IDs, and
|
|
credit card numbers, there is nothing I2P can do. As such, protocols and applications should
|
|
keep in mind what information they are trying to protect and what information they are willing
|
|
to expose.
|
|
{%- endtrans %}</p>
|
|
|
|
<h3>{{ _('I2P datagrams can be up to several KB') }}</h3>
|
|
|
|
<p>{% trans datagrams=site_url('docs/api/datagrams') -%}
|
|
Applications that use I2P datagrams (either raw or repliable ones) can essentially be thought
|
|
of in terms of UDP - the datagrams are unordered, best effort, and connectionless - but unlike
|
|
UDP, applications don't need to worry about MTU detection and can simply fire off large datagrams.
|
|
While the upper limit is nominally 32 KB, the message is fragmented for transport, thus dropping
|
|
the reliability of the whole. Datagrams over about 10 KB are not currently recommended.
|
|
See the <a href="{{ datagrams }}">datagram page</a> for details.
|
|
For many applications, 10 KB of data is sufficient for an
|
|
entire request or response, allowing them to transparently operate in I2P as a UDP-like
|
|
application without having to write fragmentation, resends, etc.
|
|
{%- endtrans %}</p>
|
|
|
|
<h2 id="options">{{ _('Development options') }}</h2>
|
|
|
|
<p>{% trans -%}
|
|
There are several means of sending data over I2P, each with their own pros and cons.
|
|
The streaming lib is the recommended interface, used by the majority of I2P applications.
|
|
{%- endtrans %}</p>
|
|
|
|
<h3>{{ _('Streaming Lib') }}</h3>
|
|
<p>{% trans streaming=site_url('docs/api/streaming') -%}
|
|
The <a href="{{ streaming }}">full streaming library</a> is now the standard
|
|
interface. It allows programming using TCP-like sockets, as explained in the <a href="#start.streaming">Streaming development guide</a>.
|
|
{%- endtrans %}</p>
|
|
|
|
<h3>BOB</h3>
|
|
<p>{% trans bob=site_url('docs/api/bob'), boburl=i2pconv('bob.i2p') -%}
|
|
BOB is the <a href="{{ bob }}">Basic Open Bridge</a>,
|
|
allowing an application in any language to make streaming connections
|
|
to and from I2P. At this point in time it lacks UDP support, but UDP support
|
|
is planned in the near future. BOB also contains several tools, such as
|
|
destination key generation, and verification that an address conforms to
|
|
I2P specifications. Up to date info and applications that use BOB can be
|
|
found at this <a href="http://{{ boburl }}/">eepsite</a>.
|
|
{%- endtrans %}</p>
|
|
|
|
|
|
<h3>SAM, SAM V2, SAM V3</h3>
|
|
|
|
<p><i>{{ _('SAM is not recommended. SAM V2 is okay, SAM V3 is recommended.') }}</i></p>
|
|
<p>{% trans sam=site_url('docs/api/sam') -%}
|
|
SAM is the <a href="{{ sam }}">Simple Anonymous Messaging</a> protocol, allowing an
|
|
application written in any language to talk to a SAM bridge through a plain TCP socket and have
|
|
that bridge multiplex all of its I2P traffic, transparently coordinating the encryption/decryption
|
|
and event based handling. SAM supports three styles of operation:
|
|
{%- endtrans %}</p>
|
|
<ul>
|
|
<li>{% trans -%}
|
|
streams, for when Alice and Bob want to send data to each other reliably and in order
|
|
{%- endtrans %}</li>
|
|
<li>{% trans -%}
|
|
repliable datagrams, for when Alice wants to send Bob a message that Bob can reply to
|
|
{%- endtrans %}</li>
|
|
<li>{% trans -%}
|
|
raw datagrams, for when Alice wants to squeeze the most bandwidth and performance as possible,
|
|
and Bob doesn't care whether the data's sender is authenticated or not (e.g. the data transferred
|
|
is self authenticating)
|
|
{%- endtrans %}</li>
|
|
</ul>
|
|
<p>{% trans -%}
|
|
SAM V3 aims at the same goal as SAM and SAM V2, but does not require
|
|
multiplexing/demultiplexing. Each I2P stream is handled by its own socket between the application
|
|
and the SAM bridge. Besides, datagrams can be sent and received by the application through datagram
|
|
communications with the SAM bridge.
|
|
{%- endtrans %}</p>
|
|
|
|
<p>{% trans sam=site_url('docs/api/sam'), samv2=site_url('docs/api/samv2'), samv3=site_url('docs/api/samv3') -%}
|
|
<a href="{{ samv2 }}">SAM V2</a> is a new version used by imule
|
|
that fixes some of the problems in <a href="{{ sam }}">SAM</a>.
|
|
<br />
|
|
<a href="{{ samv3 }}">SAM V3</a> is used by imule since version 1.4.0.
|
|
{%- endtrans %}</p>
|
|
|
|
<h3>I2PTunnel</h3>
|
|
<p>{% trans -%}
|
|
The I2PTunnel application allows applications to build specific TCP-like tunnels to peers
|
|
by creating either I2PTunnel 'client' applications (which listen on a specific port and connect
|
|
to a specific I2P destination whenever a socket to that port is opened) or I2PTunnel 'server'
|
|
applications (which listen to a specific I2P destination and whenever it gets a new I2P
|
|
connection it outproxies to a specific TCP host/port). These streams are 8-bit clean, and are
|
|
authenticated and secured through the same streaming library that SAM uses, but there is a
|
|
nontrivial overhead involved with creating multiple unique I2PTunnel instances, since each have
|
|
their own unique I2P destination and their own set of tunnels, keys, etc.
|
|
{%- endtrans %}</p>
|
|
|
|
<h3>SOCKS</h3>
|
|
<p>{% trans -%}
|
|
I2P supports a SOCKS V4 and V5 proxy.
|
|
Outbound connections work well. Inbound (server) and UDP functionality may be incomplete
|
|
and untested.
|
|
{%- endtrans %}</p>
|
|
|
|
<h3>Ministreaming</h3>
|
|
<p><i>{{ _('Removed') }}</i></p>
|
|
<p>{% trans -%}
|
|
There used to be a simple "ministreaming" library,
|
|
but now ministreaming.jar contains only the interfaces for the full streaming library.
|
|
{%- endtrans %}</p>
|
|
|
|
<h3>{{ _('Datagrams') }}</h3>
|
|
<p><i>{{ _('Recommended for UDP-like applications') }}</i></p>
|
|
<p>{% trans datagrams=site_url('docs/spec/datagrams') -%}
|
|
The <a href="{{ datagrams }}">Datagram library</a> allows sending UDP-like packets.
|
|
It's possible to use:
|
|
{%- endtrans %}</p>
|
|
<ul>
|
|
<li>{{ _('Repliable datagrams') }}</li>
|
|
<li>{{ _('Raw datagrams') }}</li>
|
|
</ul>
|
|
|
|
<h3>I2CP</h3>
|
|
<p><i>{{ _('Not recommended') }}</i></p>
|
|
<p>{% trans i2cp=site_url('docs/protocol/i2cp') -%}
|
|
<a href="{{ i2cp }}">I2CP</a> itself is a language independent protocol, but to implement an I2CP library
|
|
in something other than Java there is a significant amount of code to be written (encryption routines,
|
|
object marshalling, asynchronous message handling, etc). While someone could write an I2CP library in
|
|
C or something else, it would most likely be more useful to use the C SAM library instead.
|
|
{%- endtrans %}</p>
|
|
|
|
<h3>{{ _('Web Applications') }}</h3>
|
|
<p>{% trans -%}
|
|
I2P comes with the Jetty webserver, and configuring to use the Apache server instead is straightforward.
|
|
Any standard web app technology should work.
|
|
{%- endtrans %}</p>
|
|
|
|
<h2 id="start">{{ _('Start developing - a simple guide') }}</h2>
|
|
<p>{% trans -%}
|
|
Developing using I2P requires a working I2P installation and a development environment of your own choice.
|
|
If you are using Java, you can start development with the <a href="#start.streaming">streaming library</a> or datagram library.
|
|
Using another programming language, SAM or BOB can be used.
|
|
{%- endtrans %}</p>
|
|
|
|
<h3 id="start.streaming">{{ _('Developing with the streaming library') }}</h3>
|
|
|
|
<p>{% trans -%}
|
|
The following example shows how to create TCP-like client and server applications
|
|
using the streaming library.
|
|
{%- endtrans %}</p>
|
|
|
|
<p>{% trans -%}
|
|
This will require the following libraries in your classpath:
|
|
{%- endtrans %}</p>
|
|
<ul>
|
|
<li>$I2P/lib/streaming.jar: {{ _('The streaming library itself') }}</li>
|
|
<li>$I2P/lib/mstreaming.jar: {{ _('Factory and interfaces for the streaming library') }}</li>
|
|
<li>$I2P/lib/i2p.jar: {{ _('Standard I2P classes, data structures, API, and utilities') }}</li>
|
|
</ul>
|
|
|
|
<p>{% trans -%}
|
|
Network communication requires the usage of I2P network sockets.
|
|
To demonstrate this, we will create an application where a client can send text messages to a server,
|
|
who will print the messages and send them back to the client. In other words, the server will function as an echo.
|
|
{%- endtrans %}</p>
|
|
<p>{% trans -%}
|
|
We will start by initializing the server application. This requires getting an I2PSocketManager
|
|
and creating an I2PServerSocket.
|
|
We will not provide the I2PSocketManagerFactory with the saved keys for an existing Destination,
|
|
so it will create a new Destination for us.
|
|
So we will ask the I2PSocketManager for an I2PSession, so we can find out the Destination that
|
|
was created, as we will need to copy and paste that information later so the client can connect to us.
|
|
{%- endtrans %}</p>
|
|
<div class="box">
|
|
{% highlight lang='java' %}
|
|
package i2p.echoserver;
|
|
|
|
import net.i2p.client.I2PSession;
|
|
import net.i2p.client.streaming.I2PServerSocket;
|
|
import net.i2p.client.streaming.I2PSocketManager;
|
|
import net.i2p.client.streaming.I2PSocketManagerFactory;
|
|
|
|
public class Main {
|
|
|
|
public static void main(String[] args) {
|
|
//Initialize application
|
|
I2PSocketManager manager = I2PSocketManagerFactory.createManager();
|
|
I2PServerSocket serverSocket = manager.getServerSocket();
|
|
I2PSession session = manager.getSession();
|
|
//Print the base64 string, the regular string would look like garbage.
|
|
System.out.println(session.getMyDestination().toBase64());
|
|
//The additional main method code comes here...
|
|
}
|
|
|
|
}
|
|
{% endhighlight %}
|
|
<p style="text-align:center">{{ _('Code example 1: initializing the server application.') }}</p>
|
|
</div>
|
|
<p>{% trans -%}
|
|
Once we have an I2PServerSocket, we can create I2PSocket instances to accept connections from clients.
|
|
In this example, we will create a single I2PSocket instance, that can only handle one client at a time.
|
|
A real server would have to be able to handle multiple clients.
|
|
To do this, multiple I2PSocket instances would have to be created, each in separate threads.
|
|
Once we have created the I2PSocket instance, we read data, print it and send it back to the client.
|
|
The bold code is the new code we add.
|
|
{%- endtrans %}</p>
|
|
<div class="box">
|
|
{% highlight lang='java',
|
|
hl_lines=[3,4,5,6,7,8,9,10,26,27,28,29,30,33,35,36,37,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,68,70] %}
|
|
package i2p.echoserver;
|
|
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.OutputStream;
|
|
import java.net.ConnectException;
|
|
import java.net.SocketTimeoutException;
|
|
import net.i2p.I2PException;
|
|
import net.i2p.client.streaming.I2PSocket;
|
|
import net.i2p.util.I2PThread;
|
|
|
|
import net.i2p.client.I2PSession;
|
|
import net.i2p.client.streaming.I2PServerSocket;
|
|
import net.i2p.client.streaming.I2PSocketManager;
|
|
import net.i2p.client.streaming.I2PSocketManagerFactory;
|
|
|
|
public class Main {
|
|
|
|
public static void main(String[] args) {
|
|
I2PSocketManager manager = I2PSocketManagerFactory.createManager();
|
|
I2PServerSocket serverSocket = manager.getServerSocket();
|
|
I2PSession session = manager.getSession();
|
|
//Print the base64 string, the regular string would look like garbage.
|
|
System.out.println(session.getMyDestination().toBase64());
|
|
|
|
//Create socket to handle clients
|
|
I2PThread t = new I2PThread(new ClientHandler(serverSocket));
|
|
t.setName("clienthandler1");
|
|
t.setDaemon(false);
|
|
t.start();
|
|
}
|
|
|
|
private static class ClientHandler implements Runnable {
|
|
|
|
public ClientHandler(I2PServerSocket socket) {
|
|
this.socket = socket;
|
|
}
|
|
|
|
public void run() {
|
|
while(true) {
|
|
try {
|
|
I2PSocket sock = this.socket.accept();
|
|
if(sock != null) {
|
|
//Receive from clients
|
|
BufferedReader br = new BufferedReader(new InputStreamReader(sock.getInputStream()));
|
|
//Send to clients
|
|
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));
|
|
String line = br.readLine();
|
|
if(line != null) {
|
|
System.out.println("Received from client: " + line);
|
|
bw.write(line);
|
|
bw.flush(); //Flush to make sure everything got sent
|
|
}
|
|
sock.close();
|
|
}
|
|
} catch (I2PException ex) {
|
|
System.out.println("General I2P exception!");
|
|
} catch (ConnectException ex) {
|
|
System.out.println("Error connecting!");
|
|
} catch (SocketTimeoutException ex) {
|
|
System.out.println("Timeout!");
|
|
} catch (IOException ex) {
|
|
System.out.println("General read/write-exception!");
|
|
}
|
|
}
|
|
}
|
|
|
|
private I2PServerSocket socket;
|
|
|
|
}
|
|
|
|
}
|
|
{% endhighlight %}
|
|
<p style="text-align:center">{{ _('Code example 2: accepting connections from clients and handling messages.') }}</p>
|
|
</div>
|
|
|
|
|
|
<p>{% trans -%}
|
|
When you run the above server code, it should print something like this (but without the line endings, it should just be
|
|
one huge block of characters):
|
|
{%- endtrans %}
|
|
<pre id="start.streaming.destination">
|
|
y17s~L3H9q5xuIyyynyWahAuj6Jeg5VC~Klu9YPquQvD4vlgzmxn4yy~5Z0zVvKJiS2Lk
|
|
poPIcB3r9EbFYkz1mzzE3RYY~XFyPTaFQY8omDv49nltI2VCQ5cx7gAt~y4LdWqkyk3au
|
|
6HdfYSLr45zxzWRGZnTXQay9HPuYcHysZHJP1lY28QsPz36DHr6IZ0vwMENQsnQ5rhq20
|
|
jkB3iheYJeuO7MpL~1xrjgKzteirkCNHvXN8PjxNmxe-pj3QgOiow-R9rEYKyPAyGd2pe
|
|
qMD-J12CGfB6MlnmH5qPHGdZ13bUuebHiyZ1jqSprWL-SVIPcynAxD2Uu85ynxnx31Fth
|
|
nxFMk07vvggBrLM2Sw82pxNjKDbtO8reawe3cyksIXBBkuobOZdyOxp3NT~x6aLOxwkEq
|
|
BOF6kbxV7NPRPnivbNekd1E1GUq08ltDPVMO1pKJuGMsFyZC4Q~osZ8nI59ryouXgn97Q
|
|
5ZDEO8-Iazx50~yUQTRgLMOTC5hqnAAAA
|
|
</pre>
|
|
{% trans -%}
|
|
This is the base64-representation of the server Destination. The client will need this string to reach the server.
|
|
{%- endtrans %}</p>
|
|
|
|
<p>{% trans -%}
|
|
Now, we will create the client application. Again, a number of steps are required for initialization.
|
|
Again, we will need to start by getting an I2PSocketManager.
|
|
We won't use an I2PSession and an I2PServerSocket this time.
|
|
Instead, we will use the server Destination string to start our connection.
|
|
We will ask the user for the Destination string, and create an I2PSocket using this string.
|
|
Once we have an I2PSocket, we can start sending and receiving data to and from the server.
|
|
{%- endtrans %}</p>
|
|
<div class="box">
|
|
{% highlight lang='java' %}
|
|
package i2p.echoclient;
|
|
|
|
import java.io.BufferedReader;
|
|
import java.io.BufferedWriter;
|
|
import java.io.IOException;
|
|
import java.io.InputStreamReader;
|
|
import java.io.InterruptedIOException;
|
|
import java.io.OutputStream;
|
|
import java.io.OutputStreamWriter;
|
|
import java.net.ConnectException;
|
|
import java.net.NoRouteToHostException;
|
|
import net.i2p.I2PException;
|
|
import net.i2p.client.streaming.I2PSocket;
|
|
import net.i2p.client.streaming.I2PSocketManager;
|
|
import net.i2p.client.streaming.I2PSocketManagerFactory;
|
|
import net.i2p.data.DataFormatException;
|
|
import net.i2p.data.Destination;
|
|
|
|
public class Main {
|
|
|
|
public static void main(String[] args) {
|
|
I2PSocketManager manager = I2PSocketManagerFactory.createManager();
|
|
System.out.println("Please enter a Destination:");
|
|
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
|
|
String destinationString;
|
|
try {
|
|
destinationString = br.readLine();
|
|
} catch (IOException ex) {
|
|
System.out.println("Failed to get a Destination string.");
|
|
return;
|
|
}
|
|
Destination destination;
|
|
try {
|
|
destination = new Destination(destinationString);
|
|
} catch (DataFormatException ex) {
|
|
System.out.println("Destination string incorrectly formatted.");
|
|
return;
|
|
}
|
|
I2PSocket socket;
|
|
try {
|
|
socket = manager.connect(destination);
|
|
} catch (I2PException ex) {
|
|
System.out.println("General I2P exception occurred!");
|
|
return;
|
|
} catch (ConnectException ex) {
|
|
System.out.println("Failed to connect!");
|
|
return;
|
|
} catch (NoRouteToHostException ex) {
|
|
System.out.println("Couldn't find host!");
|
|
return;
|
|
} catch (InterruptedIOException ex) {
|
|
System.out.println("Sending/receiving was interrupted!");
|
|
return;
|
|
}
|
|
try {
|
|
//Write to server
|
|
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
|
|
bw.write("Hello I2P!\n");
|
|
//Flush to make sure everything got sent
|
|
bw.flush();
|
|
//Read from server
|
|
BufferedReader br2 = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
|
String s = null;
|
|
while ((s = br2.readLine()) != null) {
|
|
System.out.println("Received from server: " + s);
|
|
}
|
|
socket.close();
|
|
} catch (IOException ex) {
|
|
System.out.println("Error occurred while sending/receiving!");
|
|
}
|
|
}
|
|
|
|
}
|
|
{% endhighlight %}
|
|
<p style="text-align:center">{{ _('Code example 3: starting the client and connecting it to the server application.') }}</p>
|
|
</div>
|
|
<p>{% trans -%}
|
|
Finally, you can run both the server and the client application.
|
|
First, start the server application. It will print a Destination string (like shown <a href="#start.streaming.destination">above</a>).
|
|
Next, start the client application. When it requests a Destination string, you can enter the string printed by the server.
|
|
The client will then send 'Hello I2P!' (along with a newline) to the server, who will print the message and send it back to the client.
|
|
{%- endtrans %}</p>
|
|
<p>{% trans -%}
|
|
Congratulations, you have successfully communicated over I2P!
|
|
{%- endtrans %}</p>
|
|
|
|
<h2>{{ _('Existing Applications') }}</h2>
|
|
<p>{% trans -%}
|
|
Contact us if you would like to contribute.
|
|
{%- endtrans %}</p>
|
|
<ul>
|
|
<li>
|
|
<a href="http://{{ i2pconv('i2pbote.i2p') }}/">I2P-Bote</a> - contact HungryHobo
|
|
</li><li>
|
|
<a href="http://syndie.i2p2.de/">Syndie</a>
|
|
</li><li>
|
|
<a href="http://{{ i2pconv('www.imule.i2p') }}/">IMule</a>
|
|
</li><li>
|
|
<a href="http://{{ i2pconv('forum.i2p') }}/viewforum.php?f=25">I2Phex</a>
|
|
</li></ul>
|
|
<p>
|
|
See also all the plugins on <a href="http://{{ i2pconv('plugins.i2p') }}/">plugins.i2p</a>,
|
|
the applications and source code listed on <a href="http://{{ i2pconv('echelon.i2p') }}/">echelon.i2p</a>,
|
|
and the application code hosted on <a href="http://{{ i2pconv('git.repo.i2p') }}/">git.repo.i2p</a>.
|
|
</p><p>
|
|
See also the bundled applications in the I2P distribution - SusiMail and I2PSnark.
|
|
</p>
|
|
|
|
<h2>{{ _('Application Ideas') }}</h2>
|
|
<ul>
|
|
<li>{% trans -%}
|
|
NNTP server - there have been some in the past, none at the moment
|
|
{%- endtrans %}</li>
|
|
<li>{% trans -%}
|
|
Jabber server - there have been some in the past, and there is one at the moment, with access to the public internet
|
|
{%- endtrans %}</li>
|
|
<li>{% trans -%}
|
|
PGP Key server and/or proxy
|
|
{%- endtrans %}</li>
|
|
<li>{% trans -%}
|
|
Content Distribution / DHT applications - resurrect feedspace,
|
|
port dijjer, look for alternatives
|
|
{%- endtrans %}</li>
|
|
<li>{% trans -%}
|
|
Help out with <a href="http://syndie.i2p2.de/">Syndie</a> development
|
|
{%- endtrans %}</li>
|
|
<li>{% trans -%}
|
|
Web-based applications - The sky is the limit for hosting web-server-based
|
|
applications such as blogs, pastebins, storage, tracking, feeds, etc.
|
|
Any web or CGI technology such as Perl, PHP, Python, or Ruby will work.
|
|
{%- endtrans %}</li>
|
|
<li>{% trans -%}
|
|
Resurrect some old apps, several previously in the i2p source package -
|
|
bogobot, pants, proxyscript, q, stasher, socks proxy, i2ping, feedspace
|
|
{%- endtrans %}</li>
|
|
</ul>
|
|
|
|
{% endblock %}
|