diff options
Diffstat (limited to 'native')
-rw-r--r-- | native/jawt/jawt.c | 2 | ||||
-rw-r--r-- | native/jni/classpath/classpath_jawt.h | 1 | ||||
-rw-r--r-- | native/jni/classpath/jcl.c | 2 | ||||
-rw-r--r-- | native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c | 73 | ||||
-rw-r--r-- | native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFramePeer.c | 44 | ||||
-rw-r--r-- | native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c | 38 | ||||
-rw-r--r-- | native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c | 64 | ||||
-rw-r--r-- | native/jni/gtk-peer/gtk_jawt.c | 35 | ||||
-rw-r--r-- | native/jni/java-net/Makefile.am | 1 | ||||
-rw-r--r-- | native/jni/java-net/gnu_java_net_VMPlainSocketImpl.c | 170 | ||||
-rw-r--r-- | native/jni/java-net/javanet.c | 2 | ||||
-rw-r--r-- | native/jni/java-net/javanet.h | 1 | ||||
-rw-r--r-- | native/jni/java-nio/gnu_java_nio_VMChannel.c | 104 | ||||
-rw-r--r-- | native/jni/native-lib/cpio.c | 10 | ||||
-rw-r--r-- | native/jni/native-lib/cpio.h | 1 |
15 files changed, 406 insertions, 142 deletions
diff --git a/native/jawt/jawt.c b/native/jawt/jawt.c index a41786850..4ebb105d7 100644 --- a/native/jawt/jawt.c +++ b/native/jawt/jawt.c @@ -116,6 +116,8 @@ static JAWT_DrawingSurfaceInfo* surface->target); surface_info_x11->visualID = classpath_jawt_get_visualID (surface->env, surface->target); + surface_info_x11->depth = classpath_jawt_get_depth (surface->env, + surface->target); /* FIXME: also include bounding rectangle of drawing surface */ /* FIXME: also include current clipping region */ diff --git a/native/jni/classpath/classpath_jawt.h b/native/jni/classpath/classpath_jawt.h index 32a04dc5c..35c734a57 100644 --- a/native/jni/classpath/classpath_jawt.h +++ b/native/jni/classpath/classpath_jawt.h @@ -54,6 +54,7 @@ jint classpath_jawt_get_awt_version (void); Display* classpath_jawt_get_default_display (JNIEnv* env, jobject canvas); Drawable classpath_jawt_get_drawable (JNIEnv* env, jobject canvas); VisualID classpath_jawt_get_visualID (JNIEnv* env, jobject canvas); +int classpath_jawt_get_depth (JNIEnv* env, jobject canvas); jint classpath_jawt_lock (void); void classpath_jawt_unlock (void); diff --git a/native/jni/classpath/jcl.c b/native/jni/classpath/jcl.c index 607b54d57..cd3f5161d 100644 --- a/native/jni/classpath/jcl.c +++ b/native/jni/classpath/jcl.c @@ -58,7 +58,7 @@ static jmethodID rawData_mid = NULL; /* * JNI OnLoad constructor. */ -jint +JNIEXPORT jint JNICALL JNI_OnLoad (JavaVM *vm, void *reserved __attribute__((unused))) { JNIEnv *env; diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c index 0a35a3f18..11b0426c6 100644 --- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c +++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c @@ -49,7 +49,6 @@ exception statement from your version. */ #include <stdio.h> #include <stdlib.h> -static void install_font_peer(cairo_t *cr, struct peerfont *pfont); static void update_pattern_transform (struct cairographics2d *gr); /** @@ -327,8 +326,6 @@ Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoDrawGlyphVector pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, font); g_assert (pfont != NULL); - install_font_peer(gr->cr, pfont); - glyphs = g_malloc( sizeof(cairo_glyph_t) * n); g_assert (glyphs != NULL); @@ -354,6 +351,37 @@ Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoDrawGlyphVector JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetFont +(JNIEnv *env __attribute__ ((unused)), jobject obj __attribute__ ((unused)), + jlong pointer, jobject font) +{ + struct cairographics2d *gr = NULL; + struct peerfont *pfont = NULL; + FT_Face face = NULL; + cairo_font_face_t *ft = NULL; + + gr = JLONG_TO_PTR(struct cairographics2d, pointer); + g_assert (gr != NULL); + + pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, font); + g_assert (pfont != NULL); + + face = pango_fc_font_lock_face( (PangoFcFont *)pfont->font ); + g_assert (face != NULL); + + ft = cairo_ft_font_face_create_for_ft_face (face, 0); + g_assert (ft != NULL); + + cairo_set_font_face (gr->cr, ft); + cairo_set_font_size (gr->cr, + (pango_font_description_get_size (pfont->desc) / + (double)PANGO_SCALE)); + + cairo_font_face_destroy (ft); + pango_fc_font_unlock_face((PangoFcFont *)pfont->font); +} + +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetOperator (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), jlong pointer, jint op) @@ -748,45 +776,6 @@ Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoFillRect cairo_fill(gr->cr); } - -/************************** FONT STUFF ****************************/ -static void -install_font_peer(cairo_t *cr, - struct peerfont *pfont) -{ - cairo_font_face_t *ft; - FT_Face face = NULL; - - g_assert(cr != NULL); - g_assert(pfont != NULL); - - if (pfont->graphics_resource == NULL) - { - face = pango_fc_font_lock_face( (PangoFcFont *)pfont->font ); - g_assert (face != NULL); - - ft = cairo_ft_font_face_create_for_ft_face (face, 0); - g_assert (ft != NULL); - - cairo_set_font_face (cr, ft); - /* cairo_font_face_destroy (ft);*/ - cairo_set_font_size (cr, - (pango_font_description_get_size (pfont->desc) / - (double)PANGO_SCALE)); - ft = cairo_get_font_face (cr); - pango_fc_font_unlock_face( (PangoFcFont *)pfont->font ); - pfont->graphics_resource = ft; - } - else - { - ft = (cairo_font_face_t *) pfont->graphics_resource; - cairo_set_font_face (cr, ft); - cairo_set_font_size (cr, - (pango_font_description_get_size (pfont->desc) / - (double)PANGO_SCALE)); - } -} - static void update_pattern_transform (struct cairographics2d *gr) { diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFramePeer.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFramePeer.c index 766964314..144ca0e8a 100644 --- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFramePeer.c +++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFramePeer.c @@ -188,3 +188,47 @@ Java_gnu_java_awt_peer_gtk_GtkFramePeer_nativeSetIconImage gdk_threads_leave (); } + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkFramePeer_maximize +(JNIEnv *env, jobject obj) +{ + void *ptr; + gdk_threads_enter (); + ptr = NSA_GET_PTR (env, obj); + gtk_window_maximize (GTK_WINDOW (ptr)); + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkFramePeer_unmaximize +(JNIEnv *env, jobject obj) +{ + void *ptr; + gdk_threads_enter (); + ptr = NSA_GET_PTR (env, obj); + gtk_window_unmaximize (GTK_WINDOW (ptr)); + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkFramePeer_iconify +(JNIEnv *env, jobject obj) +{ + void *ptr; + gdk_threads_enter (); + ptr = NSA_GET_PTR (env, obj); + gtk_window_iconify (GTK_WINDOW (ptr)); + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkFramePeer_deiconify +(JNIEnv *env, jobject obj) +{ + void *ptr; + gdk_threads_enter (); + ptr = NSA_GET_PTR (env, obj); + gtk_window_deiconify (GTK_WINDOW (ptr)); + gdk_threads_leave (); +} diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c index 969b7bc5c..0f868eaed 100644 --- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c +++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c @@ -77,8 +77,10 @@ struct state_table *cp_gtk_native_state_table; struct state_table *cp_gtk_native_global_ref_table; static jclass gtkgenericpeer; +static jclass gtktoolkit; static JavaVM *java_vm; static jmethodID printCurrentThreadID; +static jmethodID setRunningID; union env_union { @@ -99,7 +101,9 @@ GtkWindowGroup *cp_gtk_global_window_group; double cp_gtk_dpi_conversion_factor; static void init_glib_threads(JNIEnv *, jint); - +static gboolean post_set_running_flag (gpointer); +static gboolean set_running_flag (gpointer); +static gboolean clear_running_flag (gpointer); static void init_dpi_conversion_factor (void); static void dpi_changed_cb (GtkSettings *settings, GParamSpec *pspec); @@ -199,6 +203,10 @@ Java_gnu_java_awt_peer_gtk_GtkToolkit_gtkInit (JNIEnv *env, cp_gtk_global_window_group = gtk_window_group_new (); init_dpi_conversion_factor (); + + gtktoolkit = (*env)->FindClass(env, "gnu/java/awt/peer/gtk/GtkMainThread"); + setRunningID = (*env)->GetStaticMethodID (env, gtktoolkit, + "setRunning", "(Z)V"); } @@ -324,6 +332,9 @@ Java_gnu_java_awt_peer_gtk_GtkToolkit_gtkMain { gdk_threads_enter (); + gtk_init_add (post_set_running_flag, NULL); + gtk_quit_add (gtk_main_level (), clear_running_flag, NULL); + gtk_main (); gdk_threads_leave (); @@ -502,3 +513,28 @@ gdk_color_to_java_color (GdkColor gdk_color) return (jint) (0xff000000 | (red << 16) | (green << 8) | blue); } + +static gboolean +post_set_running_flag (gpointer data __attribute__((unused))) +{ + g_idle_add (set_running_flag, NULL); + return FALSE; +} + +static gboolean +set_running_flag (gpointer data __attribute__((unused))) +{ + (*cp_gtk_gdk_env ())->CallStaticVoidMethod (cp_gtk_gdk_env (), + gtktoolkit, + setRunningID, TRUE); + return FALSE; +} + +static gboolean +clear_running_flag (gpointer data __attribute__((unused))) +{ + (*cp_gtk_gdk_env ())->CallStaticVoidMethod (cp_gtk_gdk_env (), + gtktoolkit, + setRunningID, FALSE); + return FALSE; +} diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c index 3f288af5c..aa70b9d2d 100644 --- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c +++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c @@ -44,7 +44,6 @@ exception statement from your version. */ #include <X11/Xatom.h> #include <gdk/gdkkeysyms.h> -#define AWT_WINDOW_OPENED 200 #define AWT_WINDOW_CLOSING 201 #define AWT_WINDOW_CLOSED 202 #define AWT_WINDOW_ICONIFIED 203 @@ -55,6 +54,10 @@ exception statement from your version. */ #define AWT_WINDOW_LOST_FOCUS 208 #define AWT_WINDOW_STATE_CHANGED 209 +#define AWT_FRAME_NORMAL 0 +#define AWT_FRAME_ICONIFIED 1 +#define AWT_FRAME_MAXIMIZED_BOTH 6 + /* Virtual Keys */ /* This list should be kept in the same order as the VK_ field declarations in KeyEvent.java. */ @@ -1046,7 +1049,6 @@ static gboolean window_delete_cb (GtkWidget *widget, GdkEvent *event, jobject peer); static void window_destroy_cb (GtkWidget *widget, GdkEvent *event, jobject peer); -static void window_show_cb (GtkWidget *widget, jobject peer); static void window_focus_state_change_cb (GtkWidget *widget, GParamSpec *pspec, jobject peer); @@ -1322,9 +1324,6 @@ Java_gnu_java_awt_peer_gtk_GtkWindowPeer_connectSignals g_signal_connect (G_OBJECT (ptr), "destroy-event", G_CALLBACK (window_destroy_cb), *gref); - g_signal_connect (G_OBJECT (ptr), "show", - G_CALLBACK (window_show_cb), *gref); - g_signal_connect (G_OBJECT (ptr), "notify::has-toplevel-focus", G_CALLBACK (window_focus_state_change_cb), *gref); @@ -1661,16 +1660,6 @@ window_destroy_cb (GtkWidget *widget __attribute__((unused)), } static void -window_show_cb (GtkWidget *widget __attribute__((unused)), - jobject peer) -{ - (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, - postWindowEventID, - (jint) AWT_WINDOW_OPENED, - (jobject) NULL, (jint) 0); -} - -static void window_focus_state_change_cb (GtkWidget *widget, GParamSpec *pspec __attribute__((unused)), jobject peer) @@ -1718,41 +1707,24 @@ window_window_state_cb (GtkWidget *widget __attribute__((unused)), GdkEvent *event, jobject peer) { - jint new_state; - - /* Handle WINDOW_ICONIFIED and WINDOW_DEICONIFIED events. */ - if (event->window_state.changed_mask & GDK_WINDOW_STATE_ICONIFIED) - { - /* We've either been iconified or deiconified. */ - if (event->window_state.new_window_state & GDK_WINDOW_STATE_ICONIFIED) - { - /* We've been iconified. */ - (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, - postWindowEventID, - (jint) AWT_WINDOW_ICONIFIED, - (jobject) NULL, (jint) 0); - } - else - { - /* We've been deiconified. */ - (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, - postWindowEventID, - (jint) AWT_WINDOW_DEICONIFIED, - (jobject) NULL, (jint) 0); - } - } - - /* Post a WINDOW_STATE_CHANGED event, passing the new frame state to - GtkWindowPeer. */ - new_state = AWT_FRAME_STATE_NORMAL; - - if (event->window_state.new_window_state & GDK_WINDOW_STATE_ICONIFIED) - new_state |= AWT_FRAME_STATE_ICONIFIED; + jint new_java_state = 0; + /* Put together the new state and let the java side figure out what + * to post */ + GdkWindowState new_state = event->window_state.new_window_state; + /* The window can be either iconfified, maximized, iconified + maximized + * or normal. */ + if ((new_state & GDK_WINDOW_STATE_ICONIFIED) != 0) + new_java_state |= AWT_FRAME_ICONIFIED; + if ((new_state & GDK_WINDOW_STATE_MAXIMIZED) != 0) + new_java_state |= AWT_FRAME_MAXIMIZED_BOTH; + if ((new_state & (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_ICONIFIED)) + == 0) + new_java_state = AWT_FRAME_NORMAL; (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, postWindowEventID, (jint) AWT_WINDOW_STATE_CHANGED, - (jobject) NULL, new_state); + (jobject) NULL, new_java_state); return TRUE; } diff --git a/native/jni/gtk-peer/gtk_jawt.c b/native/jni/gtk-peer/gtk_jawt.c index 763db8d1e..2348a63fb 100644 --- a/native/jni/gtk-peer/gtk_jawt.c +++ b/native/jni/gtk-peer/gtk_jawt.c @@ -122,6 +122,41 @@ classpath_jawt_get_visualID (JNIEnv* env, jobject canvas) /* Does not require locking: meant to be called after the drawing surface is locked. */ +int +classpath_jawt_get_depth (JNIEnv* env, jobject canvas) +{ + GtkWidget *widget; + GdkVisual *visual; + void *ptr; + jobject peer; + jclass class_id; + jmethodID method_id; + + class_id = (*env)->GetObjectClass (env, canvas); + + method_id = (*env)->GetMethodID (env, class_id, + "getPeer", + "()Ljava/awt/peer/ComponentPeer;"); + + peer = (*env)->CallObjectMethod (env, canvas, method_id); + + ptr = NSA_GET_PTR (env, peer); + + widget = GTK_WIDGET (ptr); + + if (GTK_WIDGET_REALIZED (widget)) + { + visual = gtk_widget_get_visual (widget); + g_assert (visual != NULL); + + return visual->depth; + } + else + return (VisualID) NULL; +} + +/* Does not require locking: meant to be called after the drawing + surface is locked. */ Drawable classpath_jawt_get_drawable (JNIEnv* env, jobject canvas) { diff --git a/native/jni/java-net/Makefile.am b/native/jni/java-net/Makefile.am index b743f2ffe..1278b946c 100644 --- a/native/jni/java-net/Makefile.am +++ b/native/jni/java-net/Makefile.am @@ -13,7 +13,6 @@ libjavanet_la_SOURCES = javanet.c \ java_net_VMInetAddress.c \ java_net_VMNetworkInterface.c \ java_net_VMURLConnection.c \ - gnu_java_net_VMPlainDatagramSocketImpl.c \ gnu_java_net_VMPlainSocketImpl.c \ $(local_sources) diff --git a/native/jni/java-net/gnu_java_net_VMPlainSocketImpl.c b/native/jni/java-net/gnu_java_net_VMPlainSocketImpl.c index 6ebb64fa5..53ef04d47 100644 --- a/native/jni/java-net/gnu_java_net_VMPlainSocketImpl.c +++ b/native/jni/java-net/gnu_java_net_VMPlainSocketImpl.c @@ -40,6 +40,8 @@ exception statement from your version. */ #include <config.h> #endif /* HAVE_CONFIG_H */ +#include <config-int.h> + #include <sys/ioctl.h> #include <sys/types.h> #include <sys/socket.h> @@ -47,6 +49,7 @@ exception statement from your version. */ #include <ifaddrs.h> #include <netinet/in.h> #include <netinet/tcp.h> +#include <net/if.h> #include <errno.h> #include <stdlib.h> #include <stdio.h> @@ -56,16 +59,14 @@ exception statement from your version. */ #include <jni.h> #include <jcl.h> -/* #include "javanet.h" */ +#include "cpnative.h" +#include "cpnet.h" +#include "cpio.h" +#include "javanet.h" #include "gnu_java_net_VMPlainSocketImpl.h" -#define IO_EXCEPTION "java/io/IOException" -#define SOCKET_EXCEPTION "java/net/SocketException" -#define BIND_EXCEPTION "java/net/BindException" - -#define THROW_NO_NETWORK(env) JCL_ThrowException (env, "java/lang/InternalError", "this platform not configured for network support") - +#define THROW_NO_NETWORK(env) JCL_ThrowException (env, "java/lang/InternalError", "this platform not configured for network support") /* * Class: gnu_java_net_VMPlainSocketImpl @@ -102,6 +103,8 @@ Java_gnu_java_net_VMPlainSocketImpl_bind (JNIEnv *env, if (-1 == ret) JCL_ThrowException (env, BIND_EXCEPTION, strerror (errno)); + + cpio_closeOnExec(ret); } @@ -158,7 +161,10 @@ Java_gnu_java_net_VMPlainSocketImpl_listen (JNIEnv *env, } -/* These constants are also defined in java/net/SocketOptions.java */ +/* These constants are also defined in java/net/SocketOptions.java. + * Except for CPNET_IP_TTL which is defined in + * vm/reference/gnu/java/net/VMPlainSocketImpl.java . + */ enum java_sockopt { CPNET_SO_KEEPALIVE = 0x8, CPNET_SO_LINGER = 0x80, @@ -173,7 +179,8 @@ enum java_sockopt { CPNET_IP_MULTICAST_IF = 0x10, CPNET_IP_MULTICAST_IF2 = 0x1F, CPNET_IP_MULTICAST_LOOP = 0x12, - CPNET_IP_TOS = 0x03 + CPNET_IP_TOS = 0x03, + CPNET_IP_TTL = 0x1E61 }; @@ -195,7 +202,7 @@ Java_gnu_java_net_VMPlainSocketImpl_setOption (JNIEnv *env, struct timeval _timeo; void *optval = (void *) &_value; socklen_t optlen = sizeof (int); - + switch (joption) { case CPNET_IP_MULTICAST_LOOP: @@ -209,7 +216,7 @@ Java_gnu_java_net_VMPlainSocketImpl_setOption (JNIEnv *env, case CPNET_SO_LINGER: optname = SO_LINGER; - if (_value == 0) + if (_value == -1) _linger.l_onoff = 0; else _linger.l_onoff = 1; @@ -256,6 +263,11 @@ Java_gnu_java_net_VMPlainSocketImpl_setOption (JNIEnv *env, optname = IP_TOS; break; + case CPNET_IP_TTL: + level = IPPROTO_IP; + optname = IP_TTL; + break; + case CPNET_SO_BINDADDR: case CPNET_IP_MULTICAST_IF: case CPNET_IP_MULTICAST_IF2: @@ -339,6 +351,11 @@ Java_gnu_java_net_VMPlainSocketImpl_getOption (JNIEnv *env, optname = IP_TOS; break; + case CPNET_IP_TTL: + level = IPPROTO_IP; + optname = IP_TTL; + break; + case CPNET_SO_BINDADDR: case CPNET_IP_MULTICAST_IF: case CPNET_IP_MULTICAST_IF2: @@ -349,14 +366,108 @@ Java_gnu_java_net_VMPlainSocketImpl_getOption (JNIEnv *env, if (getsockopt (fd, level, optname, optval, &optlen) == -1) JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + /* Returns the linger value if it is enabled or -1 in case + * it is disabled. This is how the Java API expects it. + */ if (joption == CPNET_SO_LINGER) - return linger.l_linger; + return (linger.l_onoff) ? linger.l_linger : -1; if (joption == CPNET_SO_TIMEOUT) return (timeo.tv_sec * 1000) + (timeo.tv_usec / 1000); return value; } +JNIEXPORT void JNICALL +Java_gnu_java_net_VMPlainSocketImpl_setMulticastInterface (JNIEnv *env, + jclass c __attribute__((unused)), + jint fd, + jint optionId __attribute__((unused)), + jobject addr) +{ + int result; + cpnet_address *cpaddr = _javanet_get_ip_netaddr (env, addr); + + if ((*env)->ExceptionOccurred (env)) + return; + + result = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, + (struct sockaddr *) cpaddr->data, cpaddr->len); + + cpnet_freeAddress (env, cpaddr); + + if (result == -1) + JCL_ThrowException (env, SOCKET_EXCEPTION, cpnative_getErrorString (errno)); +} + +JNIEXPORT void JNICALL +Java_gnu_java_net_VMPlainSocketImpl_setMulticastInterface6 (JNIEnv *env, + jclass c __attribute__((unused)), + jint fd, + jint optionId __attribute__((unused)), + jstring ifname) +{ +#ifdef HAVE_SETSOCKOPT +#ifdef HAVE_INET6 + int result; + const char *str_ifname = JCL_jstring_to_cstring (env, ifname); + u_int if_index; + + if ((*env)->ExceptionOccurred (env)) + { + JCL_free_cstring(env, ifname, str_ifname); + return; + } + + if_index = if_nametoindex(str_ifname); + if (!if_index) + { + JCL_free_cstring(env, ifname, str_ifname); + JCL_ThrowException (env, SOCKET_EXCEPTION, "interface does not exist"); + return; + } + + result = setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, + (u_int *) &if_index, sizeof(if_index)); + + JCL_free_cstring(env, ifname, str_ifname); + + if (result == -1) + JCL_ThrowException (env, SOCKET_EXCEPTION, cpnative_getErrorString (errno)); +#else + (void) fd; + JCL_ThrowException (env, "java/lang/InternalError", + "IPv6 support not available"); +#endif /* HAVE_INET6 */ +#else + (void) fd; + JCL_ThrowException (env, "java/lang/InternalError", + "socket options not supported"); +#endif /* HAVE_SETSOCKOPT */ +} + +JNIEXPORT jobject JNICALL +Java_gnu_java_net_VMPlainSocketImpl_getMulticastInterface (JNIEnv *env, + jclass c __attribute__((unused)), + jint fd, + jint optionId __attribute__((unused))) +{ + jobject obj; + cpnet_address *cpaddr; + int result = cpnet_getMulticastIF (env, fd, &cpaddr); + + if (result != CPNATIVE_OK) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + cpnative_getErrorString (result)); + return (0); + } + + obj = _javanet_create_inetaddress (env, cpaddr); + cpnet_freeAddress (env, cpaddr); + + return obj; +} + /* * Class: gnu_java_net_VMPlainSocketImpl @@ -538,7 +649,7 @@ Java_gnu_java_net_VMPlainSocketImpl_leave6 (JNIEnv *env, (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT); - if (-1 == setsockopt (fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, + if (-1 == setsockopt (fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &maddr, sizeof (struct ipv6_mreq))) JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno)); #else @@ -555,8 +666,8 @@ Java_gnu_java_net_VMPlainSocketImpl_leave6 (JNIEnv *env, #endif /* HAVE_SETSOCKOPT */ } -static uint32_t getif_address (JNIEnv *env, char *ifname); -static int getif_index (JNIEnv *env, char *ifname); +static uint32_t getif_address (JNIEnv *env, const char *ifname); +static int getif_index (JNIEnv *env, const char *ifname); /* * Class: gnu_java_net_VMPlainSocketImpl @@ -572,10 +683,14 @@ Java_gnu_java_net_VMPlainSocketImpl_joinGroup (JNIEnv *env, #ifdef HAVE_SETSOCKOPT struct ip_mreq maddr; jbyte *addr_elems; + const char *str_ifname; if (ifname != NULL) { - maddr.imr_interface.s_addr = getif_address (env, ifname); + str_ifname = JCL_jstring_to_cstring(env, ifname); + maddr.imr_interface.s_addr = getif_address (env, str_ifname); + JCL_free_cstring(env, ifname, str_ifname); + if ((*env)->ExceptionCheck (env)) return; } @@ -593,6 +708,7 @@ Java_gnu_java_net_VMPlainSocketImpl_joinGroup (JNIEnv *env, if (-1 == setsockopt (fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &maddr, sizeof (struct ip_mreq))) JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno)); + #else (void) fd; (void) addr; @@ -617,10 +733,14 @@ Java_gnu_java_net_VMPlainSocketImpl_joinGroup6 (JNIEnv *env, #ifdef HAVE_INET6 struct ipv6_mreq maddr; jbyte *addr_elems; + const char *str_ifname; if (ifname == NULL) { - maddr.ipv6mr_interface = getif_index (env, ifname); + str_ifname = JCL_jstring_to_cstring(env, ifname); + maddr.ipv6mr_interface = getif_index (env, str_ifname); + JCL_free_cstring(env, ifname, str_ifname); + if ((*env)->ExceptionCheck (env)) return; } @@ -666,10 +786,14 @@ Java_gnu_java_net_VMPlainSocketImpl_leaveGroup (JNIEnv *env, #ifdef HAVE_SETSOCKOPT struct ip_mreq maddr; jbyte *addr_elems; + const char *str_ifname; if (ifname != NULL) { - maddr.imr_interface.s_addr = getif_address (env, ifname); + str_ifname = JCL_jstring_to_cstring(env, ifname); + maddr.imr_interface.s_addr = getif_address (env, str_ifname); + JCL_free_cstring(env, ifname, str_ifname); + if ((*env)->ExceptionCheck (env)) return; } @@ -711,10 +835,14 @@ Java_gnu_java_net_VMPlainSocketImpl_leaveGroup6 (JNIEnv *env, #ifdef HAVE_INET6 struct ipv6_mreq maddr; jbyte *addr_elems; + const char *str_ifname; if (ifname == NULL) { - maddr.ipv6mr_interface = getif_index (env, ifname); + str_ifname = JCL_jstring_to_cstring(env, ifname); + maddr.ipv6mr_interface = getif_index (env, str_ifname); + JCL_free_cstring(env, ifname, str_ifname); + if ((*env)->ExceptionCheck (env)) return; } @@ -747,7 +875,7 @@ Java_gnu_java_net_VMPlainSocketImpl_leaveGroup6 (JNIEnv *env, } static uint32_t -getif_address (JNIEnv *env, char *ifname) +getif_address (JNIEnv *env, const char *ifname) { #ifdef HAVE_GETIFADDRS struct ifaddrs *ifaddrs, *i; @@ -789,7 +917,7 @@ getif_address (JNIEnv *env, char *ifname) } static int -getif_index (JNIEnv *env, char *ifname) +getif_index (JNIEnv *env, const char *ifname) { #ifdef HAVE_GETIFADDRS struct ifaddrs *ifaddrs, *i; diff --git a/native/jni/java-net/javanet.c b/native/jni/java-net/javanet.c index a8213044f..1d2f7202a 100644 --- a/native/jni/java-net/javanet.c +++ b/native/jni/java-net/javanet.c @@ -232,7 +232,7 @@ _javanet_create_integer (JNIEnv * env, jint val) /* * Builds an InetAddress object from a 32 bit address in host byte order */ -static jobject +jobject _javanet_create_inetaddress (JNIEnv * env, cpnet_address *netaddr) { #ifndef WITHOUT_NETWORK diff --git a/native/jni/java-net/javanet.h b/native/jni/java-net/javanet.h index 411c6c651..96dba881b 100644 --- a/native/jni/java-net/javanet.h +++ b/native/jni/java-net/javanet.h @@ -81,6 +81,7 @@ exception statement from your version. */ extern int _javanet_get_int_field(JNIEnv *, jobject, const char *); extern cpnet_address *_javanet_get_ip_netaddr(JNIEnv *, jobject); +extern jobject _javanet_create_inetaddress (JNIEnv *, cpnet_address *); extern void _javanet_create(JNIEnv *, jobject, jboolean); extern void _javanet_close(JNIEnv *, jobject, int); extern void _javanet_connect(JNIEnv *, jobject, jobject, jint, jboolean); diff --git a/native/jni/java-nio/gnu_java_nio_VMChannel.c b/native/jni/java-nio/gnu_java_nio_VMChannel.c index b4f444361..33a4f66de 100644 --- a/native/jni/java-nio/gnu_java_nio_VMChannel.c +++ b/native/jni/java-nio/gnu_java_nio_VMChannel.c @@ -40,6 +40,8 @@ exception statement from your version. */ #include <config.h> #endif +#include <config-int.h> + #include <sys/types.h> #include <sys/ioctl.h> #include <sys/mman.h> @@ -57,6 +59,7 @@ exception statement from your version. */ #include <jni.h> #include <jcl.h> +#include "cpio.h" #include "gnu_java_nio_VMChannel.h" #include "javanio.h" @@ -64,7 +67,9 @@ exception statement from your version. */ #include <fcntl.h> #endif /* HAVE_FCNTL_H */ +#define CONNECT_EXCEPTION "java/net/ConnectException" #define IO_EXCEPTION "java/io/IOException" +#define SOCKET_EXCEPTION "java/net/SocketException" #define INTERRUPTED_IO_EXCEPTION "java/io/InterruptedIOException" #define NON_READABLE_CHANNEL_EXCEPTION "java/nio/channels/NonReadableChannelException" #define NON_WRITABLE_CHANNEL_EXCEPTION "java/nio/channels/NonWritableChannelException" @@ -101,6 +106,7 @@ void JCL_print_buffer(JNIEnv *, struct JCL_buffer *); int JCL_init_buffer(JNIEnv *, struct JCL_buffer *, jobject); void JCL_release_buffer(JNIEnv *, struct JCL_buffer *, jobject, jint); void JCL_cleanup_buffers(JNIEnv *, struct JCL_buffer *, jint, jobjectArray, jint, jlong); +int JCL_thread_interrupted(JNIEnv *, jclass); static jfieldID address_fid; static jmethodID get_position_mid; @@ -110,6 +116,7 @@ static jmethodID set_limit_mid; static jmethodID has_array_mid; static jmethodID array_mid; static jmethodID array_offset_mid; +static jmethodID thread_interrupted_mid; jmethodID get_method_id(JNIEnv *env, jclass clazz, const char *name, @@ -119,7 +126,7 @@ get_method_id(JNIEnv *env, jclass clazz, const char *name, /* NIODBG("name: %s; sig: %s", name, sig); */ if (mid == NULL) { - JCL_ThrowException(env, "java/lang/InternalError", name); + JCL_ThrowException(env, "java/lang/InternalError", name); return NULL; } @@ -247,6 +254,13 @@ JCL_cleanup_buffers(JNIEnv *env, } +int +JCL_thread_interrupted(JNIEnv *env, jclass c) +{ + return (int) (*env)->CallBooleanMethod(env, c, thread_interrupted_mid); +} + + /* * Class: gnu_java_nio_VMChannel * Method: stdin_fd @@ -291,7 +305,7 @@ Java_gnu_java_nio_VMChannel_stderr_1fd (JNIEnv *env __attribute__((unused)), JNIEXPORT void JNICALL Java_gnu_java_nio_VMChannel_initIDs (JNIEnv *env, - jclass clazz __attribute__ ((__unused__))) + jclass clazz) { jclass bufferClass = JCL_FindClass(env, "java/nio/Buffer"); jclass byteBufferClass = JCL_FindClass(env, "java/nio/ByteBuffer"); @@ -316,6 +330,8 @@ Java_gnu_java_nio_VMChannel_initIDs (JNIEnv *env, has_array_mid = get_method_id(env, byteBufferClass, "hasArray", "()Z"); array_mid = get_method_id(env, byteBufferClass, "array", "()[B"); array_offset_mid = get_method_id(env, byteBufferClass, "arrayOffset", "()I"); + + thread_interrupted_mid = get_method_id(env, clazz, "isThreadInterrupted", "()Z"); } JNIEXPORT void JNICALL @@ -973,7 +989,8 @@ Java_gnu_java_nio_VMChannel_connect (JNIEnv *env, jclass clazz __attribute__((un if ((*env)->GetArrayLength (env, addr) != 4) { - JCL_ThrowException (env, "java/io/IOException", "expecting 4-byte address"); + JCL_ThrowException (env, SOCKET_EXCEPTION, + "expecting 4-byte address"); return JNI_FALSE; } @@ -984,7 +1001,7 @@ Java_gnu_java_nio_VMChannel_connect (JNIEnv *env, jclass clazz __attribute__((un origflags = fcntl (fd, F_GETFL, 0); if (origflags == -1) { - JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno)); return JNI_FALSE; } /* Set nonblocking mode, if not already set. */ @@ -993,7 +1010,7 @@ Java_gnu_java_nio_VMChannel_connect (JNIEnv *env, jclass clazz __attribute__((un flags = origflags | O_NONBLOCK; if (fcntl (fd, F_SETFL, flags) == -1) { - JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno)); return JNI_FALSE; } } @@ -1022,7 +1039,7 @@ Java_gnu_java_nio_VMChannel_connect (JNIEnv *env, jclass clazz __attribute__((un if (fcntl (fd, F_SETFL, origflags) == -1) { /* oops */ - JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno)); return JNI_FALSE; } } @@ -1033,7 +1050,7 @@ Java_gnu_java_nio_VMChannel_connect (JNIEnv *env, jclass clazz __attribute__((un ret = cpnio_select (fd + 1, NULL, &wrfds, NULL, &timeo); if (ret == -1) { - JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno)); return JNI_FALSE; } if (ret == 0) /* connect timed out */ @@ -1046,13 +1063,13 @@ Java_gnu_java_nio_VMChannel_connect (JNIEnv *env, jclass clazz __attribute__((un } else if (ECONNREFUSED == errno) { - JCL_ThrowException (env, "java/net/ConnectException", + JCL_ThrowException (env, CONNECT_EXCEPTION, strerror (errno)); return JNI_FALSE; } else { - JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno)); return JNI_FALSE; } } @@ -1063,13 +1080,13 @@ Java_gnu_java_nio_VMChannel_connect (JNIEnv *env, jclass clazz __attribute__((un return JNI_FALSE; else if (ECONNREFUSED == errno) { - JCL_ThrowException (env, "java/net/ConnectException", + JCL_ThrowException (env, CONNECT_EXCEPTION, strerror (errno)); return JNI_FALSE; } else { - JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno)); return JNI_FALSE; } } @@ -1080,7 +1097,7 @@ Java_gnu_java_nio_VMChannel_connect (JNIEnv *env, jclass clazz __attribute__((un (void) addr; (void) port; (void) timeout; - JCL_ThrowException (env, IO_EXCEPTION, "connect not supported"); + JCL_ThrowException (env, SOCKET_EXCEPTION, "connect not supported"); return JNI_FALSE; #endif /* HAVE_CONNECT */ } @@ -1109,7 +1126,7 @@ Java_gnu_java_nio_VMChannel_connect6 (JNIEnv *env, jclass clazz __attribute__((u origflags = fcntl (fd, F_GETFL, 0); if (origflags == -1) { - JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno)); return JNI_FALSE; } /* Set nonblocking mode, if not already set. */ @@ -1118,7 +1135,7 @@ Java_gnu_java_nio_VMChannel_connect6 (JNIEnv *env, jclass clazz __attribute__((u flags = origflags | O_NONBLOCK; if (fcntl (fd, F_SETFL, flags) == -1) { - JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno)); return JNI_FALSE; } } @@ -1146,7 +1163,7 @@ Java_gnu_java_nio_VMChannel_connect6 (JNIEnv *env, jclass clazz __attribute__((u if (fcntl (fd, F_SETFL, origflags) == -1) { /* oops */ - JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno)); return JNI_FALSE; } } @@ -1157,7 +1174,7 @@ Java_gnu_java_nio_VMChannel_connect6 (JNIEnv *env, jclass clazz __attribute__((u ret = cpnio_select (fd + 1, NULL, &wrfds, NULL, &timeo); if (ret == -1) { - JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno)); return JNI_FALSE; } if (ret == 0) /* connect timed out */ @@ -1170,13 +1187,13 @@ Java_gnu_java_nio_VMChannel_connect6 (JNIEnv *env, jclass clazz __attribute__((u } else if (ECONNREFUSED == errno) { - JCL_ThrowException (env, "java/net/ConnectException", + JCL_ThrowException (env, CONNECT_EXCEPTION, strerror (errno)); return JNI_FALSE; } else { - JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno)); return JNI_FALSE; } } @@ -1187,13 +1204,13 @@ Java_gnu_java_nio_VMChannel_connect6 (JNIEnv *env, jclass clazz __attribute__((u return JNI_FALSE; else if (ECONNREFUSED == errno) { - JCL_ThrowException (env, "java/net/ConnectException", + JCL_ThrowException (env, CONNECT_EXCEPTION, strerror (errno)); return JNI_FALSE; } else { - JCL_ThrowException (env, "java/io/IOException", strerror (errno)); + JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno)); return JNI_FALSE; } } @@ -1204,7 +1221,7 @@ Java_gnu_java_nio_VMChannel_connect6 (JNIEnv *env, jclass clazz __attribute__((u (void) addr; (void) port; (void) timeout; - JCL_ThrowException (env, IO_EXCEPTION, "IPv6 connect not supported"); + JCL_ThrowException (env, SOCKET_EXCEPTION, "IPv6 connect not supported"); return JNI_FALSE; #endif /* HAVE_CONNECT && HAVE_INET6 */ } @@ -1338,11 +1355,12 @@ Java_gnu_java_nio_VMChannel_getpeername (JNIEnv *env, jclass clazz __attribute__ */ JNIEXPORT jint JNICALL Java_gnu_java_nio_VMChannel_accept (JNIEnv *env, - jclass clazz __attribute__((unused)), + jclass clazz, jint fd) { #ifdef HAVE_ACCEPT int ret; + int tmp_errno = 0; #ifdef HAVE_INET6 struct sockaddr_in6 addr; @@ -1355,14 +1373,38 @@ Java_gnu_java_nio_VMChannel_accept (JNIEnv *env, do { ret = cpnio_accept (fd, (struct sockaddr *) &addr, &alen); + tmp_errno = errno; + + if (ret == -1) + switch (tmp_errno) + { + case EINTR: + /* Check if interrupted by Thread.interrupt(). If not then some + * other unrelated signal interrupted the system function and + * we should start over again. + */ + if (JCL_thread_interrupted(env, clazz)) + { + JCL_ThrowException (env, "java/net/SocketException", strerror (tmp_errno)); + return -1; + } + break; +#if defined(EWOULDBLOCK) && defined(EAGAIN) && EWOULDBLOCK != EAGAIN + case EWOULDBLOCK: +#endif + case EAGAIN: + /* Socket in non-blocking mode and no pending connection. */ + return -1; + default: + JCL_ThrowException (env, "java/net/SocketException", strerror (tmp_errno)); + return -1; + } + else + break; } - while (ret == -1 && EINTR == errno); + while (1); - if (ret == -1) - { - if (EWOULDBLOCK != ret && EAGAIN != ret) - JCL_ThrowException (env, "java/net/SocketException", strerror (errno)); - } + cpio_closeOnExec(ret); return ret; #else @@ -1582,7 +1624,11 @@ Java_gnu_java_nio_VMChannel_lock (JNIEnv *env, struct flock fl; fl.l_start = (off_t) pos; - fl.l_len = (off_t) len; + /* Long.MAX_VALUE means lock everything possible starting at pos. */ + if (len == 9223372036854775807LL) + fl.l_len = 0; + else + fl.l_len = (off_t) len; fl.l_pid = getpid (); fl.l_type = (shared ? F_RDLCK : F_WRLCK); fl.l_whence = SEEK_SET; diff --git a/native/jni/native-lib/cpio.c b/native/jni/native-lib/cpio.c index 4d23b7a1f..2777a31b2 100644 --- a/native/jni/native-lib/cpio.c +++ b/native/jni/native-lib/cpio.c @@ -473,3 +473,13 @@ int cpio_readDir (void *handle, char *filename) strncpy (filename, dBuf->d_name, FILENAME_MAX); return 0; } + + +int +cpio_closeOnExec(int fd) +{ + if (fcntl (fd, F_SETFD, FD_CLOEXEC) == -1) + return errno; + + return 0; +} diff --git a/native/jni/native-lib/cpio.h b/native/jni/native-lib/cpio.h index 97483d294..b388b5b50 100644 --- a/native/jni/native-lib/cpio.h +++ b/native/jni/native-lib/cpio.h @@ -64,6 +64,7 @@ JNIEXPORT int cpio_read (int fd, void *data, jint len, jint *bytes_read); JNIEXPORT int cpio_write (int fd, const void *data, jint len, jint *bytes_written); JNIEXPORT int cpio_fsync (int fd); JNIEXPORT int cpio_truncate (int fd, jlong size); +JNIEXPORT int cpio_closeOnExec(int fd); #define CPFILE_FILE 0 #define CPFILE_DIRECTORY 1 |