Socket.cpp 6.92 KB
Newer Older
Martin Hurton's avatar
Martin Hurton committed
1
/*
2
    Copyright (c) 2007-2010 iMatix Corporation
Martin Hurton's avatar
Martin Hurton committed
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

    This file is part of 0MQ.

    0MQ is free software; you can redistribute it and/or modify it under
    the terms of the Lesser GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    0MQ is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    Lesser GNU General Public License for more details.

    You should have received a copy of the Lesser GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <errno.h>

25
#include "../../src/stdint.hpp"
26
#include "../c/zmq.h"
27

Martin Hurton's avatar
Martin Hurton committed
28 29 30 31 32
#include "org_zmq_Socket.h"

static jfieldID socket_handle_fid = NULL;
static jmethodID create_socket_mid = NULL;

Martin Sustrik's avatar
Martin Sustrik committed
33
static void raise_exception (JNIEnv *env, int err)
Martin Hurton's avatar
Martin Hurton committed
34 35 36 37 38 39
{
    //  Get exception class.
    jclass exception_class = env->FindClass ("java/lang/Exception");
    assert (exception_class);

    //  Get text description of the exception.
40
    const char *err_msg = zmq_strerror (err);
Martin Hurton's avatar
Martin Hurton committed
41 42 43 44 45 46 47 48 49

    //  Raise the exception.
    int rc = env->ThrowNew (exception_class, err_msg);
    assert (rc == 0);

    //  Free the local ref.
    env->DeleteLocalRef (exception_class);
}

Martin Sustrik's avatar
Martin Sustrik committed
50 51
JNIEXPORT void JNICALL Java_org_zmq_Socket_construct (JNIEnv *env, jobject obj,
    jobject context, jint type)
Martin Hurton's avatar
Martin Hurton committed
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
{
    if (socket_handle_fid == NULL) {
        jclass cls = env->GetObjectClass (obj);
        assert (cls);
        socket_handle_fid = env->GetFieldID (cls, "socketHandle", "J");
        assert (socket_handle_fid);
        env->DeleteLocalRef (cls);
    }

    if (create_socket_mid == NULL) {
        jclass cls = env->FindClass ("org/zmq/Context");
        assert (cls);
        create_socket_mid = env->GetMethodID (cls, "createSocket", "(I)J");
        assert (create_socket_mid);
        env->DeleteLocalRef (cls);
    }

Martin Sustrik's avatar
Martin Sustrik committed
69
    void *s = (void*) env->CallLongMethod (context, create_socket_mid, type);
Martin Hurton's avatar
Martin Hurton committed
70 71 72 73 74 75
    if (env->ExceptionCheck ())
        return;

    env->SetLongField (obj, socket_handle_fid, (jlong) s);
}

Martin Sustrik's avatar
Martin Sustrik committed
76
JNIEXPORT void JNICALL Java_org_zmq_Socket_finalize (JNIEnv *env, jobject obj)
Martin Hurton's avatar
Martin Hurton committed
77 78 79 80 81 82 83
{
    void *s = (void*) env->GetLongField (obj, socket_handle_fid);
    assert (s);
    int rc = zmq_close (s);
    assert (rc == 0);
}

84 85
JNIEXPORT void JNICALL Java_org_zmq_Socket_setsockopt__IJ (JNIEnv *env,
    jobject obj, jint option, jlong optval)
Martin Hurton's avatar
Martin Hurton committed
86
{
87 88 89 90 91 92 93
    switch (option) {
    case ZMQ_HWM:
    case ZMQ_LWM:
    case ZMQ_SWAP:
    case ZMQ_AFFINITY:
    case ZMQ_RATE:
    case ZMQ_RECOVERY_IVL:
94
    case ZMQ_MCAST_LOOP:
95 96 97 98 99 100 101 102 103 104 105 106 107 108
        {
            void *s = (void*) env->GetLongField (obj, socket_handle_fid);
            assert (s);

            int64_t value = optval;
            int rc = zmq_setsockopt (s, option, &value, sizeof (value));
            if (rc != 0)
                raise_exception (env, errno);
            return;
        }
    default:
        raise_exception (env, EINVAL);
        return;
    }
Martin Hurton's avatar
Martin Hurton committed
109 110
}

111 112
JNIEXPORT void JNICALL Java_org_zmq_Socket_setsockopt__ILjava_lang_String_2 (
    JNIEnv *env, jobject obj, jint option, jstring optval)
Martin Hurton's avatar
Martin Hurton committed
113
{
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
    switch (option) {
    case ZMQ_IDENTITY:
    case ZMQ_SUBSCRIBE:
    case ZMQ_UNSUBSCRIBE:
        {
            if (optval == NULL) {
                raise_exception (env, EINVAL);
                return;
            }

            void *s = (void*) env->GetLongField (obj, socket_handle_fid);
            assert (s);

            const char *value = env->GetStringUTFChars (optval, NULL);
            assert (value);
            int rc = zmq_setsockopt (s, option, value, strlen (value));
            env->ReleaseStringUTFChars (optval, value);
            if (rc != 0)
                raise_exception (env, errno);
            return;
        }
    default:
Martin Hurton's avatar
Martin Hurton committed
136 137 138 139 140
        raise_exception (env, EINVAL);
        return;
    }
}

Martin Sustrik's avatar
Martin Sustrik committed
141 142
JNIEXPORT void JNICALL Java_org_zmq_Socket_bind (JNIEnv *env, jobject obj,
    jstring addr)
Martin Hurton's avatar
Martin Hurton committed
143 144 145 146 147 148 149 150 151 152
{
    void *s = (void*) env->GetLongField (obj, socket_handle_fid);
    assert (s);

    if (addr == NULL) {
        raise_exception (env, EINVAL);
        return;
    }

    const char *c_addr = env->GetStringUTFChars (addr, NULL);
Martin Sustrik's avatar
Martin Sustrik committed
153 154
    if (c_addr == NULL) {
        raise_exception (env, EINVAL);
Martin Hurton's avatar
Martin Hurton committed
155
        return;
Martin Sustrik's avatar
Martin Sustrik committed
156
    }
Martin Hurton's avatar
Martin Hurton committed
157 158 159 160 161 162 163 164

    int rc = zmq_bind (s, c_addr);
    env->ReleaseStringUTFChars (addr, c_addr);

    if (rc == -1)
        raise_exception (env, errno);
}

Martin Sustrik's avatar
Martin Sustrik committed
165 166
JNIEXPORT void JNICALL Java_org_zmq_Socket_connect (JNIEnv *env, jobject obj,
    jstring addr)
Martin Hurton's avatar
Martin Hurton committed
167 168 169 170 171 172 173 174 175 176
{
    void *s = (void*) env->GetLongField (obj, socket_handle_fid);
    assert (s);

    if (addr == NULL) {
        raise_exception (env, EINVAL);
        return;
    }

    const char *c_addr = env->GetStringUTFChars (addr, NULL);
Martin Sustrik's avatar
Martin Sustrik committed
177 178
    if (c_addr == NULL) {
        raise_exception (env, EINVAL);
Martin Hurton's avatar
Martin Hurton committed
179
        return;
Martin Sustrik's avatar
Martin Sustrik committed
180
    }
Martin Hurton's avatar
Martin Hurton committed
181 182 183 184 185 186 187 188

    int rc = zmq_connect (s, c_addr);
    env->ReleaseStringUTFChars (addr, c_addr);

    if (rc == -1)
        raise_exception (env, errno);
}

Martin Sustrik's avatar
Martin Sustrik committed
189 190
JNIEXPORT jboolean JNICALL Java_org_zmq_Socket_send (JNIEnv *env, jobject obj,
    jbyteArray msg, jlong flags)
Martin Hurton's avatar
Martin Hurton committed
191 192 193 194
{
    void *s = (void*) env->GetLongField (obj, socket_handle_fid);
    assert (s);

Martin Sustrik's avatar
Martin Sustrik committed
195 196
    jsize size = env->GetArrayLength (msg); 
    jbyte *data = env->GetByteArrayElements (msg, 0);
Martin Hurton's avatar
Martin Hurton committed
197

Martin Sustrik's avatar
Martin Sustrik committed
198 199 200 201
    zmq_msg_t message;
    int rc = zmq_msg_init_size (&message, size);
    assert (rc == 0);
    memcpy (zmq_msg_data (&message), data, size);
Martin Hurton's avatar
Martin Hurton committed
202

Martin Sustrik's avatar
Martin Sustrik committed
203 204 205 206 207 208 209 210 211 212
    env->ReleaseByteArrayElements (msg, data, 0);

    rc = zmq_send (s, &message, (int) flags);
        
    if (rc == -1 && errno == EAGAIN) {
        rc = zmq_msg_close (&message);
        assert (rc == 0);
        return JNI_FALSE;
    }
    
Martin Hurton's avatar
Martin Hurton committed
213 214
    if (rc == -1) {
        raise_exception (env, errno);
Martin Sustrik's avatar
Martin Sustrik committed
215 216 217
        rc = zmq_msg_close (&message);
        assert (rc == 0);
        return JNI_FALSE;
Martin Hurton's avatar
Martin Hurton committed
218 219
    }

Martin Sustrik's avatar
Martin Sustrik committed
220 221 222
    rc = zmq_msg_close (&message);
    assert (rc == 0);
    return JNI_TRUE;
Martin Hurton's avatar
Martin Hurton committed
223 224
}

Martin Sustrik's avatar
Martin Sustrik committed
225
JNIEXPORT void JNICALL Java_org_zmq_Socket_flush (JNIEnv *env, jobject obj)
Martin Hurton's avatar
Martin Hurton committed
226 227 228 229
{
    void *s = (void*) env->GetLongField (obj, socket_handle_fid);
    assert (s);

Martin Sustrik's avatar
Martin Sustrik committed
230 231 232 233 234 235
    int rc = zmq_flush (s);

    if (rc == -1) {
        raise_exception (env, errno);
        return ;
    }
Martin Hurton's avatar
Martin Hurton committed
236 237
}

Martin Sustrik's avatar
Martin Sustrik committed
238 239
JNIEXPORT jbyteArray JNICALL Java_org_zmq_Socket_recv (JNIEnv *env, jobject obj,
    jlong flags)
Martin Hurton's avatar
Martin Hurton committed
240 241 242 243
{
    void *s = (void*) env->GetLongField (obj, socket_handle_fid);
    assert (s);

Martin Sustrik's avatar
Martin Sustrik committed
244 245 246
    zmq_msg_t message;
    zmq_msg_init (&message);
    int rc = zmq_recv (s, &message, (int) flags);
Martin Hurton's avatar
Martin Hurton committed
247

Martin Sustrik's avatar
Martin Sustrik committed
248 249
    if (rc == -1 && errno == EAGAIN) {
        zmq_msg_close (&message);
Martin Hurton's avatar
Martin Hurton committed
250
        return NULL;
Martin Sustrik's avatar
Martin Sustrik committed
251
    }
Martin Hurton's avatar
Martin Hurton committed
252 253 254

    if (rc == -1) {
        raise_exception (env, errno);
Martin Sustrik's avatar
Martin Sustrik committed
255
        zmq_msg_close (&message);
Martin Hurton's avatar
Martin Hurton committed
256 257 258
        return NULL;
    }

Martin Sustrik's avatar
Martin Sustrik committed
259 260 261 262 263 264
    jbyteArray data = env->NewByteArray (zmq_msg_size (&message));
    assert (data);
    env->SetByteArrayRegion (data, 0, zmq_msg_size (&message),
        (jbyte*) zmq_msg_data (&message));

    return data;
Martin Hurton's avatar
Martin Hurton committed
265
}