Skip to content

Commit

Permalink
Merge branch 'Prototik-fd-improvements'
Browse files Browse the repository at this point in the history
  • Loading branch information
hypfvieh committed Oct 10, 2023
2 parents 92da3ab + b9f09b4 commit fd27028
Show file tree
Hide file tree
Showing 15 changed files with 407 additions and 77 deletions.
100 changes: 67 additions & 33 deletions dbus-java-core/src/main/java/org/freedesktop/dbus/FileDescriptor.java
Original file line number Diff line number Diff line change
@@ -1,60 +1,94 @@
package org.freedesktop.dbus;

import org.freedesktop.dbus.exceptions.MarshallingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.freedesktop.dbus.spi.message.ISocketProvider;
import org.freedesktop.dbus.utils.ReflectionFileDescriptorHelper;

import java.lang.reflect.*;
import java.util.Optional;

/**
* Represents a FileDescriptor to be passed over the bus. Can be created from
* either an integer(gotten through some JNI/JNA/JNR call) or from a
* java.io.FileDescriptor.
*
* Represents a FileDescriptor to be passed over the bus. <br>
* Can be created from either an integer (gotten through some JNI/JNA/JNR call) or from a
* {@link java.io.FileDescriptor}.
*/
public class FileDescriptor {

private final Logger logger = LoggerFactory.getLogger(getClass());
public final class FileDescriptor {

private final int fd;

public FileDescriptor(int _fd) {
fd = _fd;
}

public FileDescriptor(java.io.FileDescriptor _data) throws MarshallingException {
fd = getFileDescriptor(_data);
}
/**
* Converts this DBus {@link FileDescriptor} to a {@link java.io.FileDescriptor}.<br>
* Tries to use the provided ISocketProvider if present first. <br>
* If not present or conversion failed, tries to convert using reflection.
*
* @param _provider provider or null
*
* @return java file descriptor
* @throws MarshallingException when converting fails
*/
public java.io.FileDescriptor toJavaFileDescriptor(ISocketProvider _provider) throws MarshallingException {
if (_provider != null) {
Optional<java.io.FileDescriptor> result = _provider.createFileDescriptor(fd);
if (result.isPresent()) {
return result.get();
}
}

public java.io.FileDescriptor toJavaFileDescriptor() throws MarshallingException {
return createFileDescriptorByReflection(fd);
return ReflectionFileDescriptorHelper.getInstance()
.flatMap(helper -> helper.createFileDescriptor(fd))
.orElseThrow(() -> new MarshallingException("Could not create new FileDescriptor instance"));
}

public int getIntFileDescriptor() {
return fd;
}

private int getFileDescriptor(java.io.FileDescriptor _data) throws MarshallingException {
Field declaredField;
try {
declaredField = _data.getClass().getDeclaredField("fd");
declaredField.setAccessible(true);
return declaredField.getInt(_data);
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException _ex) {
logger.error("Could not get filedescriptor by reflection.", _ex);
throw new MarshallingException("Could not get member 'fd' of FileDescriptor by reflection!", _ex);
@Override
public boolean equals(Object _o) {
if (this == _o) {
return true;
}
if (_o == null || getClass() != _o.getClass()) {
return false;
}
FileDescriptor that = (FileDescriptor) _o;
return fd == that.fd;
}

@Override
public int hashCode() {
return fd;
}

private java.io.FileDescriptor createFileDescriptorByReflection(long _demarshallint) throws MarshallingException {
try {
Constructor<java.io.FileDescriptor> constructor = java.io.FileDescriptor.class.getDeclaredConstructor(int.class);
constructor.setAccessible(true);
return constructor.newInstance((int) _demarshallint);
} catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException
| IllegalArgumentException | InvocationTargetException _ex) {
logger.error("Could not create new FileDescriptor instance by reflection.", _ex);
throw new MarshallingException("Could not create new FileDescriptor instance by reflection", _ex);
@Override
public String toString() {
return FileDescriptor.class.getSimpleName() + "[fd=" + fd + "]";
}

/**
* Utility method to create a DBus {@link FileDescriptor} from a {@link java.io.FileDescriptor}.<br>
* Tries to use the provided ISocketProvider if present first.<br>
* If not present or conversion failed, tries to convert using reflection.
*
* @param _data file descriptor
* @param _provider socket provider or null
*
* @return DBus FileDescriptor
* @throws MarshallingException when conversion fails
*/
public static FileDescriptor fromJavaFileDescriptor(java.io.FileDescriptor _data, ISocketProvider _provider) throws MarshallingException {
if (_provider != null) {
Optional<Integer> result = _provider.getFileDescriptorValue(_data);
if (result.isPresent()) {
return new FileDescriptor(result.get());
}
}

return new FileDescriptor(ReflectionFileDescriptorHelper.getInstance()
.flatMap(helper -> helper.getFileDescriptorValue(_data))
.orElseThrow(() -> new MarshallingException("Could not get FileDescriptor value")));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1275,6 +1275,10 @@ public TransportConfig getTransportConfig() {
return transport.getTransportConfig();
}

public boolean isFileDescriptorSupported() {
return transport.isFileDescriptorSupported();
}

@Override
public String toString() {
return getClass().getSimpleName() + "[address=" + busAddress + "]";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ private void authenticate(SocketChannel _sock) throws IOException {
private TransportConnection createInputOutput(SocketChannel _socket) {
IMessageReader reader = null;
IMessageWriter writer = null;
ISocketProvider providerImpl = null;
try {
for (ISocketProvider provider : spiLoader) {
logger.debug("Found ISocketProvider {}", provider);
Expand All @@ -244,6 +245,7 @@ private TransportConnection createInputOutput(SocketChannel _socket) {
writer = provider.createWriter(_socket);
if (reader != null && writer != null) {
logger.debug("Using ISocketProvider {}", provider);
providerImpl = provider;
break;
}
}
Expand All @@ -261,7 +263,7 @@ private TransportConnection createInputOutput(SocketChannel _socket) {
// allows it
}

return new TransportConnection(messageFactory, _socket, writer, reader);
return new TransportConnection(messageFactory, _socket, providerImpl, writer, reader);
}

/**
Expand Down Expand Up @@ -313,6 +315,10 @@ public TransportConfig getTransportConfig() {
return config;
}

public boolean isFileDescriptorSupported() {
return fileDescriptorSupported;
}

@Override
public String toString() {
StringBuilder sb = new StringBuilder(getClass().getSimpleName());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package org.freedesktop.dbus.connections.transports;

import org.freedesktop.dbus.messages.MessageFactory;
import org.freedesktop.dbus.spi.message.IMessageReader;
import org.freedesktop.dbus.spi.message.IMessageWriter;
import org.freedesktop.dbus.spi.message.*;

import java.io.Closeable;
import java.io.IOException;
Expand All @@ -27,12 +26,14 @@ public class TransportConnection implements Closeable {
private final SocketChannel channel;
private final IMessageWriter writer;
private final IMessageReader reader;
private final ISocketProvider socketProviderImpl;

private final MessageFactory messageFactory;

public TransportConnection(MessageFactory _factory, SocketChannel _channel, IMessageWriter _writer, IMessageReader _reader) {
public TransportConnection(MessageFactory _factory, SocketChannel _channel, ISocketProvider _socketProviderImpl, IMessageWriter _writer, IMessageReader _reader) {
messageFactory = _factory;
channel = _channel;
socketProviderImpl = _socketProviderImpl;
writer = _writer;
reader = _reader;
}
Expand All @@ -49,6 +50,10 @@ public IMessageReader getReader() {
return reader;
}

public ISocketProvider getSocketProviderImpl() {
return socketProviderImpl;
}

public long getId() {
return id;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@ public abstract class AbstractInputStreamMessageReader implements IMessageReader
private final byte[] buf;
private final byte[] tbuf;
private final SocketChannel inputChannel;
private final boolean hasFileDescriptorSupport;

private byte[] header;
private byte[] body;

public AbstractInputStreamMessageReader(final SocketChannel _in, boolean _hasFileDescriptorSupport) {
hasFileDescriptorSupport = _hasFileDescriptorSupport;
private final ISocketProvider socketProviderImpl;

public AbstractInputStreamMessageReader(final SocketChannel _in, ISocketProvider _socketProviderImpl) {
socketProviderImpl = Objects.requireNonNull(_socketProviderImpl, "ISocketProvider implementation required");
inputChannel = Objects.requireNonNull(_in, "SocketChannel required");
len = new int[4];
tbuf = new byte[4];
Expand Down Expand Up @@ -168,7 +169,7 @@ public final Message readMessage() throws IOException, DBusException {

try {
List<FileDescriptor> fds = null;
if (hasFileDescriptorSupport) {
if (socketProviderImpl.isFileDescriptorPassingSupported()) {
fds = readFileDescriptors(inputChannel);
}

Expand Down Expand Up @@ -203,6 +204,14 @@ public final Message readMessage() throws IOException, DBusException {
*/
protected abstract List<FileDescriptor> readFileDescriptors(SocketChannel _inputChannel) throws DBusException;

protected Logger getLogger() {
return logger;
}

protected ISocketProvider getSocketProviderImpl() {
return socketProviderImpl;
}

@Override
public void close() throws IOException {
if (inputChannel.isOpen()) {
Expand All @@ -218,7 +227,7 @@ public boolean isClosed() {

@Override
public String toString() {
return getClass().getSimpleName() + " [inputChannel=" + inputChannel + ", hasFileDescriptorSupport=" + hasFileDescriptorSupport + "]";
return getClass().getSimpleName() + " [inputChannel=" + inputChannel + ", socketProviderImpl=" + socketProviderImpl + "]";
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ public abstract class AbstractOutputStreamMessageWriter implements IMessageWrite
private final Logger logger = LoggerFactory.getLogger(getClass());

private final SocketChannel outputChannel;
private final boolean hasFileDescriptorSupport;

public AbstractOutputStreamMessageWriter(final SocketChannel _out, boolean _fileDescriptorSupport) {
private final ISocketProvider socketProviderImpl;

public AbstractOutputStreamMessageWriter(final SocketChannel _out, ISocketProvider _socketProviderImpl) {
outputChannel = Objects.requireNonNull(_out, "SocketChannel required");
hasFileDescriptorSupport = _fileDescriptorSupport;
socketProviderImpl = Objects.requireNonNull(_socketProviderImpl, "ISocketProvider implementation required");
}

@Override
Expand All @@ -40,6 +41,10 @@ public final void writeMessage(Message _msg) throws IOException {
return;
}

if (socketProviderImpl.isFileDescriptorPassingSupported()) {
writeFileDescriptors(outputChannel, _msg.getFiledescriptors());
}

for (byte[] buf : _msg.getWireData()) {
if (logger.isTraceEnabled()) {
logger.trace("{}", null == buf ? "(buffer was null)" : Hexdump.format(buf));
Expand All @@ -51,10 +56,6 @@ public final void writeMessage(Message _msg) throws IOException {
outputChannel.write(ByteBuffer.wrap(buf));
}

if (hasFileDescriptorSupport) {
writeFileDescriptors(outputChannel, _msg.getFiledescriptors());
}

logger.trace("Message sent: {}", _msg);
}

Expand All @@ -69,6 +70,14 @@ public final void writeMessage(Message _msg) throws IOException {
*/
protected abstract void writeFileDescriptors(SocketChannel _outputChannel, List<FileDescriptor> _filedescriptors) throws IOException;

protected Logger getLogger() {
return logger;
}

protected ISocketProvider getSocketProviderImpl() {
return socketProviderImpl;
}

@Override
public void close() throws IOException {
logger.debug("Closing Message Writer");
Expand All @@ -85,7 +94,7 @@ public boolean isClosed() {

@Override
public String toString() {
return getClass().getSimpleName() + " [outputChannel=" + outputChannel + ", hasFileDescriptorSupport=" + hasFileDescriptorSupport + "]";
return getClass().getSimpleName() + " [outputChannel=" + outputChannel + ", socketProviderImpl=" + socketProviderImpl + "]";
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package org.freedesktop.dbus.spi.message;

import java.io.IOException;
import java.nio.channels.SocketChannel;

/**
* Default internally used socket provider implementation.
*
* @author hypfvieh
* @since 5.0.0 - 2023-10-09
*/
final class DefaultSocketProvider implements ISocketProvider {

static final ISocketProvider INSTANCE = new DefaultSocketProvider();

private DefaultSocketProvider() {

}

@Override
public IMessageReader createReader(SocketChannel _socket) throws IOException {
return new InputStreamMessageReader(_socket);
}

@Override
public IMessageWriter createWriter(SocketChannel _socket) throws IOException {
return new OutputStreamMessageWriter(_socket);
}

@Override
public void setFileDescriptorSupport(boolean _support) {
// not supported
}

@Override
public boolean isFileDescriptorPassingSupported() {
return false;
}

}
Loading

0 comments on commit fd27028

Please sign in to comment.