0
# Utility Classes
1
2
File descriptor access, peer credentials, socket factories, and native library management for advanced socket operations and system-level integration.
3
4
## Capabilities
5
6
### FileDescriptorAccess
7
8
Low-level file descriptor access and manipulation for advanced socket operations and system integration.
9
10
```java { .api }
11
/**
12
* Utility for accessing and manipulating file descriptors
13
*/
14
public class FileDescriptorAccess {
15
16
/**
17
* Gets the file descriptor from a socket
18
* @param socket The socket to get file descriptor from
19
* @return FileDescriptor instance
20
* @throws IOException if access fails
21
*/
22
public static FileDescriptor getFileDescriptor(AFSocket socket) throws IOException;
23
24
/**
25
* Creates a socket from an existing file descriptor
26
* @param fd The file descriptor
27
* @return AFUNIXSocket instance wrapping the file descriptor
28
* @throws IOException if socket creation fails
29
*/
30
public static AFUNIXSocket fromFileDescriptor(FileDescriptor fd) throws IOException;
31
32
/**
33
* Duplicates a file descriptor
34
* @param fd The file descriptor to duplicate
35
* @return New FileDescriptor instance
36
* @throws IOException if duplication fails
37
*/
38
public static FileDescriptor duplicate(FileDescriptor fd) throws IOException;
39
40
/**
41
* Checks if a file descriptor is valid
42
* @param fd The file descriptor to validate
43
* @return true if valid
44
*/
45
public static boolean isValid(FileDescriptor fd);
46
47
/**
48
* Gets the native file descriptor number (Unix/Linux)
49
* @param fd The file descriptor
50
* @return Native file descriptor number
51
* @throws IOException if access fails
52
*/
53
public static int getNativeFileDescriptor(FileDescriptor fd) throws IOException;
54
}
55
```
56
57
**Usage Examples:**
58
59
```java
60
import java.io.FileDescriptor;
61
import java.io.IOException;
62
import org.newsclub.net.unix.*;
63
64
// Advanced file descriptor operations
65
public class FileDescriptorDemo {
66
67
public static void demonstrateFileDescriptorAccess() throws IOException {
68
File socketFile = new File("/tmp/fd-demo.sock");
69
AFUNIXSocketAddress addr = AFUNIXSocketAddress.of(socketFile);
70
71
// Create server socket and access its file descriptor
72
try (AFUNIXServerSocket server = AFUNIXServerSocket.newInstance()) {
73
server.bind(addr);
74
75
// Get the file descriptor
76
FileDescriptor serverFd = FileDescriptorAccess.getFileDescriptor(server);
77
System.out.println("Server file descriptor valid: " + FileDescriptorAccess.isValid(serverFd));
78
79
if (FileDescriptorAccess.isValid(serverFd)) {
80
int nativeFd = FileDescriptorAccess.getNativeFileDescriptor(serverFd);
81
System.out.println("Native FD number: " + nativeFd);
82
83
// Duplicate the file descriptor
84
FileDescriptor duplicatedFd = FileDescriptorAccess.duplicate(serverFd);
85
System.out.println("Duplicated FD valid: " + FileDescriptorAccess.isValid(duplicatedFd));
86
}
87
88
// Accept a connection and work with client file descriptor
89
System.out.println("Waiting for client connection...");
90
try (AFUNIXSocket client = server.accept()) {
91
FileDescriptor clientFd = FileDescriptorAccess.getFileDescriptor(client);
92
93
// Pass file descriptor to another process or thread
94
passFileDescriptorToWorker(clientFd);
95
}
96
}
97
}
98
99
public static void createSocketFromFileDescriptor(FileDescriptor fd) throws IOException {
100
if (!FileDescriptorAccess.isValid(fd)) {
101
throw new IOException("Invalid file descriptor provided");
102
}
103
104
// Create socket from existing file descriptor
105
try (AFUNIXSocket socket = FileDescriptorAccess.fromFileDescriptor(fd)) {
106
System.out.println("Created socket from file descriptor");
107
108
// Use the socket normally
109
OutputStream os = socket.getOutputStream();
110
os.write("Hello from FD socket".getBytes());
111
os.flush();
112
}
113
}
114
115
private static void passFileDescriptorToWorker(FileDescriptor fd) {
116
// Implementation for passing FD to worker thread or process
117
System.out.println("Passing file descriptor to worker: " +
118
FileDescriptorAccess.isValid(fd));
119
}
120
}
121
```
122
123
### PeerCredentials
124
125
Access to peer process credentials (PID, UID, GID) for authentication and security purposes.
126
127
```java { .api }
128
/**
129
* Access to peer process credentials
130
*/
131
public class PeerCredentials {
132
133
/**
134
* Gets peer credentials from a connected socket
135
* @param socket The connected socket
136
* @return PeerCredentials instance
137
* @throws IOException if credentials cannot be retrieved
138
* @throws OperationNotSupportedSocketException if not supported on platform
139
*/
140
public static PeerCredentials fromSocket(AFUNIXSocket socket) throws IOException;
141
142
/**
143
* Gets the process ID of the peer
144
* @return Process ID (PID)
145
*/
146
public long getPid();
147
148
/**
149
* Gets the user ID of the peer
150
* @return User ID (UID)
151
*/
152
public long getUid();
153
154
/**
155
* Gets the group ID of the peer
156
* @return Group ID (GID)
157
*/
158
public long getGid();
159
160
/**
161
* Checks if the peer is running as root
162
* @return true if peer UID is 0
163
*/
164
public boolean isRoot();
165
166
/**
167
* Checks if the peer has the same UID as current process
168
* @return true if UIDs match
169
*/
170
public boolean isSameUser();
171
172
/**
173
* Gets a string representation of the credentials
174
* @return formatted credentials string
175
*/
176
@Override
177
public String toString();
178
179
/**
180
* Validates peer credentials against expected values
181
* @param expectedUid Expected user ID (optional, -1 to skip)
182
* @param expectedGid Expected group ID (optional, -1 to skip)
183
* @return true if credentials match expectations
184
*/
185
public boolean validate(long expectedUid, long expectedGid);
186
}
187
```
188
189
**Usage Examples:**
190
191
```java
192
// Peer credential authentication and authorization
193
public class PeerCredentialSecurity {
194
195
public static void authenticateConnection(AFUNIXSocket clientSocket) throws IOException {
196
try {
197
PeerCredentials credentials = PeerCredentials.fromSocket(clientSocket);
198
199
System.out.println("Peer credentials: " + credentials);
200
System.out.println(" PID: " + credentials.getPid());
201
System.out.println(" UID: " + credentials.getUid());
202
System.out.println(" GID: " + credentials.getGid());
203
System.out.println(" Is Root: " + credentials.isRoot());
204
System.out.println(" Same User: " + credentials.isSameUser());
205
206
// Authentication logic
207
if (authenticatePeer(credentials)) {
208
System.out.println("Peer authenticated successfully");
209
handleAuthenticatedClient(clientSocket, credentials);
210
} else {
211
System.out.println("Peer authentication failed");
212
clientSocket.close();
213
}
214
215
} catch (OperationNotSupportedSocketException e) {
216
System.err.println("Peer credentials not supported on this platform: " + e.getMessage());
217
// Fall back to alternative authentication
218
handleAlternativeAuth(clientSocket);
219
}
220
}
221
222
private static boolean authenticatePeer(PeerCredentials credentials) {
223
// Example authentication policies
224
225
// Policy 1: Only allow same user
226
if (credentials.isSameUser()) {
227
return true;
228
}
229
230
// Policy 2: Allow root user
231
if (credentials.isRoot()) {
232
return true;
233
}
234
235
// Policy 3: Allow specific UIDs
236
long[] allowedUids = {1000, 1001, 1002}; // Example UIDs
237
for (long allowedUid : allowedUids) {
238
if (credentials.getUid() == allowedUid) {
239
return true;
240
}
241
}
242
243
// Policy 4: Validate specific UID/GID combination
244
if (credentials.validate(1000, 100)) { // UID 1000, GID 100
245
return true;
246
}
247
248
return false;
249
}
250
251
private static void handleAuthenticatedClient(AFUNIXSocket socket, PeerCredentials credentials) {
252
// Handle authenticated client with appropriate permissions
253
System.out.println("Handling authenticated client with PID " + credentials.getPid());
254
}
255
256
private static void handleAlternativeAuth(AFUNIXSocket socket) {
257
// Alternative authentication mechanism
258
System.out.println("Using alternative authentication method");
259
}
260
}
261
262
// Server implementation with peer credential checking
263
public class SecureUnixSocketServer {
264
private final AFUNIXSocketAddress serverAddress;
265
private final Set<Long> authorizedUids;
266
267
public SecureUnixSocketServer(File socketFile, Set<Long> authorizedUids) throws AFException {
268
this.serverAddress = AFUNIXSocketAddress.of(socketFile);
269
this.authorizedUids = new HashSet<>(authorizedUids);
270
}
271
272
public void start() throws IOException {
273
try (AFUNIXServerSocket server = AFUNIXServerSocket.newInstance()) {
274
server.bind(serverAddress);
275
System.out.println("Secure server listening on: " + serverAddress.getFile());
276
277
while (!Thread.interrupted()) {
278
try (AFUNIXSocket client = server.accept()) {
279
handleSecureClient(client);
280
} catch (IOException e) {
281
System.err.println("Error handling client: " + e.getMessage());
282
}
283
}
284
}
285
}
286
287
private void handleSecureClient(AFUNIXSocket client) throws IOException {
288
try {
289
PeerCredentials credentials = PeerCredentials.fromSocket(client);
290
291
if (!authorizedUids.contains(credentials.getUid())) {
292
System.err.println("Unauthorized UID: " + credentials.getUid());
293
return;
294
}
295
296
System.out.println("Authorized client connected: " + credentials);
297
298
// Process client request
299
processClientRequest(client, credentials);
300
301
} catch (OperationNotSupportedSocketException e) {
302
System.err.println("Platform doesn't support peer credentials - rejecting connection");
303
}
304
}
305
306
private void processClientRequest(AFUNIXSocket client, PeerCredentials credentials) throws IOException {
307
InputStream is = client.getInputStream();
308
OutputStream os = client.getOutputStream();
309
310
// Read request
311
byte[] buffer = new byte[1024];
312
int bytesRead = is.read(buffer);
313
String request = new String(buffer, 0, bytesRead, StandardCharsets.UTF_8);
314
315
// Process based on credentials
316
String response = processRequest(request, credentials);
317
318
// Send response
319
os.write(response.getBytes(StandardCharsets.UTF_8));
320
os.flush();
321
}
322
323
private String processRequest(String request, PeerCredentials credentials) {
324
// Process request with authorization context
325
return "Processed request '" + request + "' for user " + credentials.getUid();
326
}
327
}
328
```
329
330
### AFSocketFactory and AFUNIXSocketFactory
331
332
Socket factory implementations for creating and managing AF socket instances with custom configurations.
333
334
```java { .api }
335
/**
336
* Base factory class for creating AF sockets
337
*/
338
public abstract class AFSocketFactory {
339
340
/**
341
* Creates a new AF socket
342
* @return New socket instance
343
* @throws IOException if socket creation fails
344
*/
345
public abstract AFSocket createSocket() throws IOException;
346
347
/**
348
* Creates a new AF server socket
349
* @return New server socket instance
350
* @throws IOException if server socket creation fails
351
*/
352
public abstract AFServerSocket createServerSocket() throws IOException;
353
354
/**
355
* Creates a connected socket to the specified address
356
* @param address Target address
357
* @return Connected socket instance
358
* @throws IOException if connection fails
359
*/
360
public abstract AFSocket connectTo(AFSocketAddress address) throws IOException;
361
362
/**
363
* Gets the socket domain supported by this factory
364
* @return Socket domain
365
*/
366
public abstract AFSocketDomain getSocketDomain();
367
368
/**
369
* Sets default socket options for created sockets
370
* @param options Socket options to apply
371
*/
372
public abstract void setDefaultSocketOptions(Map<String, Object> options);
373
}
374
375
/**
376
* Factory for creating Unix Domain Sockets
377
*/
378
public class AFUNIXSocketFactory extends AFSocketFactory {
379
380
/**
381
* Gets the singleton instance
382
* @return AFUNIXSocketFactory instance
383
*/
384
public static AFUNIXSocketFactory getInstance();
385
386
/**
387
* Creates a new AFUNIXSocketFactory with custom configuration
388
* @param config Factory configuration
389
* @return Configured factory instance
390
*/
391
public static AFUNIXSocketFactory create(SocketFactoryConfig config);
392
393
@Override
394
public AFUNIXSocket createSocket() throws IOException;
395
396
@Override
397
public AFUNIXServerSocket createServerSocket() throws IOException;
398
399
@Override
400
public AFUNIXSocket connectTo(AFSocketAddress address) throws IOException;
401
402
/**
403
* Creates a socket bound to the specified address
404
* @param address Address to bind to
405
* @return Bound socket instance
406
* @throws IOException if binding fails
407
*/
408
public AFUNIXSocket createBoundSocket(AFUNIXSocketAddress address) throws IOException;
409
410
/**
411
* Creates a server socket bound to the specified address
412
* @param address Address to bind to
413
* @param backlog Connection backlog
414
* @return Bound server socket instance
415
* @throws IOException if binding fails
416
*/
417
public AFUNIXServerSocket createBoundServerSocket(AFUNIXSocketAddress address, int backlog) throws IOException;
418
}
419
```
420
421
**Usage Examples:**
422
423
```java
424
// Custom socket factory with preconfigured options
425
public class CustomSocketFactory {
426
427
public static void demonstrateFactoryUsage() throws IOException {
428
// Get standard factory
429
AFUNIXSocketFactory factory = AFUNIXSocketFactory.getInstance();
430
431
// Configure default options
432
Map<String, Object> defaultOptions = new HashMap<>();
433
defaultOptions.put("SO_TIMEOUT", 30000); // 30 second timeout
434
defaultOptions.put("SO_KEEPALIVE", true); // Enable keep-alive
435
defaultOptions.put("SO_REUSEADDR", true); // Enable address reuse
436
factory.setDefaultSocketOptions(defaultOptions);
437
438
// Create sockets with default options applied
439
try (AFUNIXSocket socket = factory.createSocket()) {
440
System.out.println("Created socket with default options");
441
442
// Connect to server
443
AFUNIXSocketAddress serverAddr = AFUNIXSocketAddress.of(new File("/tmp/server.sock"));
444
socket.connect(serverAddr);
445
446
// Socket already has timeout and keep-alive configured
447
System.out.println("Socket timeout: " + socket.getSoTimeout());
448
System.out.println("Keep-alive: " + socket.getKeepAlive());
449
}
450
451
// Create server socket with factory
452
AFUNIXSocketAddress serverAddr = AFUNIXSocketAddress.of(new File("/tmp/factory-server.sock"));
453
try (AFUNIXServerSocket server = factory.createBoundServerSocket(serverAddr, 50)) {
454
System.out.println("Server socket created with factory");
455
456
// Accept connections
457
try (AFUNIXSocket client = server.accept()) {
458
System.out.println("Client connected: " + client.getRemoteSocketAddress());
459
}
460
}
461
}
462
463
public static class SocketFactoryConfig {
464
private int defaultTimeout = 0;
465
private boolean defaultKeepAlive = false;
466
private boolean defaultReuseAddress = true;
467
private int defaultBufferSize = 8192;
468
469
public SocketFactoryConfig setTimeout(int timeout) {
470
this.defaultTimeout = timeout;
471
return this;
472
}
473
474
public SocketFactoryConfig setKeepAlive(boolean keepAlive) {
475
this.defaultKeepAlive = keepAlive;
476
return this;
477
}
478
479
public SocketFactoryConfig setReuseAddress(boolean reuseAddress) {
480
this.defaultReuseAddress = reuseAddress;
481
return this;
482
}
483
484
public SocketFactoryConfig setBufferSize(int bufferSize) {
485
this.defaultBufferSize = bufferSize;
486
return this;
487
}
488
489
// Getters
490
public int getDefaultTimeout() { return defaultTimeout; }
491
public boolean isDefaultKeepAlive() { return defaultKeepAlive; }
492
public boolean isDefaultReuseAddress() { return defaultReuseAddress; }
493
public int getDefaultBufferSize() { return defaultBufferSize; }
494
}
495
496
// Custom factory implementation
497
public static AFUNIXSocketFactory createCustomFactory() {
498
SocketFactoryConfig config = new SocketFactoryConfig()
499
.setTimeout(60000) // 1 minute timeout
500
.setKeepAlive(true) // Enable keep-alive
501
.setReuseAddress(true) // Enable address reuse
502
.setBufferSize(16384); // 16KB buffer
503
504
return AFUNIXSocketFactory.create(config);
505
}
506
}
507
```
508
509
### Native Library Management
510
511
Native library loading and management for cross-platform socket implementations.
512
513
```java { .api }
514
/**
515
* Loads native libraries for junixsocket
516
*/
517
public class NativeLibraryLoader {
518
519
/**
520
* Loads the native junixsocket library
521
* @return true if library loaded successfully
522
*/
523
public static boolean loadNativeLibrary();
524
525
/**
526
* Checks if native library is loaded
527
* @return true if native library is available
528
*/
529
public static boolean isNativeLibraryLoaded();
530
531
/**
532
* Gets the native library version
533
* @return Version string or null if not loaded
534
*/
535
public static String getNativeLibraryVersion();
536
537
/**
538
* Gets native library information
539
* @return Library information string
540
*/
541
public static String getNativeLibraryInfo();
542
543
/**
544
* Forces reload of native library
545
* @return true if reload successful
546
*/
547
public static boolean reloadNativeLibrary();
548
549
/**
550
* Gets supported platforms for native library
551
* @return Set of supported platform names
552
*/
553
public static Set<String> getSupportedPlatforms();
554
}
555
556
/**
557
* JNI interface to native Unix socket implementations
558
*/
559
public class NativeUnixSocket {
560
561
/**
562
* Checks if native implementation is loaded and available
563
* @return true if native implementation is available
564
*/
565
public static boolean isLoaded();
566
567
/**
568
* Gets the native socket implementation version
569
* @return Version information
570
*/
571
public static String getVersion();
572
573
/**
574
* Performs native library self-test
575
* @return true if self-test passes
576
*/
577
public static boolean selfTest();
578
579
/**
580
* Gets platform-specific capabilities
581
* @return Map of capability names to availability
582
*/
583
public static Map<String, Boolean> getPlatformCapabilities();
584
585
/**
586
* Gets native library build information
587
* @return Build information string
588
*/
589
public static String getBuildInfo();
590
}
591
```
592
593
**Usage Examples:**
594
595
```java
596
// Native library management and diagnostics
597
public class NativeLibraryDiagnostics {
598
599
public static void performDiagnostics() {
600
System.out.println("junixsocket Native Library Diagnostics");
601
System.out.println("=====================================");
602
603
// Check native library status
604
boolean loaded = NativeLibraryLoader.isNativeLibraryLoaded();
605
System.out.println("Native library loaded: " + loaded);
606
607
if (!loaded) {
608
System.out.println("Attempting to load native library...");
609
boolean loadResult = NativeLibraryLoader.loadNativeLibrary();
610
System.out.println("Load result: " + loadResult);
611
612
if (!loadResult) {
613
System.err.println("Failed to load native library");
614
printTroubleshootingInfo();
615
return;
616
}
617
}
618
619
// Display library information
620
System.out.println("Native library version: " + NativeLibraryLoader.getNativeLibraryVersion());
621
System.out.println("Native library info: " + NativeLibraryLoader.getNativeLibraryInfo());
622
623
// Display supported platforms
624
Set<String> supportedPlatforms = NativeLibraryLoader.getSupportedPlatforms();
625
System.out.println("Supported platforms: " + supportedPlatforms);
626
627
// Check native Unix socket implementation
628
System.out.println("\nNative Unix Socket Implementation:");
629
System.out.println("Available: " + NativeUnixSocket.isLoaded());
630
631
if (NativeUnixSocket.isLoaded()) {
632
System.out.println("Version: " + NativeUnixSocket.getVersion());
633
System.out.println("Build info: " + NativeUnixSocket.getBuildInfo());
634
635
// Perform self-test
636
boolean selfTestResult = NativeUnixSocket.selfTest();
637
System.out.println("Self-test result: " + selfTestResult);
638
639
if (selfTestResult) {
640
// Display platform capabilities
641
Map<String, Boolean> capabilities = NativeUnixSocket.getPlatformCapabilities();
642
System.out.println("Platform capabilities:");
643
for (Map.Entry<String, Boolean> entry : capabilities.entrySet()) {
644
System.out.printf(" %-30s: %s%n",
645
entry.getKey(),
646
entry.getValue() ? "✓" : "✗");
647
}
648
}
649
}
650
}
651
652
private static void printTroubleshootingInfo() {
653
System.err.println("\nTroubleshooting Information:");
654
System.err.println("Current platform: " + System.getProperty("os.name") +
655
" " + System.getProperty("os.arch"));
656
System.err.println("Java version: " + System.getProperty("java.version"));
657
System.err.println("Java library path: " + System.getProperty("java.library.path"));
658
659
System.err.println("\nPossible solutions:");
660
System.err.println("1. Ensure you're using a supported platform");
661
System.err.println("2. Check that the native library is included in your dependencies");
662
System.err.println("3. Verify Java library path contains junixsocket native libraries");
663
System.err.println("4. Try updating to the latest junixsocket version");
664
}
665
666
public static void validateEnvironment() throws IOException {
667
if (!NativeLibraryLoader.isNativeLibraryLoaded()) {
668
if (!NativeLibraryLoader.loadNativeLibrary()) {
669
throw new IOException("Failed to load junixsocket native library");
670
}
671
}
672
673
if (!NativeUnixSocket.isLoaded()) {
674
throw new IOException("Native Unix socket implementation not available");
675
}
676
677
if (!NativeUnixSocket.selfTest()) {
678
throw new IOException("Native library self-test failed");
679
}
680
681
System.out.println("Environment validation successful - all native components available");
682
}
683
684
public static void main(String[] args) {
685
try {
686
performDiagnostics();
687
validateEnvironment();
688
} catch (Exception e) {
689
System.err.println("Diagnostic failed: " + e.getMessage());
690
System.exit(1);
691
}
692
}
693
}
694
695
// Application initialization with native library verification
696
public class ApplicationInitializer {
697
698
public static void initializeWithNativeSupport() throws IOException {
699
System.out.println("Initializing application with junixsocket native support...");
700
701
// Verify native library availability
702
if (!NativeLibraryLoader.isNativeLibraryLoaded()) {
703
throw new IOException("Native library not loaded - cannot initialize Unix socket support");
704
}
705
706
// Check native implementation
707
if (!NativeUnixSocket.isLoaded()) {
708
throw new IOException("Native Unix socket implementation not available");
709
}
710
711
// Perform basic functionality test
712
if (!NativeUnixSocket.selfTest()) {
713
System.err.println("Warning: Native library self-test failed - some features may not work correctly");
714
}
715
716
// Log initialization success
717
System.out.println("Native support initialized successfully");
718
System.out.println(" Library version: " + NativeLibraryLoader.getNativeLibraryVersion());
719
System.out.println(" Implementation version: " + NativeUnixSocket.getVersion());
720
721
// Initialize socket services
722
initializeSocketServices();
723
}
724
725
private static void initializeSocketServices() {
726
System.out.println("Socket services initialized");
727
}
728
}
729
```
730
731
## Advanced Utility Patterns
732
733
### Resource Management
734
735
```java
736
// Resource management utility for socket cleanup
737
public class SocketResourceManager {
738
private final Set<AutoCloseable> managedResources = ConcurrentHashMap.newKeySet();
739
740
public <T extends AutoCloseable> T manage(T resource) {
741
managedResources.add(resource);
742
return resource;
743
}
744
745
public void closeAll() {
746
for (AutoCloseable resource : managedResources) {
747
try {
748
resource.close();
749
} catch (Exception e) {
750
System.err.println("Error closing resource: " + e.getMessage());
751
}
752
}
753
managedResources.clear();
754
}
755
756
public AFUNIXSocket createManagedSocket() throws IOException {
757
return manage(AFUNIXSocket.newInstance());
758
}
759
760
public AFUNIXServerSocket createManagedServerSocket() throws IOException {
761
return manage(AFUNIXServerSocket.newInstance());
762
}
763
}
764
```