This commit is contained in:
Administrator
2025-04-24 10:16:38 +08:00
parent 6de65562be
commit 7267aec1fd
108 changed files with 7621 additions and 1890 deletions
+435
View File
@@ -0,0 +1,435 @@
package org.kne.cloud.network;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.net.InetAddress;
import java.net.ProtocolFamily;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.SocketException;
import java.net.SocketOptions;
import java.net.StandardProtocolFamily;
import java.net.UnknownHostException;
import org.kne.cloud.network.klalb.KLALBVirtualRawSocketImpl;
public class RawSocket {
public static final ProtocolFamily PF_INET=StandardProtocolFamily.INET;
public static final ProtocolFamily PF_INET6=StandardProtocolFamily.INET6;
private static final VarHandle STATE ;
static {
try {
MethodHandles.Lookup l = MethodHandles.lookup();
STATE = l.findVarHandle(RawSocket.class, "state", int.class);
} catch (Exception e) {
throw new InternalError(e);
}
}
//the underlying SocketImpl, may be null, may be swapped when connecting
private RawSocketImpl impl;
// state bits
private static final int SOCKET_CREATED = 1 << 0; // impl.create(boolean) called
private static final int BOUND = 1 << 1;
private static final int CONNECTED = 1 << 2;
private static final int CLOSED = 1 << 3;
private static final int SHUT_IN = 1 << 9;
private static final int SHUT_OUT = 1 << 10;
private volatile int state;
// used to coordinate creating and closing underlying socket
private final Object socketLock = new Object();
InetAddress connectedAddress = null;
private boolean explicitFilter = false;
private int bytesLeftToFilter;
/**
* Atomically sets state to the result of a bitwise OR of the current value
* and the given mask.
* @return the previous state value
*/
private int getAndBitwiseOrState(int mask) {
return (int) STATE.getAndBitwiseOr(this, mask);
}
private static boolean isBound(int s) {
return (s & BOUND) != 0;
}
private static boolean isConnected(int s) {
return (s & CONNECTED) != 0;
}
private static boolean isClosed(int s) {
return (s & CLOSED) != 0;
}
private static boolean isInputShutdown(int s) {
return (s & SHUT_IN) != 0;
}
private static boolean isOutputShutdown(int s) {
return (s & SHUT_OUT) != 0;
}
protected RawSocket(RawSocketImpl impl) {
this.impl=impl;
}
public RawSocket(RawSocketImpl impl, Inet6Address bindAddress) throws SocketException {
this.impl=impl;
bind(bindAddress);
}
public RawSocket(KLALBVirtualRawSocketImpl impl, Inet6Address bindAddress, int bindProtocol) throws SocketException {
this.impl=impl;
bind(bindAddress,bindProtocol);
}
public boolean isConnected() {
return isConnected(state);
}
public boolean isBound() {
return isBound(state);
}
public boolean isOpen() {
return !isClosed(state);
}
public boolean isClosed() {
return isClosed(state);
}
private void checkAddress(InetAddress addr, String op) {
if (addr == null) {
return;
}
if (!(addr instanceof Inet4Address || addr instanceof Inet6Address)) {
throw new IllegalArgumentException(op + ": invalid address type");
}
}
private RawSocketImpl getImpl() throws SocketException {
if ((state & SOCKET_CREATED) == 0) {
synchronized (socketLock) {
int s = state; // re-read state
if ((s & SOCKET_CREATED) == 0) {
if (isClosed(s)) {
throw new SocketException("Socket is closed");
}
RawSocketImpl impl = this.impl;
if (impl == null) {
this.impl = impl = createImpl();
}
try {
impl.create();
} catch (SocketException e) {
throw e;
} catch (IOException e) {
throw new SocketException(e.getMessage(), e);
}
getAndBitwiseOrState(SOCKET_CREATED);
}
}
}
return impl;
}
private static RawSocketImpl createImpl() {
RawSocketImplFactory factory = RawSocket.factory;
if (factory != null) {
return factory.createRawSocketImpl();
} else {
return null;
// RawSocketImpl delegate = RawSocketImpl.createPlatformSocketImpl(false);
// return new SocksSocketImpl(delegate);
}
}
private static volatile RawSocketImplFactory factory;
static RawSocketImplFactory socketImplFactory() {
return factory;
}
@Deprecated(since = "17")
public static synchronized void setSocketImplFactory(RawSocketImplFactory fac)
throws IOException
{
if (factory != null) {
throw new SocketException("factory already defined");
}
@SuppressWarnings("removal")
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkSetFactory();
}
factory = fac;
}
public void bind(InetAddress address) throws SocketException {
bind(address,-1);
}
public void bind(InetAddress address,int protocolNumber)
throws SocketException
{
int s = state;
if (isClosed(s))
throw new SocketException("Socket is closed");
if (isBound(s))
throw new SocketException("Already bound");
if (address == null) {
try {
address = Inet6Address.getByName("::0");
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
checkAddress (address, "bind");
getImpl().bind(address,protocolNumber);
getAndBitwiseOrState(BOUND);
}
public void bindDevice(String device)
throws UnsupportedOperationException, IllegalStateException, IOException
{
if(!isOpen())
throw new IllegalStateException();
throw new UnsupportedOperationException();
}
public InetAddress getLocalAddress() {
if (isClosed())
return null;
InetAddress in;
try {
in = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR);
if (in.isAnyLocalAddress()) {
in = InetAddress.getByName("::0");
}
} catch (Exception e) {
try {
in = InetAddress.getByName("::0");
} catch (UnknownHostException e1) {
e1.printStackTrace();
in=null;
}
}
return in;
}
public void close() {
synchronized (socketLock) {
if ((state & CLOSED) == 0) {
int s = getAndBitwiseOrState(CLOSED);
if ((s & (SOCKET_CREATED | CLOSED)) == SOCKET_CREATED) {
// close underlying socket if created
impl.close();
}
}
}
}
public void setIPHeaderInclude(boolean on) throws IOException {
impl.setIPHeaderInclude(on);
}
public boolean getIPHeaderInclude() throws IOException {
return impl.getIPHeaderInclude();
}
public void setSendBufferSize(int size) throws SocketException {
if (size <= 0)
throw new IllegalArgumentException("negative send size");
if (isClosed())
throw new SocketException("Socket is closed");
getImpl().setOption(SocketOptions.SO_SNDBUF, size);
}
public int getSendBufferSize() throws SocketException {
if (isClosed())
throw new SocketException("Socket is closed");
int result = 0;
Object o = getImpl().getOption(SocketOptions.SO_SNDBUF);
if (o instanceof Integer i) {
result = i.intValue();
}
return result;
}
public void setReceiveBufferSize(int size) throws SocketException {
if (size <= 0)
throw new IllegalArgumentException("invalid receive size");
if (isClosed())
throw new SocketException("Socket is closed");
getImpl().setOption(SocketOptions.SO_RCVBUF, size);
}
public int getReceiveBufferSize() throws SocketException {
if (isClosed())
throw new SocketException("Socket is closed");
int result = 0;
Object o = getImpl().getOption(SocketOptions.SO_RCVBUF);
if (o instanceof Integer i) {
result = i.intValue();
}
return result;
}
public void setUseSelectTimeout(boolean useSelect) throws IOException {
impl.setUseSelectTimeout(useSelect);
}
public boolean getUseSelectTimeout() throws IOException {
return impl.getUseSelectTimeout();
}
/* public void setSendTimeout(int timeout) throws SocketException {
impl.setSendTimeout( timeout);
}
public int getSendTimeout() throws SocketException {
return impl.getSendTimeout();
}*/
public void setSoTimeout(int timeout) throws SocketException {
if (isClosed())
throw new SocketException("Socket is closed");
if (timeout < 0)
throw new IllegalArgumentException("timeout can't be negative");
getImpl().setOption(SocketOptions.SO_TIMEOUT, timeout);
}
public int getSoTimeout() throws SocketException {
if (isClosed())
throw new SocketException("Socket is closed");
Object o = getImpl().getOption(SocketOptions.SO_TIMEOUT);
/* extra type safety */
if (o instanceof Integer i) {
return i.intValue();
} else {
return 0;
}
}
public void send(DatagramPacket p) throws IOException {
synchronized (p) {
if (isClosed())
throw new SocketException("Socket is closed");
InetAddress packetAddress = p.getAddress();
checkAddress(packetAddress, "send");
if (isConnected()) {
// we're connected
if (packetAddress == null) {
p.setAddress(connectedAddress);
} else if ((!packetAddress.equals(connectedAddress)) ) {
throw new IllegalArgumentException("connected address " +
"and packet address" +
" differ");
}
} else {
if (packetAddress == null) {
throw new IllegalArgumentException("Address not set");
}
}
// Check whether the socket is bound
if (!isBound())
bind(InetAddress.getByName("::0"));
// call the method to send
getImpl().send(p);
}
}
public synchronized void receive(DatagramPacket p) throws IOException {
synchronized (p) {
if (!isBound())
bind(InetAddress.getByName("::0"));
DatagramPacket tmp = null;
if (explicitFilter) {
// We have to do the filtering the old fashioned way since
// the native impl doesn't support connect or the connect
// via the impl failed, or .. "explicitFilter" may be set when
// a socket is connected via the impl, for a period of time
// when packets from other sources might be queued on socket.
boolean stop = false;
while (!stop) {
// peek at the packet to see who it is from.
DatagramPacket peekPacket = new DatagramPacket(new byte[1], 1);
getImpl().peekData(peekPacket);
InetAddress peekAddress = peekPacket.getAddress();
if ((!connectedAddress.equals(peekAddress)) ) {
// throw the packet away and silently continue
tmp = new DatagramPacket(
new byte[1024], 1024);
getImpl().receive(tmp);
if (explicitFilter) {
if (checkFiltering(tmp)) {
stop = true;
}
}
} else {
stop = true;
}
}
}
// If the security check succeeds, or the datagram is
// connected then receive the packet
getImpl().receive(p);
if (explicitFilter && tmp == null) {
// packet was not filtered, account for it here
checkFiltering(p);
}
}
}
private boolean checkFiltering(DatagramPacket p) throws SocketException {
bytesLeftToFilter -= p.getLength();
if (bytesLeftToFilter <= 0 || getImpl().dataAvailable() <= 0) {
explicitFilter = false;
return true;
}
return false;
}
}