[jnr-netdb] 01/02: Merge fix from master for 'Use _r() versions of getservbyname, getservbyport, etc for linux'

Miguel Landaeta nomadium at moszumanska.debian.org
Thu Feb 12 02:40:44 UTC 2015


This is an automated email from the git hooks/post-receive script.

nomadium pushed a commit to tag 1.0.7
in repository jnr-netdb.

commit 0b0c5af3ebd23454d39ba6bf5f198736bbc46644
Author: Wayne Meissner <wmeissner at gmail.com>
Date:   Tue Jul 10 23:21:49 2012 +1000

    Merge fix from master for 'Use _r() versions of getservbyname, getservbyport, etc for linux'
---
 src/jnr/netdb/NativeProtocolsDB.java | 131 +++++++++++++++++++-------
 src/jnr/netdb/NativeServicesDB.java  | 174 ++++++++++++++++++++++++++---------
 2 files changed, 228 insertions(+), 77 deletions(-)

diff --git a/src/jnr/netdb/NativeProtocolsDB.java b/src/jnr/netdb/NativeProtocolsDB.java
index ac9e61e..80dbd5e 100644
--- a/src/jnr/netdb/NativeProtocolsDB.java
+++ b/src/jnr/netdb/NativeProtocolsDB.java
@@ -18,11 +18,9 @@
 
 package jnr.netdb;
 
-import com.kenai.jaffl.CallingConvention;
-import com.kenai.jaffl.Library;
-import com.kenai.jaffl.LibraryOption;
-import com.kenai.jaffl.Platform;
-import com.kenai.jaffl.Pointer;
+import com.kenai.jaffl.*;
+import com.kenai.jaffl.annotations.Direct;
+
 import java.util.ArrayList;
 
 import java.util.Collection;
@@ -38,9 +36,7 @@ import static com.kenai.jaffl.Platform.OS.*;
 /**
  *
  */
-final class NativeProtocolsDB implements ProtocolsDB {
-
-    private final LibProto lib;
+abstract class NativeProtocolsDB implements ProtocolsDB {
 
     public static final NativeProtocolsDB getInstance() {
         return SingletonHolder.INSTANCE;
@@ -50,10 +46,6 @@ final class NativeProtocolsDB implements ProtocolsDB {
         public static final NativeProtocolsDB INSTANCE = load();
     }
 
-    NativeProtocolsDB(LibProto lib) {
-        this.lib = lib;
-    }
-
     private static final NativeProtocolsDB load() {
         try {
             Platform.OS os = Platform.getPlatform().getOS();
@@ -75,14 +67,19 @@ final class NativeProtocolsDB implements ProtocolsDB {
                 String[] libnames = os.equals(SOLARIS)
                 ? new String[] { "socket", "nsl", "c" }
                 : new String[] { "c" };
-                lib = Library.loadLibrary(LibProto.class, libnames);
+                lib = os.equals(LINUX)
+                        ? Library.loadLibrary(LinuxLibProto.class, libnames)
+                        : Library.loadLibrary(LibProto.class, libnames);
             }
-                        
+
+            NativeProtocolsDB protocolsDB = os.equals(LINUX)
+                    ? new LinuxNativeProtocolsDB((LinuxLibProto) lib)
+                    : new DefaultNativeProtocolsDB(lib);
             // Try to lookup a protocol to make sure the library loaded and found the functions
-            lib.getprotobyname("ip");
-            lib.getprotobynumber(0);
-            
-            return new NativeProtocolsDB(lib);
+            protocolsDB.getProtocolByName("ip");
+            protocolsDB.getProtocolByNumber(0);
+
+            return protocolsDB;
         } catch (Throwable t) {
             Logger.getLogger(NativeProtocolsDB.class.getName()).log(Level.WARNING, "Failed to load native protocols db", t);
             return null;
@@ -99,10 +96,17 @@ final class NativeProtocolsDB implements ProtocolsDB {
         UnixProtoent getprotobyname(String name);
         UnixProtoent getprotobynumber(int proto);
         UnixProtoent getprotoent();
+        void setprotoent(int stayopen);
         void endprotoent();
     }
-    
-    private final Protocol protocolFromNative(UnixProtoent p) {
+
+    public static interface LinuxLibProto extends LibProto{
+        int getprotobyname_r(String proto, @Direct UnixProtoent protoent, Pointer buf, NativeLong buflen, Pointer result);
+        int getprotobynumber_r(int proto, @Direct UnixProtoent protoent, Pointer buf, NativeLong buflen, Pointer result);
+        int getprotoent_r(@Direct UnixProtoent protoent, Pointer buf, NativeLong buflen, Pointer result);
+    }
+
+    static Protocol protocolFromNative(UnixProtoent p) {
         if (p == null) {
             return null;
         }
@@ -116,26 +120,85 @@ final class NativeProtocolsDB implements ProtocolsDB {
         return new Protocol(p.name.get(), (short) p.proto.get(), aliases);
     }
 
-    public Protocol getProtocolByName(String name) {
-        return protocolFromNative(lib.getprotobyname(name));
-    }
+    static final class DefaultNativeProtocolsDB extends NativeProtocolsDB {
+        private final LibProto lib;
+
+        DefaultNativeProtocolsDB(LibProto lib) {
+            this.lib = lib;
+        }
+
+        public synchronized Protocol getProtocolByName(String name) {
+            return protocolFromNative(lib.getprotobyname(name));
+        }
+
+        public synchronized Protocol getProtocolByNumber(Integer proto) {
+            return protocolFromNative(lib.getprotobynumber(proto));
+        }
 
-    public Protocol getProtocolByNumber(Integer proto) {
-        return protocolFromNative(lib.getprotobynumber(proto));
+        public synchronized Collection<Protocol> getAllProtocols() {
+            UnixProtoent p;
+            List<Protocol> allProtocols = new ArrayList<Protocol>();
+
+            lib.setprotoent(0);
+            try {
+                while ((p = lib.getprotoent()) != null) {
+                    allProtocols.add(protocolFromNative(p));
+                }
+            } finally {
+                lib.endprotoent();
+            }
+
+            return allProtocols;
+        }
     }
 
-    public Collection<Protocol> getAllProtocols() {
-        UnixProtoent p;
-        List<Protocol> allProtocols = new ArrayList<Protocol>();
+    static final class LinuxNativeProtocolsDB extends NativeProtocolsDB {
+        private static final int BUFLEN = 4096;
+        private final Pointer buf;
+        private final LinuxLibProto lib;
 
-        try {
-            while ((p = lib.getprotoent()) != null) {
-                allProtocols.add(protocolFromNative(p));
+
+        LinuxNativeProtocolsDB(LinuxLibProto lib) {
+            this.lib = lib;
+            this.buf = MemoryIO.allocateDirect(BUFLEN);
+        }
+
+        public synchronized Protocol getProtocolByName(String name) {
+            UnixProtoent protoent = new UnixProtoent();
+            Pointer result = MemoryIO.allocateDirect(8);
+            if (lib.getprotobyname_r(name, protoent, buf, new NativeLong(BUFLEN), result) == 0) {
+                return result.getPointer(0) != null ? protocolFromNative(protoent) : null;
             }
-        } finally {
-            lib.endprotoent();
+
+            throw new RuntimeException("getprotobyname_r failed");
         }
 
-        return allProtocols;
+        public synchronized Protocol getProtocolByNumber(Integer number) {
+            UnixProtoent protoent = new UnixProtoent();
+            Pointer result = MemoryIO.allocateDirect(8);
+            if (lib.getprotobynumber_r(number, protoent, buf, new NativeLong(BUFLEN), result) == 0) {
+                return result.getPointer(0) != null ? protocolFromNative(protoent) : null;
+            }
+
+            throw new RuntimeException("getprotobynumber_r failed");
+        }
+
+        public synchronized Collection<Protocol> getAllProtocols() {
+            UnixProtoent p = new UnixProtoent();
+            List<Protocol> allProtocols = new ArrayList<Protocol>();
+            Pointer result = MemoryIO.allocateDirect(8);
+            NativeLong buflen = new NativeLong(BUFLEN);
+
+            lib.setprotoent(0);
+            try {
+                while (lib.getprotoent_r(p, buf, buflen, result) == 0 && result.getPointer(0) != null) {
+                    allProtocols.add(protocolFromNative(p));
+                }
+            } finally {
+                lib.endprotoent();
+            }
+
+            return allProtocols;
+        }
     }
 }
diff --git a/src/jnr/netdb/NativeServicesDB.java b/src/jnr/netdb/NativeServicesDB.java
index a45d9ae..ac47860 100644
--- a/src/jnr/netdb/NativeServicesDB.java
+++ b/src/jnr/netdb/NativeServicesDB.java
@@ -18,11 +18,10 @@
 
 package jnr.netdb;
 
-import com.kenai.jaffl.CallingConvention;
-import com.kenai.jaffl.Library;
-import com.kenai.jaffl.LibraryOption;
-import com.kenai.jaffl.Platform;
-import com.kenai.jaffl.Pointer;
+import com.kenai.jaffl.*;
+import com.kenai.jaffl.annotations.Direct;
+import com.kenai.jaffl.annotations.Out;
+
 import java.nio.ByteOrder;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -38,9 +37,9 @@ import static com.kenai.jaffl.Platform.OS.*;
 /**
  *
  */
-final class NativeServicesDB implements ServicesDB {
+abstract class NativeServicesDB implements ServicesDB {
 
-    private final LibServices lib;
+    protected final LibServices lib;
 
     public NativeServicesDB(LibServices lib) {
         this.lib = lib;
@@ -71,18 +70,31 @@ final class NativeServicesDB implements ServicesDB {
                 Map<LibraryOption, Object> options = new HashMap<LibraryOption, Object>();
                 options.put(LibraryOption.CallingConvention, CallingConvention.STDCALL);
                 lib = Library.loadLibrary(LibServices.class, options, "Ws2_32");
+
             } else {
                 String[] libnames = os.equals(SOLARIS)
-                ? new String[] { "socket", "nsl", "c" }
-                : new String[] { "c" };
-                lib = Library.loadLibrary(LibServices.class, libnames);
+                    ? new String[] { "socket", "nsl", "c" }
+                    : new String[] { "c" };
+
+                if (os.equals(LINUX)) {
+                    lib = Library.loadLibrary(LinuxLibServices.class, libnames);
+                } else {
+                    lib = Library.loadLibrary(LibServices.class, libnames);
+                }
             }
 
+            NativeServicesDB services = os.equals(LINUX)
+                    ? new LinuxServicesDB(lib)
+                    : new DefaultNativeServicesDB(lib);
             // Try to lookup a service to make sure the library loaded and found the functions
-            lib.getservbyname("bootps", "udp");
-            lib.getservbyport(67, "udp");
+            if (services.getServiceByName("comsat", "udp") == null) {
+                return null;
+            }
+            services.getServiceByName("bootps", "udp");
+            services.getServiceByPort(67, "udp");
+
+            return services;
 
-            return new NativeServicesDB(lib);
         } catch (Throwable t) {
             Logger.getLogger(NativeServicesDB.class.getName()).log(Level.WARNING, "Failed to load native services db", t);
             return null;
@@ -96,60 +108,136 @@ final class NativeServicesDB implements ServicesDB {
         public final String proto = new UTF8StringRef();
     }
 
+    public static class LinuxServent extends UnixServent {
+        public static final int BUFLEN = 4096;
+        public final MemoryIO buf;
+
+        public LinuxServent() {
+            this.buf = MemoryIO.allocateDirect(BUFLEN, true);
+        }
+    }
+
     public static interface LibServices {
         UnixServent getservbyname(String name, String proto);
         UnixServent getservbyport(Integer port, String proto);
         UnixServent getservent();
         void endservent();
     }
-    
-    public Collection<Service> getAllServices() {
-        UnixServent s;
-        List<Service> allServices = new ArrayList<Service>();
 
-        try {
-            while ((s = lib.getservent()) != null) {
-                allServices.add(serviceFromNative(s));
-            }
-        } finally {
-            lib.endservent();
+    public static interface LinuxLibServices extends LibServices {
+        int getservbyname_r(String name, String proto, @Direct UnixServent servent,
+                                    Pointer buf, NativeLong buflen, @Out Pointer result);
+        int getservbyport_r(Integer port, String proto, @Direct UnixServent servent,
+                                    Pointer buf, NativeLong buflen, @Out Pointer result);
+        int getservent_r(@Direct UnixServent servent,
+                         Pointer buf, NativeLong buflen, Pointer result);
+    }
+
+    static int ntohs(int value) {
+        int hostValue =  ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN) ? Short.reverseBytes((short) value) : value;
+        if (hostValue < 0) {
+            // The byte flipping above will return numbers >= 32768 as a negative value,
+            // so they need to be converted back to a unsigned 16 bit value.
+            hostValue = ((hostValue & 0x7FFF) + 0x8000);
         }
 
-        return allServices;
+        return hostValue;
+    }
+
+    static int htons(int value) {
+        return ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN) ? Short.reverseBytes((short) value) : value;
     }
 
-    private final Service serviceFromNative(UnixServent s) {
+    static Service serviceFromNative(UnixServent s) {
         if (s == null) {
             return null;
         }
 
-        // servent#port is in network byte order - but jaffl will assume it is in host byte order
-        // so it needs to be reversed again to be correct.
-        int port = ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN) ? Short.reverseBytes((short) s.port.get()) : s.port.get();
-        if (port < 0) {
-            // The s_port field is really an unsigned 16 bit quantity, but the
-            // byte flipping above will return numbers >= 32768 as a negative value,
-            // so they need to be converted back to a unsigned 16 bit value.
-            port = (int) ((port & 0x7FFF) + 0x8000);
-        }
-
         List<String> emptyAliases = Collections.emptyList();
         Pointer ptr;
         final Collection<String> aliases = ((ptr = s.aliases.get()) != null)
                 ? StringUtil.getNullTerminatedStringArray(ptr) : emptyAliases;
 
-        return s != null ? new Service(s.name.get(), port, s.proto.get(), aliases) : null;
+        return new Service(s.name.get(), ntohs(s.port.get()), s.proto.get(), aliases);
     }
 
-    public Service getServiceByName(String name, String proto) {
-        return serviceFromNative(lib.getservbyname(name, proto));
-    }
+    static final class DefaultNativeServicesDB extends NativeServicesDB {
+        DefaultNativeServicesDB(LibServices lib) {
+            super(lib);
+        }
 
-    public Service getServiceByPort(Integer port, String proto) {
-        int nport = ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN) ? Short.reverseBytes(port.shortValue()) : port.shortValue();
-        
-        return serviceFromNative(lib.getservbyport(nport, proto));
+        public Collection<Service> getAllServices() {
+            UnixServent s;
+            List<Service> allServices = new ArrayList<Service>();
+
+            try {
+                while ((s = lib.getservent()) != null) {
+                    allServices.add(serviceFromNative(s));
+                }
+            } finally {
+                lib.endservent();
+            }
+
+            return allServices;
+        }
+
+
+        public Service getServiceByName(String name, String proto) {
+            return serviceFromNative(lib.getservbyname(name, proto));
+        }
+
+        public Service getServiceByPort(Integer port, String proto) {
+            return serviceFromNative(lib.getservbyport(htons(port), proto));
+        }
     }
 
+    static final class LinuxServicesDB extends NativeServicesDB {
+        private static final int BUFLEN = 4096;
+        private final LinuxLibServices lib;
+        private final Pointer buf;
+
+        LinuxServicesDB(LibServices lib) {
+            super(lib);
+            this.lib = (LinuxLibServices) lib;
+            this.buf = MemoryIO.allocateDirect(BUFLEN);
+        }
+
+        public synchronized Service getServiceByName(String name, String proto) {
+            UnixServent servent = new UnixServent();
+            Pointer result = MemoryIO.allocateDirect(8);
+            if (lib.getservbyname_r(name, proto, servent, buf, new NativeLong(BUFLEN), result) == 0) {
+                return result.getPointer(0) != null ? serviceFromNative(servent) : null;
+            }
+
+            throw new RuntimeException("getservbyname_r failed");
+        }
+
+        public synchronized Service getServiceByPort(Integer port, String proto) {
+            UnixServent servent = new UnixServent();
+            Pointer result = MemoryIO.allocateDirect(8);
+            if (lib.getservbyport_r(htons(port), proto, servent, buf, new NativeLong(BUFLEN), result) == 0) {
+                return result.getPointer(0) != null ? serviceFromNative(servent) : null;
+            }
+
+            throw new RuntimeException("getservbyport_r failed");
+        }
+
+        public synchronized Collection<Service> getAllServices() {
+            UnixServent s = new UnixServent();
+            List<Service> allServices = new ArrayList<Service>();
+            Pointer result = MemoryIO.allocateDirect(8);
+            NativeLong buflen = new NativeLong(BUFLEN);
+
+            try {
+                while (lib.getservent_r(s, buf, buflen, result) == 0 && result.getPointer(0) != null) {
+                    allServices.add(serviceFromNative(s));
+                }
+            } finally {
+                lib.endservent();
+            }
+
+            return allServices;
+        }
+    }
 
 }

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/jnr-netdb.git



More information about the pkg-java-commits mailing list