aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/gnunet/transport/Transport.java
blob: 8409ec8a00139eb976b55e498dc79a2b7c808c33 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
package org.gnunet.transport;

import org.gnunet.hello.HelloMessage;
import org.gnunet.mq.Envelope;
import org.gnunet.mq.NotifySentHandler;
import org.gnunet.transport.messages.*;
import org.gnunet.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.LinkedList;
import java.util.List;

/**
 * ...
 *
 * @author Florian Dold
 */
public class Transport {
    private static final Logger logger = LoggerFactory
            .getLogger(Transport.class);
    /**
     * Client that connects to the transport service,
     */
    private final Client client;

    /**
     * Hello of our peer. May be null if not received yet.
     */
    private HelloMessage myHello;

    /**
     * Callbacks waiting for a hello.
     */
    private List<GetHelloHolder> getHelloHolderList = new LinkedList<GetHelloHolder>();

    /**
     * Wrapper to give each get hello getRequestIdentifier a unique identity.
     */
    private class GetHelloHolder {
        HelloUpdateCallback cb;
    }

    private final class TransportReceiver extends RunaboutMessageReceiver {
        public void visit(HelloMessage m) {
            System.out.println("got hello");
            myHello = m;
            List<GetHelloHolder> list = getHelloHolderList;
            getHelloHolderList = new LinkedList<GetHelloHolder>();
            for (GetHelloHolder h : list) {
                h.cb.onHello(m);
            }
        }
        public void visit(ConnectMessage m) {
          // FIXME: implement
        }
        public void visit(DisconnectMessage m) {
          // FIXME: implement
        }
        public void visit(RecvMessage m) {
          // FIXME: implement
        }
        @Override
        public void handleError() {
            logger.warn("Error receiving from the transport service, reconnecting.");
            // FIXME: there is no backoff ...
            client.reconnect();
            sendStart();
        }
    }

    private void sendStart() {
        org.gnunet.transport.messages.StartMessage m = new StartMessage();
        // no self check or payload traffic for now
        m.options = 0;
        m.self = new PeerIdentity();
        client.send(m);
    }

    /**
     * Create a handle to the transport service.
     *
     * @param cfg configuration to use for connecting
     */
    public Transport(Configuration cfg) {
        client = new Client("transport", cfg);
        client.installReceiver(new TransportReceiver());
        sendStart();
    }

    /**
     * Ask the transport service to establish a connection to
     * the given peer.
     *
     * @param target who we should try to connect to
     * @param cb     callback to be called when getRequestIdentifier was transmitted to transport
     *               service
     * @return a handle to onCancel the operation
     */
    public Cancelable tryConnect(PeerIdentity target, final TryConnectCallback cb) {
        RequestConnectMessage m = new RequestConnectMessage();
        m.peer = target;
        m.reserved = 0;
        final Envelope ev = new Envelope(m);
        ev.notifySent(new NotifySentHandler() {
            @Override
            public void onSent() {
                cb.onDone();
            }
        });
        client.send(ev);

        return new Cancelable() {
            @Override
            public void cancel() {
                ev.cancel();
            }
        };
    }


    /**
     * Obtain the HELLO message for this peer.
     *
     * @param rec function to call with the HELLO
     * @return handle to onCancel the operation
     */
    public Cancelable getHello(final HelloUpdateCallback rec) {
        if (myHello != null) {
            return Scheduler.add(new Scheduler.Task() {
                @Override
                public void run(Scheduler.RunContext ctx) {
                    rec.onHello(myHello);
                }
            });
        }
        System.out.println("waiting for hello");
        final GetHelloHolder holder = new GetHelloHolder();
        holder.cb = rec;
        getHelloHolderList.add(holder);
        return new Cancelable() {
            @Override
            public void cancel() {
                getHelloHolderList.remove(holder);
            }
        };
    }

    /**
     * Offer the transport service the HELLO of another peer.  Note that
     * the transport service may just ignore this message if the HELLO is
     * malformed or useless due to our local configuration.
     *
     * @param hello the hello message
     * @param cont  continuation to call when HELLO has been sent
     * @return a GNUNET_TRANSPORT_OfferHelloHandle handle or NULL on failure,
     *         in case of failure cont will not be called
     */

    public Cancelable offerHello(HelloMessage hello,
                          final OfferHelloContinuation cont) {
        final Envelope ev = new Envelope(hello);
        ev.notifySent(new NotifySentHandler() {
            @Override
            public void onSent() {
                cont.onDone();
            }
        });
        client.send(ev);
        return new Cancelable() {
            @Override
            public void cancel() {
                ev.cancel();
            }
        };
    }

    public void disconnect() {
        client.disconnect();
    }

}