aboutsummaryrefslogtreecommitdiff
path: root/src/org/gnunet/util/Service.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/gnunet/util/Service.java')
-rw-r--r--src/org/gnunet/util/Service.java97
1 files changed, 68 insertions, 29 deletions
diff --git a/src/org/gnunet/util/Service.java b/src/org/gnunet/util/Service.java
index bbbba00..69742b6 100644
--- a/src/org/gnunet/util/Service.java
+++ b/src/org/gnunet/util/Service.java
@@ -29,14 +29,21 @@ import java.net.Inet4Address;
29import java.net.InetAddress; 29import java.net.InetAddress;
30import java.net.InetSocketAddress; 30import java.net.InetSocketAddress;
31import java.net.SocketAddress; 31import java.net.SocketAddress;
32import java.nio.ByteBuffer;
32import java.nio.channels.Channel; 33import java.nio.channels.Channel;
33import java.nio.channels.FileChannel; 34import java.nio.channels.FileChannel;
35import java.nio.channels.Pipe;
34import java.nio.channels.SelectableChannel; 36import java.nio.channels.SelectableChannel;
35import java.util.LinkedList; 37import java.util.LinkedList;
36 38
37/** 39/**
38 * Server the entry point class for every gnunet-java component providing services 40 * Server the entry point class for every gnunet-java component providing services
39 * to other components. 41 * to other components.
42 *
43 * The configuration for the server (i.e. ports/interfaces) is loaded with the standard configuration system.
44 *
45 * Note that other processes can send signals to the service via a pipe, whose name has to be given in the
46 * environment variable GNUNET_OS_CONTROL_PIPE
40 */ 47 */
41public abstract class Service extends Program { 48public abstract class Service extends Program {
42 private static final Logger logger = LoggerFactory 49 private static final Logger logger = LoggerFactory
@@ -47,8 +54,9 @@ public abstract class Service extends Program {
47 private RelativeTime idleTimeout; 54 private RelativeTime idleTimeout;
48 private boolean requireFound; 55 private boolean requireFound;
49 56
57
50 private Cancelable sigpipeTask; 58 private Cancelable sigpipeTask;
51 private SelectableChannel sigpipeChannel; 59 private Pipe.SourceChannel sigpipeChannel;
52 60
53 public Service(String serviceName, RelativeTime idleTimeout, boolean requireFound, String[] args) { 61 public Service(String serviceName, RelativeTime idleTimeout, boolean requireFound, String[] args) {
54 super(args); 62 super(args);
@@ -57,63 +65,94 @@ public abstract class Service extends Program {
57 this.requireFound = requireFound; 65 this.requireFound = requireFound;
58 } 66 }
59 67
60 68 /**
69 * Obtain the server used by a service. Note that the server must NOT
70 * be destroyed by the caller.
71 *
72 * @return handle to the server for this service, NULL if there is none
73 */
61 public final Server getServer() { 74 public final Server getServer() {
62 return s; 75 return s;
63 } 76 }
64 77
78 /**
79 * Stop the service.
80 */
65 public void stop() { 81 public void stop() {
66 82 s.stopListening();
67 } 83 }
68 84
69 public void start() { 85 public void runHook() {
70 super.start();
71 String ip4AddrList = getConfiguration().getValueString(serviceName, "ACCEPT_FROM"); 86 String ip4AddrList = getConfiguration().getValueString(serviceName, "ACCEPT_FROM");
72 String ip6AddrList = getConfiguration().getValueString(serviceName, "ACCEPT_FROM6"); 87 String ip6AddrList = getConfiguration().getValueString(serviceName, "ACCEPT_FROM6");
73 int port = (int) getConfiguration().getValueNumer(serviceName, "PORT"); 88 int port = (int) getConfiguration().getValueNumer(serviceName, "PORT");
74 89
75 LinkedList<SocketAddress> addrs = new LinkedList<SocketAddress>(); 90 LinkedList<SocketAddress> addrs = new LinkedList<SocketAddress>();
76 91
77 for (String ip4Addr : ip4AddrList.split("[;]")) { 92 if (ip4AddrList != null) {
78 InetAddress addr = Resolver.getInetAddressFromString(ip4Addr); 93 for (String ip4Addr : ip4AddrList.split("[;]")) {
79 addrs.add(new InetSocketAddress(addr, port)); 94 InetAddress addr = Resolver.getInetAddressFromString(ip4Addr);
95 addrs.add(new InetSocketAddress(addr, port));
96 }
80 } 97 }
81 98
82 for (String ip6Addr : ip6AddrList.split("[;]")) { 99 if (ip6AddrList != null) {
83 InetAddress addr = Resolver.getInetAddressFromString(ip6Addr); 100 for (String ip6Addr : ip6AddrList.split("[;]")) {
84 addrs.add(new InetSocketAddress(addr, port)); 101 InetAddress addr = Resolver.getInetAddressFromString(ip6Addr);
102 addrs.add(new InetSocketAddress(addr, port));
103 }
85 } 104 }
86 105
87 s = new Server(addrs, idleTimeout, requireFound); 106 s = new Server(addrs, idleTimeout, requireFound);
88 107
89 String pipeName = System.getenv("GNUNET_OS_CONTROL_PIPE"); 108 String pipeName = System.getenv("GNUNET_OS_CONTROL_PIPE");
90 if (pipeName != null) { 109 if (pipeName != null && !pipeName.isEmpty()) {
91 logger.debug("service started with control pipe"); 110 Scheduler.FilePipe p = Scheduler.openFilePipe(new File(pipeName));
92 FileChannel f;
93 try {
94 f = (new FileInputStream(pipeName)).getChannel();
95 } catch (FileNotFoundException e) {
96 logger.error("could not open control pipe");
97 }
98 111
99 Scheduler.TaskConfiguration t = new Scheduler.TaskConfiguration(RelativeTime.FOREVER, 112 Scheduler.TaskConfiguration t = new Scheduler.TaskConfiguration(RelativeTime.FOREVER,
100 new SigpipeTask()); 113 new SigpipeTask());
114 t.selectRead(p.getSource());
101 sigpipeTask = t.schedule(); 115 sigpipeTask = t.schedule();
116 sigpipeChannel = p.getSource();
102 } 117 }
103 }
104 118
105 public class SigpipeTask implements Scheduler.Task { 119 run();
120 }
106 121
122 private class SigpipeTask implements Scheduler.Task {
107 @Override 123 @Override
108 public void run(Scheduler.RunContext ctx) { 124 public void run(Scheduler.RunContext ctx) {
109 Scheduler.TaskConfiguration t = new Scheduler.TaskConfiguration(RelativeTime.FOREVER, 125 ByteBuffer b = ByteBuffer.allocate(1);
110 new SigpipeTask()); 126 int n;
111 sigpipeTask = t.schedule(); 127 try {
128 n = sigpipeChannel.read(b);
129 } catch (IOException e) {
130 logger.error("error reading signal pipe", e);
131 return;
132 }
133 b.flip();
134 boolean stopped = false;
135
136 if (n == 1) {
137 byte sig = b.get();
138 // 15=sigterm
139 if (sig == 15) {
140 logger.info("service shutting down");
141 getServer().stopListening();
142 stopped = true;
143 }
144 }
145 if (!stopped) {
146 Scheduler.TaskConfiguration t = new Scheduler.TaskConfiguration(RelativeTime.FOREVER, this);
147 sigpipeTask = t.schedule();
148 } else {
149 try {
150 sigpipeChannel.close();
151 } catch (IOException e) {
152 logger.error("could not close sigpipe channel, quitting");
153 System.exit(2);
154 }
155 }
112 } 156 }
113 } 157 }
114
115 /**
116 * Override to implement the behavior of the Program.
117 */
118 public abstract void run();
119} \ No newline at end of file 158} \ No newline at end of file