Passing Java Socket FD to C Hack

Discussion in 'Java' started by Amir Michail, Feb 5, 2005.

  1. Amir  Michail

    Amir Michail Guest

    Hi,

    I tried this hack for passing a Java socket fd to C but could not get
    it to work:

    http://www.geocities.com/SiliconValley/Vista/2013/JavaOOB.html

    Here's the code I have:

    JNIEXPORT void JNICALL
    Java_UnixProcess_closeSockets__Ljava_net_Socket_2
    (JNIEnv *env, jclass cls, jobject obj) {

    struct Hjava_io_FileDescriptor *fd; /* Java-struct-excavation aids */
    struct Hjava_net_SocketImpl *impl;
    struct Hjava_net_Socket *socket;
    int sockfd;

    /* dig deep into "this" to get the UNIX file descriptor */
    //socket = unhand(this)->socket;

    socket = obj;
    impl = unhand(socket)->impl;
    fd = unhand(impl)->fd;
    sockfd = (int)(unhand(fd)->fd - 1);
    /* "The FileDescriptor object integer class variable fd represents
    the actual file descriptor plus 1." - Mark Yarvis */

    closeSockets(sockfd);

    }

    I get this error:

    UnixProcessImp.c: In function
    `Java_UnixProcess_closeSockets__Ljava_net_Socket_2':
    UnixProcessImp.c:97: error: invalid type argument of `->'
    UnixProcessImp.c:98: error: invalid type argument of `->'
    UnixProcessImp.c:99: error: invalid type argument of `->'

    which corrrespond to these lines:

    impl = unhand(socket)->impl;
    fd = unhand(impl)->fd;
    sockfd = (int)(unhand(fd)->fd - 1);



    Here are the header files generated by javah:

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class java_net_Socket */

    #ifndef _Included_java_net_Socket
    #define _Included_java_net_Socket
    #ifdef __cplusplus
    extern "C" {
    #endif
    /* Inaccessible static: factory */
    #ifdef __cplusplus
    }
    #endif
    #endif


    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class java_net_SocketImpl */

    #ifndef _Included_java_net_SocketImpl
    #define _Included_java_net_SocketImpl
    #ifdef __cplusplus
    extern "C" {
    #endif
    #ifdef __cplusplus
    }
    #endif
    #endif


    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class java_io_FileDescriptor */

    #ifndef _Included_java_io_FileDescriptor
    #define _Included_java_io_FileDescriptor
    #ifdef __cplusplus
    extern "C" {
    #endif
    /* Inaccessible static: in */
    /* Inaccessible static: out */
    /* Inaccessible static: err */
    /*
    * Class: java_io_FileDescriptor
    * Method: sync
    * Signature: ()V
    */
    JNIEXPORT void JNICALL Java_java_io_FileDescriptor_sync
    (JNIEnv *, jobject);

    /*
    * Class: java_io_FileDescriptor
    * Method: initIDs
    * Signature: ()V
    */
    JNIEXPORT void JNICALL Java_java_io_FileDescriptor_initIDs
    (JNIEnv *, jclass);

    #ifdef __cplusplus
    }
    #endif
    #endif



    Amir
     
    Amir Michail, Feb 5, 2005
    #1
    1. Advertising

  2. On 4 Feb 2005 20:42:29 -0800, Amir Michail wrote:
    > I tried this hack for passing a Java socket fd to C but could not
    > get it to work:
    >
    > http://www.geocities.com/SiliconValley/Vista/2013/JavaOOB.html


    [...]

    > I get this error:
    >
    > UnixProcessImp.c: In function
    > `Java_UnixProcess_closeSockets__Ljava_net_Socket_2':
    > UnixProcessImp.c:97: error: invalid type argument of `->'
    > UnixProcessImp.c:98: error: invalid type argument of `->'
    > UnixProcessImp.c:99: error: invalid type argument of `->'


    I believe that unhand() comes from JNI 1.0 and is now obsolete. At any
    rate I've never encountered it in the 6 or so years since I wrote my
    first native method.

    I've previously used this mechanism to do what you're trying:

    static int getFd(JNIEnv *env, jobject sock)
    {
    JNIEnv e = *env;
    jclass clazz;
    jfieldID fid;
    jobject impl;
    jobject fdesc;

    /* get the SocketImpl from the Socket */
    if (!(clazz = e->GetObjectClass(env,sock)) ||
    !(fid = e->GetFieldID(env,clazz,"impl","Ljava/net/SocketImpl;")) ||
    !(impl = e->GetObjectField(env,sock,fid))) return -1;

    /* get the FileDescriptor from the SocketImpl */
    if (!(clazz = e->GetObjectClass(env,impl)) ||
    !(fid = e->GetFieldID(env,clazz,"fd","Ljava/io/FileDescriptor;")) ||
    !(fdesc = e->GetObjectField(env,impl,fid))) return -1;

    /* get the fd from the FileDescriptor */
    if (!(clazz = e->GetObjectClass(env,fdesc)) ||
    !(fid = e->GetFieldID(env,clazz,"fd","I"))) return -1;

    /* return the descriptor */
    return e->GetIntField(env,fdesc,fid);
    }

    Note that since the code traverses private class members, there is no
    guarantee that it will work correctly in all versions of the class
    libraries or with libraries from other vendors than Sun. I haven't
    used this code in several years, so you may wish to use "javap -s" to
    confirm the class structure assumed by the code.

    With *some* (but not all) JVMs, you will need to subtract 1 from the
    returned value to get the true descriptor. I believe that was only
    true of early JVM's (prior to 1.2 or so), but YMMV.

    /gordon

    --
    [ do not email me copies of your followups ]
    g o r d o n + n e w s @ b a l d e r 1 3 . s e
     
    Gordon Beaton, Feb 5, 2005
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Laszlo Nagy
    Replies:
    1
    Views:
    5,117
    Mark Wooding
    Jan 27, 2009
  2. Jean-Paul Calderone
    Replies:
    0
    Views:
    1,033
    Jean-Paul Calderone
    Jan 27, 2009
  3. Laszlo Nagy
    Replies:
    0
    Views:
    601
    Laszlo Nagy
    Feb 1, 2009
  4. Steve Holden
    Replies:
    0
    Views:
    716
    Steve Holden
    Feb 1, 2009
  5. Steve Holden
    Replies:
    1
    Views:
    760
Loading...

Share This Page