[zeromq-dev] Is there a way to safely read a string from Java given a C (char *) using Java? (Monitoring ZeroMQ sockets in Java)

Chinmay nchinmay at hotmail.com
Thu Apr 25 15:58:42 CEST 2013


I am using JZMQ wrapper for ZeroMQ 3.2.3 and in a thread I have the need to
detect `ZMQ_EVENT_ACCEPTED` and `ZMQ_EVENT_DISCONNECTED` events. The ZeroMQ
C library has the function `int zmq_socket_monitor (void *socket, char *
*addr, int events);` as detailed by
http://api.zeromq.org/3-2:zmq-socket-monitor. The events are returned to my
application on a separate receiving `PAIR` socket as detailed by the above link.

JZMQ however does not have a binding for the above function. So I tried
making one.

    /**
     * Called by Java's Socket::monitorSocket(String inProcAddr, int events).
     */
    JNIEXPORT jint JNICALL Java_org_zeromq_ZMQ_00024Socket_monitorSocket
(JNIEnv *env, 
    																	  jobject obj, 
    																	  jstring addr, 
    																	  jint events)
    {
    #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,2,2)
    	void *s = get_socket (env, obj);
    
        if (addr == NULL) {
            raise_exception (env, EINVAL);
            return -1;
        }
    
        const char *c_addr = env->GetStringUTFChars (addr, NULL);
        if (c_addr == NULL) {
            raise_exception (env, EINVAL);
            return -1;
        }
    
        int rc = zmq_socket_monitor (s, c_addr, events);
        int err = zmq_errno();
        env->ReleaseStringUTFChars (addr, c_addr);
    
        if (rc != 0) {
            raise_exception (env, err);        
        }
    
    	return rc;
    #else
    	return -1;
    #endif
    }

Now my receiving `PAIR` socket in java will receive a message for events
which will have structure as per the C struct (as per zmq.h)

    /*  Socket event data (union member per event)                         
      */
    typedef struct {
        int event;
        union {
        struct {
            char *addr;
            int fd;
        } connected;
        struct {
            char *addr;
            int err;
        } connect_delayed;
        struct {
            char *addr;
            int interval;
        } connect_retried;
        struct {
            char *addr;
            int fd;
        } listening;
        struct {
            char *addr;
            int err;
        } bind_failed;
        struct {
            char *addr;
            int fd;
        } accepted;
        struct {
            char *addr;
            int err;
        } accept_failed;
        struct {
            char *addr;
            int fd;
        } closed;
        struct {
            char *addr;
            int err;
        } close_failed;
        struct {
            char *addr;
            int fd;
        } disconnected;
        } data;
    } zmq_event_t;

Since I will get this data in Java, can I assume on a 64 bit machine, the
first 8 bytes correspond to the `char *addr` and the remaining 8 byte `int`
is the fd/err/interval? More importantly is there a way to get the string
corresponding safely to this `char *addr`, possibly by making another java
function to make a JNI call that returns a `jstring`? By 'safely' I mean
calling with a wrong pointer value I don't want to crash the system.




More information about the zeromq-dev mailing list