diff options
Diffstat (limited to 'src/org/gnunet/util/Service.java')
-rw-r--r-- | src/org/gnunet/util/Service.java | 97 |
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; | |||
29 | import java.net.InetAddress; | 29 | import java.net.InetAddress; |
30 | import java.net.InetSocketAddress; | 30 | import java.net.InetSocketAddress; |
31 | import java.net.SocketAddress; | 31 | import java.net.SocketAddress; |
32 | import java.nio.ByteBuffer; | ||
32 | import java.nio.channels.Channel; | 33 | import java.nio.channels.Channel; |
33 | import java.nio.channels.FileChannel; | 34 | import java.nio.channels.FileChannel; |
35 | import java.nio.channels.Pipe; | ||
34 | import java.nio.channels.SelectableChannel; | 36 | import java.nio.channels.SelectableChannel; |
35 | import java.util.LinkedList; | 37 | import 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 | */ |
41 | public abstract class Service extends Program { | 48 | public 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 |