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.FileDescriptor;
21 import java.io.IOException;
22 import java.lang.reflect.InvocationTargetException;
23 import java.net.SocketException;
24 import java.nio.ByteBuffer;
25 import java.util.concurrent.atomic.AtomicInteger;
26 import java.util.concurrent.atomic.AtomicLong;
27
28
29
30
31
32
33 class AFSocketCore extends AFCore {
34 private final AtomicInteger pendingAccepts = new AtomicInteger(0);
35 private static final int SHUT_RD_WR = 2;
36
37
38
39
40 final AtomicLong inode = new AtomicLong(-1);
41
42 AFSocketAddress socketAddress;
43
44 private final AFAddressFamily<?> af;
45 private boolean shutdownOnClose = true;
46
47 protected AFSocketCore(Object observed, FileDescriptor fd,
48 AncillaryDataSupport ancillaryDataSupport, AFAddressFamily<?> af, boolean datagramMode) {
49 super(observed, fd, ancillaryDataSupport, datagramMode);
50 this.af = af;
51 }
52
53 protected AFAddressFamily<?> addressFamily() {
54 return af;
55 }
56
57 @Override
58 @SuppressWarnings("UnsafeFinalization" )
59 protected void doClose() throws IOException {
60 if (isShutdownOnClose()) {
61 NativeUnixSocket.shutdown(fd, SHUT_RD_WR);
62 unblockAccepts();
63 }
64
65 super.doClose();
66 }
67
68 protected void unblockAccepts() {
69 }
70
71 AFSocketAddress receive(ByteBuffer dst) throws IOException {
72 ByteBuffer socketAddressBuffer = AFSocketAddress.SOCKETADDRESS_BUFFER_TL.get();
73 int read = read(dst, socketAddressBuffer, 0);
74 if (read > 0) {
75 return AFSocketAddress.ofInternal(socketAddressBuffer, af);
76 } else {
77 return null;
78 }
79 }
80
81 boolean isConnected(boolean boundOk) {
82 try {
83 if (fd.valid()) {
84 switch (NativeUnixSocket.socketStatus(fd)) {
85 case NativeUnixSocket.SOCKETSTATUS_CONNECTED:
86 return true;
87 case NativeUnixSocket.SOCKETSTATUS_BOUND:
88 if (boundOk) {
89 return true;
90 }
91 break;
92 default:
93 }
94 }
95 } catch (IOException e) {
96 throw new IllegalStateException(e);
97 }
98 return false;
99 }
100
101 @SuppressWarnings({"unchecked"})
102 <T> T getOption(AFSocketOption<T> name) throws IOException {
103 Class<T> type = name.type();
104 if (Boolean.class.isAssignableFrom(type)) {
105 return (T) (Object) (NativeUnixSocket.getSocketOption(fd, name.level(), name.optionName(),
106 Integer.class) != 0);
107 } else if (NamedInteger.HasOfValue.class.isAssignableFrom(type)) {
108 @SuppressWarnings("all")
109 int v = NativeUnixSocket.getSocketOption(fd, name.level(), name.optionName(), Integer.class);
110 try {
111 return (T) type.getMethod("ofValue", int.class).invoke(null, v);
112 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException
113 | NoSuchMethodException | SecurityException e) {
114 throw new IOException("Value casting problem", e);
115 }
116 } else {
117 return NativeUnixSocket.getSocketOption(fd, name.level(), name.optionName(), type);
118 }
119 }
120
121 <T> void setOption(AFSocketOption<T> name, T value) throws IOException {
122 final Object val;
123 if (value instanceof Boolean) {
124 val = (((Boolean) value) ? 1 : 0);
125 } else if (value instanceof NamedInteger) {
126 val = ((NamedInteger) value).value();
127 } else {
128 val = value;
129 }
130 int level = name.level();
131 int optionName = name.optionName();
132 NativeUnixSocket.setSocketOption(fd, level, optionName, val);
133 if (level == 271 && optionName == 135) {
134
135
136 try {
137 Thread.sleep(1);
138 } catch (InterruptedException e) {
139
140 }
141 }
142 }
143
144 protected void incPendingAccepts() throws SocketException {
145 if (pendingAccepts.incrementAndGet() >= Integer.MAX_VALUE) {
146 throw new SocketException("Too many pending accepts");
147 }
148 }
149
150 protected void decPendingAccepts() throws SocketException {
151 pendingAccepts.decrementAndGet();
152 }
153
154 protected boolean hasPendingAccepts() {
155 return pendingAccepts.get() > 0;
156 }
157
158 boolean isShutdownOnClose() {
159 return shutdownOnClose;
160 }
161
162 void setShutdownOnClose(boolean enabled) {
163 this.shutdownOnClose = enabled;
164 }
165 }