Java Unix Domain Socket implementation providing AF_UNIX, AF_TIPC, AF_VSOCK, and AF_SYSTEM socket support with traditional and NIO APIs
—
File descriptor access, peer credentials, socket factories, and native library management for advanced socket operations and system-level integration.
Low-level file descriptor access and manipulation for advanced socket operations and system integration.
/**
* Utility for accessing and manipulating file descriptors
*/
public class FileDescriptorAccess {
/**
* Gets the file descriptor from a socket
* @param socket The socket to get file descriptor from
* @return FileDescriptor instance
* @throws IOException if access fails
*/
public static FileDescriptor getFileDescriptor(AFSocket socket) throws IOException;
/**
* Creates a socket from an existing file descriptor
* @param fd The file descriptor
* @return AFUNIXSocket instance wrapping the file descriptor
* @throws IOException if socket creation fails
*/
public static AFUNIXSocket fromFileDescriptor(FileDescriptor fd) throws IOException;
/**
* Duplicates a file descriptor
* @param fd The file descriptor to duplicate
* @return New FileDescriptor instance
* @throws IOException if duplication fails
*/
public static FileDescriptor duplicate(FileDescriptor fd) throws IOException;
/**
* Checks if a file descriptor is valid
* @param fd The file descriptor to validate
* @return true if valid
*/
public static boolean isValid(FileDescriptor fd);
/**
* Gets the native file descriptor number (Unix/Linux)
* @param fd The file descriptor
* @return Native file descriptor number
* @throws IOException if access fails
*/
public static int getNativeFileDescriptor(FileDescriptor fd) throws IOException;
}Usage Examples:
import java.io.FileDescriptor;
import java.io.IOException;
import org.newsclub.net.unix.*;
// Advanced file descriptor operations
public class FileDescriptorDemo {
public static void demonstrateFileDescriptorAccess() throws IOException {
File socketFile = new File("/tmp/fd-demo.sock");
AFUNIXSocketAddress addr = AFUNIXSocketAddress.of(socketFile);
// Create server socket and access its file descriptor
try (AFUNIXServerSocket server = AFUNIXServerSocket.newInstance()) {
server.bind(addr);
// Get the file descriptor
FileDescriptor serverFd = FileDescriptorAccess.getFileDescriptor(server);
System.out.println("Server file descriptor valid: " + FileDescriptorAccess.isValid(serverFd));
if (FileDescriptorAccess.isValid(serverFd)) {
int nativeFd = FileDescriptorAccess.getNativeFileDescriptor(serverFd);
System.out.println("Native FD number: " + nativeFd);
// Duplicate the file descriptor
FileDescriptor duplicatedFd = FileDescriptorAccess.duplicate(serverFd);
System.out.println("Duplicated FD valid: " + FileDescriptorAccess.isValid(duplicatedFd));
}
// Accept a connection and work with client file descriptor
System.out.println("Waiting for client connection...");
try (AFUNIXSocket client = server.accept()) {
FileDescriptor clientFd = FileDescriptorAccess.getFileDescriptor(client);
// Pass file descriptor to another process or thread
passFileDescriptorToWorker(clientFd);
}
}
}
public static void createSocketFromFileDescriptor(FileDescriptor fd) throws IOException {
if (!FileDescriptorAccess.isValid(fd)) {
throw new IOException("Invalid file descriptor provided");
}
// Create socket from existing file descriptor
try (AFUNIXSocket socket = FileDescriptorAccess.fromFileDescriptor(fd)) {
System.out.println("Created socket from file descriptor");
// Use the socket normally
OutputStream os = socket.getOutputStream();
os.write("Hello from FD socket".getBytes());
os.flush();
}
}
private static void passFileDescriptorToWorker(FileDescriptor fd) {
// Implementation for passing FD to worker thread or process
System.out.println("Passing file descriptor to worker: " +
FileDescriptorAccess.isValid(fd));
}
}Access to peer process credentials (PID, UID, GID) for authentication and security purposes.
/**
* Access to peer process credentials
*/
public class PeerCredentials {
/**
* Gets peer credentials from a connected socket
* @param socket The connected socket
* @return PeerCredentials instance
* @throws IOException if credentials cannot be retrieved
* @throws OperationNotSupportedSocketException if not supported on platform
*/
public static PeerCredentials fromSocket(AFUNIXSocket socket) throws IOException;
/**
* Gets the process ID of the peer
* @return Process ID (PID)
*/
public long getPid();
/**
* Gets the user ID of the peer
* @return User ID (UID)
*/
public long getUid();
/**
* Gets the group ID of the peer
* @return Group ID (GID)
*/
public long getGid();
/**
* Checks if the peer is running as root
* @return true if peer UID is 0
*/
public boolean isRoot();
/**
* Checks if the peer has the same UID as current process
* @return true if UIDs match
*/
public boolean isSameUser();
/**
* Gets a string representation of the credentials
* @return formatted credentials string
*/
@Override
public String toString();
/**
* Validates peer credentials against expected values
* @param expectedUid Expected user ID (optional, -1 to skip)
* @param expectedGid Expected group ID (optional, -1 to skip)
* @return true if credentials match expectations
*/
public boolean validate(long expectedUid, long expectedGid);
}Usage Examples:
// Peer credential authentication and authorization
public class PeerCredentialSecurity {
public static void authenticateConnection(AFUNIXSocket clientSocket) throws IOException {
try {
PeerCredentials credentials = PeerCredentials.fromSocket(clientSocket);
System.out.println("Peer credentials: " + credentials);
System.out.println(" PID: " + credentials.getPid());
System.out.println(" UID: " + credentials.getUid());
System.out.println(" GID: " + credentials.getGid());
System.out.println(" Is Root: " + credentials.isRoot());
System.out.println(" Same User: " + credentials.isSameUser());
// Authentication logic
if (authenticatePeer(credentials)) {
System.out.println("Peer authenticated successfully");
handleAuthenticatedClient(clientSocket, credentials);
} else {
System.out.println("Peer authentication failed");
clientSocket.close();
}
} catch (OperationNotSupportedSocketException e) {
System.err.println("Peer credentials not supported on this platform: " + e.getMessage());
// Fall back to alternative authentication
handleAlternativeAuth(clientSocket);
}
}
private static boolean authenticatePeer(PeerCredentials credentials) {
// Example authentication policies
// Policy 1: Only allow same user
if (credentials.isSameUser()) {
return true;
}
// Policy 2: Allow root user
if (credentials.isRoot()) {
return true;
}
// Policy 3: Allow specific UIDs
long[] allowedUids = {1000, 1001, 1002}; // Example UIDs
for (long allowedUid : allowedUids) {
if (credentials.getUid() == allowedUid) {
return true;
}
}
// Policy 4: Validate specific UID/GID combination
if (credentials.validate(1000, 100)) { // UID 1000, GID 100
return true;
}
return false;
}
private static void handleAuthenticatedClient(AFUNIXSocket socket, PeerCredentials credentials) {
// Handle authenticated client with appropriate permissions
System.out.println("Handling authenticated client with PID " + credentials.getPid());
}
private static void handleAlternativeAuth(AFUNIXSocket socket) {
// Alternative authentication mechanism
System.out.println("Using alternative authentication method");
}
}
// Server implementation with peer credential checking
public class SecureUnixSocketServer {
private final AFUNIXSocketAddress serverAddress;
private final Set<Long> authorizedUids;
public SecureUnixSocketServer(File socketFile, Set<Long> authorizedUids) throws AFException {
this.serverAddress = AFUNIXSocketAddress.of(socketFile);
this.authorizedUids = new HashSet<>(authorizedUids);
}
public void start() throws IOException {
try (AFUNIXServerSocket server = AFUNIXServerSocket.newInstance()) {
server.bind(serverAddress);
System.out.println("Secure server listening on: " + serverAddress.getFile());
while (!Thread.interrupted()) {
try (AFUNIXSocket client = server.accept()) {
handleSecureClient(client);
} catch (IOException e) {
System.err.println("Error handling client: " + e.getMessage());
}
}
}
}
private void handleSecureClient(AFUNIXSocket client) throws IOException {
try {
PeerCredentials credentials = PeerCredentials.fromSocket(client);
if (!authorizedUids.contains(credentials.getUid())) {
System.err.println("Unauthorized UID: " + credentials.getUid());
return;
}
System.out.println("Authorized client connected: " + credentials);
// Process client request
processClientRequest(client, credentials);
} catch (OperationNotSupportedSocketException e) {
System.err.println("Platform doesn't support peer credentials - rejecting connection");
}
}
private void processClientRequest(AFUNIXSocket client, PeerCredentials credentials) throws IOException {
InputStream is = client.getInputStream();
OutputStream os = client.getOutputStream();
// Read request
byte[] buffer = new byte[1024];
int bytesRead = is.read(buffer);
String request = new String(buffer, 0, bytesRead, StandardCharsets.UTF_8);
// Process based on credentials
String response = processRequest(request, credentials);
// Send response
os.write(response.getBytes(StandardCharsets.UTF_8));
os.flush();
}
private String processRequest(String request, PeerCredentials credentials) {
// Process request with authorization context
return "Processed request '" + request + "' for user " + credentials.getUid();
}
}Socket factory implementations for creating and managing AF socket instances with custom configurations.
/**
* Base factory class for creating AF sockets
*/
public abstract class AFSocketFactory {
/**
* Creates a new AF socket
* @return New socket instance
* @throws IOException if socket creation fails
*/
public abstract AFSocket createSocket() throws IOException;
/**
* Creates a new AF server socket
* @return New server socket instance
* @throws IOException if server socket creation fails
*/
public abstract AFServerSocket createServerSocket() throws IOException;
/**
* Creates a connected socket to the specified address
* @param address Target address
* @return Connected socket instance
* @throws IOException if connection fails
*/
public abstract AFSocket connectTo(AFSocketAddress address) throws IOException;
/**
* Gets the socket domain supported by this factory
* @return Socket domain
*/
public abstract AFSocketDomain getSocketDomain();
/**
* Sets default socket options for created sockets
* @param options Socket options to apply
*/
public abstract void setDefaultSocketOptions(Map<String, Object> options);
}
/**
* Factory for creating Unix Domain Sockets
*/
public class AFUNIXSocketFactory extends AFSocketFactory {
/**
* Gets the singleton instance
* @return AFUNIXSocketFactory instance
*/
public static AFUNIXSocketFactory getInstance();
/**
* Creates a new AFUNIXSocketFactory with custom configuration
* @param config Factory configuration
* @return Configured factory instance
*/
public static AFUNIXSocketFactory create(SocketFactoryConfig config);
@Override
public AFUNIXSocket createSocket() throws IOException;
@Override
public AFUNIXServerSocket createServerSocket() throws IOException;
@Override
public AFUNIXSocket connectTo(AFSocketAddress address) throws IOException;
/**
* Creates a socket bound to the specified address
* @param address Address to bind to
* @return Bound socket instance
* @throws IOException if binding fails
*/
public AFUNIXSocket createBoundSocket(AFUNIXSocketAddress address) throws IOException;
/**
* Creates a server socket bound to the specified address
* @param address Address to bind to
* @param backlog Connection backlog
* @return Bound server socket instance
* @throws IOException if binding fails
*/
public AFUNIXServerSocket createBoundServerSocket(AFUNIXSocketAddress address, int backlog) throws IOException;
}Usage Examples:
// Custom socket factory with preconfigured options
public class CustomSocketFactory {
public static void demonstrateFactoryUsage() throws IOException {
// Get standard factory
AFUNIXSocketFactory factory = AFUNIXSocketFactory.getInstance();
// Configure default options
Map<String, Object> defaultOptions = new HashMap<>();
defaultOptions.put("SO_TIMEOUT", 30000); // 30 second timeout
defaultOptions.put("SO_KEEPALIVE", true); // Enable keep-alive
defaultOptions.put("SO_REUSEADDR", true); // Enable address reuse
factory.setDefaultSocketOptions(defaultOptions);
// Create sockets with default options applied
try (AFUNIXSocket socket = factory.createSocket()) {
System.out.println("Created socket with default options");
// Connect to server
AFUNIXSocketAddress serverAddr = AFUNIXSocketAddress.of(new File("/tmp/server.sock"));
socket.connect(serverAddr);
// Socket already has timeout and keep-alive configured
System.out.println("Socket timeout: " + socket.getSoTimeout());
System.out.println("Keep-alive: " + socket.getKeepAlive());
}
// Create server socket with factory
AFUNIXSocketAddress serverAddr = AFUNIXSocketAddress.of(new File("/tmp/factory-server.sock"));
try (AFUNIXServerSocket server = factory.createBoundServerSocket(serverAddr, 50)) {
System.out.println("Server socket created with factory");
// Accept connections
try (AFUNIXSocket client = server.accept()) {
System.out.println("Client connected: " + client.getRemoteSocketAddress());
}
}
}
public static class SocketFactoryConfig {
private int defaultTimeout = 0;
private boolean defaultKeepAlive = false;
private boolean defaultReuseAddress = true;
private int defaultBufferSize = 8192;
public SocketFactoryConfig setTimeout(int timeout) {
this.defaultTimeout = timeout;
return this;
}
public SocketFactoryConfig setKeepAlive(boolean keepAlive) {
this.defaultKeepAlive = keepAlive;
return this;
}
public SocketFactoryConfig setReuseAddress(boolean reuseAddress) {
this.defaultReuseAddress = reuseAddress;
return this;
}
public SocketFactoryConfig setBufferSize(int bufferSize) {
this.defaultBufferSize = bufferSize;
return this;
}
// Getters
public int getDefaultTimeout() { return defaultTimeout; }
public boolean isDefaultKeepAlive() { return defaultKeepAlive; }
public boolean isDefaultReuseAddress() { return defaultReuseAddress; }
public int getDefaultBufferSize() { return defaultBufferSize; }
}
// Custom factory implementation
public static AFUNIXSocketFactory createCustomFactory() {
SocketFactoryConfig config = new SocketFactoryConfig()
.setTimeout(60000) // 1 minute timeout
.setKeepAlive(true) // Enable keep-alive
.setReuseAddress(true) // Enable address reuse
.setBufferSize(16384); // 16KB buffer
return AFUNIXSocketFactory.create(config);
}
}Native library loading and management for cross-platform socket implementations.
/**
* Loads native libraries for junixsocket
*/
public class NativeLibraryLoader {
/**
* Loads the native junixsocket library
* @return true if library loaded successfully
*/
public static boolean loadNativeLibrary();
/**
* Checks if native library is loaded
* @return true if native library is available
*/
public static boolean isNativeLibraryLoaded();
/**
* Gets the native library version
* @return Version string or null if not loaded
*/
public static String getNativeLibraryVersion();
/**
* Gets native library information
* @return Library information string
*/
public static String getNativeLibraryInfo();
/**
* Forces reload of native library
* @return true if reload successful
*/
public static boolean reloadNativeLibrary();
/**
* Gets supported platforms for native library
* @return Set of supported platform names
*/
public static Set<String> getSupportedPlatforms();
}
/**
* JNI interface to native Unix socket implementations
*/
public class NativeUnixSocket {
/**
* Checks if native implementation is loaded and available
* @return true if native implementation is available
*/
public static boolean isLoaded();
/**
* Gets the native socket implementation version
* @return Version information
*/
public static String getVersion();
/**
* Performs native library self-test
* @return true if self-test passes
*/
public static boolean selfTest();
/**
* Gets platform-specific capabilities
* @return Map of capability names to availability
*/
public static Map<String, Boolean> getPlatformCapabilities();
/**
* Gets native library build information
* @return Build information string
*/
public static String getBuildInfo();
}Usage Examples:
// Native library management and diagnostics
public class NativeLibraryDiagnostics {
public static void performDiagnostics() {
System.out.println("junixsocket Native Library Diagnostics");
System.out.println("=====================================");
// Check native library status
boolean loaded = NativeLibraryLoader.isNativeLibraryLoaded();
System.out.println("Native library loaded: " + loaded);
if (!loaded) {
System.out.println("Attempting to load native library...");
boolean loadResult = NativeLibraryLoader.loadNativeLibrary();
System.out.println("Load result: " + loadResult);
if (!loadResult) {
System.err.println("Failed to load native library");
printTroubleshootingInfo();
return;
}
}
// Display library information
System.out.println("Native library version: " + NativeLibraryLoader.getNativeLibraryVersion());
System.out.println("Native library info: " + NativeLibraryLoader.getNativeLibraryInfo());
// Display supported platforms
Set<String> supportedPlatforms = NativeLibraryLoader.getSupportedPlatforms();
System.out.println("Supported platforms: " + supportedPlatforms);
// Check native Unix socket implementation
System.out.println("\nNative Unix Socket Implementation:");
System.out.println("Available: " + NativeUnixSocket.isLoaded());
if (NativeUnixSocket.isLoaded()) {
System.out.println("Version: " + NativeUnixSocket.getVersion());
System.out.println("Build info: " + NativeUnixSocket.getBuildInfo());
// Perform self-test
boolean selfTestResult = NativeUnixSocket.selfTest();
System.out.println("Self-test result: " + selfTestResult);
if (selfTestResult) {
// Display platform capabilities
Map<String, Boolean> capabilities = NativeUnixSocket.getPlatformCapabilities();
System.out.println("Platform capabilities:");
for (Map.Entry<String, Boolean> entry : capabilities.entrySet()) {
System.out.printf(" %-30s: %s%n",
entry.getKey(),
entry.getValue() ? "✓" : "✗");
}
}
}
}
private static void printTroubleshootingInfo() {
System.err.println("\nTroubleshooting Information:");
System.err.println("Current platform: " + System.getProperty("os.name") +
" " + System.getProperty("os.arch"));
System.err.println("Java version: " + System.getProperty("java.version"));
System.err.println("Java library path: " + System.getProperty("java.library.path"));
System.err.println("\nPossible solutions:");
System.err.println("1. Ensure you're using a supported platform");
System.err.println("2. Check that the native library is included in your dependencies");
System.err.println("3. Verify Java library path contains junixsocket native libraries");
System.err.println("4. Try updating to the latest junixsocket version");
}
public static void validateEnvironment() throws IOException {
if (!NativeLibraryLoader.isNativeLibraryLoaded()) {
if (!NativeLibraryLoader.loadNativeLibrary()) {
throw new IOException("Failed to load junixsocket native library");
}
}
if (!NativeUnixSocket.isLoaded()) {
throw new IOException("Native Unix socket implementation not available");
}
if (!NativeUnixSocket.selfTest()) {
throw new IOException("Native library self-test failed");
}
System.out.println("Environment validation successful - all native components available");
}
public static void main(String[] args) {
try {
performDiagnostics();
validateEnvironment();
} catch (Exception e) {
System.err.println("Diagnostic failed: " + e.getMessage());
System.exit(1);
}
}
}
// Application initialization with native library verification
public class ApplicationInitializer {
public static void initializeWithNativeSupport() throws IOException {
System.out.println("Initializing application with junixsocket native support...");
// Verify native library availability
if (!NativeLibraryLoader.isNativeLibraryLoaded()) {
throw new IOException("Native library not loaded - cannot initialize Unix socket support");
}
// Check native implementation
if (!NativeUnixSocket.isLoaded()) {
throw new IOException("Native Unix socket implementation not available");
}
// Perform basic functionality test
if (!NativeUnixSocket.selfTest()) {
System.err.println("Warning: Native library self-test failed - some features may not work correctly");
}
// Log initialization success
System.out.println("Native support initialized successfully");
System.out.println(" Library version: " + NativeLibraryLoader.getNativeLibraryVersion());
System.out.println(" Implementation version: " + NativeUnixSocket.getVersion());
// Initialize socket services
initializeSocketServices();
}
private static void initializeSocketServices() {
System.out.println("Socket services initialized");
}
}// Resource management utility for socket cleanup
public class SocketResourceManager {
private final Set<AutoCloseable> managedResources = ConcurrentHashMap.newKeySet();
public <T extends AutoCloseable> T manage(T resource) {
managedResources.add(resource);
return resource;
}
public void closeAll() {
for (AutoCloseable resource : managedResources) {
try {
resource.close();
} catch (Exception e) {
System.err.println("Error closing resource: " + e.getMessage());
}
}
managedResources.clear();
}
public AFUNIXSocket createManagedSocket() throws IOException {
return manage(AFUNIXSocket.newInstance());
}
public AFUNIXServerSocket createManagedServerSocket() throws IOException {
return manage(AFUNIXServerSocket.newInstance());
}
}Install with Tessl CLI
npx tessl i tessl/maven-com-kohlschutter-junixsocket--junixsocket-core