aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ISSUES121
-rwxr-xr-xbin/gnunet-ballot12
-rwxr-xr-xbin/gnunet-daemon-ballot-ca12
-rwxr-xr-xbin/gnunet-daemon-ballot-tally12
-rw-r--r--src/main/java/org/gnunet/arm/Arm.java70
-rw-r--r--src/main/java/org/gnunet/arm/ArmMonitor.java27
-rw-r--r--src/main/java/org/gnunet/arm/ResultHandler.java31
-rw-r--r--src/main/java/org/gnunet/arm/ServiceListHandler.java28
-rw-r--r--src/main/java/org/gnunet/arm/ServiceStatusHandler.java25
-rw-r--r--src/main/java/org/gnunet/arm/messages/ListResultMessage.java41
-rw-r--r--src/main/java/org/gnunet/arm/messages/RequestMessage.java25
-rw-r--r--src/main/java/org/gnunet/arm/messages/ResultMessage.java35
-rw-r--r--src/main/java/org/gnunet/arm/messages/StatusMessage.java61
-rw-r--r--src/main/java/org/gnunet/construct/parsers/FillParser.java3
-rw-r--r--src/main/java/org/gnunet/construct/parsers/StringParser.java7
-rw-r--r--src/main/java/org/gnunet/identity/Identity.java344
-rw-r--r--src/main/java/org/gnunet/identity/IdentityCallback.java27
-rw-r--r--src/main/java/org/gnunet/identity/IdentityContinuation.java26
-rw-r--r--src/main/java/org/gnunet/identity/IdentityListCallback.java29
-rw-r--r--src/main/java/org/gnunet/identity/messages/CreateRequestMessage.java63
-rw-r--r--src/main/java/org/gnunet/identity/messages/DeleteMessage.java36
-rw-r--r--src/main/java/org/gnunet/identity/messages/GetDefaultMessage.java98
-rw-r--r--src/main/java/org/gnunet/identity/messages/RenameMessage.java58
-rw-r--r--src/main/java/org/gnunet/identity/messages/ResultCodeMessage.java121
-rw-r--r--src/main/java/org/gnunet/identity/messages/SetDefaultMessage.java85
-rw-r--r--src/main/java/org/gnunet/identity/messages/StartMessage.java73
-rw-r--r--src/main/java/org/gnunet/identity/messages/UpdateListMessage.java104
-rw-r--r--src/main/java/org/gnunet/mq/MessageQueue.java4
-rw-r--r--src/main/java/org/gnunet/testbed/Controller.java11
-rw-r--r--src/main/java/org/gnunet/testbed/callbacks/ControllerEventCallback.java21
-rw-r--r--src/main/java/org/gnunet/testbed/messages/PeerInformationMessage.java3
-rw-r--r--src/main/java/org/gnunet/util/AbsoluteTime.java46
-rw-r--r--src/main/java/org/gnunet/util/Connection.java9
-rw-r--r--src/main/java/org/gnunet/util/CryptoECC.java52
-rw-r--r--src/main/java/org/gnunet/util/Helper.java308
-rw-r--r--src/main/java/org/gnunet/util/MessageStreamTokenizer.java122
-rw-r--r--src/main/java/org/gnunet/util/MstCalllback.java27
-rw-r--r--src/main/java/org/gnunet/util/Scheduler.java466
-rw-r--r--src/main/java/org/gnunet/util/Server.java3
-rw-r--r--src/main/java/org/gnunet/util/Service.java3
-rw-r--r--src/main/java/org/gnunet/voting/Ballot.java220
-rw-r--r--src/main/java/org/gnunet/voting/BallotTool.java27
-rw-r--r--src/main/java/org/gnunet/voting/CertificateAuthorityDaemon.java70
-rw-r--r--src/main/java/org/gnunet/voting/CertificateAuthorityService.java55
-rw-r--r--src/main/java/org/gnunet/voting/CertifyGroupCommand.java (renamed from src/main/java/org/gnunet/voting/PermissionCommand.java)31
-rw-r--r--src/main/java/org/gnunet/voting/RegisterCommand.java20
-rw-r--r--src/main/java/org/gnunet/voting/SubmitCommand.java36
-rw-r--r--src/main/java/org/gnunet/voting/TallyAuthorityDaemon.java102
-rw-r--r--src/main/java/org/gnunet/voting/messages/BallotRegisterFailureMessage.java37
-rw-r--r--src/main/java/org/gnunet/voting/messages/BallotRegisterRequestMessage.java3
-rw-r--r--src/main/java/org/gnunet/voting/messages/BallotRegisterSuccessMessage.java (renamed from src/main/java/org/gnunet/voting/messages/BallotRegisterRespondMessage.java)8
-rw-r--r--src/main/java/org/gnunet/voting/messages/CertificateDenyMessage.java34
-rw-r--r--src/main/java/org/gnunet/voting/messages/CertificateGrantMessage.java19
-rw-r--r--src/main/java/org/gnunet/voting/messages/CertificateRequestMessage.java11
-rw-r--r--src/main/java/org/gnunet/voting/messages/CertificateResponseMessage.java9
-rw-r--r--src/main/java/org/gnunet/voting/messages/QueryFailureMessage.java3
-rw-r--r--src/main/java/org/gnunet/voting/messages/SubmitFailureMessage.java32
-rw-r--r--src/main/java/org/gnunet/voting/messages/SubmitMessage.java26
-rw-r--r--src/main/java/org/gnunet/voting/messages/SubmitResponseMessage.java9
-rw-r--r--src/main/java/org/gnunet/voting/messages/SubmitSuccessMessage.java13
-rw-r--r--src/main/resources/org/gnunet/construct/MsgMap.txt24
-rw-r--r--src/main/resources/org/gnunet/voting/template.espec31
-rw-r--r--src/test/java/org/gnunet/identity/IdentityTest.java123
-rw-r--r--src/test/java/org/gnunet/testbed/TestbedTest.java72
-rw-r--r--src/test/java/org/gnunet/util/CryptoECCTest.java8
65 files changed, 2924 insertions, 748 deletions
diff --git a/ISSUES b/ISSUES
index 2a13bdf..6ab87fb 100644
--- a/ISSUES
+++ b/ISSUES
@@ -1,91 +1,46 @@
1== testbed == 1testbed api is now quite complete
2 2 * problem with reconfigure was a bug in the testbed service
3padding: PACKED / NETWORK_STRUCT don't really pack some misaligned structs: 3 * only thing left to to is to implement arm for manageService
4 struct GNUNET_TESTBED_PeerConfigurationInformationMessage 4 * (BUT: I don't get how arm works in conjunction with testbed -- when the arm api can't connect to
5is misaligned anyway, *but* sizeof the struct is 84, when it should be 82! 5 arm it tries to start the arm service *locally*, which is often wrong ...)
6 6 * talked to sriharsha about it
7see https://gnunet.org/bugs/view.php?id=3043 7
8 8gnunet-java finally has a proper stream tokenizer ...
9I managed to break testbed (this is a GNUNET_assert, no GNUNET_break) 9 * and locking has been removes from Scheduler, Helper is properly implemented
10 Sep 24 20:06:14-146897 testbed-18586 ERROR Assertion failed at testing.c:1548. 10
11but this only occurs *after* the shutdown and when trying to reconfigure a peer! 11new java API implementation for identity :)
12 12 * why is there no way to import keys?
13OPTIONS/PREFIX does not work with testbed helper 13 * at least API-wise
14 14 * voting should use identity ...
15what works (and is tested) now in org.gnunet.testbed: 15
16 * creating and destroying peers 16timing information in ballot: we talked about round times,
17 * starting and stopping peers 17but shouldn't this be done transparently by consensus?
18 * getting peer id / configuration 18aren't START_TIME, CLOSING_TIME, QUERY_TIME, END_TIME and maybe CONSENSUS_PARAMS be enough?
19 * overlay-connecting two peers 19
20other stuff: 20certificate authority: is the CAs pubkey different from its peer?
21 * does gnunet-java need barriers? 21 * it definitely makes sense to have it seperate for other cert methods
22 * what's the state of the overlay implementation 22 * like sending a cert per email, snail mail, social network ...
23 * does service_connect do anything other than retrieve the configuration? 23 * how do we specify how to reach the cert? one peer? multiple peers?
24 * primary purpose is to be able to have opqueue management, right? 24 * maybe use GADS? (I know very little about GADS right now)
25 * why do we have manage service when we have arm? 25 * does it even make sense to have the CA service at this time?
26 * someone has to start arm, I suppose?
27
28== crypto ==
29two types of public keys, do I understand the reasons correctly:
30 * NaCl compatibility
31 * fastest representation for each type of operation
32
33why is there no way to convert from signing key -> encryption key?
34 * other way around is not possible
35
36
37== voting ==
38 26
39what now works: 27what now works:
40 * creating a ballot and registering it 28 * authorities check for double vote submission, late / early voting, early result query,
41 * selecting a choice in the ballot and submitting it 29 double registering, vouchers (I don't like to call vouchers receipts because that term has
42 * vote + 512-bit ballot GUID 30 a certain meaning in voting literature already)
43 * querying the results (also with the GUID)
44
45next steps??
46- Ballot: (a) voter ID, (b) election information, (c) election eligibility group (Bavaria 18+), (d) ballot GUID
47- no double submission: check: no duplicate voter ID (for any given election)
48- no early queries
49- voter <--> CA interaction
50 => ideally, CA has a list of voter public keys or at least a policy (i.e. "accept all")
51 for a certain voter group (i.e. Bavaria 18+).
52 => CA also has a private CA key (surprise!)
53 => Voter has voter public key and voter group, sends THOSE to CA;
54 => CA signs: this voter is in this voter group (with expiration time for signature!)
55 => voter takes signature, can re-use it for ALL elections with this voter group
56- Authorities have CA public keys, check voter group sigs.
57
58what should be stored in the ballot about authorities: peer identities or peer public keys?
59=> public keys
60
61 * pubkey makes more sense, but I have the feeling that GNUnet prefers to use
62 peer IDs whenever possible
63=> Nah.
64
65docs of identity service say:
66 For giving names to other users and manage their public keys securely, we use GNS.
67In what way does GNS manage public keys?
68 GNS allows you to give names to other user's public keys.
69Does GNS in any way relate peer identities to public keys?
70 No.
71
72persistent storage of tallies?
73 => Later.
74 31
75now that the pubkey is smaller, are there reasons for still having 32but: group certs are not checked right now
76a separate peer identity?
77 * except for that it would be a lot of work to change now
78=> exactly.
79 33
80the command line took looks a bit complicated now, any suggestions? 34how to test voting without waiting too long or missing the right time?
81=> Later.
82 35
83asking permission to vote should not require the private key, right? 36any progress on crypto?
84 * how do we do this interface-wise? pubkey on the command line? 37 * luckily the private key has the same size, so identity can be used
85=> Identity service, ego!
86 38
87== general java stuff == 39next:
88what's your opinion on option types: should they be used more in gnunet-java? 40 * use identity
41 * multiple authorities should do consensus on unencrypted votes
42 * tests for this with testbed
43 * encrypting votes
89 44
90We have a lot of callbacks in java that all do almost the same. Should we have a generic callback type? 45suggestions?
91 46
diff --git a/bin/gnunet-ballot b/bin/gnunet-ballot
new file mode 100755
index 0000000..e76c423
--- /dev/null
+++ b/bin/gnunet-ballot
@@ -0,0 +1,12 @@
1#!/bin/sh
2
3if [ "%GNJ_INSTALLED" = "true" ];
4then
5 export CLASSPATH="%INSTALL_PATH/share/java/*"
6else
7 DIR=`dirname $0`
8 # if we are in the development environment use class files directly instead of jar
9 export CLASSPATH="$DIR/../build-gradle/classes/main/:$DIR/../build-gradle/resources/main/:$DIR/../lib/*"
10fi
11
12java -ea org.gnunet.voting.BallotTool "$@"
diff --git a/bin/gnunet-daemon-ballot-ca b/bin/gnunet-daemon-ballot-ca
new file mode 100755
index 0000000..b85a67f
--- /dev/null
+++ b/bin/gnunet-daemon-ballot-ca
@@ -0,0 +1,12 @@
1#!/bin/sh
2
3if [ "%GNJ_INSTALLED" = "true" ];
4then
5 export CLASSPATH="%INSTALL_PATH/share/java/*"
6else
7 DIR=`dirname $0`
8 # if we are in the development environment use class files directly instead of jar
9 export CLASSPATH="$DIR/../build-gradle/classes/main/:$DIR/../build-gradle/resources/main/:$DIR/../lib/*"
10fi
11
12java -ea org.gnunet.voting.CertificateAuthorityDaemon "$@"
diff --git a/bin/gnunet-daemon-ballot-tally b/bin/gnunet-daemon-ballot-tally
new file mode 100755
index 0000000..b24b5eb
--- /dev/null
+++ b/bin/gnunet-daemon-ballot-tally
@@ -0,0 +1,12 @@
1#!/bin/sh
2
3if [ "%GNJ_INSTALLED" = "true" ];
4then
5 export CLASSPATH="%INSTALL_PATH/share/java/*"
6else
7 DIR=`dirname $0`
8 # if we are in the development environment use class files directly instead of jar
9 export CLASSPATH="$DIR/../build-gradle/classes/main/:$DIR/../build-gradle/resources/main/:$DIR/../lib/*"
10fi
11
12java -ea org.gnunet.voting.TallyAuthorityDaemon "$@"
diff --git a/src/main/java/org/gnunet/arm/Arm.java b/src/main/java/org/gnunet/arm/Arm.java
new file mode 100644
index 0000000..503413f
--- /dev/null
+++ b/src/main/java/org/gnunet/arm/Arm.java
@@ -0,0 +1,70 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21package org.gnunet.arm;
22
23import org.gnunet.util.Client;
24import org.gnunet.util.Configuration;
25
26/**
27 * API for the Automatic Restart Manager (ARM)
28 */
29public class Arm {
30 private final Configuration configuration;
31 private Client client;
32 public Arm(Configuration configuration) {
33 this.configuration = configuration;
34 client = new Client("arm", configuration);
35 }
36
37 /**
38 * Disconnect from ARM, the Arm object may not be used afterwards.
39 */
40 public void disconnect() {
41 client.disconnect();
42 }
43 public void requestServiceList(ServiceListHandler serviceListHandler) {
44
45 }
46
47 /**
48 * Request a service to be stopped.
49 * Stopping arm itself will not invalidate its handle, and
50 * ARM API will try to restore connection to the ARM service,
51 * even if ARM connection was lost because you asked for ARM to be stopped.
52 * Call Arm.disconnect to free the handle and prevent
53 * further connection attempts.
54 *
55 * @param serviceName name of the service
56 * @param resultHandler called with the result of the request
57 */
58 public void requestServiceStop(String serviceName, ResultHandler resultHandler) {
59
60 }
61
62 /**
63 * Request for a service to be started.
64 *
65 * @param serviceName name of the service
66 */
67 public void requestServiceStart(String serviceName, ResultHandler resultHandler) {
68
69 }
70}
diff --git a/src/main/java/org/gnunet/arm/ArmMonitor.java b/src/main/java/org/gnunet/arm/ArmMonitor.java
new file mode 100644
index 0000000..641b862
--- /dev/null
+++ b/src/main/java/org/gnunet/arm/ArmMonitor.java
@@ -0,0 +1,27 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21package org.gnunet.arm;
22
23/**
24 * API for monitoring ARM services.
25 */
26public class ArmMonitor {
27}
diff --git a/src/main/java/org/gnunet/arm/ResultHandler.java b/src/main/java/org/gnunet/arm/ResultHandler.java
new file mode 100644
index 0000000..05c34f9
--- /dev/null
+++ b/src/main/java/org/gnunet/arm/ResultHandler.java
@@ -0,0 +1,31 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21package org.gnunet.arm;
22
23/**
24 * Created with IntelliJ IDEA.
25 * User: dold
26 * Date: 10/7/13
27 * Time: 4:00 PM
28 * To change this template use File | Settings | File Templates.
29 */
30public interface ResultHandler {
31}
diff --git a/src/main/java/org/gnunet/arm/ServiceListHandler.java b/src/main/java/org/gnunet/arm/ServiceListHandler.java
new file mode 100644
index 0000000..8d9de04
--- /dev/null
+++ b/src/main/java/org/gnunet/arm/ServiceListHandler.java
@@ -0,0 +1,28 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21package org.gnunet.arm;
22
23
24import java.util.List;
25
26public interface ServiceListHandler {
27 void onServiceList(List<String> services);
28}
diff --git a/src/main/java/org/gnunet/arm/ServiceStatusHandler.java b/src/main/java/org/gnunet/arm/ServiceStatusHandler.java
new file mode 100644
index 0000000..cedcc48
--- /dev/null
+++ b/src/main/java/org/gnunet/arm/ServiceStatusHandler.java
@@ -0,0 +1,25 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21package org.gnunet.arm;
22
23public interface ServiceStatusHandler {
24
25}
diff --git a/src/main/java/org/gnunet/arm/messages/ListResultMessage.java b/src/main/java/org/gnunet/arm/messages/ListResultMessage.java
new file mode 100644
index 0000000..03f995f
--- /dev/null
+++ b/src/main/java/org/gnunet/arm/messages/ListResultMessage.java
@@ -0,0 +1,41 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21package org.gnunet.arm.messages;
22
23import org.gnunet.construct.*;
24import org.gnunet.util.GnunetMessage;
25
26@UnionCase(13)
27public class ListResultMessage implements GnunetMessage.Body {
28 public class StringMessage implements Message {
29 @ZeroTerminatedString
30 public String string;
31 }
32
33 @UInt64
34 public long requestId;
35
36 @UInt16
37 public int count;
38
39 @FillWith
40 public StringMessage[] services;
41}
diff --git a/src/main/java/org/gnunet/arm/messages/RequestMessage.java b/src/main/java/org/gnunet/arm/messages/RequestMessage.java
new file mode 100644
index 0000000..fa0c18c
--- /dev/null
+++ b/src/main/java/org/gnunet/arm/messages/RequestMessage.java
@@ -0,0 +1,25 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21package org.gnunet.arm.messages;
22
23
24public class RequestMessage {
25}
diff --git a/src/main/java/org/gnunet/arm/messages/ResultMessage.java b/src/main/java/org/gnunet/arm/messages/ResultMessage.java
new file mode 100644
index 0000000..4883c14
--- /dev/null
+++ b/src/main/java/org/gnunet/arm/messages/ResultMessage.java
@@ -0,0 +1,35 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21package org.gnunet.arm.messages;
22
23import org.gnunet.construct.UInt32;
24import org.gnunet.construct.UInt64;
25import org.gnunet.construct.UnionCase;
26import org.gnunet.util.GnunetMessage;
27
28@UnionCase(10)
29public class ResultMessage implements GnunetMessage.Body {
30 @UInt64
31 public long requestId;
32
33 @UInt32
34 public int result;
35}
diff --git a/src/main/java/org/gnunet/arm/messages/StatusMessage.java b/src/main/java/org/gnunet/arm/messages/StatusMessage.java
new file mode 100644
index 0000000..cdfde6c
--- /dev/null
+++ b/src/main/java/org/gnunet/arm/messages/StatusMessage.java
@@ -0,0 +1,61 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21/*
22 This file is part of GNUnet.
23 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
24
25 GNUnet is free software; you can redistribute it and/or modify
26 it under the terms of the GNU General Public License as published
27 by the Free Software Foundation; either version 3, or (at your
28 option) any later version.
29
30 GNUnet is distributed in the hope that it will be useful, but
31 WITHOUT ANY WARRANTY; without even the implied warranty of
32 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33 General Public License for more details.
34
35 You should have received a copy of the GNU General Public License
36 along with GNUnet; see the file COPYING. If not, write to the
37 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
38 Boston, MA 02111-1307, USA.
39 */
40
41package org.gnunet.arm.messages;
42
43import org.gnunet.construct.*;
44import org.gnunet.util.GnunetMessage;
45
46@UnionCase(11)
47public class StatusMessage implements GnunetMessage.Body {
48 public class StringMessage implements Message {
49 @ZeroTerminatedString
50 public String string;
51 }
52
53 @UInt64
54 public long requestId;
55
56 @UInt32
57 public int status;
58
59 @ZeroTerminatedString
60 public String serviceName;
61}
diff --git a/src/main/java/org/gnunet/construct/parsers/FillParser.java b/src/main/java/org/gnunet/construct/parsers/FillParser.java
index 156e120..19ce252 100644
--- a/src/main/java/org/gnunet/construct/parsers/FillParser.java
+++ b/src/main/java/org/gnunet/construct/parsers/FillParser.java
@@ -66,15 +66,12 @@ public class FillParser implements Parser {
66 throw new AssertionError("FillParser expects a non-null frameSizePath. Does the message have a @FrameSizePath annotation?"); 66 throw new AssertionError("FillParser expects a non-null frameSizePath. Does the message have a @FrameSizePath annotation?");
67 } 67 }
68 68
69
70
71 final int frameSize = ReflectUtil.justGetInt(dstObj, frameSizePath); 69 final int frameSize = ReflectUtil.justGetInt(dstObj, frameSizePath);
72 int remaining = frameOffset + frameSize - srcBuf.position(); 70 int remaining = frameOffset + frameSize - srcBuf.position();
73 int size = 0; 71 int size = 0;
74 72
75 Class<?> elemType = targetField.getType().getComponentType(); 73 Class<?> elemType = targetField.getType().getComponentType();
76 74
77
78 ArrayList<Message> list = new ArrayList<Message>(10); 75 ArrayList<Message> list = new ArrayList<Message>(10);
79 76
80 while (remaining > 0) { 77 while (remaining > 0) {
diff --git a/src/main/java/org/gnunet/construct/parsers/StringParser.java b/src/main/java/org/gnunet/construct/parsers/StringParser.java
index b4e62ca..a91778b 100644
--- a/src/main/java/org/gnunet/construct/parsers/StringParser.java
+++ b/src/main/java/org/gnunet/construct/parsers/StringParser.java
@@ -67,7 +67,7 @@ public class StringParser implements Parser {
67 if (frameSizePath == null) { 67 if (frameSizePath == null) {
68 throw new AssertionError("optional string with no length field in the message!"); 68 throw new AssertionError("optional string with no length field in the message!");
69 } 69 }
70 final int frameSize = ReflectUtil.justGetInt(dstObj, frameSizePath); 70 final int frameSize = ReflectUtil.justGetInt(frameObj, frameSizePath);
71 int remaining = frameOffset + frameSize - srcBuf.position(); 71 int remaining = frameOffset + frameSize - srcBuf.position();
72 72
73 if (remaining == 0) { 73 if (remaining == 0) {
@@ -79,6 +79,11 @@ public class StringParser implements Parser {
79 } 79 }
80 } 80 }
81 81
82 if (!srcBuf.hasRemaining()) {
83 throw new ProtocolViolationException("no data for non-optional string field " +
84 targetField);
85 }
86
82 int length = 0; 87 int length = 0;
83 88
84 while (srcBuf.get(srcBuf.position() + length) != 0) { 89 while (srcBuf.get(srcBuf.position() + length) != 0) {
diff --git a/src/main/java/org/gnunet/identity/Identity.java b/src/main/java/org/gnunet/identity/Identity.java
new file mode 100644
index 0000000..657a0b9
--- /dev/null
+++ b/src/main/java/org/gnunet/identity/Identity.java
@@ -0,0 +1,344 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21package org.gnunet.identity;
22
23
24import com.google.common.collect.Lists;
25import org.gnunet.identity.messages.*;
26import org.gnunet.mq.Envelope;
27import org.gnunet.requests.RequestContainer;
28import org.gnunet.requests.SequentialRequestContainer;
29import org.gnunet.util.*;
30import org.slf4j.Logger;
31import org.slf4j.LoggerFactory;
32
33import java.util.List;
34
35public class Identity {
36 private static final Logger logger = LoggerFactory
37 .getLogger(Identity.class);
38 private Configuration configuration;
39 private SequentialRequestContainer<IdentityRequest> requests;
40 private Client client;
41 private IdentityListCallback identityListCallback;
42 private List<Ego> knownEgos = Lists.newLinkedList();
43
44 private static Ego anonymousEgo;
45
46 public static class Ego {
47 private String name;
48 private CryptoECC.PrivateKey privateKey;
49
50 public Ego(String egoName, CryptoECC.PrivateKey privateKey) {
51 this.name = egoName;
52 this.privateKey = privateKey;
53 }
54 public CryptoECC.PrivateKey getPrivateKey() {
55 return privateKey;
56 }
57 public CryptoECC.PublicSignKey getPublicKey() {
58 return CryptoECC.computePublicKey(privateKey);
59 }
60 public String getName() {
61 return name;
62 }
63 }
64
65 public abstract class IdentityRequest extends RequestContainer.Request {
66
67 public void onError(String errorMessage) {
68 throw new AssertionError("unexpected error message: " + errorMessage);
69 }
70
71 public void onResult() {
72 throw new AssertionError("unexpected result");
73 }
74 }
75
76 public class GetDefaultRequest extends IdentityRequest {
77 IdentityCallback identityCallback;
78 String serviceName;
79 GetDefaultRequest(String serviceName, IdentityCallback identityCallback) {
80 this.identityCallback = identityCallback;
81 this.serviceName = serviceName;
82 }
83 @Override
84 public Envelope assembleRequest() {
85 GetDefaultMessage m = new GetDefaultMessage();
86 m.nameLength = serviceName.length() + 1;
87 m.serviceName = serviceName;
88 return new Envelope(m);
89 }
90
91 @Override
92 public void onError(String errorMessage) {
93 identityCallback.onError(errorMessage);
94 }
95 }
96
97 public class SetDefaultRequest extends IdentityRequest {
98 IdentityContinuation cont;
99 String serviceName;
100 Ego ego;
101 SetDefaultRequest(String serviceName, Ego ego) {
102 this.serviceName = serviceName;
103 this.ego = ego;
104 }
105 @Override
106 public Envelope assembleRequest() {
107 SetDefaultMessage m = new SetDefaultMessage();
108 m.nameLength = serviceName.length() + 1;
109 m.serviceName = serviceName;
110 m.privateKey = ego.privateKey;
111 return new Envelope(m);
112 }
113 @Override
114 public void onError(String errorMessage) {
115 cont.onError(errorMessage);
116 }
117 @Override
118 public void onResult() {
119 cont.onDone();
120 }
121 }
122
123 public class RenameRequest extends IdentityRequest {
124 IdentityContinuation cont;
125 String oldName;
126 String newName;
127 RenameRequest(String newName, String oldName) {
128 this.oldName = oldName;
129 this.newName = newName;
130 }
131 @Override
132 public Envelope assembleRequest() {
133 RenameMessage m = new RenameMessage();
134 m.newName = newName;
135 m.newNameLength = newName.length() + 1;
136 m.oldName = oldName;
137 m.oldNameLength = oldName.length() + 1;
138 return new Envelope(m);
139 }
140 @Override
141 public void onError(String errorMessage) {
142 cont.onError(errorMessage);
143 }
144 @Override
145 public void onResult() {
146 cont.onDone();
147 }
148 }
149
150 public class DeleteRequest extends IdentityRequest {
151 IdentityContinuation cont;
152 String name;
153 DeleteRequest(String name) {
154 this.name = name;
155 }
156 @Override
157 public Envelope assembleRequest() {
158 DeleteMessage m = new DeleteMessage();
159 m.name = name;
160 m.nameLength = name.length() + 1;
161 return new Envelope(m);
162 }
163 @Override
164 public void onError(String errorMessage) {
165 cont.onError(errorMessage);
166 }
167 @Override
168 public void onResult() {
169 cont.onDone();
170 }
171 }
172
173 public class CreateRequest extends IdentityRequest {
174 final CryptoECC.PrivateKey privateKey;
175 IdentityContinuation cont;
176 String name;
177 CreateRequest(String name, CryptoECC.PrivateKey privateKey, IdentityContinuation cont) {
178 this.cont = cont;
179 this.privateKey = privateKey;
180 this.name = name;
181 }
182 @Override
183 public Envelope assembleRequest() {
184 CreateRequestMessage m = new CreateRequestMessage();
185 m.name = name;
186 m.nameLength = name.length() + 1;
187 m.privateKey = privateKey;
188 return new Envelope(m);
189 }
190 @Override
191 public void onError(String errorMessage) {
192 cont.onError(errorMessage);
193 }
194
195 @Override
196 public void onResult() {
197 cont.onDone();
198 }
199 }
200
201 public static Ego getAnonymousEgo() {
202 if (anonymousEgo == null) {
203 anonymousEgo = new Ego(null, CryptoECC.getAnonymous());
204 }
205 return anonymousEgo;
206 }
207
208
209 public Identity() {
210 // do nothing
211 }
212
213 public void connect(Configuration configuration, IdentityListCallback identityListCallback) {
214 this.configuration = configuration;
215 this.client = new Client("identity", configuration);
216 this.client.installReceiver(new IdentityReceiver());
217 requests = new SequentialRequestContainer<IdentityRequest>(this.client);
218 this.identityListCallback = identityListCallback;
219 StartMessage m = new StartMessage();
220 client.send(m);
221 }
222
223 public Cancelable get(String serviceName, IdentityCallback identityCallback) {
224 return requests.addRequest(new GetDefaultRequest(serviceName, identityCallback));
225 }
226
227 /**
228 * Set the default ego for a service.
229 *
230 * @param serviceName service
231 * @param ego ego
232 * @return object for cancellation
233 */
234 public Cancelable set(String serviceName, Ego ego) {
235 return requests.addRequest(new SetDefaultRequest(serviceName, ego));
236 }
237
238 public void disconnect() {
239 client.disconnect();
240 client = null;
241 }
242
243 /**
244 * Create a new ego with the given name.
245 *
246 * @param name ego name
247 * @param cont continuation
248 * @return object for cancellation
249 */
250 public Cancelable create(String name, IdentityContinuation cont) {
251 CryptoECC.PrivateKey privateKey = CryptoECC.PrivateKey.createRandom();
252 return requests.addRequest(new CreateRequest(name, privateKey, cont));
253 }
254
255 /**
256 * Rename an ego.
257 *
258 * @param oldName old name of the ego
259 * @param newName new name of the ego
260 * @return object for cancellation
261 */
262 public Cancelable rename(String oldName, String newName) {
263 return requests.addRequest(new RenameRequest(newName, oldName));
264 }
265
266 /**
267 * Delete an ego.
268 *
269 * @param name name of the ego to delete
270 * @return object for cancellation
271 */
272 public Cancelable delete(String name) {
273 return requests.addRequest(new DeleteRequest(name));
274 }
275
276 private Ego getEgoForKey(CryptoECC.PrivateKey privateKey) {
277 for (Ego ex : knownEgos) {
278 if (ex.privateKey.equals(privateKey)) {
279 return ex;
280 }
281 }
282 return null;
283 }
284
285 public class IdentityReceiver extends RunaboutMessageReceiver {
286 @Override
287 public void handleError() {
288 logger.warn("identity service disconnected");
289 client.reconnect();
290 }
291
292 public void visit(ResultCodeMessage m) {
293 IdentityRequest r = requests.getRequest();
294 if (null == r) {
295 logger.warn("unsolicited result code message");
296 return;
297 }
298 if (m.errorMessage != null) {
299 r.onError(m.errorMessage);
300 } else {
301 r.onResult();
302 }
303 requests.next();
304 }
305
306 public void visit(SetDefaultMessage m) {
307 IdentityRequest r = requests.getRequest();
308 if (!(r instanceof GetDefaultRequest)) {
309 logger.error("unexpected 'default ego' response");
310 return;
311 }
312 GetDefaultRequest gdr = (GetDefaultRequest) r;
313 Ego ego = getEgoForKey(m.privateKey);
314 if (null != ego)
315 gdr.identityCallback.onEgo(ego);
316 }
317
318 public void visit(final UpdateListMessage m) {
319 if (m.endOfList != 0) {
320 identityListCallback.onListEnd();
321 return;
322 }
323 if (m.nameLength == 0) {
324 Ego e = getEgoForKey(m.privateKey);
325 if (null != e) {
326 knownEgos.remove(e);
327 }
328 identityListCallback.onEgoDelete(e);
329 } else {
330 Ego existingEgo = getEgoForKey(m.privateKey);
331 if (existingEgo == null) {
332 Ego ego = new Ego(m.egoName, m.privateKey);
333 knownEgos.add(ego);
334 identityListCallback.onEgoAdd(ego);
335 } else {
336 // rename
337 String oldName = existingEgo.name;
338 existingEgo.name = m.egoName;
339 identityListCallback.onEgoRename(oldName, existingEgo);
340 }
341 }
342 }
343 }
344}
diff --git a/src/main/java/org/gnunet/identity/IdentityCallback.java b/src/main/java/org/gnunet/identity/IdentityCallback.java
new file mode 100644
index 0000000..b952c41
--- /dev/null
+++ b/src/main/java/org/gnunet/identity/IdentityCallback.java
@@ -0,0 +1,27 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21package org.gnunet.identity;
22
23public interface IdentityCallback {
24 void onEgo(Identity.Ego ego);
25
26 void onError(String errorMessage);
27}
diff --git a/src/main/java/org/gnunet/identity/IdentityContinuation.java b/src/main/java/org/gnunet/identity/IdentityContinuation.java
new file mode 100644
index 0000000..52de2d0
--- /dev/null
+++ b/src/main/java/org/gnunet/identity/IdentityContinuation.java
@@ -0,0 +1,26 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21package org.gnunet.identity;
22
23public interface IdentityContinuation {
24 void onError(String errorMessage);
25 void onDone();
26}
diff --git a/src/main/java/org/gnunet/identity/IdentityListCallback.java b/src/main/java/org/gnunet/identity/IdentityListCallback.java
new file mode 100644
index 0000000..afe251d
--- /dev/null
+++ b/src/main/java/org/gnunet/identity/IdentityListCallback.java
@@ -0,0 +1,29 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21package org.gnunet.identity;
22
23
24public interface IdentityListCallback {
25 void onEgoAdd(Identity.Ego ego);
26 void onEgoDelete(Identity.Ego ego);
27 void onEgoRename(String oldName, Identity.Ego ego);
28 void onListEnd();
29}
diff --git a/src/main/java/org/gnunet/identity/messages/CreateRequestMessage.java b/src/main/java/org/gnunet/identity/messages/CreateRequestMessage.java
new file mode 100644
index 0000000..475100c
--- /dev/null
+++ b/src/main/java/org/gnunet/identity/messages/CreateRequestMessage.java
@@ -0,0 +1,63 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21/*
22 This file is part of GNUnet.
23 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
24
25 GNUnet is free software; you can redistribute it and/or modify
26 it under the terms of the GNU General Public License as published
27 by the Free Software Foundation; either version 3, or (at your
28 option) any later version.
29
30 GNUnet is distributed in the hope that it will be useful, but
31 WITHOUT ANY WARRANTY; without even the implied warranty of
32 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33 General Public License for more details.
34
35 You should have received a copy of the GNU General Public License
36 along with GNUnet; see the file COPYING. If not, write to the
37 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
38 Boston, MA 02111-1307, USA.
39 */
40
41package org.gnunet.identity.messages;
42
43import org.gnunet.construct.NestedMessage;
44import org.gnunet.construct.UInt16;
45import org.gnunet.construct.UnionCase;
46import org.gnunet.construct.ZeroTerminatedString;
47import org.gnunet.util.CryptoECC;
48import org.gnunet.util.GnunetMessage;
49
50@UnionCase(629)
51public class CreateRequestMessage implements GnunetMessage.Body {
52 /**
53 * Length of the name, INCLUDING the 0-terminator.
54 */
55 @UInt16
56 public int nameLength;
57 @UInt16
58 public int reserved;
59 @NestedMessage
60 public CryptoECC.PrivateKey privateKey;
61 @ZeroTerminatedString
62 public String name;
63}
diff --git a/src/main/java/org/gnunet/identity/messages/DeleteMessage.java b/src/main/java/org/gnunet/identity/messages/DeleteMessage.java
new file mode 100644
index 0000000..7c48c1f
--- /dev/null
+++ b/src/main/java/org/gnunet/identity/messages/DeleteMessage.java
@@ -0,0 +1,36 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21package org.gnunet.identity.messages;
22
23import org.gnunet.construct.UInt16;
24import org.gnunet.construct.UnionCase;
25import org.gnunet.construct.ZeroTerminatedString;
26import org.gnunet.util.GnunetMessage;
27
28@UnionCase(631)
29public class DeleteMessage implements GnunetMessage.Body {
30 @UInt16
31 public int nameLength;
32 @UInt16
33 public int reserved;
34 @ZeroTerminatedString
35 public String name;
36}
diff --git a/src/main/java/org/gnunet/identity/messages/GetDefaultMessage.java b/src/main/java/org/gnunet/identity/messages/GetDefaultMessage.java
new file mode 100644
index 0000000..fab5f33
--- /dev/null
+++ b/src/main/java/org/gnunet/identity/messages/GetDefaultMessage.java
@@ -0,0 +1,98 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21/*
22 This file is part of GNUnet.
23 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
24
25 GNUnet is free software; you can redistribute it and/or modify
26 it under the terms of the GNU General Public License as published
27 by the Free Software Foundation; either version 3, or (at your
28 option) any later version.
29
30 GNUnet is distributed in the hope that it will be useful, but
31 WITHOUT ANY WARRANTY; without even the implied warranty of
32 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33 General Public License for more details.
34
35 You should have received a copy of the GNU General Public License
36 along with GNUnet; see the file COPYING. If not, write to the
37 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
38 Boston, MA 02111-1307, USA.
39 */
40
41/*
42 This file is part of GNUnet.
43 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
44
45 GNUnet is free software; you can redistribute it and/or modify
46 it under the terms of the GNU General Public License as published
47 by the Free Software Foundation; either version 3, or (at your
48 option) any later version.
49
50 GNUnet is distributed in the hope that it will be useful, but
51 WITHOUT ANY WARRANTY; without even the implied warranty of
52 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
53 General Public License for more details.
54
55 You should have received a copy of the GNU General Public License
56 along with GNUnet; see the file COPYING. If not, write to the
57 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
58 Boston, MA 02111-1307, USA.
59 */
60
61/*
62 This file is part of GNUnet.
63 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
64
65 GNUnet is free software; you can redistribute it and/or modify
66 it under the terms of the GNU General Public License as published
67 by the Free Software Foundation; either version 3, or (at your
68 option) any later version.
69
70 GNUnet is distributed in the hope that it will be useful, but
71 WITHOUT ANY WARRANTY; without even the implied warranty of
72 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
73 General Public License for more details.
74
75 You should have received a copy of the GNU General Public License
76 along with GNUnet; see the file COPYING. If not, write to the
77 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
78 Boston, MA 02111-1307, USA.
79 */
80
81package org.gnunet.identity.messages;
82
83import org.gnunet.construct.NestedMessage;
84import org.gnunet.construct.UInt16;
85import org.gnunet.construct.UnionCase;
86import org.gnunet.construct.ZeroTerminatedString;
87import org.gnunet.util.CryptoECC;
88import org.gnunet.util.GnunetMessage;
89
90@UnionCase(627)
91public class GetDefaultMessage implements GnunetMessage.Body {
92 @UInt16
93 public int nameLength;
94 @UInt16
95 public int reserved;
96 @ZeroTerminatedString
97 public String serviceName;
98}
diff --git a/src/main/java/org/gnunet/identity/messages/RenameMessage.java b/src/main/java/org/gnunet/identity/messages/RenameMessage.java
new file mode 100644
index 0000000..a5b9d2e
--- /dev/null
+++ b/src/main/java/org/gnunet/identity/messages/RenameMessage.java
@@ -0,0 +1,58 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21/*
22 This file is part of GNUnet.
23 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
24
25 GNUnet is free software; you can redistribute it and/or modify
26 it under the terms of the GNU General Public License as published
27 by the Free Software Foundation; either version 3, or (at your
28 option) any later version.
29
30 GNUnet is distributed in the hope that it will be useful, but
31 WITHOUT ANY WARRANTY; without even the implied warranty of
32 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33 General Public License for more details.
34
35 You should have received a copy of the GNU General Public License
36 along with GNUnet; see the file COPYING. If not, write to the
37 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
38 Boston, MA 02111-1307, USA.
39 */
40
41package org.gnunet.identity.messages;
42
43import org.gnunet.construct.UInt16;
44import org.gnunet.construct.UnionCase;
45import org.gnunet.construct.ZeroTerminatedString;
46import org.gnunet.util.GnunetMessage;
47
48@UnionCase(630)
49public class RenameMessage implements GnunetMessage.Body {
50 @UInt16
51 public int oldNameLength;
52 @UInt16
53 public int newNameLength;
54 @ZeroTerminatedString
55 public String oldName;
56 @ZeroTerminatedString
57 public String newName;
58}
diff --git a/src/main/java/org/gnunet/identity/messages/ResultCodeMessage.java b/src/main/java/org/gnunet/identity/messages/ResultCodeMessage.java
new file mode 100644
index 0000000..c761603
--- /dev/null
+++ b/src/main/java/org/gnunet/identity/messages/ResultCodeMessage.java
@@ -0,0 +1,121 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21/*
22 This file is part of GNUnet.
23 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
24
25 GNUnet is free software; you can redistribute it and/or modify
26 it under the terms of the GNU General Public License as published
27 by the Free Software Foundation; either version 3, or (at your
28 option) any later version.
29
30 GNUnet is distributed in the hope that it will be useful, but
31 WITHOUT ANY WARRANTY; without even the implied warranty of
32 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33 General Public License for more details.
34
35 You should have received a copy of the GNU General Public License
36 along with GNUnet; see the file COPYING. If not, write to the
37 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
38 Boston, MA 02111-1307, USA.
39 */
40
41/*
42 This file is part of GNUnet.
43 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
44
45 GNUnet is free software; you can redistribute it and/or modify
46 it under the terms of the GNU General Public License as published
47 by the Free Software Foundation; either version 3, or (at your
48 option) any later version.
49
50 GNUnet is distributed in the hope that it will be useful, but
51 WITHOUT ANY WARRANTY; without even the implied warranty of
52 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
53 General Public License for more details.
54
55 You should have received a copy of the GNU General Public License
56 along with GNUnet; see the file COPYING. If not, write to the
57 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
58 Boston, MA 02111-1307, USA.
59 */
60
61/*
62 This file is part of GNUnet.
63 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
64
65 GNUnet is free software; you can redistribute it and/or modify
66 it under the terms of the GNU General Public License as published
67 by the Free Software Foundation; either version 3, or (at your
68 option) any later version.
69
70 GNUnet is distributed in the hope that it will be useful, but
71 WITHOUT ANY WARRANTY; without even the implied warranty of
72 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
73 General Public License for more details.
74
75 You should have received a copy of the GNU General Public License
76 along with GNUnet; see the file COPYING. If not, write to the
77 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
78 Boston, MA 02111-1307, USA.
79 */
80
81/*
82 This file is part of GNUnet.
83 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
84
85 GNUnet is free software; you can redistribute it and/or modify
86 it under the terms of the GNU General Public License as published
87 by the Free Software Foundation; either version 3, or (at your
88 option) any later version.
89
90 GNUnet is distributed in the hope that it will be useful, but
91 WITHOUT ANY WARRANTY; without even the implied warranty of
92 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
93 General Public License for more details.
94
95 You should have received a copy of the GNU General Public License
96 along with GNUnet; see the file COPYING. If not, write to the
97 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
98 Boston, MA 02111-1307, USA.
99 */
100
101package org.gnunet.identity.messages;
102
103import org.gnunet.construct.*;
104import org.gnunet.util.CryptoECC;
105import org.gnunet.util.GnunetMessage;
106
107/**
108 * Answer from service to client about last operation;
109 * GET_DEFAULT maybe answered with this message on failure;
110 * CREATE and RENAME will always be answered with this message.
111 */
112@UnionCase(625)
113public class ResultCodeMessage implements GnunetMessage.Body {
114 /**
115 * Result code, currently unused.
116 */
117 @UInt32
118 public int resultCode;
119 @ZeroTerminatedString(optional = true)
120 public String errorMessage;
121}
diff --git a/src/main/java/org/gnunet/identity/messages/SetDefaultMessage.java b/src/main/java/org/gnunet/identity/messages/SetDefaultMessage.java
new file mode 100644
index 0000000..bcdb233
--- /dev/null
+++ b/src/main/java/org/gnunet/identity/messages/SetDefaultMessage.java
@@ -0,0 +1,85 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21/*
22 This file is part of GNUnet.
23 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
24
25 GNUnet is free software; you can redistribute it and/or modify
26 it under the terms of the GNU General Public License as published
27 by the Free Software Foundation; either version 3, or (at your
28 option) any later version.
29
30 GNUnet is distributed in the hope that it will be useful, but
31 WITHOUT ANY WARRANTY; without even the implied warranty of
32 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33 General Public License for more details.
34
35 You should have received a copy of the GNU General Public License
36 along with GNUnet; see the file COPYING. If not, write to the
37 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
38 Boston, MA 02111-1307, USA.
39 */
40
41/*
42 This file is part of GNUnet.
43 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
44
45 GNUnet is free software; you can redistribute it and/or modify
46 it under the terms of the GNU General Public License as published
47 by the Free Software Foundation; either version 3, or (at your
48 option) any later version.
49
50 GNUnet is distributed in the hope that it will be useful, but
51 WITHOUT ANY WARRANTY; without even the implied warranty of
52 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
53 General Public License for more details.
54
55 You should have received a copy of the GNU General Public License
56 along with GNUnet; see the file COPYING. If not, write to the
57 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
58 Boston, MA 02111-1307, USA.
59 */
60
61package org.gnunet.identity.messages;
62
63import org.gnunet.construct.NestedMessage;
64import org.gnunet.construct.UInt16;
65import org.gnunet.construct.UnionCase;
66import org.gnunet.construct.ZeroTerminatedString;
67import org.gnunet.util.CryptoECC;
68import org.gnunet.util.GnunetMessage;
69
70
71/**
72 * Used from service to client as a result to the GET_DEFAULT
73 * message, used from client to service to SET_DEFAULT.
74 */
75@UnionCase(628)
76public class SetDefaultMessage implements GnunetMessage.Body {
77 @UInt16
78 public int nameLength;
79 @UInt16
80 public int reserved;
81 @NestedMessage
82 public CryptoECC.PrivateKey privateKey;
83 @ZeroTerminatedString
84 public String serviceName;
85}
diff --git a/src/main/java/org/gnunet/identity/messages/StartMessage.java b/src/main/java/org/gnunet/identity/messages/StartMessage.java
new file mode 100644
index 0000000..b8fbbee
--- /dev/null
+++ b/src/main/java/org/gnunet/identity/messages/StartMessage.java
@@ -0,0 +1,73 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21/*
22 This file is part of GNUnet.
23 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
24
25 GNUnet is free software; you can redistribute it and/or modify
26 it under the terms of the GNU General Public License as published
27 by the Free Software Foundation; either version 3, or (at your
28 option) any later version.
29
30 GNUnet is distributed in the hope that it will be useful, but
31 WITHOUT ANY WARRANTY; without even the implied warranty of
32 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33 General Public License for more details.
34
35 You should have received a copy of the GNU General Public License
36 along with GNUnet; see the file COPYING. If not, write to the
37 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
38 Boston, MA 02111-1307, USA.
39 */
40
41/*
42 This file is part of GNUnet.
43 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
44
45 GNUnet is free software; you can redistribute it and/or modify
46 it under the terms of the GNU General Public License as published
47 by the Free Software Foundation; either version 3, or (at your
48 option) any later version.
49
50 GNUnet is distributed in the hope that it will be useful, but
51 WITHOUT ANY WARRANTY; without even the implied warranty of
52 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
53 General Public License for more details.
54
55 You should have received a copy of the GNU General Public License
56 along with GNUnet; see the file COPYING. If not, write to the
57 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
58 Boston, MA 02111-1307, USA.
59 */
60
61package org.gnunet.identity.messages;
62
63import org.gnunet.construct.NestedMessage;
64import org.gnunet.construct.UInt16;
65import org.gnunet.construct.UnionCase;
66import org.gnunet.construct.ZeroTerminatedString;
67import org.gnunet.util.CryptoECC;
68import org.gnunet.util.GnunetMessage;
69
70@UnionCase(624)
71public class StartMessage implements GnunetMessage.Body {
72
73}
diff --git a/src/main/java/org/gnunet/identity/messages/UpdateListMessage.java b/src/main/java/org/gnunet/identity/messages/UpdateListMessage.java
new file mode 100644
index 0000000..f1fb8ab
--- /dev/null
+++ b/src/main/java/org/gnunet/identity/messages/UpdateListMessage.java
@@ -0,0 +1,104 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21/*
22 This file is part of GNUnet.
23 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
24
25 GNUnet is free software; you can redistribute it and/or modify
26 it under the terms of the GNU General Public License as published
27 by the Free Software Foundation; either version 3, or (at your
28 option) any later version.
29
30 GNUnet is distributed in the hope that it will be useful, but
31 WITHOUT ANY WARRANTY; without even the implied warranty of
32 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33 General Public License for more details.
34
35 You should have received a copy of the GNU General Public License
36 along with GNUnet; see the file COPYING. If not, write to the
37 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
38 Boston, MA 02111-1307, USA.
39 */
40
41/*
42 This file is part of GNUnet.
43 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
44
45 GNUnet is free software; you can redistribute it and/or modify
46 it under the terms of the GNU General Public License as published
47 by the Free Software Foundation; either version 3, or (at your
48 option) any later version.
49
50 GNUnet is distributed in the hope that it will be useful, but
51 WITHOUT ANY WARRANTY; without even the implied warranty of
52 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
53 General Public License for more details.
54
55 You should have received a copy of the GNU General Public License
56 along with GNUnet; see the file COPYING. If not, write to the
57 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
58 Boston, MA 02111-1307, USA.
59 */
60
61/*
62 This file is part of GNUnet.
63 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
64
65 GNUnet is free software; you can redistribute it and/or modify
66 it under the terms of the GNU General Public License as published
67 by the Free Software Foundation; either version 3, or (at your
68 option) any later version.
69
70 GNUnet is distributed in the hope that it will be useful, but
71 WITHOUT ANY WARRANTY; without even the implied warranty of
72 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
73 General Public License for more details.
74
75 You should have received a copy of the GNU General Public License
76 along with GNUnet; see the file COPYING. If not, write to the
77 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
78 Boston, MA 02111-1307, USA.
79 */
80
81package org.gnunet.identity.messages;
82
83import org.gnunet.construct.NestedMessage;
84import org.gnunet.construct.UInt16;
85import org.gnunet.construct.UnionCase;
86import org.gnunet.construct.ZeroTerminatedString;
87import org.gnunet.util.CryptoECC;
88import org.gnunet.util.GnunetMessage;
89
90
91/**
92 * Service informs client about status of a pseudonym.
93 */
94@UnionCase(626)
95public class UpdateListMessage implements GnunetMessage.Body{
96 @UInt16
97 public int nameLength;
98 @UInt16
99 public int endOfList;
100 @NestedMessage
101 public CryptoECC.PrivateKey privateKey;
102 @ZeroTerminatedString
103 public String egoName;
104}
diff --git a/src/main/java/org/gnunet/mq/MessageQueue.java b/src/main/java/org/gnunet/mq/MessageQueue.java
index cab1003..85abd67 100644
--- a/src/main/java/org/gnunet/mq/MessageQueue.java
+++ b/src/main/java/org/gnunet/mq/MessageQueue.java
@@ -73,6 +73,10 @@ public abstract class MessageQueue {
73 trySubmitNext(); 73 trySubmitNext();
74 } 74 }
75 75
76 /**
77 * Report to the message queue that the message has been sent irrevocably.
78 * Only up to calling reportMessageSend, a message can be canceled.
79 */
76 protected void reportMessageSent() { 80 protected void reportMessageSent() {
77 if (null == currentEnvelope) 81 if (null == currentEnvelope)
78 throw new AssertionError(); 82 throw new AssertionError();
diff --git a/src/main/java/org/gnunet/testbed/Controller.java b/src/main/java/org/gnunet/testbed/Controller.java
index 3a4c540..939f855 100644
--- a/src/main/java/org/gnunet/testbed/Controller.java
+++ b/src/main/java/org/gnunet/testbed/Controller.java
@@ -352,20 +352,16 @@ public class Controller {
352 * @param host host to run the controller on; This should be the same host if 352 * @param host host to run the controller on; This should be the same host if
353 * the controller was previously started with 353 * the controller was previously started with
354 * GNUNET_TESTBED_controller_start() 354 * GNUNET_TESTBED_controller_start()
355 * @param event_mask bit mask with set of events to call 'cc' for;
356 * or-ed values of "1LL" shifted by the
357 * respective 'enum GNUNET_TESTBED_EventType'
358 * (i.e. "(1LL << GNUNET_TESTBED_ET_CONNECT) | ...")
359 * @param cb controller callback to invoke on events
360 */ 355 */
361 public Controller(Host host, long event_mask, ControllerEventCallback cb) { 356 public Controller(Host host) {
362 this.host = host; 357 this.host = host;
363 client = new Client("testbed", host.cfg); 358 client = new Client("testbed", host.cfg);
364 client.installReceiver(new ControllerMessageReceiver()); 359 client.installReceiver(new ControllerMessageReceiver());
365 requests = new MatchingRequestContainer<Long, OperationRequest>(client); 360 requests = new MatchingRequestContainer<Long, OperationRequest>(client);
366 361
367 ControllerInitMessage m = new ControllerInitMessage(); 362 ControllerInitMessage m = new ControllerInitMessage();
368 m.event_mask = event_mask; 363 // we are interested in all events
364 m.event_mask = 1 | 2 | 4 | 8 | 16;
369 m.controler_hostname = (host.hostname == null) ? "127.0.0.1" : host.hostname; 365 m.controler_hostname = (host.hostname == null) ? "127.0.0.1" : host.hostname;
370 m.host_id = host.id; 366 m.host_id = host.id;
371 client.send(m); 367 client.send(m);
@@ -500,7 +496,6 @@ public class Controller {
500 return requests.addRequest(r.operationId, r); 496 return requests.addRequest(r.operationId, r);
501 } 497 }
502 498
503
504 public Cancelable requestInformation(PeerInformationCallback cb) { 499 public Cancelable requestInformation(PeerInformationCallback cb) {
505 PeerInformationRequest r = new PeerInformationRequest(this, cb); 500 PeerInformationRequest r = new PeerInformationRequest(this, cb);
506 return requests.addRequest(r.operationId, r); 501 return requests.addRequest(r.operationId, r);
diff --git a/src/main/java/org/gnunet/testbed/callbacks/ControllerEventCallback.java b/src/main/java/org/gnunet/testbed/callbacks/ControllerEventCallback.java
deleted file mode 100644
index 573c38a..0000000
--- a/src/main/java/org/gnunet/testbed/callbacks/ControllerEventCallback.java
+++ /dev/null
@@ -1,21 +0,0 @@
1package org.gnunet.testbed.callbacks;
2
3
4
5public abstract class ControllerEventCallback {
6 void onPeerStart() {
7 throw new AssertionError("event not handled");
8 }
9 void onPeerStop() {
10 throw new AssertionError("event not handled");
11 }
12 void onPeerConnect() {
13 throw new AssertionError("event not handled");
14 }
15 void onPeerDisconnect() {
16 throw new AssertionError("event not handled");
17 }
18 void onOperationFinished() {
19 throw new AssertionError("event not handled");
20 }
21}
diff --git a/src/main/java/org/gnunet/testbed/messages/PeerInformationMessage.java b/src/main/java/org/gnunet/testbed/messages/PeerInformationMessage.java
index b009f58..670da41 100644
--- a/src/main/java/org/gnunet/testbed/messages/PeerInformationMessage.java
+++ b/src/main/java/org/gnunet/testbed/messages/PeerInformationMessage.java
@@ -48,9 +48,6 @@ public class PeerInformationMessage implements GnunetMessage.Body {
48 @UInt16 48 @UInt16
49 public int uncompressedConfigSize; 49 public int uncompressedConfigSize;
50 50
51 @UInt16
52 public int pading1;
53
54 @FillWith @UInt8 51 @FillWith @UInt8
55 public byte[] compressedConfig; 52 public byte[] compressedConfig;
56} 53}
diff --git a/src/main/java/org/gnunet/util/AbsoluteTime.java b/src/main/java/org/gnunet/util/AbsoluteTime.java
index 265abf5..6027198 100644
--- a/src/main/java/org/gnunet/util/AbsoluteTime.java
+++ b/src/main/java/org/gnunet/util/AbsoluteTime.java
@@ -23,7 +23,11 @@ package org.gnunet.util;
23import org.slf4j.Logger; 23import org.slf4j.Logger;
24import org.slf4j.LoggerFactory; 24import org.slf4j.LoggerFactory;
25 25
26import java.text.ParseException;
27import java.text.SimpleDateFormat;
28import java.util.Calendar;
26import java.util.Date; 29import java.util.Date;
30import java.util.GregorianCalendar;
27 31
28/** 32/**
29 * A specific point in time. 33 * A specific point in time.
@@ -270,4 +274,46 @@ public class AbsoluteTime implements Comparable<AbsoluteTime> {
270 public long getSeconds() { 274 public long getSeconds() {
271 return abs_value_us / (1000 * 1000); 275 return abs_value_us / (1000 * 1000);
272 } 276 }
277
278 public static AbsoluteTime fromSeconds(long stamp) {
279 return new AbsoluteTime(stamp * 1000 * 1000);
280 }
281
282 public String toFancyString() {
283 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
284 return sdf.format(new Date(getMilliseconds()));
285 }
286
287 private long getMilliseconds() {
288 return abs_value_us / 1000;
289 }
290
291 public static AbsoluteTime fromString(String s) {
292 Date date = null;
293
294 try {
295 SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
296 date = sdf.parse(s);
297 return new AbsoluteTime(date.getTime() * 1000);
298 } catch (ParseException e) {
299 // try next format
300 }
301
302 try {
303 SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd HH:mm");
304 date = sdf.parse(s);
305 return new AbsoluteTime(date.getTime() * 1000);
306 } catch (ParseException e) {
307 // try next format
308 }
309
310 try {
311 SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd");
312 date = sdf.parse(s);
313 return new AbsoluteTime(date.getTime() * 1000);
314 } catch (ParseException e) {
315 // try next format
316 }
317 return null;
318 }
273} 319}
diff --git a/src/main/java/org/gnunet/util/Connection.java b/src/main/java/org/gnunet/util/Connection.java
index 1c569c4..c8b6a48 100644
--- a/src/main/java/org/gnunet/util/Connection.java
+++ b/src/main/java/org/gnunet/util/Connection.java
@@ -31,6 +31,7 @@ import java.io.IOException;
31import java.net.InetAddress; 31import java.net.InetAddress;
32import java.net.InetSocketAddress; 32import java.net.InetSocketAddress;
33import java.nio.ByteBuffer; 33import java.nio.ByteBuffer;
34import java.nio.channels.SelectionKey;
34import java.nio.channels.SocketChannel; 35import java.nio.channels.SocketChannel;
35import java.nio.channels.spi.SelectorProvider; 36import java.nio.channels.spi.SelectorProvider;
36import java.util.LinkedList; 37import java.util.LinkedList;
@@ -101,7 +102,7 @@ public class Connection {
101 /** 102 /**
102 * Timeout task for the connect notify. 103 * Timeout task for the connect notify.
103 */ 104 */
104 private Scheduler.TaskConfiguration notifyConnectedTimeout; 105 private Scheduler.TaskIdentifier notifyConnectedTimeout;
105 106
106 /** 107 /**
107 * Continuation to call when connected 108 * Continuation to call when connected
@@ -159,7 +160,7 @@ public class Connection {
159 private MessageReceiver receiver; 160 private MessageReceiver receiver;
160 private RelativeTime timeout; 161 private RelativeTime timeout;
161 private GnunetMessage.Header msgh = null; 162 private GnunetMessage.Header msgh = null;
162 private Scheduler.TaskConfiguration recvTask = null; 163 private Scheduler.TaskIdentifier recvTask = null;
163 private boolean finished = false; 164 private boolean finished = false;
164 // is this receiver actively working? if not, the connection process has to kick off the receiver 165 // is this receiver actively working? if not, the connection process has to kick off the receiver
165 // (or select behaves badly) 166 // (or select behaves badly)
@@ -367,7 +368,7 @@ public class Connection {
367 // of a message, only the max. wait time before transmission. 368 // of a message, only the max. wait time before transmission.
368 // cancel must be called on the transmitTask if we disconnect 369 // cancel must be called on the transmitTask if we disconnect
369 Scheduler.TaskConfiguration tc = new Scheduler.TaskConfiguration(RelativeTime.FOREVER, this); 370 Scheduler.TaskConfiguration tc = new Scheduler.TaskConfiguration(RelativeTime.FOREVER, this);
370 tc.selectWrite(connectionChannel); 371 tc.addSelectEvent(connectionChannel, SelectionKey.OP_WRITE);
371 this.transmitTask = tc.schedule(); 372 this.transmitTask = tc.schedule();
372 } 373 }
373 374
@@ -450,7 +451,7 @@ public class Connection {
450 return; 451 return;
451 } 452 }
452 453
453 tc.selectConnect(channel); 454 tc.addSelectEvent(channel, SelectionKey.OP_CONNECT);
454 455
455 addressProbe.connectTask = tc.schedule(); 456 addressProbe.connectTask = tc.schedule();
456 } 457 }
diff --git a/src/main/java/org/gnunet/util/CryptoECC.java b/src/main/java/org/gnunet/util/CryptoECC.java
index d27a2a4..a02cf70 100644
--- a/src/main/java/org/gnunet/util/CryptoECC.java
+++ b/src/main/java/org/gnunet/util/CryptoECC.java
@@ -24,17 +24,16 @@ import org.gnunet.construct.FixedSizeIntegerArray;
24import org.gnunet.construct.Message; 24import org.gnunet.construct.Message;
25 25
26import java.io.File; 26import java.io.File;
27import java.io.FileOutputStream;
28import java.io.IOError; 27import java.io.IOError;
29import java.io.IOException; 28import java.io.IOException;
30import java.math.BigInteger; 29import java.math.BigInteger;
31import java.nio.ByteBuffer; 30import java.nio.ByteBuffer;
32import java.nio.file.Files; 31import java.nio.file.Files;
33import java.nio.file.OpenOption;
34import java.nio.file.StandardOpenOption; 32import java.nio.file.StandardOpenOption;
35import java.security.MessageDigest; 33import java.security.MessageDigest;
36import java.security.NoSuchAlgorithmException; 34import java.security.NoSuchAlgorithmException;
37import java.security.SecureRandom; 35import java.security.SecureRandom;
36import java.util.Arrays;
38import java.util.Random; 37import java.util.Random;
39 38
40/** 39/**
@@ -42,7 +41,6 @@ import java.util.Random;
42 * Original Java version written and placed into the public domain by k3d3 (https://github.com/k3d3/ed25519-java). 41 * Original Java version written and placed into the public domain by k3d3 (https://github.com/k3d3/ed25519-java).
43 */ 42 */
44public class CryptoECC { 43public class CryptoECC {
45
46 /** 44 /**
47 * Private ECC key. 45 * Private ECC key.
48 */ 46 */
@@ -91,7 +89,7 @@ public class CryptoECC {
91 /** 89 /**
92 * Public ECC key. 90 * Public ECC key.
93 */ 91 */
94 public static final class PublicKey implements Message { 92 public static final class PublicSignKey implements Message {
95 /** 93 /**
96 * x-coordinate of the point on the curve. 94 * x-coordinate of the point on the curve.
97 * The number is stored as little endian. 95 * The number is stored as little endian.
@@ -116,8 +114,8 @@ public class CryptoECC {
116 return new BigInteger[]{decodeint(x), decodeint(y)}; 114 return new BigInteger[]{decodeint(x), decodeint(y)};
117 } 115 }
118 116
119 public static PublicKey fromString(String s) { 117 public static PublicSignKey fromString(String s) {
120 PublicKey pk = new PublicKey(); 118 PublicSignKey pk = new PublicSignKey();
121 byte[] data = Strings.stringToData(s, 32); 119 byte[] data = Strings.stringToData(s, 32);
122 if (null == data) 120 if (null == data)
123 return null; 121 return null;
@@ -126,6 +124,26 @@ public class CryptoECC {
126 pk.y = encodeint(point[1]); 124 pk.y = encodeint(point[1]);
127 return pk; 125 return pk;
128 } 126 }
127
128 @Override
129 public boolean equals(Object o) {
130 if (this == o) return true;
131 if (o == null || getClass() != o.getClass()) return false;
132
133 PublicSignKey that = (PublicSignKey) o;
134
135 if (!Arrays.equals(x, that.x)) return false;
136 if (!Arrays.equals(y, that.y)) return false;
137
138 return true;
139 }
140
141 @Override
142 public int hashCode() {
143 int result = Arrays.hashCode(x);
144 result = 31 * result + Arrays.hashCode(y);
145 return result;
146 }
129 } 147 }
130 148
131 /** 149 /**
@@ -336,10 +354,10 @@ public class CryptoECC {
336 * @param sk private key 354 * @param sk private key
337 * @return public key derived from 'sk' 355 * @return public key derived from 'sk'
338 */ 356 */
339 static public PublicKey computePublicKey(PrivateKey sk) { 357 static public PublicSignKey computePublicKey(PrivateKey sk) {
340 BigInteger a = computePublicKeyCoefficient(sk); 358 BigInteger a = computePublicKeyCoefficient(sk);
341 BigInteger[] A = scalarmult(B, a); 359 BigInteger[] A = scalarmult(B, a);
342 PublicKey publicKey = new PublicKey(); 360 PublicSignKey publicKey = new PublicSignKey();
343 publicKey.x = encodeint(A[0]); 361 publicKey.x = encodeint(A[0]);
344 publicKey.y = encodeint(A[1]); 362 publicKey.y = encodeint(A[1]);
345 return publicKey; 363 return publicKey;
@@ -370,7 +388,7 @@ public class CryptoECC {
370 * parameter for performance reasons 388 * parameter for performance reasons
371 * @return a signature on m 389 * @return a signature on m
372 */ 390 */
373 public static Signature sign(byte[] m, PrivateKey sk, PublicKey pk) { 391 public static Signature sign(byte[] m, PrivateKey sk, PublicSignKey pk) {
374 byte[] compressed_pk = encodepoint(new BigInteger[]{decodeint(pk.x), decodeint(pk.y)}); 392 byte[] compressed_pk = encodepoint(new BigInteger[]{decodeint(pk.x), decodeint(pk.y)});
375 byte[] h = sha512.digest(sk.d); 393 byte[] h = sha512.digest(sk.d);
376 BigInteger a = BigInteger.valueOf(2).pow(b-2); 394 BigInteger a = BigInteger.valueOf(2).pow(b-2);
@@ -453,7 +471,7 @@ public class CryptoECC {
453 * @param pk public key of the signature creator 471 * @param pk public key of the signature creator
454 * @return whether the signature is valid 472 * @return whether the signature is valid
455 */ 473 */
456 public static boolean verify(Signature sig, byte[] m, PublicKey pk) { 474 public static boolean verify(Signature sig, byte[] m, PublicSignKey pk) {
457 BigInteger[] R = decodepoint(sig.r); 475 BigInteger[] R = decodepoint(sig.r);
458 BigInteger[] A = new BigInteger[]{decodeint(pk.x), decodeint(pk.y)}; 476 BigInteger[] A = new BigInteger[]{decodeint(pk.x), decodeint(pk.y)};
459 BigInteger S = decodeint(sig.s); 477 BigInteger S = decodeint(sig.s);
@@ -472,7 +490,7 @@ public class CryptoECC {
472 * @param publicKey public key to use for the ECDH (yG) 490 * @param publicKey public key to use for the ECDH (yG)
473 * @return key material (xyG) 491 * @return key material (xyG)
474 */ 492 */
475 public static HashCode ecdh(PrivateKey privateKey, PublicKey publicKey) { 493 public static HashCode ecdh(PrivateKey privateKey, PublicSignKey publicKey) {
476 BigInteger[] publicPoint = new BigInteger[]{decodeint(publicKey.x), decodeint(publicKey.y)}; 494 BigInteger[] publicPoint = new BigInteger[]{decodeint(publicKey.x), decodeint(publicKey.y)};
477 BigInteger coeff = computePublicKeyCoefficient(privateKey); 495 BigInteger coeff = computePublicKeyCoefficient(privateKey);
478 BigInteger[] R = scalarmult(publicPoint, coeff); 496 BigInteger[] R = scalarmult(publicPoint, coeff);
@@ -480,4 +498,16 @@ public class CryptoECC {
480 sha512.update(R[0].toByteArray()); 498 sha512.update(R[0].toByteArray());
481 return new HashCode(sha512.digest(R[1].toByteArray())); 499 return new HashCode(sha512.digest(R[1].toByteArray()));
482 } 500 }
501
502 /**
503 * Get the shared private key we use for anonymous users.
504 *
505 * @return "anonymous" private key
506 */
507 public static PrivateKey getAnonymous() {
508 PrivateKey privateKey = new PrivateKey();
509 privateKey.d = encodeint(BigInteger.ONE);
510 return privateKey;
511 }
512
483} 513}
diff --git a/src/main/java/org/gnunet/util/Helper.java b/src/main/java/org/gnunet/util/Helper.java
index ea757f6..64d4aaa 100644
--- a/src/main/java/org/gnunet/util/Helper.java
+++ b/src/main/java/org/gnunet/util/Helper.java
@@ -19,23 +19,18 @@
19 */ 19 */
20package org.gnunet.util; 20package org.gnunet.util;
21 21
22
22import org.gnunet.construct.Construct; 23import org.gnunet.construct.Construct;
23import org.gnunet.construct.Message;
24import org.gnunet.construct.MessageLoader;
25import org.gnunet.construct.ProtocolViolationException;
26import org.gnunet.mq.Envelope; 24import org.gnunet.mq.Envelope;
27import org.gnunet.mq.MessageQueue; 25import org.gnunet.mq.MessageQueue;
28import org.slf4j.Logger; 26import org.slf4j.Logger;
29import org.slf4j.LoggerFactory; 27import org.slf4j.LoggerFactory;
30 28
31import java.io.File; 29import java.io.ByteArrayOutputStream;
32import java.io.IOError; 30import java.io.IOError;
33import java.io.IOException; 31import java.io.IOException;
34import java.nio.Buffer;
35import java.nio.ByteBuffer; 32import java.nio.ByteBuffer;
36import java.nio.channels.Channels; 33import java.nio.channels.*;
37import java.nio.channels.ReadableByteChannel;
38import java.util.EnumSet;
39import java.util.LinkedList; 34import java.util.LinkedList;
40import java.util.List; 35import java.util.List;
41 36
@@ -50,145 +45,103 @@ public class Helper extends MessageQueue {
50 private final ProcessBuilder processBuilder; 45 private final ProcessBuilder processBuilder;
51 private final RunaboutMessageReceiver receiver; 46 private final RunaboutMessageReceiver receiver;
52 private Process process; 47 private Process process;
53 private volatile GnunetMessage.Body writeMessage; 48
54 private WriteThread writeThread; 49 private WriteThread writeThread;
55 private ReadThread readThread; 50 private ReadThread readThread;
51
52 private Scheduler.TaskConfiguration writeTaskConfig;
53 private Scheduler.TaskIdentifier writeTaskId;
54
55 private Scheduler.TaskConfiguration readTaskConfig;
56 private Scheduler.TaskIdentifier readTaskId;
57
58 private ByteBuffer writeBuffer = ByteBuffer.allocate(1024);
59
60 private MessageStreamTokenizer mst;
61
62 private boolean killed;
63
64
56 /** 65 /**
57 * Task that guarantees scheduler lifeness while the helper process 66 * Thread that writes data from a pipe to the helper process.
58 * is running.
59 */ 67 */
60 private Cancelable lifenessTask;
61
62 private final class WriteThread extends Thread { 68 private final class WriteThread extends Thread {
69 final Pipe pipe;
70 public WriteThread() {
71 try {
72 pipe = Pipe.open();
73 } catch (IOException e) {
74 throw new RuntimeException("JVM does not support pipes");
75 }
76 }
63 @Override 77 @Override
64 public void run() { 78 public void run() {
65 logger.debug("in write thread"); 79 WritableByteChannel channel = Channels.newChannel(process.getOutputStream());
66 GnunetMessage.Body msg; 80 ByteBuffer buffer = ByteBuffer.allocate(1024);
67 while (true) { 81 while (true) {
68 synchronized (Helper.this) { 82 buffer.clear();
69 while (writeMessage == null) {
70 try {
71 Helper.this.wait();
72 } catch (InterruptedException e) {
73 // do nothing
74 }
75 }
76 // we now have a message we can send
77 msg = writeMessage;
78 writeMessage = null;
79 // somebody can set the next send message
80 }
81 logger.debug("helper got message");
82 GnunetMessage gm = GnunetMessage.fromBody(msg);
83 byte[] data = Construct.toBinary(gm);
84 try { 83 try {
85 process.getOutputStream().write(data); 84 logger.debug("waiting for readable pipe in thread");
86 process.getOutputStream().flush(); 85 int n = pipe.source().read(buffer);
86 if (n == -1) {
87 logger.debug("write thread pipe closed");
88 return;
89 }
90 logger.debug("read {} bytes from pipe", n);
91 buffer.flip();
92 while (buffer.hasRemaining()) {
93 n = channel.write(buffer);
94 process.getOutputStream().flush();
95 logger.debug("written {} bytes to process", n);
96 }
97 } catch (ClosedChannelException e) {
98 logger.debug("channel closed for write thread");
99 return;
87 } catch (IOException e) { 100 } catch (IOException e) {
88 throw new IOError(e); 101 throw new IOError(e);
89 } 102 }
90 logger.debug("helper wrote message, size {}, size in header {}, adding cont", data.length, gm.header.messageSize);
91 Scheduler.addContinuation(new Scheduler.Task() {
92 @Override
93 public void run(Scheduler.RunContext ctx) {
94 reportMessageSent();
95 }
96 }, EnumSet.noneOf(Scheduler.Reason.class));
97 logger.debug("cont added");
98 } 103 }
99 } 104 }
100 } 105 }
101 106
107 /**
108 * Thread that reads data from the helper process and writes it
109 * to a pipe.
110 */
102 private final class ReadThread extends Thread { 111 private final class ReadThread extends Thread {
103 private ByteBuffer buffer; 112 Pipe pipe;
104 ReadableByteChannel channel;
105
106 /**
107 * Read until our buffer is full, or an error occurs.
108 *
109 * @return true on success
110 */
111 private boolean fillBuffer() {
112 while (buffer.hasRemaining()) {
113 try {
114 int n = channel.read(buffer);
115 if (n == -1) {
116 logger.debug("read eof");
117 return false;
118 }
119 } catch (IOException e) {
120 logger.debug("read error");
121 return false;
122 }
123 }
124 logger.debug("filled buffer");
125 return true;
126 }
127
128 private void scheduleInvokeReceiver(final GnunetMessage.Body body) {
129 Scheduler.addContinuation(new Scheduler.Task() {
130 @Override
131 public void run(Scheduler.RunContext ctx) {
132 logger.debug("calling receiver with message");
133 receiver.process(body);
134 }
135 }, EnumSet.noneOf(Scheduler.Reason.class));
136 113
114 public ReadThread() {
115 try {
116 pipe = Pipe.open();
117 } catch (IOException e) {
118 throw new RuntimeException("JVM does not support pipes");
119 }
137 } 120 }
138
139 @Override 121 @Override
140 public void run() { 122 public void run() {
141 // allocate just enough for the message header 123 byte[] buf = new byte[1024];
142 buffer = ByteBuffer.allocate(4);
143 channel = Channels.newChannel(process.getInputStream());
144 while (true) { 124 while (true) {
145 // FIXME: use some more general mechanism for reading messages (like a message stream tokenizer) 125 int n;
146 logger.debug("helper ready to receive message");
147 buffer.clear();
148 buffer.limit(4);
149 if (!fillBuffer())
150 return;
151 buffer.rewind();
152 GnunetMessage.Header msgh = Construct.parseAs(buffer, GnunetMessage.Header.class);
153 logger.debug("helper received header of size {}, type {}", msgh.messageSize, msgh.messageType);
154 if (msgh.messageSize > GnunetMessage.Header.SIZE) {
155 if (buffer.capacity() < msgh.messageSize) {
156 ByteBuffer newBuf = ByteBuffer.allocate(msgh.messageSize);
157 buffer.flip();
158 newBuf.put(buffer);
159 buffer = newBuf;
160 }
161 buffer.limit(msgh.messageSize);
162 if (!fillBuffer())
163 return;
164 }
165 // we now have a complete message
166 // prepare for reading again
167 buffer.flip();
168
169 boolean found = true;
170 try { 126 try {
171 MessageLoader.getUnionClass(GnunetMessage.Body.class, msgh.messageType); 127 logger.debug("reading from process");
172 } catch (ProtocolViolationException e) { 128 n = process.getInputStream().read(buf);
173 found = false; 129 if (n == -1) {
130 logger.debug("reached EOF while reading from process");
131 break;
132 }
133 logger.debug("read {} bytes from process", n);
134 ByteBuffer b = ByteBuffer.wrap(buf, 0, n);
135 while (b.hasRemaining()) {
136 pipe.sink().write(b);
137 }
138 } catch (ClosedChannelException e) {
139 logger.debug("channel closed for read thread");
140 return;
174 } 141 }
175 logger.debug("about to parse message"); 142 catch (IOException e) {
176 if (found) { 143 throw new IOError(e);
177 logger.debug("found");
178 GnunetMessage msg;
179 msg = Construct.parseAs(buffer, GnunetMessage.class);
180 logger.debug("parsed");
181 scheduleInvokeReceiver(msg.body);
182 logger.debug("scheduled");
183 } else {
184 logger.debug("not found");
185 UnknownMessageBody b = new UnknownMessageBody();
186 b.data = buffer.array();
187 b.id = msgh.messageType;
188 scheduleInvokeReceiver(b);
189 logger.debug("scheduled");
190 } 144 }
191 logger.debug("scheduled call to receiver");
192 } 145 }
193 } 146 }
194 } 147 }
@@ -203,6 +156,50 @@ public class Helper extends MessageQueue {
203 return prefix + "/lib/" + "gnunet/" + "libexec/" + binaryName; 156 return prefix + "/lib/" + "gnunet/" + "libexec/" + binaryName;
204 } 157 }
205 158
159
160 private class ReadTask implements Scheduler.Task {
161 @Override
162 public void run(Scheduler.RunContext ctx) {
163 readTaskId = null;
164 int n = mst.readFrom(readThread.pipe.source());
165 if (n != -1 && readThread.pipe.source().isOpen()) {
166 readTaskId = readTaskConfig.schedule();
167 }
168 }
169 }
170
171 private class WriteTask implements Scheduler.Task {
172 @Override
173 public void run(Scheduler.RunContext ctx) {
174 writeTaskId = null;
175 try {
176 int n = writeThread.pipe.sink().write(writeBuffer);
177 logger.debug("wrote {} bytes in write task", n);
178 } catch (IOException e) {
179 throw new IOError(e);
180 }
181 if (writeBuffer.hasRemaining()) {
182 writeTaskId = writeTaskConfig.schedule();
183 } else {
184 reportMessageSent();
185 reportReadyForSubmit();
186 }
187 }
188 }
189
190 private class HelperMstCallback implements MstCalllback {
191 @Override
192 public void onUnknownMessage(UnknownMessageBody b) {
193 logger.warn("got unknown message type");
194 }
195
196 @Override
197 public void onKnownMessage(GnunetMessage msg) {
198 logger.debug("processing message from helper");
199 receiver.process(msg.body);
200 }
201 }
202
206 /** 203 /**
207 * Create and start a new helper process 204 * Create and start a new helper process
208 * 205 *
@@ -229,21 +226,31 @@ public class Helper extends MessageQueue {
229 throw new IOError(e); 226 throw new IOError(e);
230 } 227 }
231 228
232 lifenessTask = Scheduler.addDelayed(RelativeTime.FOREVER, new Scheduler.Task() { 229 mst = new MessageStreamTokenizer(new HelperMstCallback());
233 @Override
234 public void run(Scheduler.RunContext ctx) {
235 // do nothing
236 }
237 });
238 230
239 writeThread = new WriteThread(); 231 writeThread = new WriteThread();
240 readThread = new ReadThread(); 232 readThread = new ReadThread();
241 233
242 logger.debug("creating helper"); 234 logger.debug("creating helper");
243 235
236 try {
237 readThread.pipe.source().configureBlocking(false);
238 writeThread.pipe.sink().configureBlocking(false);
239 } catch (IOException e) {
240 throw new IOError(e);
241 }
242
244 writeThread.start(); 243 writeThread.start();
245 readThread.start(); 244 readThread.start();
246 245
246 readTaskConfig = new Scheduler.TaskConfiguration(RelativeTime.FOREVER, new ReadTask());
247 readTaskConfig.addSelectEvent(readThread.pipe.source(), SelectionKey.OP_READ);
248
249 writeTaskConfig = new Scheduler.TaskConfiguration(RelativeTime.FOREVER, new WriteTask());
250 writeTaskConfig.addSelectEvent(writeThread.pipe.sink(), SelectionKey.OP_WRITE);
251
252 readTaskId = readTaskConfig.schedule();
253
247 reportReadyForSubmit(); 254 reportReadyForSubmit();
248 } 255 }
249 256
@@ -255,7 +262,24 @@ public class Helper extends MessageQueue {
255 * @return true on success, false on failure 262 * @return true on success, false on failure
256 */ 263 */
257 public boolean kill(boolean softkill) { 264 public boolean kill(boolean softkill) {
258 lifenessTask.cancel(); 265 killed = true;
266 if (readTaskId != null) {
267 readTaskId.cancel();
268 readTaskId = null;
269 }
270 if (writeTaskId != null) {
271 writeTaskId.cancel();
272 writeTaskId = null;
273 }
274
275 try {
276 readThread.pipe.source().close();
277 readThread.pipe.sink().close();
278 writeThread.pipe.source().close();
279 writeThread.pipe.sink().close();
280 } catch (IOException e) {
281 throw new IOError(e);
282 }
259 if (softkill) { 283 if (softkill) {
260 try { 284 try {
261 process.getInputStream().close(); 285 process.getInputStream().close();
@@ -278,7 +302,6 @@ public class Helper extends MessageQueue {
278 public boolean waitFor() { 302 public boolean waitFor() {
279 try { 303 try {
280 process.waitFor(); 304 process.waitFor();
281 process.waitFor();
282 } catch (InterruptedException e) { 305 } catch (InterruptedException e) {
283 return false; 306 return false;
284 } 307 }
@@ -287,20 +310,27 @@ public class Helper extends MessageQueue {
287 310
288 @Override 311 @Override
289 protected void submit(Envelope ev) { 312 protected void submit(Envelope ev) {
313 if (writeTaskId != null) {
314 throw new AssertionError();
315 }
290 logger.debug("submitting envelope to helper thread"); 316 logger.debug("submitting envelope to helper thread");
291 synchronized (this) { 317 final GnunetMessage gm = new GnunetMessage();
292 if (writeMessage != null) 318 gm.header = new GnunetMessage.Header();
293 throw new AssertionError("message queue not implemented correctly"); 319 gm.body = ev.message;
294 writeMessage = ev.message; 320 Construct.patch(gm);
295 notifyAll(); 321 gm.header.messageSize = Construct.getSize(gm);
322 if (writeBuffer.capacity() < gm.header.messageSize) {
323 writeBuffer = ByteBuffer.allocate(gm.header.messageSize);
296 } 324 }
297 reportReadyForSubmit(); 325 writeBuffer.clear();
326 int n = Construct.write(writeBuffer, gm);
327 writeBuffer.flip();
328 logger.debug("wrote message size {} to write buffer", n);
329 writeTaskId = writeTaskConfig.schedule();
298 } 330 }
299 331
300 @Override 332 @Override
301 protected void retract() { 333 protected void retract() {
302 synchronized (this) { 334 throw new UnsupportedOperationException();
303 writeMessage = null;
304 }
305 } 335 }
306} 336}
diff --git a/src/main/java/org/gnunet/util/MessageStreamTokenizer.java b/src/main/java/org/gnunet/util/MessageStreamTokenizer.java
new file mode 100644
index 0000000..4cf0d03
--- /dev/null
+++ b/src/main/java/org/gnunet/util/MessageStreamTokenizer.java
@@ -0,0 +1,122 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21package org.gnunet.util;
22
23import org.gnunet.construct.Construct;
24import org.gnunet.construct.MessageLoader;
25import org.gnunet.construct.ProtocolViolationException;
26import org.slf4j.Logger;
27import org.slf4j.LoggerFactory;
28
29import java.io.IOError;
30import java.io.IOException;
31import java.nio.ByteBuffer;
32import java.nio.channels.Channel;
33import java.nio.channels.ClosedChannelException;
34import java.nio.channels.Pipe;
35import java.nio.channels.ReadableByteChannel;
36
37/**
38 * Extract GNUnet messages from a stream of bytes.
39 */
40public class MessageStreamTokenizer {
41 private static final Logger logger = LoggerFactory
42 .getLogger(Service.class);
43 private MstCalllback mstCalllback;
44 private ByteBuffer buffer;
45 GnunetMessage.Header msgh;
46 public MessageStreamTokenizer(MstCalllback mstCalllback) {
47 this.mstCalllback = mstCalllback;
48 // large enough buffer for a message header
49 this.buffer = ByteBuffer.allocate(4);
50 }
51
52 public void ensureBufferSize() {
53 if (buffer.capacity() < msgh.messageSize) {
54 ByteBuffer buf = ByteBuffer.allocate(msgh.messageSize);
55 buffer.flip();
56 buf.put(buffer);
57 buf.flip();
58 buffer = buf;
59 }
60 }
61
62 public void readAndDispatch() {
63 Class unionClass = null;
64 boolean found = true;
65
66 try {
67 unionClass = MessageLoader.getUnionClass(GnunetMessage.Body.class, msgh.messageType);
68 } catch (ProtocolViolationException e) {
69 found = false;
70 }
71
72 logger.debug("dispatching message");
73 if (found) {
74 GnunetMessage msg;
75 try {
76 msg = Construct.parseAs(buffer, GnunetMessage.class);
77 } catch (OutOfMemoryError e) {
78 throw new OutOfMemoryError("oom while parsing " + unionClass);
79 }
80 mstCalllback.onKnownMessage(msg);
81 } else {
82 UnknownMessageBody b = new UnknownMessageBody();
83 b.id = msgh.messageType;
84 mstCalllback.onUnknownMessage(b);
85 }
86 }
87
88 /**
89 * Read from a channel into the mst.
90 *
91 * @param source channel to read from
92 * @return -1 on end of stream, number of bytes read otherwise
93 */
94 public int readFrom(ReadableByteChannel source) {
95 int n;
96 try {
97 n = source.read(buffer);
98 } catch (ClosedChannelException e) {
99 return -1;
100 }catch (IOException e) {
101 throw new IOError(e);
102 }
103 if (msgh == null && buffer.position() >= 4) {
104 logger.debug("got header in mst");
105 // remember write position and prepare for reading
106 int writePos = buffer.position();
107 buffer.flip();
108 msgh = Construct.parseAs(buffer, GnunetMessage.Header.class);
109 ensureBufferSize();
110 // prepare for writing again, and restore write position
111 buffer.position(0);
112 buffer.compact();
113 }
114 if (msgh != null && buffer.position() >= msgh.messageSize) {
115 buffer.flip();
116 readAndDispatch();
117 msgh = null;
118 buffer.compact();
119 }
120 return n;
121 }
122}
diff --git a/src/main/java/org/gnunet/util/MstCalllback.java b/src/main/java/org/gnunet/util/MstCalllback.java
new file mode 100644
index 0000000..33abd40
--- /dev/null
+++ b/src/main/java/org/gnunet/util/MstCalllback.java
@@ -0,0 +1,27 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21package org.gnunet.util;
22
23public interface MstCalllback {
24 void onUnknownMessage(UnknownMessageBody b);
25
26 void onKnownMessage(GnunetMessage msg);
27}
diff --git a/src/main/java/org/gnunet/util/Scheduler.java b/src/main/java/org/gnunet/util/Scheduler.java
index f5eee8c..1f8d9dc 100644
--- a/src/main/java/org/gnunet/util/Scheduler.java
+++ b/src/main/java/org/gnunet/util/Scheduler.java
@@ -20,6 +20,7 @@
20 20
21package org.gnunet.util; 21package org.gnunet.util;
22 22
23import com.google.common.collect.Lists;
23import org.slf4j.Logger; 24import org.slf4j.Logger;
24import org.slf4j.LoggerFactory; 25import org.slf4j.LoggerFactory;
25 26
@@ -28,10 +29,13 @@ import java.nio.ByteBuffer;
28import java.nio.channels.*; 29import java.nio.channels.*;
29import java.nio.channels.spi.SelectorProvider; 30import java.nio.channels.spi.SelectorProvider;
30import java.util.*; 31import java.util.*;
31import java.util.concurrent.locks.ReentrantLock;
32 32
33/** 33/**
34 * Schedule computations using continuation passing style. 34 * Schedule computations using continuation passing style.
35 * <p/>
36 * By design, it is not safe to scheduler tasks from different threads.
37 * When threads can't be avoided, they should communicate with the scheduler by
38 * a pipe.
35 * 39 *
36 * @author Florian Dold 40 * @author Florian Dold
37 */ 41 */
@@ -39,12 +43,10 @@ public class Scheduler {
39 private static final Logger logger = LoggerFactory 43 private static final Logger logger = LoggerFactory
40 .getLogger(Scheduler.class); 44 .getLogger(Scheduler.class);
41 45
42 private static ReentrantLock lock = new ReentrantLock(true);
43
44 /** 46 /**
45 * Task that we are currently executing, or null if no task is currently running. 47 * Task that we are currently executing, or null if no task is currently running.
46 */ 48 */
47 private static TaskConfiguration activeTask = null; 49 private static TaskIdentifier activeTask = null;
48 50
49 /** 51 /**
50 * Number of tasks in the ready lists, that is, number of tasks that is ready to run 52 * Number of tasks in the ready lists, that is, number of tasks that is ready to run
@@ -69,21 +71,14 @@ public class Scheduler {
69 * For every priority, there is a list of tasks that is definitely ready to run. 71 * For every priority, there is a list of tasks that is definitely ready to run.
70 */ 72 */
71 @SuppressWarnings("unchecked") 73 @SuppressWarnings("unchecked")
72 final private static LinkedList<TaskConfiguration>[] readyLists = new LinkedList[Priority.numberOfPriorities]; 74 final private static LinkedList<TaskIdentifier>[] readyLists = new LinkedList[Priority.numberOfPriorities];
73 75
74 static { 76 static {
75 for (int i = 0; i < Priority.numberOfPriorities; ++i) { 77 for (int i = 0; i < Priority.numberOfPriorities; ++i) {
76 readyLists[i] = new LinkedList<TaskConfiguration>(); 78 readyLists[i] = new LinkedList<TaskIdentifier>();
77 } 79 }
78 } 80 }
79 81
80 private static final int EVENT_READ = 0, EVENT_WRITE = 1, EVENT_ACCEPT = 2, EVENT_CONNECT = 3;
81 private static final int[] eventToInterestOp = new int[]{SelectionKey.OP_READ, SelectionKey.OP_WRITE,
82 SelectionKey.OP_ACCEPT, SelectionKey.OP_CONNECT};
83 private static final Reason[] eventToReason = new Reason[]{Reason.READ_READY, Reason.WRITE_READY,
84 Reason.ACCEPT_READY, Reason.CONNECT_READY};
85
86
87 /** 82 /**
88 * Selector, used to check file descriptors for readiness. 83 * Selector, used to check file descriptors for readiness.
89 */ 84 */
@@ -102,37 +97,20 @@ public class Scheduler {
102 /** 97 /**
103 * true iff the scheduler is currently running. 98 * true iff the scheduler is currently running.
104 */ 99 */
105 private static boolean scheduler_running = false; 100 private static boolean schedulerRunning = false;
106
107 101
108 /** 102 /**
109 * Pending tasks are waiting for an event. Each pending task has a (possibly infinitely long) 103 * Pending tasks are waiting for an event. Each pending task has a (possibly infinitely long)
110 * deadline after which the task is executed regardless of the prerequisites. 104 * deadline after which the task is executed regardless of the prerequisites.
111 */ 105 */
112 final private static Queue<TaskConfiguration> pending = new PriorityQueue<TaskConfiguration>(5, new Comparator 106 final private static Queue<TaskIdentifier> pending = new PriorityQueue<TaskIdentifier>(5, new Comparator
113 <TaskConfiguration>() { 107 <TaskIdentifier>() {
114 @Override 108 @Override
115 public int compare(TaskConfiguration a, TaskConfiguration b) { 109 public int compare(TaskIdentifier a, TaskIdentifier b) {
116 return a.deadline.compareTo(b.deadline); 110 return a.deadline.compareTo(b.deadline);
117 } 111 }
118 }); 112 });
119 113
120
121 /**
122 * Reset the scheduler forcefully.
123 * Intended to be used internally in the Scheduler, as well as in test teardown.
124 */
125 public static void forceReset() {
126 scheduler_running = false;
127 readyCount = 0;
128 activeTask = null;
129 for (int i = 0; i < Priority.numberOfPriorities; ++i) {
130 readyLists[i] = new LinkedList<TaskConfiguration>();
131 }
132 pending.clear();
133 }
134
135
136 /** 114 /**
137 * Reasons for executing a task. 115 * Reasons for executing a task.
138 */ 116 */
@@ -147,94 +125,133 @@ public class Scheduler {
147 /** 125 /**
148 * The reason this task has been called by the scheduler. 126 * The reason this task has been called by the scheduler.
149 */ 127 */
150 public Set<Reason> reasons = EnumSet.noneOf(Reason.class); 128 public EnumSet<Reason> reasons = EnumSet.noneOf(Reason.class);
151 } 129 }
152 130
153 /** 131 /**
154 * A task is the basic unit of work that is managed by the scheduler. 132 * Which operations is a task identifier interested in?
155 */ 133 */
156 public static interface Task { 134 private static class TaskInterestOps {
157 public void run(RunContext ctx); 135 TaskIdentifier tid;
136 int interestOps;
158 } 137 }
159 138
160 /** 139 /**
161 * A TaskConfiguration represents a Task that will execute or has already been executed. 140 * Manage subscriptions for selection events on channels.
162 */ 141 */
163 public static class TaskConfiguration implements Cancelable { 142 private static class Subscriptions {
164 private final Task task; 143 private static class ChannelInterest {
165 private RunContext ctx = new RunContext(); 144 SelectableChannel channel;
166 private boolean lifeness = true; 145 int interestOps;
167 private Priority priority;
168 private final AbsoluteTime deadline;
169
170 private ArrayList<SelectableChannel> eventChannels = null;
171 private ArrayList<Integer> eventTypes = null;
172
173 private boolean hasRun = false;
174 private boolean isCanceled = false;
175
176 /**
177 * Create a TaskIdentifier.
178 *
179 * @param delay when will the task be run?
180 * may be null to indicate that this task may not be run
181 * (but only queued directly)
182 * @param task task to run with this TaskIdentifier
183 */
184 TaskConfiguration(RelativeTime delay, Task task) {
185 this.task = task;
186 if (delay == null)
187 this.deadline = null;
188 else
189 this.deadline = delay.toAbsolute();
190 } 146 }
191 147
192 /** 148 List<ChannelInterest> channelInterests = Lists.newLinkedList();
193 * Register the task configuration to run once the given event completed. 149
194 * 150 void add(SelectableChannel channel, int interestOps) {
195 * @param channel channel that we wait for an event on 151 boolean found = false;
196 * @param eventType the event we wait on 152 for (ChannelInterest ci : channelInterests) {
197 */ 153 if (ci.channel == channel) {
198 private void addChannelEvent(SelectableChannel channel, int eventType) { 154 ci.interestOps |= interestOps;
199 if (channel == null) { 155 if ((ci.interestOps | SelectionKey.OP_CONNECT | SelectionKey.OP_READ) != 0) {
200 throw new AssertionError("channel must be non-null"); 156 throw new AssertionError("OP_CONNECT and OP_READ are incompatible in java");
157 }
158 found = true;
159 break;
160 }
201 } 161 }
202 if (eventChannels == null) { 162 if (!found) {
203 eventChannels = new ArrayList<SelectableChannel>(); 163 ChannelInterest ci = new ChannelInterest();
204 eventTypes = new ArrayList<Integer>(); 164 ci.channel = channel;
165 ci.interestOps = interestOps;
166 channelInterests.add(ci);
205 } 167 }
206 eventChannels.add(channel); 168 }
207 eventTypes.add(eventType);
208 169
209 int interestOp = eventToInterestOp[eventType]; 170 void apply(TaskIdentifier tid) {
171 for (ChannelInterest ci : channelInterests) {
172 SelectionKey key = ci.channel.keyFor(selector);
173 if (key == null || !key.isValid()) {
174 try {
175 key = ci.channel.register(selector, ci.interestOps);
176 key.attach(new LinkedList());
177 } catch (ClosedChannelException e) {
178 throw new IOError(e);
179 }
180 } else {
181 key.interestOps(key.interestOps() | ci.interestOps);
182 }
183 @SuppressWarnings("unchecked")
184 LinkedList<TaskInterestOps> opl = (LinkedList<TaskInterestOps>) key.attachment();
185 TaskInterestOps tio = new TaskInterestOps();
186 tio.tid = tid;
187 tio.interestOps = ci.interestOps;
188 opl.add(tio);
189 }
190 }
210 191
211 SelectionKey key = channel.keyFor(selector); 192 void stop(TaskIdentifier tid) {
212 if (key == null || !key.isValid()) { 193 for (ChannelInterest ci : channelInterests) {
213 try { 194 SelectionKey key = ci.channel.keyFor(selector);
214 // tread safety ... avoid deadlock 195 if (key == null || !key.isValid()) {
215 selector.wakeup(); 196 logger.warn("missing selection key");
216 key = channel.register(selector, interestOp, new TaskConfiguration[4]); 197 return;
217 } catch (ClosedChannelException e) {
218 throw new IOError(e);
219 } 198 }
220 } else { 199 @SuppressWarnings("unchecked")
221 if ((key.interestOps() & interestOp) != 0) { 200 LinkedList<TaskInterestOps> interestList = (LinkedList<TaskInterestOps>) key.attachment();
222 throw new AssertionError("interest op registered twice"); 201 Iterator<TaskInterestOps> it = interestList.iterator();
202 int remainingInterestOps = 0;
203 while (it.hasNext()) {
204 TaskInterestOps ops = it.next();
205 if (ops.tid == tid) {
206 it.remove();
207 } else {
208 remainingInterestOps |= ops.interestOps;
209 }
223 } 210 }
224 key.interestOps(key.interestOps() | interestOp); 211 key.interestOps(remainingInterestOps);
225 } 212 }
213 }
214 }
226 215
227 TaskConfiguration[] subscribers = (TaskConfiguration[]) key.attachment(); 216 /**
228 if (subscribers[eventType] != null) { 217 * A task is the basic unit of work that is managed by the scheduler.
229 throw new AssertionError("subscriber registered twice"); 218 */
230 } 219 public static interface Task {
231 subscribers[eventType] = this; 220 public void run(RunContext ctx);
221 }
232 222
233 if (subscribers[EVENT_CONNECT] != null && subscribers[EVENT_READ] != null) { 223 /**
234 throw new AssertionError("OP_CONNECT and OP_READ are incompatible in java"); 224 * Representation of a task that has been scheduled, and can be canceled
235 } 225 * until the task has run.
226 */
227 public static class TaskIdentifier implements Cancelable {
228 private boolean hasRun = false;
229 private boolean isCanceled = false;
230 private final Task task;
231 private final RunContext ctx = new RunContext();
232 private final boolean lifeness;
233 private final Priority priority;
234 private final AbsoluteTime deadline;
235 private final Subscriptions subscriptions;
236
237 public TaskIdentifier(Task task, EnumSet<Reason> reasons) {
238 this.ctx.reasons = reasons;
239 this.task = task;
240 lifeness = true;
241 priority = Priority.DEFAULT;
242 deadline = null;
243 subscriptions = null;
244 }
245
246 public TaskIdentifier(TaskConfiguration tc) {
247 this.task = tc.task;
248 this.subscriptions = tc.subscriptions;
249 this.deadline = tc.deadline;
250 this.priority = tc.priority;
251 this.lifeness = tc.lifeness;
236 } 252 }
237 253
254
238 private void run() { 255 private void run() {
239 if (hasRun) { 256 if (hasRun) {
240 throw new AssertionError("same task ran twice"); 257 throw new AssertionError("same task ran twice");
@@ -242,14 +259,18 @@ public class Scheduler {
242 if (isCanceled) { 259 if (isCanceled) {
243 return; 260 return;
244 } 261 }
245 TaskConfiguration old = activeTask; 262 TaskIdentifier old = activeTask;
246 activeTask = this; 263 activeTask = this;
247 task.run(ctx); 264 task.run(ctx);
248 hasRun = true; 265 hasRun = true;
249 activeTask = old; 266 activeTask = old;
250 } 267 }
251 268
269 @Override
252 public void cancel() { 270 public void cancel() {
271 if (hasRun) {
272 throw new AssertionError("can't cancel task that already ran");
273 }
253 if (isCanceled) { 274 if (isCanceled) {
254 throw new AssertionError("task canceled twice"); 275 throw new AssertionError("task canceled twice");
255 } 276 }
@@ -257,55 +278,59 @@ public class Scheduler {
257 pending.remove(this); 278 pending.remove(this);
258 } 279 }
259 280
260 public Cancelable schedule() { 281 public void deregister() {
261 lock.lock(); 282 if (subscriptions != null) {
262 if (this.deadline == null) 283 subscriptions.stop(this);
263 throw new AssertionError("a task without deadline may not be scheduled");
264 if (priority == null) {
265 if (activeTask != null) {
266 priority = activeTask.priority;
267 } else {
268 priority = Priority.DEFAULT;
269 }
270 } 284 }
271 pending.add(this);
272 lock.unlock();
273 return this;
274 } 285 }
286 }
275 287
276 private void deregister() { 288 /**
277 if (eventChannels == null) { 289 * A TaskConfiguration contains all information to schedule a task.
278 return; 290 */
279 } 291 public static class TaskConfiguration {
280 lock.lock(); 292 private final Task task;
281 for (int i = 0; i < eventChannels.size(); ++i) { 293 private boolean lifeness = true;
282 SelectionKey key = eventChannels.get(i).keyFor(selector); 294 private Priority priority;
283 TaskConfiguration[] subscribers = (TaskConfiguration[]) key.attachment(); 295 private final AbsoluteTime deadline;
284 int interestOp = eventToInterestOp[eventTypes.get(i)];
285 if (subscribers[eventTypes.get(i)] == null || (key.interestOps() | interestOp) == 0) {
286 throw new AssertionError("deregistering event that has not been registered");
287 }
288 subscribers[eventTypes.get(i)] = null;
289 key.interestOps(key.interestOps() & (~interestOp));
290 }
291 296
292 lock.unlock(); 297 private Subscriptions subscriptions;
293 }
294 298
295 public void selectRead(SelectableChannel channel) { 299 /**
296 addChannelEvent(channel, EVENT_READ); 300 * Create a TaskIdentifier.
301 *
302 * @param delay when will the task be run?
303 * may be null to indicate that this task may not be run
304 * (but only queued directly)
305 * @param task task to run with this TaskIdentifier
306 */
307 TaskConfiguration(RelativeTime delay, Task task) {
308 if (delay == null)
309 throw new AssertionError("task delay may not be 'null'");
310 this.task = task;
311 this.deadline = delay.toAbsolute();
297 } 312 }
298 313
299 public void selectWrite(SelectableChannel channel) { 314 public TaskIdentifier schedule() {
300 addChannelEvent(channel, EVENT_WRITE);
301 }
302 315
303 public void selectConnect(SelectableChannel channel) { 316 if (priority == null) {
304 addChannelEvent(channel, EVENT_CONNECT); 317 if (activeTask != null) {
318 priority = activeTask.priority;
319 } else {
320 priority = Priority.DEFAULT;
321 }
322 }
323 TaskIdentifier tid = new TaskIdentifier(this);
324 if (subscriptions != null)
325 subscriptions.apply(tid);
326 pending.add(tid);
327 return tid;
305 } 328 }
306 329
307 public void selectAccept(SelectableChannel channel) { 330 public void addSelectEvent(SelectableChannel channel, int event) {
308 addChannelEvent(channel, EVENT_ACCEPT); 331 if (subscriptions == null)
332 subscriptions = new Subscriptions();
333 subscriptions.add(channel, event);
309 } 334 }
310 } 335 }
311 336
@@ -314,14 +339,7 @@ public class Scheduler {
314 * the same priority. 339 * the same priority.
315 */ 340 */
316 public static void addContinuation(Task task, EnumSet<Reason> reasons) { 341 public static void addContinuation(Task task, EnumSet<Reason> reasons) {
317 lock.lock(); 342 queueReady(new TaskIdentifier(task, reasons));
318 TaskConfiguration t = new TaskConfiguration(null, task);
319 t.ctx.reasons = reasons;
320 t.priority = Priority.DEFAULT;
321 queueReady(t);
322 logger.debug("about to wake up");
323 lock.unlock();
324 selector.wakeup();
325 } 343 }
326 344
327 /** 345 /**
@@ -343,26 +361,41 @@ public class Scheduler {
343 * @param task the task to run after delay 361 * @param task the task to run after delay
344 * @return the TaskIdentifier, can be used to cancel the task until it has been executed. 362 * @return the TaskIdentifier, can be used to cancel the task until it has been executed.
345 */ 363 */
346 public static TaskConfiguration addDelayed(RelativeTime delay, Task task) { 364 public static TaskIdentifier addDelayed(RelativeTime delay, Task task) {
347 TaskConfiguration tid = new TaskConfiguration(delay, task); 365 TaskConfiguration tid = new TaskConfiguration(delay, task);
348 tid.schedule(); 366 return tid.schedule();
349 return tid;
350 } 367 }
351 368
352 public static TaskConfiguration addRead(RelativeTime timeout, 369 /**
353 SelectableChannel chan, Task task) { 370 * Add a task to run after the specified delay, or after the given channel
371 * is ready to read, whichever occurs first.
372 *
373 * @param timeout time to wait until running the task
374 * @param chan chennel of interest
375 * @param task task to run
376 * @return task identifier
377 */
378 public static TaskIdentifier addRead(RelativeTime timeout,
379 SelectableChannel chan, Task task) {
354 TaskConfiguration tid = new TaskConfiguration(timeout, task); 380 TaskConfiguration tid = new TaskConfiguration(timeout, task);
355 tid.addChannelEvent(chan, EVENT_READ); 381 tid.addSelectEvent(chan, SelectionKey.OP_READ);
356 tid.schedule(); 382 return tid.schedule();
357 return tid;
358 } 383 }
359 384
360 public static TaskConfiguration addWrite(RelativeTime timeout, 385 /**
361 SelectableChannel chan, Task task) { 386 * Add a task to run after the specified delay, or after the given channel
387 * is ready to write, whichever occurs first.
388 *
389 * @param timeout to wait until running the task
390 * @param chan channel of interest
391 * @param task task to run
392 * @return task identifier
393 */
394 public static TaskIdentifier addWrite(RelativeTime timeout,
395 SelectableChannel chan, Task task) {
362 TaskConfiguration tid = new TaskConfiguration(timeout, task); 396 TaskConfiguration tid = new TaskConfiguration(timeout, task);
363 tid.addChannelEvent(chan, EVENT_WRITE); 397 tid.addSelectEvent(chan, SelectionKey.OP_WRITE);
364 tid.schedule(); 398 return tid.schedule();
365 return tid;
366 } 399 }
367 400
368 /** 401 /**
@@ -372,14 +405,11 @@ public class Scheduler {
372 * @return true to continue the main loop, false to exit 405 * @return true to continue the main loop, false to exit
373 */ 406 */
374 private static boolean checkLiveness() { 407 private static boolean checkLiveness() {
375 lock.lock();
376 if (readyCount > 0) { 408 if (readyCount > 0) {
377 lock.unlock();
378 return true; 409 return true;
379 } 410 }
380 for (TaskConfiguration t : pending) { 411 for (TaskIdentifier t : pending) {
381 if (t.lifeness) { 412 if (t.lifeness) {
382 lock.unlock();
383 return true; 413 return true;
384 } 414 }
385 } 415 }
@@ -387,30 +417,23 @@ public class Scheduler {
387 if (!pending.isEmpty()) { 417 if (!pending.isEmpty()) {
388 logger.debug("tasks pending but not alive -- disconnect"); 418 logger.debug("tasks pending but not alive -- disconnect");
389 shutdown(); 419 shutdown();
390 lock.unlock();
391 return true; 420 return true;
392 } 421 }
393
394 lock.unlock();
395 return false; 422 return false;
396 } 423 }
397 424
398
399 /** 425 /**
400 * Queue a Task for execution. 426 * Queue a Task for execution.
401 * 427 *
402 * @param tid TaskIdentifier of the ready task 428 * @param tid TaskIdentifier of the ready task
403 */ 429 */
404 private static void queueReady(TaskConfiguration tid) { 430 private static void queueReady(TaskIdentifier tid) {
405 lock.lock();
406 int idx = tid.priority.ordinal(); 431 int idx = tid.priority.ordinal();
407 readyLists[idx].add(tid); 432 readyLists[idx].add(tid);
408 readyCount++; 433 readyCount++;
409 pending.remove(tid); 434 pending.remove(tid);
410 lock.unlock();
411 } 435 }
412 436
413
414 /** 437 /**
415 * Queue all tasks with expired timeout. 438 * Queue all tasks with expired timeout.
416 * 439 *
@@ -418,11 +441,10 @@ public class Scheduler {
418 */ 441 */
419 private static RelativeTime handleTimeouts() { 442 private static RelativeTime handleTimeouts() {
420 RelativeTime timeout = RelativeTime.FOREVER; 443 RelativeTime timeout = RelativeTime.FOREVER;
421 lock.lock();
422 444
423 // check if any timeouts occurred 445 // check if any timeouts occurred
424 while (true) { 446 while (true) {
425 TaskConfiguration t = pending.peek(); 447 TaskIdentifier t = pending.peek();
426 if (t == null) { 448 if (t == null) {
427 break; 449 break;
428 } 450 }
@@ -436,25 +458,19 @@ public class Scheduler {
436 break; 458 break;
437 } 459 }
438 } 460 }
439 lock.unlock();
440 return timeout; 461 return timeout;
441 } 462 }
442 463
443 /** 464
444 * If there is a subscribing task for the given event type, add it to the set of executable tasks. 465 private static void addReasonsFromInterestOp(EnumSet<Reason> reasons, int interestOps) {
445 * 466 if ((interestOps & SelectionKey.OP_READ) != 0)
446 * @param executableTasks set of executable tasks 467 reasons.add(Reason.READ_READY);
447 * @param subscribers subscriber set, one subscriber for each event type 468 if ((interestOps & SelectionKey.OP_WRITE) != 0)
448 * @param eventType event type we are interested in 469 reasons.add(Reason.WRITE_READY);
449 */ 470 if ((interestOps & SelectionKey.OP_CONNECT) != 0)
450 private static void addSubscriberTask(Collection<TaskConfiguration> executableTasks, 471 reasons.add(Reason.CONNECT_READY);
451 TaskConfiguration[] subscribers, int eventType) { 472 if ((interestOps & SelectionKey.OP_ACCEPT) != 0)
452 TaskConfiguration tc = subscribers[eventType]; 473 reasons.add(Reason.ACCEPT_READY);
453 if (tc == null) {
454 return;
455 }
456 executableTasks.add(tc);
457 tc.ctx.reasons.add(eventToReason[eventType]);
458 } 474 }
459 475
460 /** 476 /**
@@ -463,10 +479,8 @@ public class Scheduler {
463 * @param timeout timeout for select 479 * @param timeout timeout for select
464 */ 480 */
465 private static void handleSelect(RelativeTime timeout) { 481 private static void handleSelect(RelativeTime timeout) {
466 if (!lock.isHeldByCurrentThread()) 482 // gnunet-java uses microseconds, but the select api uses milliseconds
467 throw new AssertionError();
468 long timeout_ms = timeout.getMicroseconds() / 1000; 483 long timeout_ms = timeout.getMicroseconds() / 1000;
469 lock.unlock();
470 try { 484 try {
471 // selector.select(0) would block indefinitely (counter-intuitive, java's fault) 485 // selector.select(0) would block indefinitely (counter-intuitive, java's fault)
472 if (timeout_ms == 0) { 486 if (timeout_ms == 0) {
@@ -480,39 +494,29 @@ public class Scheduler {
480 } 494 }
481 } catch (IOException e) { 495 } catch (IOException e) {
482 throw new IOError(e); 496 throw new IOError(e);
483 } finally {
484 lock.lock();
485 } 497 }
486 498
487 logger.debug("select over"); 499 logger.debug("select over");
488 500
489 // we use a set so that we don't execute any task twice 501 // we use a set so that we don't execute any task twice
490 Collection<TaskConfiguration> executableTasks = new HashSet<TaskConfiguration>(); 502 Collection<TaskIdentifier> executableTasks = new HashSet<TaskIdentifier>();
491 for (SelectionKey sk : selector.selectedKeys()) { 503 for (SelectionKey sk : selector.selectedKeys()) {
492 TaskConfiguration[] subscribers = (TaskConfiguration[]) sk.attachment(); 504 @SuppressWarnings("unchecked")
493 505 LinkedList<TaskInterestOps> subscribers = (LinkedList<TaskInterestOps>) sk.attachment();
494 if (sk.isReadable()) { 506 for (TaskInterestOps ops : subscribers) {
495 addSubscriberTask(executableTasks, subscribers, EVENT_READ); 507 if ((sk.readyOps() & ops.interestOps) != 0) {
496 } 508 executableTasks.add(ops.tid);
497 if (sk.isWritable()) { 509 addReasonsFromInterestOp(ops.tid.ctx.reasons, sk.readyOps() & ops.interestOps);
498 addSubscriberTask(executableTasks, subscribers, EVENT_WRITE); 510 }
499 }
500 if (sk.isAcceptable()) {
501 addSubscriberTask(executableTasks, subscribers, EVENT_ACCEPT);
502 }
503 if (sk.isConnectable()) {
504 addSubscriberTask(executableTasks, subscribers, EVENT_CONNECT);
505 } 511 }
506
507 } 512 }
508 for (TaskConfiguration tt : executableTasks) { 513 for (TaskIdentifier tt : executableTasks) {
509 // cancel subscriptions to other events, we can execute now! 514 // cancel subscriptions to other events, we can execute now!
510 tt.deregister(); 515 tt.deregister();
511 queueReady(tt); 516 queueReady(tt);
512 } 517 }
513 } 518 }
514 519
515
516 /** 520 /**
517 * Initialize and run scheduler. This function will return when all tasks 521 * Initialize and run scheduler. This function will return when all tasks
518 * have completed. 522 * have completed.
@@ -529,10 +533,10 @@ public class Scheduler {
529 */ 533 */
530 public static void run(Task initialTask) { 534 public static void run(Task initialTask) {
531 logger.debug("running scheduler"); 535 logger.debug("running scheduler");
532 if (scheduler_running) { 536 if (schedulerRunning) {
533 throw new AssertionError("Scheduler already running"); 537 throw new AssertionError("Scheduler already running");
534 } 538 }
535 scheduler_running = true; 539 schedulerRunning = true;
536 try { 540 try {
537 run_unchecked(initialTask); 541 run_unchecked(initialTask);
538 } finally { 542 } finally {
@@ -543,7 +547,6 @@ public class Scheduler {
543 } 547 }
544 } 548 }
545 549
546
547 /** 550 /**
548 * Initialize and run scheduler. This function will return when all tasks 551 * Initialize and run scheduler. This function will return when all tasks
549 * have completed. Don't check if the scheduler is already running or not. 552 * have completed. Don't check if the scheduler is already running or not.
@@ -556,12 +559,7 @@ public class Scheduler {
556 } 559 }
557 560
558 // the gnunet main loop 561 // the gnunet main loop
559 while (true) { 562 while (checkLiveness()) {
560 lock.lock();
561 if (checkLiveness() == false) {
562 lock.unlock();
563 break;
564 }
565 RelativeTime nextTimeout = handleTimeouts(); 563 RelativeTime nextTimeout = handleTimeouts();
566 if (nextTimeout.getMicroseconds() < 0) { 564 if (nextTimeout.getMicroseconds() < 0) {
567 logger.warn("negative timeout for select"); 565 logger.warn("negative timeout for select");
@@ -569,7 +567,6 @@ public class Scheduler {
569 567
570 // don't select if there are no tasks; we are done! 568 // don't select if there are no tasks; we are done!
571 if (readyCount == 0 && pending.isEmpty()) { 569 if (readyCount == 0 && pending.isEmpty()) {
572 lock.unlock();
573 return; 570 return;
574 } 571 }
575 572
@@ -580,7 +577,6 @@ public class Scheduler {
580 handleSelect(nextTimeout); 577 handleSelect(nextTimeout);
581 } 578 }
582 runReady(); 579 runReady();
583 lock.unlock();
584 } 580 }
585 581
586 if (readyCount != 0) { 582 if (readyCount != 0) {
@@ -618,9 +614,9 @@ public class Scheduler {
618 // start executing from the highest priority down to 0 614 // start executing from the highest priority down to 0
619 for (int p = Priority.numberOfPriorities - 1; p >= 0; p--) { 615 for (int p = Priority.numberOfPriorities - 1; p >= 0; p--) {
620 // execute all tasks with priority p 616 // execute all tasks with priority p
621 LinkedList<TaskConfiguration> queue = readyLists[p]; 617 LinkedList<TaskIdentifier> queue = readyLists[p];
622 while (!queue.isEmpty()) { 618 while (!queue.isEmpty()) {
623 TaskConfiguration tid = queue.removeFirst(); 619 TaskIdentifier tid = queue.removeFirst();
624 readyCount--; 620 readyCount--;
625 tid.run(); 621 tid.run();
626 } 622 }
@@ -637,13 +633,27 @@ public class Scheduler {
637 */ 633 */
638 public static void shutdown() { 634 public static void shutdown() {
639 // queueReady() while iterating would yield concurrent modification exn otherwise 635 // queueReady() while iterating would yield concurrent modification exn otherwise
640 for (TaskConfiguration tid : new ArrayList<TaskConfiguration>(pending)) { 636 for (TaskIdentifier tid : new ArrayList<TaskIdentifier>(pending)) {
641 tid.ctx.reasons.add(Reason.SHUTDOWN); 637 tid.ctx.reasons.add(Reason.SHUTDOWN);
642 queueReady(tid); 638 queueReady(tid);
643 } 639 }
644 pending.clear(); 640 pending.clear();
645 } 641 }
646 642
643 /**
644 * Reset the scheduler forcefully.
645 * Intended to be used internally in the Scheduler, as well as in test teardown.
646 */
647 public static void forceReset() {
648 schedulerRunning = false;
649 readyCount = 0;
650 activeTask = null;
651 for (int i = 0; i < Priority.numberOfPriorities; ++i) {
652 readyLists[i] = Lists.newLinkedList();
653 }
654 pending.clear();
655 }
656
647 657
648 /** 658 /**
649 * A handle to a file system object that can be selected on. 659 * A handle to a file system object that can be selected on.
diff --git a/src/main/java/org/gnunet/util/Server.java b/src/main/java/org/gnunet/util/Server.java
index 8a86b45..7f816d0 100644
--- a/src/main/java/org/gnunet/util/Server.java
+++ b/src/main/java/org/gnunet/util/Server.java
@@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory;
27 27
28import java.io.IOException; 28import java.io.IOException;
29import java.net.SocketAddress; 29import java.net.SocketAddress;
30import java.nio.channels.SelectionKey;
30import java.nio.channels.ServerSocketChannel; 31import java.nio.channels.ServerSocketChannel;
31import java.nio.channels.SocketChannel; 32import java.nio.channels.SocketChannel;
32import java.util.ArrayList; 33import java.util.ArrayList;
@@ -403,7 +404,7 @@ public class Server {
403 addAcceptSocket(sock); 404 addAcceptSocket(sock);
404 } 405 }
405 }); 406 });
406 b.selectAccept(sock); 407 b.addSelectEvent(sock, SelectionKey.OP_ACCEPT);
407 acceptTask = b.schedule(); 408 acceptTask = b.schedule();
408 } 409 }
409 410
diff --git a/src/main/java/org/gnunet/util/Service.java b/src/main/java/org/gnunet/util/Service.java
index d93e296..a150089 100644
--- a/src/main/java/org/gnunet/util/Service.java
+++ b/src/main/java/org/gnunet/util/Service.java
@@ -30,6 +30,7 @@ import java.net.InetSocketAddress;
30import java.net.SocketAddress; 30import java.net.SocketAddress;
31import java.nio.ByteBuffer; 31import java.nio.ByteBuffer;
32import java.nio.channels.Pipe; 32import java.nio.channels.Pipe;
33import java.nio.channels.SelectionKey;
33import java.util.LinkedList; 34import java.util.LinkedList;
34 35
35/** 36/**
@@ -107,7 +108,7 @@ public abstract class Service extends Program {
107 108
108 Scheduler.TaskConfiguration t = new Scheduler.TaskConfiguration(RelativeTime.FOREVER, 109 Scheduler.TaskConfiguration t = new Scheduler.TaskConfiguration(RelativeTime.FOREVER,
109 new SigpipeTask()); 110 new SigpipeTask());
110 t.selectRead(p.getSource()); 111 t.addSelectEvent(p.getSource(), SelectionKey.OP_READ);
111 sigpipeTask = t.schedule(); 112 sigpipeTask = t.schedule();
112 sigpipeChannel = p.getSource(); 113 sigpipeChannel = p.getSource();
113 } 114 }
diff --git a/src/main/java/org/gnunet/voting/Ballot.java b/src/main/java/org/gnunet/voting/Ballot.java
index 49f1465..0d8de27 100644
--- a/src/main/java/org/gnunet/voting/Ballot.java
+++ b/src/main/java/org/gnunet/voting/Ballot.java
@@ -24,7 +24,7 @@ import com.google.common.base.Joiner;
24import com.google.common.base.Optional; 24import com.google.common.base.Optional;
25import com.google.common.collect.BiMap; 25import com.google.common.collect.BiMap;
26import com.google.common.collect.HashBiMap; 26import com.google.common.collect.HashBiMap;
27import com.google.common.collect.Maps; 27import com.google.common.primitives.Longs;
28import org.gnunet.util.*; 28import org.gnunet.util.*;
29 29
30import java.security.MessageDigest; 30import java.security.MessageDigest;
@@ -38,18 +38,22 @@ import java.util.regex.Pattern;
38public class Ballot { 38public class Ballot {
39 39
40 String topic; 40 String topic;
41 String group;
41 List<String> choices; 42 List<String> choices;
42 AbsoluteTime electionStartTime; 43 AbsoluteTime startTime;
43 AbsoluteTime electionEndTime; 44 AbsoluteTime closingTime;
45 AbsoluteTime queryTime;
46 AbsoluteTime endTime;
44 BiMap<String,PeerIdentity> authorities; 47 BiMap<String,PeerIdentity> authorities;
45 SortedMap<String,CryptoECC.Signature> registrationSigs; 48 SortedMap<String,CryptoECC.Signature> registrationSigs;
46 CryptoECC.PublicKey caPub; 49 CryptoECC.PublicSignKey caPub;
47 CryptoECC.PublicKey issuerPub; 50 CryptoECC.PublicSignKey issuerPub;
48 CryptoECC.Signature issuerSig; 51 CryptoECC.Signature issuerSig;
49 CryptoECC.PublicKey voter_pub; 52 CryptoECC.PublicSignKey voterPub;
53 CryptoECC.Signature voterGroupCert;
50 CryptoECC.Signature permission; 54 CryptoECC.Signature permission;
51 CryptoECC.PublicKey voter_sig; 55 CryptoECC.PublicSignKey voterSig;
52 SortedMap<String,CryptoECC.Signature> vouchers; 56 SortedMap<String,CryptoECC.Signature> voucherSigs;
53 57
54 /** 58 /**
55 * Choice in plaintext. 59 * Choice in plaintext.
@@ -60,8 +64,8 @@ public class Ballot {
60 /** 64 /**
61 * Load a ballot from file. 65 * Load a ballot from file.
62 * 66 *
67 * @param filename name of file to load ballot from
63 * @throws InvalidBallotException 68 * @throws InvalidBallotException
64 * @param filename
65 */ 69 */
66 public Ballot(String filename) { 70 public Ballot(String filename) {
67 Configuration cfg = new Configuration(); 71 Configuration cfg = new Configuration();
@@ -69,10 +73,49 @@ public class Ballot {
69 fillBallot(cfg); 73 fillBallot(cfg);
70 } 74 }
71 75
76 /**
77 * Load a ballot from a configuration.
78 *
79 * @param cfg configuration to load ballot from
80 * @throws InvalidBallotException
81 */
72 public Ballot(Configuration cfg) { 82 public Ballot(Configuration cfg) {
73 fillBallot(cfg); 83 fillBallot(cfg);
74 } 84 }
75 85
86 /**
87 * Parse the specified time value from the ballot,
88 * converting a human-readable time value to human time when no
89 * timestamp is given.
90 * @param cfg configuration to read the value from
91 * @param timeValueName name suffix of the time option
92 * @return the time value
93 */
94 private AbsoluteTime getTime(Configuration cfg, String timeValueName) {
95 Optional<String> optTimeHuman = cfg.getValueString("election", "TIME_" + timeValueName);
96 Optional<String> optTimeStamp = cfg.getValueString("election", "TIMESTAMP_" + timeValueName);
97 if (optTimeStamp.isPresent()) {
98 try {
99 long stamp = Long.parseLong(optTimeStamp.get());
100 return AbsoluteTime.fromSeconds(stamp);
101 } catch (NumberFormatException e) {
102 throw new InvalidBallotException("time value " + timeValueName + " malformed");
103 }
104 } else if (optTimeHuman.isPresent()) {
105 AbsoluteTime time = AbsoluteTime.fromString(optTimeHuman.get());
106 if (null == time) {
107 throw new InvalidBallotException("timestamp value " + timeValueName + " malformed");
108 }
109 return time;
110 }
111 throw new InvalidBallotException("time value " + timeValueName + " missing");
112 }
113
114 /**
115 * Fill the ballot with information from the given configuration.
116 *
117 * @param cfg configuration to read from
118 */
76 private void fillBallot(Configuration cfg) { 119 private void fillBallot(Configuration cfg) {
77 Optional<String> optTopic = cfg.getValueString("election", "TOPIC"); 120 Optional<String> optTopic = cfg.getValueString("election", "TOPIC");
78 if (!optTopic.isPresent()) { 121 if (!optTopic.isPresent()) {
@@ -87,6 +130,11 @@ public class Ballot {
87 if (choices.size() < 2) { 130 if (choices.size() < 2) {
88 throw new InvalidBallotException("less than two choices present"); 131 throw new InvalidBallotException("less than two choices present");
89 } 132 }
133 Optional<String> optGroup = cfg.getValueString("election", "GROUP");
134 if (!optGroup.isPresent()) {
135 throw new InvalidBallotException("ballot must have elegibility group");
136 }
137 group = optGroup.get();
90 authorities = HashBiMap.create(); 138 authorities = HashBiMap.create();
91 for (Map.Entry<String,String> e : cfg.getSection("authorities").entrySet()) { 139 for (Map.Entry<String,String> e : cfg.getSection("authorities").entrySet()) {
92 String alias = e.getKey(); 140 String alias = e.getKey();
@@ -104,13 +152,13 @@ public class Ballot {
104 if (!optCaPub.isPresent()) { 152 if (!optCaPub.isPresent()) {
105 throw new InvalidBallotException("no CA pub key given"); 153 throw new InvalidBallotException("no CA pub key given");
106 } 154 }
107 caPub = CryptoECC.PublicKey.fromString(optCaPub.get()); 155 caPub = CryptoECC.PublicSignKey.fromString(optCaPub.get());
108 if (null == caPub) { 156 if (null == caPub) {
109 throw new InvalidBallotException("CA pub key invalid"); 157 throw new InvalidBallotException("CA pub key invalid");
110 } 158 }
111 Optional<String> optIssuerPub = cfg.getValueString("election", "ISSUER_PUB"); 159 Optional<String> optIssuerPub = cfg.getValueString("election", "ISSUER_PUB");
112 if (optIssuerPub.isPresent()) { 160 if (optIssuerPub.isPresent()) {
113 issuerPub = CryptoECC.PublicKey.fromString(optIssuerPub.get()); 161 issuerPub = CryptoECC.PublicSignKey.fromString(optIssuerPub.get());
114 Optional<String> optIssuerSig = cfg.getValueString("election", "ISSUER_SIG"); 162 Optional<String> optIssuerSig = cfg.getValueString("election", "ISSUER_SIG");
115 if (!optIssuerSig.isPresent()) { 163 if (!optIssuerSig.isPresent()) {
116 throw new InvalidBallotException("issuer public key present, but no signature"); 164 throw new InvalidBallotException("issuer public key present, but no signature");
@@ -128,6 +176,17 @@ public class Ballot {
128 } 176 }
129 registrationSigs.put(e.getKey(), sig); 177 registrationSigs.put(e.getKey(), sig);
130 } 178 }
179 voucherSigs = new TreeMap<String, CryptoECC.Signature>();
180 for (Map.Entry<String,String> e : cfg.getSection("vouchers").entrySet()) {
181 CryptoECC.Signature sig = CryptoECC.Signature.fromString(e.getValue());
182 if (null == sig) {
183 throw new InvalidBallotException("voucher signature has invalid format");
184 }
185 if (!authorities.containsKey(e.getKey())) {
186 throw new InvalidBallotException("ballot contains superfluous voucher signature");
187 }
188 voucherSigs.put(e.getKey(), sig);
189 }
131 Optional<String> optChoiceId = cfg.getValueString("vote", "CHOICE_ID"); 190 Optional<String> optChoiceId = cfg.getValueString("vote", "CHOICE_ID");
132 if (optChoiceId.isPresent()) { 191 if (optChoiceId.isPresent()) {
133 choiceId = Integer.parseInt(optChoiceId.get()); 192 choiceId = Integer.parseInt(optChoiceId.get());
@@ -137,11 +196,27 @@ public class Ballot {
137 } else { 196 } else {
138 choiceId = -1; 197 choiceId = -1;
139 } 198 }
199
200 Optional<String> optVoterPub = cfg.getValueString("vote", "VOTER_PUB");
201 if (optVoterPub.isPresent()) {
202 voterPub = CryptoECC.PublicSignKey.fromString(optVoterPub.get());
203 }
204
205 startTime = getTime(cfg, "START");
206 closingTime = getTime(cfg, "CLOSING");
207 queryTime = getTime(cfg, "QUERY");
208 endTime = getTime(cfg, "END");
140 } 209 }
141 210
211 /**
212 * Get a hash code that uniquely defines the election information of
213 * the ballot.
214 *
215 * @return GUID of this ballot
216 */
142 public HashCode getBallotGuid() { 217 public HashCode getBallotGuid() {
143 if (issuerSig == null) { 218 if (issuerPub == null) {
144 throw new InvalidBallotException("can't compute GUID of non-issued ballot"); 219 throw new InvalidBallotException("can't compute GUID of a ballot without issuer");
145 } 220 }
146 MessageDigest digest; 221 MessageDigest digest;
147 try { 222 try {
@@ -150,8 +225,6 @@ public class Ballot {
150 throw new RuntimeException("crypto algorithm required but not provided"); 225 throw new RuntimeException("crypto algorithm required but not provided");
151 } 226 }
152 digest.update(topic.getBytes()); 227 digest.update(topic.getBytes());
153 //digest.update(Longs.toByteArray(electionStartTime.getSeconds()));
154 //digest.update(Longs.toByteArray(electionEndTime.getSeconds()));
155 for (String choice : choices) { 228 for (String choice : choices) {
156 digest.update(choice.getBytes()); 229 digest.update(choice.getBytes());
157 } 230 }
@@ -163,11 +236,16 @@ public class Ballot {
163 digest.update(issuerPub.y); 236 digest.update(issuerPub.y);
164 digest.update(caPub.x); 237 digest.update(caPub.x);
165 digest.update(caPub.y); 238 digest.update(caPub.y);
239 digest.update(Longs.toByteArray(startTime.getSeconds()));
240 digest.update(Longs.toByteArray(endTime.getSeconds()));
241 digest.update(Longs.toByteArray(closingTime.getSeconds()));
242 digest.update(Longs.toByteArray(queryTime.getSeconds()));
166 return new HashCode(digest.digest()); 243 return new HashCode(digest.digest());
167 } 244 }
168 245
169 /** 246 /**
170 * Encode the given choice permanently in the ballot. 247 * Encode the given choice permanently in the ballot.
248 * Also encodes the voter's public key.
171 * 249 *
172 * @param choice the choice to encode the ballot 250 * @param choice the choice to encode the ballot
173 * @param privateKey the private key to use for encoding 251 * @param privateKey the private key to use for encoding
@@ -181,21 +259,39 @@ public class Ballot {
181 } 259 }
182 i++; 260 i++;
183 } 261 }
262 voterPub = CryptoECC.computePublicKey(privateKey);
184 if (choiceId == -1) { 263 if (choiceId == -1) {
185 throw new InvalidBallotException(String.format("choice '%s' not valid", choice)); 264 throw new InvalidBallotException(String.format("choice '%s' not valid", choice));
186 } 265 }
187 } 266 }
188 267
268 /**
269 * Write the current state of the ballot to a configuration.
270 *
271 * @return a configuration with the state of this ballot
272 */
189 public Configuration toConfiguration() { 273 public Configuration toConfiguration() {
190 Configuration cfg = new Configuration(); 274 Configuration cfg = new Configuration();
191 cfg.setValueString("election", "TOPIC", topic); 275 cfg.setValueString("election", "TOPIC", topic);
276 cfg.setValueString("election", "GROUP", group);
192 cfg.setValueString("election", "CHOICES", Joiner.on("//").join(choices)); 277 cfg.setValueString("election", "CHOICES", Joiner.on("//").join(choices));
193 cfg.setValueString("election", "CA_PUB", caPub.toString()); 278 cfg.setValueString("election", "CA_PUB", caPub.toString());
279 cfg.setValueNumber("election", "TIMESTAMP_START", startTime.getSeconds());
280 cfg.setValueNumber("election", "TIMESTAMP_CLOSING", startTime.getSeconds());
281 cfg.setValueNumber("election", "TIMESTAMP_QUERY", startTime.getSeconds());
282 cfg.setValueNumber("election", "TIMESTAMP_END", startTime.getSeconds());
194 for (Map.Entry<String, PeerIdentity> e : authorities.entrySet()) { 283 for (Map.Entry<String, PeerIdentity> e : authorities.entrySet()) {
195 cfg.setValueString("authorities", e.getKey(), e.getValue().toString()); 284 cfg.setValueString("authorities", e.getKey(), e.getValue().toString());
196 } 285 }
197 for (Map.Entry<String, CryptoECC.Signature> e : registrationSigs.entrySet()) { 286 if (null != registrationSigs) {
198 cfg.setValueString("registration-signatures", e.getKey(), e.getValue().toString()); 287 for (Map.Entry<String, CryptoECC.Signature> e : registrationSigs.entrySet()) {
288 cfg.setValueString("registration-signatures", e.getKey(), e.getValue().toString());
289 }
290 }
291 if (null != voucherSigs) {
292 for (Map.Entry<String, CryptoECC.Signature> e : voucherSigs.entrySet()) {
293 cfg.setValueString("vouchers", e.getKey(), e.getValue().toString());
294 }
199 } 295 }
200 if (null != issuerPub) { 296 if (null != issuerPub) {
201 cfg.setValueString("election", "ISSUER_PUB", issuerPub.toString()); 297 cfg.setValueString("election", "ISSUER_PUB", issuerPub.toString());
@@ -204,19 +300,52 @@ public class Ballot {
204 if (-1 != choiceId) { 300 if (-1 != choiceId) {
205 cfg.setValueNumber("vote", "CHOICE_ID", choiceId); 301 cfg.setValueNumber("vote", "CHOICE_ID", choiceId);
206 } 302 }
303 if (null != voterPub) {
304 cfg.setValueString("vote", "VOTER_PUB", voterPub.toString());
305 }
207 return cfg; 306 return cfg;
208 } 307 }
209 308
309 /**
310 * Serialize the ballot to a string
311 *
312 * @return the serialized ballot
313 */
210 public String serialize() { 314 public String serialize() {
211 return toConfiguration().serialize(); 315 return toConfiguration().serialize();
212 } 316 }
213 317
318
319 /**
320 * Get a human readable description of the ballot's current state.
321 *
322 * @return the ballot description
323 */
214 public String describe() { 324 public String describe() {
215 StringBuilder buf = new StringBuilder(); 325 StringBuilder buf = new StringBuilder();
326
216 buf.append("Topic: "); 327 buf.append("Topic: ");
217 buf.append("'"); 328 buf.append("'");
218 buf.append(topic); 329 buf.append(topic);
219 buf.append("'\n"); 330 buf.append("'\n");
331
332 buf.append("Voter Group: ");
333 buf.append(group);
334 buf.append("\n");
335
336 buf.append("Start Time: ");
337 buf.append(startTime.toFancyString());
338 buf.append("\n");
339 buf.append("Closing Time: ");
340 buf.append(closingTime.toFancyString());
341 buf.append("\n");
342 buf.append("Query Time: ");
343 buf.append(queryTime.toFancyString());
344 buf.append("\n");
345 buf.append("End Time: ");
346 buf.append(endTime.toFancyString());
347 buf.append("\n");
348
220 buf.append("Choices:\n"); 349 buf.append("Choices:\n");
221 for (int i = 0; i < choices.size(); i++) { 350 for (int i = 0; i < choices.size(); i++) {
222 buf.append(""+(i+1)); 351 buf.append(""+(i+1));
@@ -247,6 +376,14 @@ public class Ballot {
247 } 376 }
248 buf.append("\n"); 377 buf.append("\n");
249 } 378 }
379 if (!voucherSigs.isEmpty()) {
380 buf.append("ballot's vote has been submitted to with the following authorities:\n");
381 for (Map.Entry<String, CryptoECC.Signature> e : voucherSigs.entrySet()) {
382 buf.append(e.getKey());
383 buf.append(" ");
384 }
385 buf.append("\n");
386 }
250 else { 387 else {
251 buf.append("ballot not registered\n"); 388 buf.append("ballot not registered\n");
252 } 389 }
@@ -258,12 +395,27 @@ public class Ballot {
258 return buf.toString(); 395 return buf.toString();
259 } 396 }
260 397
398
399 /**
400 * Get the list of authorities that did not yet receive the ballot's vote.
401 *
402 * @return list of unsubmitted-to authorities
403 */
261 public List<PeerIdentity> getRemainingSubmitAuthorities() { 404 public List<PeerIdentity> getRemainingSubmitAuthorities() {
262 // FIXME: only return remaining authorities 405 LinkedList<PeerIdentity> remaining = new LinkedList<PeerIdentity>();
263 return new ArrayList<PeerIdentity>(authorities.values()); 406 for (SortedMap.Entry<String,PeerIdentity> x : authorities.entrySet()) {
407 if (!voucherSigs.containsKey(x.getKey()))
408 remaining.add(x.getValue());
409 }
410 return remaining;
264 } 411 }
265 412
266 413 /**
414 * Get a list of authorities that did not receive the registration for this
415 * ballot yet.
416 *
417 * @return list of authorities that don't know about this ballot
418 */
267 public List<PeerIdentity> getRemainingRegisterAuthorities() { 419 public List<PeerIdentity> getRemainingRegisterAuthorities() {
268 LinkedList<PeerIdentity> remaining = new LinkedList<PeerIdentity>(); 420 LinkedList<PeerIdentity> remaining = new LinkedList<PeerIdentity>();
269 for (SortedMap.Entry<String,PeerIdentity> x : authorities.entrySet()) { 421 for (SortedMap.Entry<String,PeerIdentity> x : authorities.entrySet()) {
@@ -273,16 +425,44 @@ public class Ballot {
273 return remaining; 425 return remaining;
274 } 426 }
275 427
428 /**
429 * Add the issuer to the ballot, and sign the election information in the ballot.
430 *
431 * @param privateKey private key of the issuer
432 */
276 public void issue(CryptoECC.PrivateKey privateKey) { 433 public void issue(CryptoECC.PrivateKey privateKey) {
277 issuerPub = CryptoECC.computePublicKey(privateKey); 434 issuerPub = CryptoECC.computePublicKey(privateKey);
278 issuerSig = CryptoECC.sign(getBallotGuid().data, privateKey, issuerPub); 435 issuerSig = CryptoECC.sign(getBallotGuid().data, privateKey, issuerPub);
279 } 436 }
280 437
438 /**
439 * Add an authorities registration signature to the list of known registrations.
440 *
441 * @param currentAuthority authority we registered with
442 * @param registrationSignature signature over this ballot's GUID from the authority
443 */
281 public void addRegistrationSignature(PeerIdentity currentAuthority, CryptoECC.Signature registrationSignature) { 444 public void addRegistrationSignature(PeerIdentity currentAuthority, CryptoECC.Signature registrationSignature) {
282 String alias = authorities.inverse().get(currentAuthority); 445 String alias = authorities.inverse().get(currentAuthority);
283 registrationSigs.put(alias, registrationSignature); 446 registrationSigs.put(alias, registrationSignature);
284 } 447 }
285 448
449 /**
450 * Add a voucher, that is, a signature about the fact that an authority received a vote,
451 * to the list of vouchers
452 *
453 * @param currentAuthority authority that received the vote
454 * @param voucherSignature signature from the authority
455 */
456 public void addVoucher(PeerIdentity currentAuthority, CryptoECC.Signature voucherSignature) {
457 String alias = authorities.inverse().get(currentAuthority);
458 voucherSigs.put(alias, voucherSignature);
459 }
460
461 /**
462 * Get a list of all authorities.
463 *
464 * @return list of all authorities
465 */
286 public List<PeerIdentity> getAuthorities() { 466 public List<PeerIdentity> getAuthorities() {
287 return new ArrayList<PeerIdentity>(authorities.values()); 467 return new ArrayList<PeerIdentity>(authorities.values());
288 } 468 }
diff --git a/src/main/java/org/gnunet/voting/BallotTool.java b/src/main/java/org/gnunet/voting/BallotTool.java
index 619afa5..1abf8fd 100644
--- a/src/main/java/org/gnunet/voting/BallotTool.java
+++ b/src/main/java/org/gnunet/voting/BallotTool.java
@@ -25,26 +25,15 @@ import com.google.common.base.Charsets;
25import com.google.common.io.ByteStreams; 25import com.google.common.io.ByteStreams;
26import com.google.common.io.Files; 26import com.google.common.io.Files;
27import com.google.common.io.OutputSupplier; 27import com.google.common.io.OutputSupplier;
28import org.gnunet.mesh.Mesh;
29import org.gnunet.mesh.MeshRunabout;
30import org.gnunet.mesh.TunnelEndHandler;
31import org.gnunet.util.Configuration;
32import org.gnunet.util.CryptoECC; 28import org.gnunet.util.CryptoECC;
33import org.gnunet.util.PeerIdentity;
34import org.gnunet.util.Program; 29import org.gnunet.util.Program;
35import org.gnunet.util.getopt.Argument; 30import org.gnunet.util.getopt.Argument;
36import org.gnunet.util.getopt.ArgumentAction; 31import org.gnunet.util.getopt.ArgumentAction;
37import org.gnunet.voting.messages.BallotRegisterRequestMessage;
38import org.gnunet.voting.messages.SubmitMessage;
39import org.gnunet.voting.messages.SubmitResponseMessage;
40 32
41import java.io.File; 33import java.io.File;
42import java.io.FileOutputStream; 34import java.io.FileOutputStream;
43import java.io.IOException; 35import java.io.IOException;
44import java.io.InputStream; 36import java.io.InputStream;
45import java.nio.charset.Charset;
46import java.util.List;
47import java.util.regex.Pattern;
48 37
49/** 38/**
50 * Tool for creating, manipulating and submitting ballot files. 39 * Tool for creating, manipulating and submitting ballot files.
@@ -89,11 +78,11 @@ public class BallotTool {
89 String select = null; 78 String select = null;
90 79
91 @Argument( 80 @Argument(
92 shortname = "p", 81 shortname = "G",
93 longname = "permission", 82 longname = "certify-group",
94 action = ArgumentAction.SET, 83 action = ArgumentAction.SET,
95 description = "request permission to vote from the certificate authority") 84 description = "request a certificate that the voter belongs to the ballot's group")
96 boolean permission = false; 85 boolean certifyGroup = false;
97 86
98 @Argument( 87 @Argument(
99 shortname = "V", 88 shortname = "V",
@@ -226,7 +215,7 @@ public class BallotTool {
226 System.err.println("key invalid"); 215 System.err.println("key invalid");
227 return; 216 return;
228 } 217 }
229 CryptoECC.PublicKey publicKey = CryptoECC.computePublicKey(privateKey); 218 CryptoECC.PublicSignKey publicKey = CryptoECC.computePublicKey(privateKey);
230 System.out.println(publicKey.toString()); 219 System.out.println(publicKey.toString());
231 } 220 }
232 221
@@ -302,12 +291,12 @@ public class BallotTool {
302 c.run(); 291 c.run();
303 return; 292 return;
304 } 293 }
305 if (permission) { 294 if (certifyGroup) {
306 if (this.unprocessedArgs.length != 2) { 295 if (this.unprocessedArgs.length != 2) {
307 System.err.println("-p/--permission requires exactly two positional arguments"); 296 System.err.println("-G/--certify-group requires exactly two positional arguments");
308 return; 297 return;
309 } 298 }
310 PermissionCommand c = new PermissionCommand(getConfiguration(), 299 CertifyGroupCommand c = new CertifyGroupCommand(getConfiguration(),
311 unprocessedArgs[0], unprocessedArgs[1]); 300 unprocessedArgs[0], unprocessedArgs[1]);
312 c.run(); 301 c.run();
313 return; 302 return;
diff --git a/src/main/java/org/gnunet/voting/CertificateAuthorityDaemon.java b/src/main/java/org/gnunet/voting/CertificateAuthorityDaemon.java
new file mode 100644
index 0000000..fc54bbf
--- /dev/null
+++ b/src/main/java/org/gnunet/voting/CertificateAuthorityDaemon.java
@@ -0,0 +1,70 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20package org.gnunet.voting;
21
22import com.google.common.collect.Maps;
23import org.gnunet.mesh.Mesh;
24import org.gnunet.mesh.MeshRunabout;
25import org.gnunet.testbed.CompressedConfig;
26import org.gnunet.util.*;
27import org.gnunet.voting.messages.*;
28import org.slf4j.Logger;
29import org.slf4j.LoggerFactory;
30
31import java.util.HashMap;
32import java.util.HashSet;
33import java.util.Set;
34
35/**
36 * Gives a voter a certificate that acknowledges that he belongs to a certain group
37 * (e.g. all people from bavaria over 18 years old)
38 */
39public class CertificateAuthorityDaemon extends Program {
40 private static final Logger logger = LoggerFactory
41 .getLogger(CertificateAuthorityDaemon.class);
42
43 public static final int MESH_PORT = 1002;
44 private Mesh mesh;
45
46 public class CaMeshReceiver extends MeshRunabout {
47 public void visit(CertificateRequestMessage m) {
48 logger.info("granting group cert for '" + m.group + "'");
49 CertificateGrantMessage gm = new CertificateGrantMessage();
50 gm.expiration = AbsoluteTime.FOREVER.asMessage();
51 gm.groupCertificate = CryptoECC.Signature.randomSignature();
52 getSender().receiveDone();
53 }
54 }
55
56 public CertificateAuthorityDaemon(String[] args) {
57 super(args);
58 }
59
60 public static void main(String[] args) {
61 CertificateAuthorityDaemon daemon = new CertificateAuthorityDaemon(args);
62 daemon.start();
63 }
64
65 @Override
66 public void run() {
67 logger.info("running ca daemon");
68 mesh = new Mesh(getConfiguration(), null, null, new CaMeshReceiver(), MESH_PORT);
69 }
70}
diff --git a/src/main/java/org/gnunet/voting/CertificateAuthorityService.java b/src/main/java/org/gnunet/voting/CertificateAuthorityService.java
deleted file mode 100644
index 23aa1f2..0000000
--- a/src/main/java/org/gnunet/voting/CertificateAuthorityService.java
+++ /dev/null
@@ -1,55 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20package org.gnunet.voting;
21
22import org.gnunet.mesh.Mesh;
23import org.gnunet.mesh.MeshRunabout;
24import org.gnunet.util.RelativeTime;
25import org.gnunet.util.Service;
26import org.gnunet.voting.messages.CertificateRequestMessage;
27
28/**
29 * Permits or denies a voter to participate in an election.
30 */
31public class CertificateAuthorityService extends Service {
32 public static final int MESH_PORT = 1001;
33 private Mesh mesh;
34
35
36 private class CaMeshReceiver extends MeshRunabout {
37 public void visit(CertificateRequestMessage m) {
38 // TODO: just sign the
39 }
40 }
41
42 public CertificateAuthorityService(String[] args) {
43 super("voting-ca", RelativeTime.FOREVER, true, args);
44 }
45
46 public static void main(String[] args) {
47 CertificateAuthorityService service = new CertificateAuthorityService(args);
48 service.start();
49 }
50
51 @Override
52 public void run() {
53 mesh = new Mesh(getConfiguration(), null, null, new CaMeshReceiver(), MESH_PORT);
54 }
55}
diff --git a/src/main/java/org/gnunet/voting/PermissionCommand.java b/src/main/java/org/gnunet/voting/CertifyGroupCommand.java
index 7e73dbd..e76ba1f 100644
--- a/src/main/java/org/gnunet/voting/PermissionCommand.java
+++ b/src/main/java/org/gnunet/voting/CertifyGroupCommand.java
@@ -65,17 +65,17 @@ import org.gnunet.mesh.Mesh;
65import org.gnunet.mesh.MeshRunabout; 65import org.gnunet.mesh.MeshRunabout;
66import org.gnunet.mesh.TunnelEndHandler; 66import org.gnunet.mesh.TunnelEndHandler;
67import org.gnunet.util.Configuration; 67import org.gnunet.util.Configuration;
68import org.gnunet.util.PeerIdentity; 68import org.gnunet.util.CryptoECC;
69import org.gnunet.voting.messages.CertificateGrantMessage;
70import org.gnunet.voting.messages.CertificateRequestMessage;
69import org.gnunet.voting.messages.QueryFailureMessage; 71import org.gnunet.voting.messages.QueryFailureMessage;
70import org.gnunet.voting.messages.QueryMessage;
71import org.gnunet.voting.messages.QueryResponseMessage;
72 72
73import java.io.File; 73import java.io.File;
74import java.util.List;
75import java.util.Random; 74import java.util.Random;
76 75
77public class PermissionCommand extends MeshRunabout implements TunnelEndHandler { 76public class CertifyGroupCommand extends MeshRunabout implements TunnelEndHandler {
78 private final String ballotFilename; 77 private final String ballotFilename;
78 private final String pubKeyString;
79 private Ballot ballot; 79 private Ballot ballot;
80 private final Configuration cfg; 80 private final Configuration cfg;
81 private Mesh mesh; 81 private Mesh mesh;
@@ -88,16 +88,9 @@ public class PermissionCommand extends MeshRunabout implements TunnelEndHandler
88 throw new AssertionError(); 88 throw new AssertionError();
89 } 89 }
90 90
91 public void visit(QueryResponseMessage m) { 91 public void visit(CertificateGrantMessage m) {
92 submitted = true; 92 submitted = true;
93 if (m.results.length != ballot.choices.size()) { 93 System.out.println("certificate granted");
94 System.out.println("failure to query result: malformed response");
95 } else {
96 System.out.println("got results:");
97 for (int i = 0; i < m.results.length; i++) {
98 System.out.println("'" + ballot.choices.get(i) + "': " + m.results[i]);
99 }
100 }
101 94
102 tunnel.destroy(); 95 tunnel.destroy();
103 mesh.destroy(); 96 mesh.destroy();
@@ -111,9 +104,10 @@ public class PermissionCommand extends MeshRunabout implements TunnelEndHandler
111 mesh.destroy(); 104 mesh.destroy();
112 } 105 }
113 106
114 public PermissionCommand(Configuration cfg, String ballotFilename, String pubKeyString) { 107 public CertifyGroupCommand(Configuration cfg, String ballotFilename, String pubKeyString) {
115 this.cfg = cfg; 108 this.cfg = cfg;
116 this.ballotFilename = ballotFilename; 109 this.ballotFilename = ballotFilename;
110 this.pubKeyString = pubKeyString;
117 } 111 }
118 112
119 public void run() { 113 public void run() {
@@ -126,7 +120,10 @@ public class PermissionCommand extends MeshRunabout implements TunnelEndHandler
126 120
127 Random r = new Random(); 121 Random r = new Random();
128 mesh = new Mesh(cfg, this, this); 122 mesh = new Mesh(cfg, this, this);
129 tunnel = mesh.createTunnel(null /* FIXME */, CertificateAuthorityService.MESH_PORT, true, true, null); 123 tunnel = mesh.createTunnel(null /* FIXME */, CertificateAuthorityDaemon.MESH_PORT, true, true, null);
130 //tunnel.send(m); 124 CertificateRequestMessage m = new CertificateRequestMessage();
125 m.group = ballot.group;
126 m.publicKey = CryptoECC.PublicSignKey.fromString(pubKeyString);
127 tunnel.send(m);
131 } 128 }
132} 129}
diff --git a/src/main/java/org/gnunet/voting/RegisterCommand.java b/src/main/java/org/gnunet/voting/RegisterCommand.java
index f9d4c4d..1878c48 100644
--- a/src/main/java/org/gnunet/voting/RegisterCommand.java
+++ b/src/main/java/org/gnunet/voting/RegisterCommand.java
@@ -49,16 +49,18 @@ import org.gnunet.mesh.TunnelEndHandler;
49import org.gnunet.testbed.CompressedConfig; 49import org.gnunet.testbed.CompressedConfig;
50import org.gnunet.util.Configuration; 50import org.gnunet.util.Configuration;
51import org.gnunet.util.PeerIdentity; 51import org.gnunet.util.PeerIdentity;
52import org.gnunet.voting.messages.BallotRegisterFailureMessage;
52import org.gnunet.voting.messages.BallotRegisterRequestMessage; 53import org.gnunet.voting.messages.BallotRegisterRequestMessage;
53import org.gnunet.voting.messages.BallotRegisterRespondMessage; 54import org.gnunet.voting.messages.BallotRegisterSuccessMessage;
54import org.gnunet.voting.messages.SubmitMessage;
55import org.gnunet.voting.messages.SubmitResponseMessage;
56 55
57import java.io.File; 56import java.io.File;
58import java.io.IOException; 57import java.io.IOException;
59import java.util.List; 58import java.util.List;
60import java.util.Random; 59import java.util.Random;
61 60
61/**
62 * Command for registering a ballot with an authority.
63 */
62public class RegisterCommand extends MeshRunabout implements TunnelEndHandler { 64public class RegisterCommand extends MeshRunabout implements TunnelEndHandler {
63 private final String ballotFilename; 65 private final String ballotFilename;
64 private Ballot ballot; 66 private Ballot ballot;
@@ -74,9 +76,9 @@ public class RegisterCommand extends MeshRunabout implements TunnelEndHandler {
74 throw new AssertionError(); 76 throw new AssertionError();
75 } 77 }
76 78
77 public void visit(BallotRegisterRespondMessage m) { 79 public void visit(BallotRegisterSuccessMessage m) {
78 submitted = true; 80 submitted = true;
79 System.out.println("vote successfully registered"); 81 System.out.println("ballot successfully registered");
80 ballot.addRegistrationSignature(currentAuthority, m.registrationSignature); 82 ballot.addRegistrationSignature(currentAuthority, m.registrationSignature);
81 try { 83 try {
82 Files.write(ballot.serialize(), new File(ballotFilename), Charsets.UTF_8); 84 Files.write(ballot.serialize(), new File(ballotFilename), Charsets.UTF_8);
@@ -88,6 +90,14 @@ public class RegisterCommand extends MeshRunabout implements TunnelEndHandler {
88 mesh.destroy(); 90 mesh.destroy();
89 } 91 }
90 92
93
94 public void visit(BallotRegisterFailureMessage m) {
95 submitted = true;
96 System.out.println("registering failed: " + m.reason);
97 tunnel.destroy();
98 mesh.destroy();
99 }
100
91 public RegisterCommand(Configuration cfg, String ballotFilename) { 101 public RegisterCommand(Configuration cfg, String ballotFilename) {
92 this.cfg = cfg; 102 this.cfg = cfg;
93 this.ballotFilename = ballotFilename; 103 this.ballotFilename = ballotFilename;
diff --git a/src/main/java/org/gnunet/voting/SubmitCommand.java b/src/main/java/org/gnunet/voting/SubmitCommand.java
index d00ea69..43e10c9 100644
--- a/src/main/java/org/gnunet/voting/SubmitCommand.java
+++ b/src/main/java/org/gnunet/voting/SubmitCommand.java
@@ -21,18 +21,27 @@
21package org.gnunet.voting; 21package org.gnunet.voting;
22 22
23 23
24import com.google.common.base.Charsets;
25import com.google.common.io.Files;
24import org.gnunet.mesh.Mesh; 26import org.gnunet.mesh.Mesh;
25import org.gnunet.mesh.MeshRunabout; 27import org.gnunet.mesh.MeshRunabout;
26import org.gnunet.mesh.TunnelEndHandler; 28import org.gnunet.mesh.TunnelEndHandler;
29import org.gnunet.util.AbsoluteTime;
27import org.gnunet.util.Configuration; 30import org.gnunet.util.Configuration;
31import org.gnunet.util.CryptoECC;
28import org.gnunet.util.PeerIdentity; 32import org.gnunet.util.PeerIdentity;
33import org.gnunet.voting.messages.SubmitFailureMessage;
29import org.gnunet.voting.messages.SubmitMessage; 34import org.gnunet.voting.messages.SubmitMessage;
30import org.gnunet.voting.messages.SubmitResponseMessage; 35import org.gnunet.voting.messages.SubmitSuccessMessage;
31 36
32import java.io.File; 37import java.io.File;
38import java.io.IOException;
33import java.util.List; 39import java.util.List;
34import java.util.Random; 40import java.util.Random;
35 41
42/**
43 * Command that submits a ballot with a vote to a remaining authority.
44 */
36public class SubmitCommand extends MeshRunabout implements TunnelEndHandler { 45public class SubmitCommand extends MeshRunabout implements TunnelEndHandler {
37 private final String ballotFilename; 46 private final String ballotFilename;
38 private Ballot ballot; 47 private Ballot ballot;
@@ -40,6 +49,7 @@ public class SubmitCommand extends MeshRunabout implements TunnelEndHandler {
40 private Mesh mesh; 49 private Mesh mesh;
41 private Mesh.Tunnel<Void> tunnel; 50 private Mesh.Tunnel<Void> tunnel;
42 private boolean submitted = false; 51 private boolean submitted = false;
52 private PeerIdentity currentAuthority;
43 53
44 @Override 54 @Override
45 public void onTunnelEnd(Mesh.Tunnel tunnel) { 55 public void onTunnelEnd(Mesh.Tunnel tunnel) {
@@ -47,9 +57,23 @@ public class SubmitCommand extends MeshRunabout implements TunnelEndHandler {
47 throw new AssertionError(); 57 throw new AssertionError();
48 } 58 }
49 59
50 public void visit(SubmitResponseMessage m) { 60 public void visit(SubmitSuccessMessage m) {
51 submitted = true; 61 submitted = true;
52 System.out.println("vote successfully submitted"); 62 System.out.println("vote successfully submitted");
63 ballot.addVoucher(currentAuthority, m.voucherSig);
64 try {
65 Files.write(ballot.serialize(), new File(ballotFilename), Charsets.UTF_8);
66 } catch (IOException e) {
67 System.out.println("could not write ballot file");
68 return;
69 }
70 tunnel.destroy();
71 mesh.destroy();
72 }
73
74 public void visit(SubmitFailureMessage m) {
75 submitted = true;
76 System.out.println("vote not submitted: " + m.reason);
53 tunnel.destroy(); 77 tunnel.destroy();
54 mesh.destroy(); 78 mesh.destroy();
55 } 79 }
@@ -74,9 +98,17 @@ public class SubmitCommand extends MeshRunabout implements TunnelEndHandler {
74 Random r = new Random(); 98 Random r = new Random();
75 PeerIdentity authority = remainingAuthorities.get(r.nextInt(remainingAuthorities.size())); 99 PeerIdentity authority = remainingAuthorities.get(r.nextInt(remainingAuthorities.size()));
76 System.out.println("submitting to authority" + authority.toString()); 100 System.out.println("submitting to authority" + authority.toString());
101 currentAuthority = authority;
77 mesh = new Mesh(cfg, null, this); 102 mesh = new Mesh(cfg, null, this);
78 tunnel = mesh.createTunnel(authority, TallyAuthorityDaemon.MESH_PORT, true, true, null); 103 tunnel = mesh.createTunnel(authority, TallyAuthorityDaemon.MESH_PORT, true, true, null);
79 SubmitMessage m = new SubmitMessage(); 104 SubmitMessage m = new SubmitMessage();
105 if (ballot.voterPub == null) {
106 throw new InvalidBallotException("no voter in ballot");
107 }
108 m.voterPub = ballot.voterPub;
109 // FIXME: implement certs
110 m.groupCertExpiration = AbsoluteTime.FOREVER.asMessage();
111 m.groupCert = CryptoECC.Signature.randomSignature();
80 m.ballotGuid = ballot.getBallotGuid(); 112 m.ballotGuid = ballot.getBallotGuid();
81 m.choiceId = ballot.choiceId; 113 m.choiceId = ballot.choiceId;
82 tunnel.send(m); 114 tunnel.send(m);
diff --git a/src/main/java/org/gnunet/voting/TallyAuthorityDaemon.java b/src/main/java/org/gnunet/voting/TallyAuthorityDaemon.java
index a74d175..aa27f9c 100644
--- a/src/main/java/org/gnunet/voting/TallyAuthorityDaemon.java
+++ b/src/main/java/org/gnunet/voting/TallyAuthorityDaemon.java
@@ -31,6 +31,10 @@ import org.slf4j.LoggerFactory;
31 31
32import java.util.*; 32import java.util.*;
33 33
34
35/**
36 * Daemon that is responsible for counting votes.
37 */
34public class TallyAuthorityDaemon extends Program { 38public class TallyAuthorityDaemon extends Program {
35 private static final Logger logger = LoggerFactory 39 private static final Logger logger = LoggerFactory
36 .getLogger(TallyAuthorityDaemon.class); 40 .getLogger(TallyAuthorityDaemon.class);
@@ -38,14 +42,23 @@ public class TallyAuthorityDaemon extends Program {
38 public static final int MESH_PORT = 1002; 42 public static final int MESH_PORT = 1002;
39 private Mesh mesh; 43 private Mesh mesh;
40 44
45 /**
46 * All elections known to this authority
47 */
41 private HashMap<HashCode, ElectionState> elections = Maps.newHashMap(); 48 private HashMap<HashCode, ElectionState> elections = Maps.newHashMap();
42 49
50 /**
51 * State of one election.
52 */
43 class ElectionState { 53 class ElectionState {
54 /**
55 * The ballot that describes this election.
56 */
44 Ballot ballot; 57 Ballot ballot;
45 /** 58 /**
46 * Set of voters that have submitted their ballot. 59 * Set of voters that have submitted their ballot.
47 */ 60 */
48 Set<CryptoECC.PublicKey> voters = new HashSet<CryptoECC.PublicKey>(); 61 Set<CryptoECC.PublicSignKey> voters = new HashSet<CryptoECC.PublicSignKey>();
49 62
50 /** 63 /**
51 * Maping from choice to number of votes for that choice. 64 * Maping from choice to number of votes for that choice.
@@ -53,47 +66,92 @@ public class TallyAuthorityDaemon extends Program {
53 int[] tally; 66 int[] tally;
54 } 67 }
55 68
56
57 private class TallyMeshReceiver extends MeshRunabout { 69 private class TallyMeshReceiver extends MeshRunabout {
58 public void visit(SubmitMessage m) { 70 public void visit(SubmitMessage m) {
71 logger.debug("got submit message");
59 ElectionState electionState = elections.get(m.ballotGuid); 72 ElectionState electionState = elections.get(m.ballotGuid);
60 if (null == electionState) { 73 if (null == electionState) {
61 return; 74 SubmitFailureMessage fm = new SubmitFailureMessage();
75 fm.reason = "no matching ballot found";
76 getSender().send(fm);
77 } else if (m.choiceId < 0 || m.choiceId >= electionState.tally.length) {
78 SubmitFailureMessage fm = new SubmitFailureMessage();
79 fm.reason = "invalid vote";
80 getSender().send(fm);
81 } else if (electionState.voters.contains(m.voterPub)) {
82 SubmitFailureMessage fm = new SubmitFailureMessage();
83 fm.reason = "duplicate vote detected";
84 getSender().send(fm);
85 } else if (!electionState.ballot.startTime.isDue()) {
86 SubmitFailureMessage fm = new SubmitFailureMessage();
87 fm.reason = "too early to submit vote (start "
88 + electionState.ballot.startTime.toFancyString() + ", now "
89 + AbsoluteTime.now().toFancyString() + ")";
90 getSender().send(fm);
91 } else if (!electionState.ballot.closingTime.isDue()) {
92 SubmitFailureMessage fm = new SubmitFailureMessage();
93 fm.reason = "too late to submit vote";
94 getSender().send(fm);
62 } 95 }
63 if (m.choiceId < 0 || m.choiceId >= electionState.tally.length) { 96 // FIXME: check signatures of voter and CA
64 return; 97 else {
98 electionState.voters.add(m.voterPub);
99 electionState.tally[m.choiceId] += 1;
100 SubmitSuccessMessage sm = new SubmitSuccessMessage();
101 sm.voucherSig = CryptoECC.Signature.randomSignature();
102 getSender().send(sm);
65 } 103 }
66 electionState.tally[m.choiceId] += 1; 104
67 SubmitResponseMessage rm = new SubmitResponseMessage();
68 getSender().send(rm);
69 getSender().receiveDone(); 105 getSender().receiveDone();
70 } 106 }
71 107
72 public void visit(BallotRegisterRequestMessage m) { 108 public void visit(BallotRegisterRequestMessage m) {
73 logger.info("ballot register requested"); 109 logger.info("ballot register requested");
74
75 CompressedConfig ccfg = new CompressedConfig(m.compressedBallotConfig); 110 CompressedConfig ccfg = new CompressedConfig(m.compressedBallotConfig);
76 Ballot b = new Ballot(ccfg.decompress()); 111 Ballot b;
77 ElectionState electionState = new ElectionState(); 112 HashCode guid;
78 electionState.tally = new int[b.choices.size()]; 113 try {
79 electionState.ballot = b; 114 b = new Ballot(ccfg.decompress());
80 elections.put(b.getBallotGuid(), electionState); 115 guid = b.getBallotGuid();
81 BallotRegisterRespondMessage rm = new BallotRegisterRespondMessage(); 116 } catch (InvalidBallotException e) {
82 rm.registrationSignature = CryptoECC.Signature.randomSignature(); 117 BallotRegisterFailureMessage fm = new BallotRegisterFailureMessage();
83 getSender().send(rm); 118 fm.reason = "invalid ballot (" + e.getMessage() + ")";
84 getSender().receiveDone(); 119 getSender().send(fm);
120 getSender().receiveDone();
121 return;
122 }
123 if (elections.containsKey(guid)) {
124 BallotRegisterFailureMessage fm = new BallotRegisterFailureMessage();
125 fm.reason = "ballot with same GUID already registered";
126 getSender().send(fm);
127 } else {
128 ElectionState electionState = new ElectionState();
129 electionState.tally = new int[b.choices.size()];
130 electionState.ballot = b;
131 elections.put(guid, electionState);
132 BallotRegisterSuccessMessage rm = new BallotRegisterSuccessMessage();
133 rm.registrationSignature = CryptoECC.Signature.randomSignature();
134 getSender().send(rm);
135 }
136
85 } 137 }
86 138
87 public void visit(QueryMessage m) { 139 public void visit(QueryMessage m) {
88 ElectionState electionState = elections.get(m.ballotGUID); 140 ElectionState electionState = elections.get(m.ballotGUID);
89 if (null == electionState) { 141 if (null == electionState) {
90 QueryFailureMessage rm = new QueryFailureMessage(); 142 QueryFailureMessage rm = new QueryFailureMessage();
143 rm.reason = "no matching ballot found";
91 getSender().send(rm); 144 getSender().send(rm);
92
93 } else { 145 } else {
94 QueryResponseMessage rm = new QueryResponseMessage(); 146 if (electionState.ballot.queryTime.isDue()) {
95 rm.results = electionState.tally; 147 QueryResponseMessage rm = new QueryResponseMessage();
96 getSender().send(rm); 148 rm.results = electionState.tally;
149 getSender().send(rm);
150 } else {
151 QueryFailureMessage rm = new QueryFailureMessage();
152 rm.reason = "result query not allowed yet";
153 getSender().send(rm);
154 }
97 } 155 }
98 getSender().receiveDone(); 156 getSender().receiveDone();
99 } 157 }
diff --git a/src/main/java/org/gnunet/voting/messages/BallotRegisterFailureMessage.java b/src/main/java/org/gnunet/voting/messages/BallotRegisterFailureMessage.java
new file mode 100644
index 0000000..ecce92d
--- /dev/null
+++ b/src/main/java/org/gnunet/voting/messages/BallotRegisterFailureMessage.java
@@ -0,0 +1,37 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21package org.gnunet.voting.messages;
22
23import org.gnunet.construct.NestedMessage;
24import org.gnunet.construct.UnionCase;
25import org.gnunet.construct.ZeroTerminatedString;
26import org.gnunet.util.CryptoECC;
27import org.gnunet.util.GnunetMessage;
28
29
30/**
31 * Response from the authorities to the issuer.
32 */
33@UnionCase(42002)
34public class BallotRegisterFailureMessage implements GnunetMessage.Body {
35 @ZeroTerminatedString
36 public String reason;
37}
diff --git a/src/main/java/org/gnunet/voting/messages/BallotRegisterRequestMessage.java b/src/main/java/org/gnunet/voting/messages/BallotRegisterRequestMessage.java
index 95a7c2f..6dc731f 100644
--- a/src/main/java/org/gnunet/voting/messages/BallotRegisterRequestMessage.java
+++ b/src/main/java/org/gnunet/voting/messages/BallotRegisterRequestMessage.java
@@ -4,6 +4,9 @@ import org.gnunet.construct.IntegerFill;
4import org.gnunet.construct.UnionCase; 4import org.gnunet.construct.UnionCase;
5import org.gnunet.util.GnunetMessage; 5import org.gnunet.util.GnunetMessage;
6 6
7/**
8 * Sent by an issuer to the authorities to register a ballot with them.
9 */
7@UnionCase(42001) 10@UnionCase(42001)
8public class BallotRegisterRequestMessage implements GnunetMessage.Body { 11public class BallotRegisterRequestMessage implements GnunetMessage.Body {
9 @IntegerFill(signed = false, bitSize = 8) 12 @IntegerFill(signed = false, bitSize = 8)
diff --git a/src/main/java/org/gnunet/voting/messages/BallotRegisterRespondMessage.java b/src/main/java/org/gnunet/voting/messages/BallotRegisterSuccessMessage.java
index f30f624..8ce007b 100644
--- a/src/main/java/org/gnunet/voting/messages/BallotRegisterRespondMessage.java
+++ b/src/main/java/org/gnunet/voting/messages/BallotRegisterSuccessMessage.java
@@ -5,8 +5,12 @@ import org.gnunet.construct.UnionCase;
5import org.gnunet.util.CryptoECC; 5import org.gnunet.util.CryptoECC;
6import org.gnunet.util.GnunetMessage; 6import org.gnunet.util.GnunetMessage;
7 7
8@UnionCase(42002) 8
9public class BallotRegisterRespondMessage implements GnunetMessage.Body { 9/**
10 * Response from the authorities to the issuer.
11 */
12@UnionCase(42012)
13public class BallotRegisterSuccessMessage implements GnunetMessage.Body {
10 @NestedMessage 14 @NestedMessage
11 public CryptoECC.Signature registrationSignature; 15 public CryptoECC.Signature registrationSignature;
12} 16}
diff --git a/src/main/java/org/gnunet/voting/messages/CertificateDenyMessage.java b/src/main/java/org/gnunet/voting/messages/CertificateDenyMessage.java
new file mode 100644
index 0000000..aefd6ab
--- /dev/null
+++ b/src/main/java/org/gnunet/voting/messages/CertificateDenyMessage.java
@@ -0,0 +1,34 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21package org.gnunet.voting.messages;
22
23
24import org.gnunet.construct.NestedMessage;
25import org.gnunet.construct.UnionCase;
26import org.gnunet.construct.ZeroTerminatedString;
27import org.gnunet.util.CryptoECC;
28import org.gnunet.util.GnunetMessage;
29
30@UnionCase(42011)
31public class CertificateDenyMessage implements GnunetMessage.Body {
32 @ZeroTerminatedString
33 public String reason;
34}
diff --git a/src/main/java/org/gnunet/voting/messages/CertificateGrantMessage.java b/src/main/java/org/gnunet/voting/messages/CertificateGrantMessage.java
new file mode 100644
index 0000000..f209b7a
--- /dev/null
+++ b/src/main/java/org/gnunet/voting/messages/CertificateGrantMessage.java
@@ -0,0 +1,19 @@
1package org.gnunet.voting.messages;
2
3
4import org.gnunet.construct.NestedMessage;
5import org.gnunet.construct.UInt32;
6import org.gnunet.construct.UInt64;
7import org.gnunet.construct.UnionCase;
8import org.gnunet.util.AbsoluteTime;
9import org.gnunet.util.AbsoluteTimeMessage;
10import org.gnunet.util.CryptoECC;
11import org.gnunet.util.GnunetMessage;
12
13@UnionCase(42004)
14public class CertificateGrantMessage implements GnunetMessage.Body {
15 @NestedMessage
16 public CryptoECC.Signature groupCertificate;
17 @NestedMessage
18 public AbsoluteTimeMessage expiration;
19}
diff --git a/src/main/java/org/gnunet/voting/messages/CertificateRequestMessage.java b/src/main/java/org/gnunet/voting/messages/CertificateRequestMessage.java
index e57b215..1b4514e 100644
--- a/src/main/java/org/gnunet/voting/messages/CertificateRequestMessage.java
+++ b/src/main/java/org/gnunet/voting/messages/CertificateRequestMessage.java
@@ -1,6 +1,8 @@
1package org.gnunet.voting.messages; 1package org.gnunet.voting.messages;
2 2
3import org.gnunet.construct.NestedMessage;
3import org.gnunet.construct.UnionCase; 4import org.gnunet.construct.UnionCase;
5import org.gnunet.util.CryptoECC;
4import org.gnunet.util.GnunetMessage; 6import org.gnunet.util.GnunetMessage;
5 7
6/** 8/**
@@ -9,4 +11,13 @@ import org.gnunet.util.GnunetMessage;
9 */ 11 */
10@UnionCase(42003) 12@UnionCase(42003)
11public class CertificateRequestMessage implements GnunetMessage.Body { 13public class CertificateRequestMessage implements GnunetMessage.Body {
14 /**
15 * Public Key of the voter that requests group certification.
16 */
17 @NestedMessage
18 public CryptoECC.PublicSignKey publicKey;
19 /**
20 * Group that the voter wants to be certified for.
21 */
22 public String group;
12} 23}
diff --git a/src/main/java/org/gnunet/voting/messages/CertificateResponseMessage.java b/src/main/java/org/gnunet/voting/messages/CertificateResponseMessage.java
deleted file mode 100644
index 4a1bcd6..0000000
--- a/src/main/java/org/gnunet/voting/messages/CertificateResponseMessage.java
+++ /dev/null
@@ -1,9 +0,0 @@
1package org.gnunet.voting.messages;
2
3
4import org.gnunet.construct.UnionCase;
5import org.gnunet.util.GnunetMessage;
6
7@UnionCase(42004)
8public class CertificateResponseMessage implements GnunetMessage.Body {
9}
diff --git a/src/main/java/org/gnunet/voting/messages/QueryFailureMessage.java b/src/main/java/org/gnunet/voting/messages/QueryFailureMessage.java
index 73f8fc8..8f525e0 100644
--- a/src/main/java/org/gnunet/voting/messages/QueryFailureMessage.java
+++ b/src/main/java/org/gnunet/voting/messages/QueryFailureMessage.java
@@ -21,8 +21,11 @@
21package org.gnunet.voting.messages; 21package org.gnunet.voting.messages;
22 22
23import org.gnunet.construct.UnionCase; 23import org.gnunet.construct.UnionCase;
24import org.gnunet.construct.ZeroTerminatedString;
24import org.gnunet.util.GnunetMessage; 25import org.gnunet.util.GnunetMessage;
25 26
26@UnionCase(42009) 27@UnionCase(42009)
27public class QueryFailureMessage implements GnunetMessage.Body { 28public class QueryFailureMessage implements GnunetMessage.Body {
29 @ZeroTerminatedString
30 public String reason;
28} 31}
diff --git a/src/main/java/org/gnunet/voting/messages/SubmitFailureMessage.java b/src/main/java/org/gnunet/voting/messages/SubmitFailureMessage.java
new file mode 100644
index 0000000..6e5a345
--- /dev/null
+++ b/src/main/java/org/gnunet/voting/messages/SubmitFailureMessage.java
@@ -0,0 +1,32 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21package org.gnunet.voting.messages;
22
23
24import org.gnunet.construct.UnionCase;
25import org.gnunet.construct.ZeroTerminatedString;
26import org.gnunet.util.GnunetMessage;
27
28@UnionCase(42010)
29public class SubmitFailureMessage implements GnunetMessage.Body {
30 @ZeroTerminatedString
31 public String reason;
32}
diff --git a/src/main/java/org/gnunet/voting/messages/SubmitMessage.java b/src/main/java/org/gnunet/voting/messages/SubmitMessage.java
index afd54b9..1b71d3e 100644
--- a/src/main/java/org/gnunet/voting/messages/SubmitMessage.java
+++ b/src/main/java/org/gnunet/voting/messages/SubmitMessage.java
@@ -3,17 +3,37 @@ package org.gnunet.voting.messages;
3import org.gnunet.construct.NestedMessage; 3import org.gnunet.construct.NestedMessage;
4import org.gnunet.construct.UInt32; 4import org.gnunet.construct.UInt32;
5import org.gnunet.construct.UnionCase; 5import org.gnunet.construct.UnionCase;
6import org.gnunet.construct.ZeroTerminatedString; 6import org.gnunet.util.*;
7import org.gnunet.util.GnunetMessage;
8import org.gnunet.util.HashCode;
9 7
10/** 8/**
11 * Message send by the voter to the election authority to submit a vote. 9 * Message send by the voter to the election authority to submit a vote.
12 */ 10 */
13@UnionCase(42007) 11@UnionCase(42007)
14public class SubmitMessage implements GnunetMessage.Body { 12public class SubmitMessage implements GnunetMessage.Body {
13 /**
14 * Identifier of the ballot we want to vote in.
15 */
15 @NestedMessage 16 @NestedMessage
16 public HashCode ballotGuid; 17 public HashCode ballotGuid;
18 /**
19 * Public key of the voter.
20 */
21 @NestedMessage
22 public CryptoECC.PublicSignKey voterPub;
23 /**
24 * Group certificate of the voter.
25 */
26 @NestedMessage
27 public CryptoECC.Signature groupCert;
28 /**
29 * Expiration time of the group certificate, checked by the authority.
30 */
31 @NestedMessage
32 public AbsoluteTimeMessage groupCertExpiration;
33 /**
34 * The actual vote.
35 * FIXME: this will be encrypted!
36 */
17 @UInt32 37 @UInt32
18 public int choiceId; 38 public int choiceId;
19} 39}
diff --git a/src/main/java/org/gnunet/voting/messages/SubmitResponseMessage.java b/src/main/java/org/gnunet/voting/messages/SubmitResponseMessage.java
deleted file mode 100644
index 956ecf2..0000000
--- a/src/main/java/org/gnunet/voting/messages/SubmitResponseMessage.java
+++ /dev/null
@@ -1,9 +0,0 @@
1package org.gnunet.voting.messages;
2
3
4import org.gnunet.construct.UnionCase;
5import org.gnunet.util.GnunetMessage;
6
7@UnionCase(42008)
8public class SubmitResponseMessage implements GnunetMessage.Body {
9}
diff --git a/src/main/java/org/gnunet/voting/messages/SubmitSuccessMessage.java b/src/main/java/org/gnunet/voting/messages/SubmitSuccessMessage.java
new file mode 100644
index 0000000..0c0e9e1
--- /dev/null
+++ b/src/main/java/org/gnunet/voting/messages/SubmitSuccessMessage.java
@@ -0,0 +1,13 @@
1package org.gnunet.voting.messages;
2
3
4import org.gnunet.construct.NestedMessage;
5import org.gnunet.construct.UnionCase;
6import org.gnunet.util.CryptoECC;
7import org.gnunet.util.GnunetMessage;
8
9@UnionCase(42008)
10public class SubmitSuccessMessage implements GnunetMessage.Body {
11 @NestedMessage
12 public CryptoECC.Signature voucherSig;
13}
diff --git a/src/main/resources/org/gnunet/construct/MsgMap.txt b/src/main/resources/org/gnunet/construct/MsgMap.txt
index 8f427b7..2b68b18 100644
--- a/src/main/resources/org/gnunet/construct/MsgMap.txt
+++ b/src/main/resources/org/gnunet/construct/MsgMap.txt
@@ -1,31 +1,37 @@
1org.gnunet.util.Resolver$Address|0=org.gnunet.util.Resolver$TextualAddress 1org.gnunet.util.Resolver$Address|0=org.gnunet.util.Resolver$TextualAddress
2org.gnunet.util.Resolver$Address|1=org.gnunet.util.Resolver$NumericAddress 2org.gnunet.util.Resolver$Address|1=org.gnunet.util.Resolver$NumericAddress
3org.gnunet.util.GnunetMessage$Body|1=org.gnunet.util.TestMessage
4org.gnunet.util.GnunetMessage$Body|274=org.gnunet.mesh.TunnelDestroyMessage 3org.gnunet.util.GnunetMessage$Body|274=org.gnunet.mesh.TunnelDestroyMessage
4org.gnunet.util.GnunetMessage$Body|1=org.gnunet.util.TestMessage
5org.gnunet.util.GnunetMessage$Body|273=org.gnunet.mesh.TunnelCreateMessage 5org.gnunet.util.GnunetMessage$Body|273=org.gnunet.mesh.TunnelCreateMessage
6org.gnunet.util.GnunetMessage$Body|272=org.gnunet.mesh.ClientConnectMessage 6org.gnunet.util.GnunetMessage$Body|272=org.gnunet.mesh.ClientConnectMessage
7org.gnunet.util.GnunetMessage$Body|4=org.gnunet.util.Resolver$GetMessage 7org.gnunet.util.GnunetMessage$Body|4=org.gnunet.util.Resolver$GetMessage
8org.gnunet.util.GnunetMessage$Body|5=org.gnunet.util.Resolver$ResolverResponse 8org.gnunet.util.GnunetMessage$Body|5=org.gnunet.util.Resolver$ResolverResponse
9org.gnunet.util.GnunetMessage$Body|143=org.gnunet.dht.ClientGetMessage 9org.gnunet.util.GnunetMessage$Body|143=org.gnunet.dht.ClientGetMessage
10org.gnunet.util.GnunetMessage$Body|142=org.gnunet.dht.ClientPutMessage 10org.gnunet.util.GnunetMessage$Body|142=org.gnunet.dht.ClientPutMessage
11org.gnunet.util.GnunetMessage$Body|10=org.gnunet.arm.messages.ResultMessage
12org.gnunet.util.GnunetMessage$Body|11=org.gnunet.arm.messages.StatusMessage
11org.gnunet.util.GnunetMessage$Body|286=org.gnunet.mesh.LocalAckMessage 13org.gnunet.util.GnunetMessage$Body|286=org.gnunet.mesh.LocalAckMessage
14org.gnunet.util.GnunetMessage$Body|13=org.gnunet.arm.messages.ListResultMessage
12org.gnunet.util.GnunetMessage$Body|285=org.gnunet.mesh.DataMessage 15org.gnunet.util.GnunetMessage$Body|285=org.gnunet.mesh.DataMessage
13org.gnunet.util.GnunetMessage$Body|42003=org.gnunet.voting.messages.CertificateRequestMessage 16org.gnunet.util.GnunetMessage$Body|42003=org.gnunet.voting.messages.CertificateRequestMessage
14org.gnunet.util.GnunetMessage$Body|153=org.gnunet.dht.MonitorStartStop 17org.gnunet.util.GnunetMessage$Body|153=org.gnunet.dht.MonitorStartStop
15org.gnunet.util.GnunetMessage$Body|42002=org.gnunet.voting.messages.BallotRegisterRespondMessage 18org.gnunet.util.GnunetMessage$Body|42002=org.gnunet.voting.messages.BallotRegisterFailureMessage
16org.gnunet.util.GnunetMessage$Body|42001=org.gnunet.voting.messages.BallotRegisterRequestMessage 19org.gnunet.util.GnunetMessage$Body|42001=org.gnunet.voting.messages.BallotRegisterRequestMessage
17org.gnunet.util.GnunetMessage$Body|155=org.gnunet.dht.ClientPutConfirmationMessage 20org.gnunet.util.GnunetMessage$Body|155=org.gnunet.dht.ClientPutConfirmationMessage
18org.gnunet.util.GnunetMessage$Body|42007=org.gnunet.voting.messages.SubmitMessage 21org.gnunet.util.GnunetMessage$Body|42007=org.gnunet.voting.messages.SubmitMessage
19org.gnunet.util.GnunetMessage$Body|42006=org.gnunet.voting.messages.QueryResponseMessage 22org.gnunet.util.GnunetMessage$Body|42006=org.gnunet.voting.messages.QueryResponseMessage
20org.gnunet.util.GnunetMessage$Body|42005=org.gnunet.voting.messages.QueryMessage 23org.gnunet.util.GnunetMessage$Body|42005=org.gnunet.voting.messages.QueryMessage
21org.gnunet.util.GnunetMessage$Body|42004=org.gnunet.voting.messages.CertificateResponseMessage 24org.gnunet.util.GnunetMessage$Body|42004=org.gnunet.voting.messages.CertificateGrantMessage
25org.gnunet.util.GnunetMessage$Body|42011=org.gnunet.voting.messages.CertificateDenyMessage
22org.gnunet.util.GnunetMessage$Body|144=org.gnunet.dht.ClientGetStopMessage 26org.gnunet.util.GnunetMessage$Body|144=org.gnunet.dht.ClientGetStopMessage
23org.gnunet.util.GnunetMessage$Body|145=org.gnunet.dht.ClientResultMessage 27org.gnunet.util.GnunetMessage$Body|145=org.gnunet.dht.ClientResultMessage
28org.gnunet.util.GnunetMessage$Body|42010=org.gnunet.voting.messages.SubmitFailureMessage
24org.gnunet.util.GnunetMessage$Body|42009=org.gnunet.voting.messages.QueryFailureMessage 29org.gnunet.util.GnunetMessage$Body|42009=org.gnunet.voting.messages.QueryFailureMessage
25org.gnunet.util.GnunetMessage$Body|42008=org.gnunet.voting.messages.SubmitResponseMessage 30org.gnunet.util.GnunetMessage$Body|42008=org.gnunet.voting.messages.SubmitSuccessMessage
26org.gnunet.util.GnunetMessage$Body|149=org.gnunet.dht.MonitorGetMessage 31org.gnunet.util.GnunetMessage$Body|149=org.gnunet.dht.MonitorGetMessage
27org.gnunet.util.GnunetMessage$Body|150=org.gnunet.dht.MonitorGetRespMessage 32org.gnunet.util.GnunetMessage$Body|150=org.gnunet.dht.MonitorGetRespMessage
28org.gnunet.util.GnunetMessage$Body|151=org.gnunet.dht.MonitorPutMessage 33org.gnunet.util.GnunetMessage$Body|151=org.gnunet.dht.MonitorPutMessage
34org.gnunet.util.GnunetMessage$Body|42012=org.gnunet.voting.messages.BallotRegisterSuccessMessage
29org.gnunet.util.GnunetMessage$Body|171=org.gnunet.statistics.GetResponseEndMessage 35org.gnunet.util.GnunetMessage$Body|171=org.gnunet.statistics.GetResponseEndMessage
30org.gnunet.util.GnunetMessage$Body|170=org.gnunet.statistics.GetResponseMessage 36org.gnunet.util.GnunetMessage$Body|170=org.gnunet.statistics.GetResponseMessage
31org.gnunet.util.GnunetMessage$Body|169=org.gnunet.statistics.GetMessage 37org.gnunet.util.GnunetMessage$Body|169=org.gnunet.statistics.GetMessage
@@ -57,9 +63,17 @@ org.gnunet.util.GnunetMessage$Body|74=org.gnunet.core.SendMessageRequest
57org.gnunet.util.GnunetMessage$Body|464=org.gnunet.testbed.messages.PeerCreateMessage 63org.gnunet.util.GnunetMessage$Body|464=org.gnunet.testbed.messages.PeerCreateMessage
58org.gnunet.util.GnunetMessage$Body|75=org.gnunet.core.SendMessageReady 64org.gnunet.util.GnunetMessage$Body|75=org.gnunet.core.SendMessageReady
59org.gnunet.util.GnunetMessage$Body|465=org.gnunet.testbed.messages.PeerReconfigureMessage 65org.gnunet.util.GnunetMessage$Body|465=org.gnunet.testbed.messages.PeerReconfigureMessage
66org.gnunet.util.GnunetMessage$Body|627=org.gnunet.identity.messages.GetDefaultMessage
67org.gnunet.util.GnunetMessage$Body|626=org.gnunet.identity.messages.UpdateListMessage
68org.gnunet.util.GnunetMessage$Body|625=org.gnunet.identity.messages.ResultCodeMessage
60org.gnunet.util.GnunetMessage$Body|460=org.gnunet.testbed.messages.ControllerInitMessage 69org.gnunet.util.GnunetMessage$Body|460=org.gnunet.testbed.messages.ControllerInitMessage
70org.gnunet.util.GnunetMessage$Body|624=org.gnunet.identity.messages.StartMessage
71org.gnunet.util.GnunetMessage$Body|631=org.gnunet.identity.messages.DeleteMessage
72org.gnunet.util.GnunetMessage$Body|630=org.gnunet.identity.messages.RenameMessage
61org.gnunet.util.GnunetMessage$Body|323=org.gnunet.nse.UpdateMessage 73org.gnunet.util.GnunetMessage$Body|323=org.gnunet.nse.UpdateMessage
74org.gnunet.util.GnunetMessage$Body|629=org.gnunet.identity.messages.CreateRequestMessage
62org.gnunet.util.GnunetMessage$Body|321=org.gnunet.nse.StartMessage 75org.gnunet.util.GnunetMessage$Body|321=org.gnunet.nse.StartMessage
76org.gnunet.util.GnunetMessage$Body|628=org.gnunet.identity.messages.SetDefaultMessage
63org.gnunet.util.GnunetMessage$Body|332=org.gnunet.peerinfo.InfoMessage 77org.gnunet.util.GnunetMessage$Body|332=org.gnunet.peerinfo.InfoMessage
64org.gnunet.util.GnunetMessage$Body|333=org.gnunet.peerinfo.InfoEnd 78org.gnunet.util.GnunetMessage$Body|333=org.gnunet.peerinfo.InfoEnd
65org.gnunet.util.GnunetMessage$Body|331=org.gnunet.peerinfo.ListAllPeersMessage 79org.gnunet.util.GnunetMessage$Body|331=org.gnunet.peerinfo.ListAllPeersMessage
@@ -73,4 +87,4 @@ org.gnunet.util.GnunetMessage$Body|495=org.gnunet.testbed.messages.HelperInitMes
73org.gnunet.util.GnunetMessage$Body|360=org.gnunet.transport.StartMessage 87org.gnunet.util.GnunetMessage$Body|360=org.gnunet.transport.StartMessage
74org.gnunet.util.GnunetMessage$Body|483=org.gnunet.testbed.messages.ManagePeerServiceMessage 88org.gnunet.util.GnunetMessage$Body|483=org.gnunet.testbed.messages.ManagePeerServiceMessage
75org.gnunet.construct.MessageUnion|525=org.gnunet.consensus.ConcludeDoneMessage 89org.gnunet.construct.MessageUnion|525=org.gnunet.consensus.ConcludeDoneMessage
76# generated 2013/09/25 01:34:20 90# generated 2013/10/08 22:01:30
diff --git a/src/main/resources/org/gnunet/voting/template.espec b/src/main/resources/org/gnunet/voting/template.espec
index 292887a..9af5a79 100644
--- a/src/main/resources/org/gnunet/voting/template.espec
+++ b/src/main/resources/org/gnunet/voting/template.espec
@@ -9,20 +9,23 @@ TOPIC =
9# choices for the voter, separated by a double slash 9# choices for the voter, separated by a double slash
10CHOICES = yes//no 10CHOICES = yes//no
11 11
12# group of elegible voters, voters must be certified by the CA to
13# belong to this group
14GROUP =
15
12# starting time of the election, in the local time of the election issuer 16# starting time of the election, in the local time of the election issuer
13# authorities affirm that they are available for the election from this point in time 17# authorities affirm that they are available for the election from this point in time
14ELECTION_START = 18TIME_START =
15 19
16# election start time, as posix time stamp 20# what is the deadline for vote submission?
17# ELECTION_START_POSIX 21# after this deadline, authorities work together to count ballots
22TIME_CLOSING =
18 23
19# deadline for vote submission, in the local time of the election issuer 24# when may results be queried?
20# must be later than ELECTION_START 25TIME_QUERY =
21ELECTION_END =
22 26
23# At what time must an authority complete round X of the voting protocol 27# FIXME: specify more parameters for consensus? which ones?
24# (fixme: need to define exactly which rounds there will be...) 28# CONSENSUS_PARAMETERS =
25AUTHORITY_ROUND_X_TIME =
26 29
27# public key of the certificate authority 30# public key of the certificate authority
28CA_PUB = 31CA_PUB =
@@ -48,14 +51,8 @@ CA_PUB =
48# ISSUER_SIGNATURE = 51# ISSUER_SIGNATURE =
49 52
50 53
51[voter] 54[vote]
52# before a voter can submit his vote, the permission to do so 55# voter signature, pubkey, group cert,
53# must be given by the certificate authority of the election
54# VOTER_PUB = ...
55# VOTER_CERT = ...
56
57
58[vote-data]
59# encrypted vote and non-interactive zero knowledge proofs come here 56# encrypted vote and non-interactive zero knowledge proofs come here
60 57
61 58
diff --git a/src/test/java/org/gnunet/identity/IdentityTest.java b/src/test/java/org/gnunet/identity/IdentityTest.java
new file mode 100644
index 0000000..cda4e6b
--- /dev/null
+++ b/src/test/java/org/gnunet/identity/IdentityTest.java
@@ -0,0 +1,123 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21package org.gnunet.identity;
22
23
24import org.gnunet.testing.TestingSubsystem;
25import org.gnunet.util.Program;
26import org.gnunet.util.Scheduler;
27import org.gnunet.util.Wrapper;
28import org.junit.Assert;
29import org.junit.Test;
30
31public class IdentityTest {
32 @Test
33 public void test_identity_connect() {
34 final Wrapper<Boolean> reachedEnd = new Wrapper<Boolean>(false);
35 Program.configureLogging("DEBUG");
36 TestingSubsystem ts = new TestingSubsystem("identity");
37
38 final Identity identity = new Identity();
39 identity.connect(ts.getConfiguration(), new IdentityListCallback() {
40 @Override
41 public void onEgoAdd(Identity.Ego ego) {
42 System.out.println("got ego " + ego.getName());
43 }
44
45 @Override
46 public void onEgoDelete(Identity.Ego ego) {
47 // should only happen after end of list,
48 // but we disconnect on end of list
49 Assert.fail();
50 }
51
52 @Override
53 public void onEgoRename(String oldName, Identity.Ego ego) {
54 Assert.fail();
55 }
56
57 @Override
58 public void onListEnd() {
59 System.out.println("got end of list");
60 reachedEnd.set(true);
61 identity.disconnect();
62 }
63 });
64 Scheduler.run();
65 Assert.assertTrue(reachedEnd.get());
66 }
67
68 @Test
69 public void test_identity_create() {
70 final Wrapper<Boolean> created = new Wrapper<Boolean>(false);
71 final Wrapper<Boolean> gotEnd = new Wrapper<Boolean>(false);
72 final Wrapper<Boolean> gotCreated = new Wrapper<Boolean>(false);
73 Program.configureLogging("DEBUG");
74 TestingSubsystem ts = new TestingSubsystem("identity");
75
76 final String myEgoName = "gnunet-java-test-ego";
77
78 final Identity identity = new Identity();
79 identity.connect(ts.getConfiguration(), new IdentityListCallback() {
80 @Override
81 public void onEgoAdd(Identity.Ego ego) {
82 if (created.get() && ego.getName().equals(myEgoName)) {
83 gotCreated.set(true);
84 identity.disconnect();
85 }
86 }
87
88 @Override
89 public void onEgoDelete(Identity.Ego ego) {
90 // should only happen after end of list,
91 // but we disconnect on end of list
92 Assert.fail();
93 }
94
95 @Override
96 public void onEgoRename(String oldName, Identity.Ego ego) {
97 Assert.fail();
98 }
99
100 @Override
101 public void onListEnd() {
102 System.out.println("got end of list");
103 gotEnd.set(true);
104 }
105 });
106 identity.create(myEgoName, new IdentityContinuation() {
107 @Override
108 public void onError(String errorMessage) {
109 Assert.fail(errorMessage);
110 }
111
112 @Override
113 public void onDone() {
114 Assert.assertFalse(created.get());
115 created.set(true);
116 }
117 });
118 Scheduler.run();
119 Assert.assertTrue(created.get());
120 Assert.assertTrue(gotCreated.get());
121 Assert.assertTrue(gotEnd.get());
122 }
123}
diff --git a/src/test/java/org/gnunet/testbed/TestbedTest.java b/src/test/java/org/gnunet/testbed/TestbedTest.java
index 56febde..6a6ed10 100644
--- a/src/test/java/org/gnunet/testbed/TestbedTest.java
+++ b/src/test/java/org/gnunet/testbed/TestbedTest.java
@@ -12,7 +12,7 @@ import org.junit.Test;
12 12
13public class TestbedTest extends TestingFixture { 13public class TestbedTest extends TestingFixture {
14 14
15 @Test(timeout = 1000) 15 @Test(timeout = 10000)
16 public void test_controller_proc() { 16 public void test_controller_proc() {
17 final Wrapper<Boolean> success = new Wrapper<Boolean>(false); 17 final Wrapper<Boolean> success = new Wrapper<Boolean>(false);
18 new Program("-LDEBUG") { 18 new Program("-LDEBUG") {
@@ -38,16 +38,13 @@ public class TestbedTest extends TestingFixture {
38 } 38 }
39 39
40 40
41 @Test(timeout = 1000) 41 @Test(timeout = 10000)
42 public void test_peer_create() { 42 public void test_peer_create() {
43 new Program("-LDEBUG") { 43 new Program("-LDEBUG") {
44 ControllerProc cp; 44 ControllerProc cp;
45 Host h; 45 Host h;
46 Controller c; 46 Controller c;
47 47
48 class CEC extends ControllerEventCallback {
49 }
50
51 class PCB implements PeerCreateCallback { 48 class PCB implements PeerCreateCallback {
52 @Override 49 @Override
53 public void onPeerCreated(Controller.Peer peer) { 50 public void onPeerCreated(Controller.Peer peer) {
@@ -71,7 +68,7 @@ public class TestbedTest extends TestingFixture {
71 @Override 68 @Override
72 public void onStartupSuccess(Configuration cfg) { 69 public void onStartupSuccess(Configuration cfg) {
73 System.out.println("startup success"); 70 System.out.println("startup success");
74 c = new Controller(h, 1 | 2 | 4 | 8 | 32, new CEC()); 71 c = new Controller(h);
75 // FIXME: use config from resource 72 // FIXME: use config from resource
76 c.createPeer(h, getConfiguration(), new PCB()); 73 c.createPeer(h, getConfiguration(), new PCB());
77 } 74 }
@@ -84,16 +81,13 @@ public class TestbedTest extends TestingFixture {
84 }.start(); 81 }.start();
85 } 82 }
86 83
87 @Test(timeout = 1000) 84 @Test(timeout = 10000)
88 public void test_peer_destroy() { 85 public void test_peer_destroy() {
89 new Program("-LDEBUG") { 86 new Program("-LDEBUG") {
90 ControllerProc cp; 87 ControllerProc cp;
91 Host h; 88 Host h;
92 Controller c; 89 Controller c;
93 90
94 class CEC extends ControllerEventCallback {
95 }
96
97 class PCB implements PeerCreateCallback { 91 class PCB implements PeerCreateCallback {
98 @Override 92 @Override
99 public void onPeerCreated(final Controller.Peer peer) { 93 public void onPeerCreated(final Controller.Peer peer) {
@@ -128,7 +122,7 @@ public class TestbedTest extends TestingFixture {
128 @Override 122 @Override
129 public void onStartupSuccess(Configuration cfg) { 123 public void onStartupSuccess(Configuration cfg) {
130 System.out.println("startup success"); 124 System.out.println("startup success");
131 c = new Controller(h, 1 | 2 | 4 | 8 | 32, new CEC()); 125 c = new Controller(h);
132 // FIXME: use config from resource 126 // FIXME: use config from resource
133 c.createPeer(h, getConfiguration(), new PCB()); 127 c.createPeer(h, getConfiguration(), new PCB());
134 } 128 }
@@ -141,7 +135,7 @@ public class TestbedTest extends TestingFixture {
141 }.start(); 135 }.start();
142 } 136 }
143 137
144 @Test(timeout = 5000) 138 @Test(timeout = 10000)
145 public void test_peer_start() { 139 public void test_peer_start() {
146 final Wrapper<Boolean> startSuccessful = new Wrapper<Boolean>(false); 140 final Wrapper<Boolean> startSuccessful = new Wrapper<Boolean>(false);
147 int ret = new Program("-LDEBUG") { 141 int ret = new Program("-LDEBUG") {
@@ -149,9 +143,6 @@ public class TestbedTest extends TestingFixture {
149 Host h; 143 Host h;
150 Controller c; 144 Controller c;
151 145
152 class CEC extends ControllerEventCallback {
153 }
154
155 class MyPeerChurnCallback implements PeerChurnCallback { 146 class MyPeerChurnCallback implements PeerChurnCallback {
156 147
157 @Override 148 @Override
@@ -190,7 +181,7 @@ public class TestbedTest extends TestingFixture {
190 @Override 181 @Override
191 public void onStartupSuccess(Configuration cfg) { 182 public void onStartupSuccess(Configuration cfg) {
192 System.out.println("controller started"); 183 System.out.println("controller started");
193 c = new Controller(h, 1 | 2 | 4 | 8 | 32, new CEC()); 184 c = new Controller(h);
194 // FIXME: use config from resource 185 // FIXME: use config from resource
195 c.createPeer(h, getConfiguration(), new MyPeerCreateCallback()); 186 c.createPeer(h, getConfiguration(), new MyPeerCreateCallback());
196 } 187 }
@@ -205,7 +196,7 @@ public class TestbedTest extends TestingFixture {
205 Assert.assertEquals(0, ret); 196 Assert.assertEquals(0, ret);
206 } 197 }
207 198
208 @Test(timeout = 5000) 199 @Test(timeout = 10000)
209 public void test_peer_stop() { 200 public void test_peer_stop() {
210 final Wrapper<Boolean> startSuccessful = new Wrapper<Boolean>(false); 201 final Wrapper<Boolean> startSuccessful = new Wrapper<Boolean>(false);
211 final Wrapper<Boolean> stopSuccessful = new Wrapper<Boolean>(false); 202 final Wrapper<Boolean> stopSuccessful = new Wrapper<Boolean>(false);
@@ -215,9 +206,6 @@ public class TestbedTest extends TestingFixture {
215 Controller c; 206 Controller c;
216 Controller.Peer p; 207 Controller.Peer p;
217 208
218 class CEC extends ControllerEventCallback {
219 }
220
221 class MyPeerStopCallback implements PeerChurnCallback { 209 class MyPeerStopCallback implements PeerChurnCallback {
222 210
223 @Override 211 @Override
@@ -271,7 +259,7 @@ public class TestbedTest extends TestingFixture {
271 @Override 259 @Override
272 public void onStartupSuccess(Configuration cfg) { 260 public void onStartupSuccess(Configuration cfg) {
273 System.out.println("controller started"); 261 System.out.println("controller started");
274 c = new Controller(h, 1 | 2 | 4 | 8 | 32, new CEC()); 262 c = new Controller(h);
275 // FIXME: use config from resource 263 // FIXME: use config from resource
276 c.createPeer(h, getConfiguration(), new MyPeerCreateCallback()); 264 c.createPeer(h, getConfiguration(), new MyPeerCreateCallback());
277 } 265 }
@@ -287,7 +275,7 @@ public class TestbedTest extends TestingFixture {
287 Assert.assertEquals(0, ret); 275 Assert.assertEquals(0, ret);
288 } 276 }
289 277
290 @Test(timeout = 5000) 278 @Test(timeout = 10000)
291 public void test_peer_stop_destroy() { 279 public void test_peer_stop_destroy() {
292 final Wrapper<Boolean> startSuccessful = new Wrapper<Boolean>(false); 280 final Wrapper<Boolean> startSuccessful = new Wrapper<Boolean>(false);
293 final Wrapper<Boolean> stopSuccessful = new Wrapper<Boolean>(false); 281 final Wrapper<Boolean> stopSuccessful = new Wrapper<Boolean>(false);
@@ -298,9 +286,6 @@ public class TestbedTest extends TestingFixture {
298 Controller c; 286 Controller c;
299 Controller.Peer p; 287 Controller.Peer p;
300 288
301 class CEC extends ControllerEventCallback {
302 }
303
304 class MyPeerDestroyCallback implements OperationCompletionCallback { 289 class MyPeerDestroyCallback implements OperationCompletionCallback {
305 290
306 @Override 291 @Override
@@ -367,7 +352,7 @@ public class TestbedTest extends TestingFixture {
367 @Override 352 @Override
368 public void onStartupSuccess(Configuration cfg) { 353 public void onStartupSuccess(Configuration cfg) {
369 System.out.println("controller started"); 354 System.out.println("controller started");
370 c = new Controller(h, 1 | 2 | 4 | 8 | 32, new CEC()); 355 c = new Controller(h);
371 // FIXME: use config from resource 356 // FIXME: use config from resource
372 c.createPeer(h, getConfiguration(), new MyPeerCreateCallback()); 357 c.createPeer(h, getConfiguration(), new MyPeerCreateCallback());
373 } 358 }
@@ -394,9 +379,6 @@ public class TestbedTest extends TestingFixture {
394 Controller c; 379 Controller c;
395 Controller.Peer p; 380 Controller.Peer p;
396 381
397 class CEC extends ControllerEventCallback {
398 }
399
400 class MyPeerInformationCallback implements PeerInformationCallback { 382 class MyPeerInformationCallback implements PeerInformationCallback {
401 @Override 383 @Override
402 public void onSuccess(PeerIdentity peerIdentity, Configuration configuration) { 384 public void onSuccess(PeerIdentity peerIdentity, Configuration configuration) {
@@ -433,7 +415,7 @@ public class TestbedTest extends TestingFixture {
433 @Override 415 @Override
434 public void onStartupSuccess(Configuration cfg) { 416 public void onStartupSuccess(Configuration cfg) {
435 System.out.println("controller started"); 417 System.out.println("controller started");
436 c = new Controller(h, 1 | 2 | 4 | 8 | 32, new CEC()); 418 c = new Controller(h);
437 // FIXME: use config from resource 419 // FIXME: use config from resource
438 c.createPeer(h, getConfiguration(), new MyPeerCreateCallback()); 420 c.createPeer(h, getConfiguration(), new MyPeerCreateCallback());
439 } 421 }
@@ -449,10 +431,9 @@ public class TestbedTest extends TestingFixture {
449 Assert.assertEquals(0, ret); 431 Assert.assertEquals(0, ret);
450 } 432 }
451 433
452 @Test(timeout = 5000) 434 @Test
453 public void test_peer_reconfigure() { 435 public void test_peer_reconfigure() {
454 final Wrapper<Boolean> startSuccessful = new Wrapper<Boolean>(false); 436 final Wrapper<Boolean> startSuccessful = new Wrapper<Boolean>(false);
455 final Wrapper<Boolean> infoSuccessful = new Wrapper<Boolean>(false);
456 final Wrapper<Boolean> reconfigureSuccessful = new Wrapper<Boolean>(false); 437 final Wrapper<Boolean> reconfigureSuccessful = new Wrapper<Boolean>(false);
457 int ret = new Program("-LDEBUG") { 438 int ret = new Program("-LDEBUG") {
458 ControllerProc cp; 439 ControllerProc cp;
@@ -460,9 +441,6 @@ public class TestbedTest extends TestingFixture {
460 Controller c; 441 Controller c;
461 Controller.Peer p; 442 Controller.Peer p;
462 443
463 class CEC extends ControllerEventCallback {
464 }
465
466 class MyUpdateConfigDoneCallback implements OperationCompletionCallback { 444 class MyUpdateConfigDoneCallback implements OperationCompletionCallback {
467 @Override 445 @Override
468 public void onCompletion() { 446 public void onCompletion() {
@@ -478,30 +456,15 @@ public class TestbedTest extends TestingFixture {
478 } 456 }
479 } 457 }
480 458
481 /*
482 class MyPeerInformationCallback implements PeerInformationCallback {
483 @Override
484 public void onSuccess(PeerIdentity peerIdentity, Configuration configuration) {
485 Assert.assertNotNull(peerIdentity);
486 Assert.assertNotNull(configuration);
487 Assert.assertTrue(configuration.getSections().size() > 0);
488 infoSuccessful.set(true);
489 System.out.println("updating configuration");
490 p.updateConfiguration(cfg, new MyUpdateConfigDoneCallback());
491 }
492 }
493
494 */
495
496 class MyPeerCreateCallback implements PeerCreateCallback { 459 class MyPeerCreateCallback implements PeerCreateCallback {
497 @Override 460 @Override
498 public void onPeerCreated(Controller.Peer peer) { 461 public void onPeerCreated(Controller.Peer peer) {
499 p = peer; 462 p = peer;
500 System.out.println("peer created"); 463 System.out.println("peer created");
501 startSuccessful.set(true); 464 startSuccessful.set(true);
502 //peer.requestInformation(new MyPeerInformationCallback());
503 465
504 Configuration cfg = new Configuration(); 466 Configuration cfg = new Configuration();
467 cfg.setValueNumber("foo", "bar", 42);
505 cfg.setValueString("my-test-section", "my-test-option", "my-test-value"); 468 cfg.setValueString("my-test-section", "my-test-option", "my-test-value");
506 peer.updateConfiguration(cfg, new MyUpdateConfigDoneCallback()); 469 peer.updateConfiguration(cfg, new MyUpdateConfigDoneCallback());
507 } 470 }
@@ -522,7 +485,7 @@ public class TestbedTest extends TestingFixture {
522 @Override 485 @Override
523 public void onStartupSuccess(Configuration cfg) { 486 public void onStartupSuccess(Configuration cfg) {
524 System.out.println("controller started"); 487 System.out.println("controller started");
525 c = new Controller(h, 1 | 2 | 4 | 8 | 32, new CEC()); 488 c = new Controller(h);
526 // FIXME: use config from resource 489 // FIXME: use config from resource
527 c.createPeer(h, configuration, new MyPeerCreateCallback()); 490 c.createPeer(h, configuration, new MyPeerCreateCallback());
528 } 491 }
@@ -549,9 +512,6 @@ public class TestbedTest extends TestingFixture {
549 Controller.Peer p1; 512 Controller.Peer p1;
550 int peersStarted = 0; 513 int peersStarted = 0;
551 514
552 class CEC extends ControllerEventCallback {
553 }
554
555 class MyConnectCompleteCallback implements OperationCompletionCallback { 515 class MyConnectCompleteCallback implements OperationCompletionCallback {
556 516
557 @Override 517 @Override
@@ -620,7 +580,7 @@ public class TestbedTest extends TestingFixture {
620 @Override 580 @Override
621 public void onStartupSuccess(Configuration cfg) { 581 public void onStartupSuccess(Configuration cfg) {
622 System.out.println("controller started"); 582 System.out.println("controller started");
623 c = new Controller(h, 1 | 2 | 4 | 8 | 32, new CEC()); 583 c = new Controller(h);
624 // FIXME: use config from resource 584 // FIXME: use config from resource
625 c.createPeer(h, getConfiguration(), new MyPeerCreateCallback(0)); 585 c.createPeer(h, getConfiguration(), new MyPeerCreateCallback(0));
626 c.createPeer(h, getConfiguration(), new MyPeerCreateCallback(1)); 586 c.createPeer(h, getConfiguration(), new MyPeerCreateCallback(1));
diff --git a/src/test/java/org/gnunet/util/CryptoECCTest.java b/src/test/java/org/gnunet/util/CryptoECCTest.java
index c4c85d2..1dda545 100644
--- a/src/test/java/org/gnunet/util/CryptoECCTest.java
+++ b/src/test/java/org/gnunet/util/CryptoECCTest.java
@@ -21,7 +21,7 @@ public class CryptoECCTest {
21 CryptoECC.PrivateKey privateKey = new CryptoECC.PrivateKey(); 21 CryptoECC.PrivateKey privateKey = new CryptoECC.PrivateKey();
22 privateKey.d = new byte[32]; 22 privateKey.d = new byte[32];
23 r.nextBytes(privateKey.d); 23 r.nextBytes(privateKey.d);
24 CryptoECC.PublicKey publicKey = CryptoECC.computePublicKey(privateKey); 24 CryptoECC.PublicSignKey publicKey = CryptoECC.computePublicKey(privateKey);
25 System.out.println("gen"); 25 System.out.println("gen");
26 CryptoECC.Signature sig = CryptoECC.sign(msg, privateKey, publicKey); 26 CryptoECC.Signature sig = CryptoECC.sign(msg, privateKey, publicKey);
27 System.out.println("sign"); 27 System.out.println("sign");
@@ -44,7 +44,7 @@ public class CryptoECCTest {
44 CryptoECC.PrivateKey privateKey = new CryptoECC.PrivateKey(); 44 CryptoECC.PrivateKey privateKey = new CryptoECC.PrivateKey();
45 privateKey.d = new byte[32]; 45 privateKey.d = new byte[32];
46 r.nextBytes(privateKey.d); 46 r.nextBytes(privateKey.d);
47 CryptoECC.PublicKey publicKey = CryptoECC.computePublicKey(privateKey); 47 CryptoECC.PublicSignKey publicKey = CryptoECC.computePublicKey(privateKey);
48 System.out.println("gen"); 48 System.out.println("gen");
49 CryptoECC.Signature sig = CryptoECC.sign(msg, privateKey, publicKey); 49 CryptoECC.Signature sig = CryptoECC.sign(msg, privateKey, publicKey);
50 System.out.println("sign"); 50 System.out.println("sign");
@@ -66,12 +66,12 @@ public class CryptoECCTest {
66 CryptoECC.PrivateKey privateAlice = new CryptoECC.PrivateKey(); 66 CryptoECC.PrivateKey privateAlice = new CryptoECC.PrivateKey();
67 privateAlice.d = new byte[32]; 67 privateAlice.d = new byte[32];
68 r.nextBytes(privateAlice.d); 68 r.nextBytes(privateAlice.d);
69 CryptoECC.PublicKey publicAlice = CryptoECC.computePublicKey(privateAlice); 69 CryptoECC.PublicSignKey publicAlice = CryptoECC.computePublicKey(privateAlice);
70 70
71 CryptoECC.PrivateKey privateBob = new CryptoECC.PrivateKey(); 71 CryptoECC.PrivateKey privateBob = new CryptoECC.PrivateKey();
72 privateBob.d = new byte[32]; 72 privateBob.d = new byte[32];
73 r.nextBytes(privateBob.d); 73 r.nextBytes(privateBob.d);
74 CryptoECC.PublicKey publicBob = CryptoECC.computePublicKey(privateBob); 74 CryptoECC.PublicSignKey publicBob = CryptoECC.computePublicKey(privateBob);
75 75
76 HashCode ssAlice = CryptoECC.ecdh(privateAlice, publicBob); 76 HashCode ssAlice = CryptoECC.ecdh(privateAlice, publicBob);
77 HashCode ssBob = CryptoECC.ecdh(privateBob, publicAlice); 77 HashCode ssBob = CryptoECC.ecdh(privateBob, publicAlice);