1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.newsclub.net.unix;
19
20 import java.io.Closeable;
21 import java.io.FileDescriptor;
22 import java.io.IOException;
23 import java.nio.ByteBuffer;
24 import java.nio.channels.Pipe;
25 import java.nio.channels.spi.SelectorProvider;
26
27 import com.kohlschutter.annotations.compiletime.SuppressFBWarnings;
28
29
30
31
32
33
34 public final class AFPipe extends Pipe implements Closeable {
35 static final AFSupplier<Integer> DUMMY_TIMEOUT = () -> 0;
36 private final AFCore sourceCore;
37 private final AFCore sinkCore;
38 private final SourceChannel sourceChannel;
39 private final SinkChannel sinkChannel;
40 private final int options;
41
42 AFPipe(AFSelectorProvider<?> provider, boolean selectable) throws IOException {
43 super();
44
45 NativeUnixSocket.ensureSupported();
46
47 this.sourceCore = new AFCore(this, (FileDescriptor) null);
48 this.sinkCore = new AFCore(this, (FileDescriptor) null);
49
50 boolean isSocket = NativeUnixSocket.initPipe(sourceCore.fd, sinkCore.fd, selectable);
51 this.options = isSocket ? 0 : NativeUnixSocket.OPT_NON_SOCKET;
52
53 this.sourceChannel = new SourceChannel(provider);
54 this.sinkChannel = new SinkChannel(provider);
55 }
56
57 @SuppressFBWarnings("EI_EXPOSE_REP")
58 @Override
59 public SourceChannel source() {
60 return sourceChannel;
61 }
62
63 @SuppressFBWarnings("EI_EXPOSE_REP")
64 @Override
65 public SinkChannel sink() {
66 return sinkChannel;
67 }
68
69 FileDescriptor sourceFD() {
70 return sourceCore.fd;
71 }
72
73 FileDescriptor sinkFD() {
74 return sinkCore.fd;
75 }
76
77 @Override
78 public void close() throws IOException {
79 try {
80 source().close();
81 } finally {
82 sink().close();
83 }
84 }
85
86
87
88
89
90 public final class SourceChannel extends java.nio.channels.Pipe.SourceChannel implements
91 FileDescriptorAccess {
92 SourceChannel(SelectorProvider provider) {
93 super(provider);
94 }
95
96 @Override
97 public long read(ByteBuffer[] dsts, int offset, int length) throws IOException {
98 if (length == 0) {
99 return 0;
100 }
101 return read(dsts[offset]);
102 }
103
104 @Override
105 public long read(ByteBuffer[] dsts) throws IOException {
106 return read(dsts, 0, dsts.length);
107 }
108
109 @Override
110 public int read(ByteBuffer dst) throws IOException {
111 return sourceCore.read(dst, DUMMY_TIMEOUT, null, options);
112 }
113
114 @Override
115 protected void implConfigureBlocking(boolean block) throws IOException {
116 sourceCore.implConfigureBlocking(block);
117 }
118
119 @Override
120 protected void implCloseSelectableChannel() throws IOException {
121 sourceCore.close();
122 }
123
124 @Override
125 public FileDescriptor getFileDescriptor() throws IOException {
126 return sourceCore.fd;
127 }
128 }
129
130
131
132
133
134 public final class SinkChannel extends java.nio.channels.Pipe.SinkChannel implements
135 FileDescriptorAccess {
136 SinkChannel(SelectorProvider provider) {
137 super(provider);
138 }
139
140 @Override
141 public long write(ByteBuffer[] srcs, int offset, int length) throws IOException {
142 if (length == 0) {
143 return 0;
144 }
145 return write(srcs[offset]);
146 }
147
148 @Override
149 public long write(ByteBuffer[] srcs) throws IOException {
150 return write(srcs, 0, srcs.length);
151 }
152
153 @Override
154 public int write(ByteBuffer src) throws IOException {
155 return sinkCore.write(src, DUMMY_TIMEOUT, null, options);
156 }
157
158 @Override
159 protected void implConfigureBlocking(boolean block) throws IOException {
160 sinkCore.implConfigureBlocking(block);
161 }
162
163 @Override
164 protected void implCloseSelectableChannel() throws IOException {
165 sinkCore.close();
166 }
167
168 @Override
169 public FileDescriptor getFileDescriptor() throws IOException {
170 return sinkCore.fd;
171 }
172 }
173
174
175
176
177
178
179 int getOptions() {
180 return options;
181 }
182
183
184
185
186
187
188
189 public static AFPipe open() throws IOException {
190 return AFUNIXSelectorProvider.provider().openPipe();
191 }
192 }