11 #include <sys/types.h>
12 #include <sys/socket.h>
33 typedef jbyteArray wrapped;
44 static void except(JNIEnv *jni, const char *clsname, const char *msg)
49 cls = (*jni)->FindClass(jni, clsname); assert(cls);
50 rc = (*jni)->ThrowNew(jni, cls, msg); assert(!rc);
53 static void except_errno(JNIEnv *jni, const char *clsname, int err)
54 { except(jni, clsname, strerror(err)); }
56 static void *open_struct_unchecked(JNIEnv *jni, wrapped obj, struct open *op)
62 op->arr = (*jni)->GetByteArrayElements(jni, obj, ©p);
63 if (!op->arr) return (0);
64 p = (uintptr_t)op->arr;
65 q = p + sizeof(union align) - 1;
66 q -= q%sizeof(union align);
67 fprintf(stderr, ";; offset = %"PRIuPTR"\n", q - p);
68 return (op->arr + (q - p));
71 static void *open_struct(JNIEnv *jni, wrapped obj,
72 const struct native_type *ty, struct open *op)
77 if (!obj) { except(jni, "java/lang/NullPointerException", 0); return (0); }
78 n = (*jni)->GetArrayLength(jni, obj);
79 if ((*jni)->ExceptionOccurred(jni)) return (0);
80 p = open_struct_unchecked(jni, obj, op);
82 if (n < ty->sz + sizeof(union align) - 1 || p->tag != ty->tag)
84 (*jni)->ReleaseByteArrayElements(jni, obj, op->arr, JNI_ABORT);
85 except(jni, "uk/org/distorted/tripe/JNI$NativeObjectTypeException", 0);
91 static wrapped close_struct(JNIEnv *jni, struct open *op)
93 (*jni)->ReleaseByteArrayElements(jni, op->obj, op->arr, 0);
97 static void *alloc_struct(JNIEnv *jni, const struct native_type *ty,
103 obj = (*jni)->NewByteArray(jni, ty->sz + sizeof(union align) - 1);
104 if (!obj) return (0);
105 p = open_struct_unchecked(jni, obj, op);
106 if (!p) { (*jni)->DeleteLocalRef(jni, obj); return (0); }
111 JNIEXPORT void JNICALL Java_uk_org_distorted_tripe_JNI_test
112 (JNIEnv *jni, jobject cls)
113 { printf("Hello from C!\n"); }
119 static const struct native_type toy_type =
120 { "toy", sizeof(struct toy), 0x58008918 };
122 JNIEXPORT wrapped JNICALL Java_uk_org_distorted_tripe_JNI_make
123 (JNIEnv *jni, jobject cls)
128 toy = alloc_struct(jni, &toy_type, &op_toy);
129 if (!toy) return (0);
130 toy->p = "A working thing";
131 return (close_struct(jni, &op_toy));
134 JNIEXPORT void JNICALL Java_uk_org_distorted_tripe_JNI_check
135 (JNIEnv *jni, jobject cls, wrapped wtoy)
140 toy = open_struct(jni, wtoy, &toy_type, &op_toy);
142 printf("Toy says: %s\n", toy->p);
143 close_struct(jni, &op_toy);
150 #define CF_CLOSERD 1u
151 #define CF_CLOSEWR 2u
152 #define CF_CLOSEMASK (CF_CLOSERD | CF_CLOSEWR)
154 static const struct native_type conn_type
155 = { "conn", sizeof(struct conn), 0xed030167 };
157 JNIEXPORT wrapped JNICALL Java_uk_org_distorted_tripe_JNI_connect
158 (JNIEnv *jni, jobject cls)
162 struct sockaddr_un sun;
165 conn = alloc_struct(jni, &conn_type, &op);
168 fd = socket(SOCK_STREAM, PF_UNIX, 0);
169 if (!fd) goto err_except;
171 sun.sun_family = AF_UNIX;
172 strcpy(sun.sun_path, "/tmp/mdw/sk");
173 if (connect(fd, (struct sockaddr *)&sun, sizeof(sun))) goto err_except;
176 return (close_struct(jni, &op));
179 except_errno(jni, "java/io/IOException", errno);
185 JNIEXPORT void JNICALL Java_uk_org_distorted_tripe_JNI_send
186 (JNIEnv *jni, jobject cls, wrapped wconn, jbyteArray buf,
187 jint start, jint len)
189 struct conn *conn = 0;
196 conn = open_struct(jni, wconn, &conn_type, &op);
199 bufsz = (*jni)->GetArrayLength(jni, buf);
200 if ((*jni)->ExceptionOccurred(jni)) goto end;
201 if (bufsz < start || bufsz - start < len) {
202 except(jni, "java/lang/IndexOutOfBoundsException",
203 "bad send-buffer bounds");
207 p = (*jni)->GetByteArrayElements(jni, buf, ©p);
211 n = send(conn->fd, p + start, len, 0);
213 except_errno(jni, "java/io/IOException", errno);
216 start += n; len -= n;
220 if (p) (*jni)->ReleaseByteArrayElements(jni, buf, p, JNI_ABORT);
221 if (conn) close_struct(jni, &op);
225 JNIEXPORT jint JNICALL Java_uk_org_distorted_tripe_JNI_recv
226 (JNIEnv *jni, jobject cls, wrapped wconn, jbyteArray buf,
227 jint start, jint len)
229 struct conn *conn = 0;
236 conn = open_struct(jni, wconn, &conn_type, &op);
239 bufsz = (*jni)->GetArrayLength(jni, buf);
240 if ((*jni)->ExceptionOccurred(jni)) goto end;
241 if (bufsz < start || bufsz - start < len) {
242 except(jni, "java/lang/IndexOutOfBoundsException",
243 "bad receive-buffer bounds");
247 p = (*jni)->GetByteArrayElements(jni, buf, ©p);
250 rc = recv(conn->fd, p + start, len, 0);
252 except_errno(jni, "java/io/IOException", errno);
258 if (p) (*jni)->ReleaseByteArrayElements(jni, buf, p, 0);
259 if (conn) close_struct(jni, &op);
263 JNIEXPORT void JNICALL Java_uk_org_distorted_tripe_JNI_close
264 (JNIEnv *jni, jobject cls, wrapped wconn, jint how)
266 struct conn *conn = 0;
269 conn = open_struct(jni, wconn, &conn_type, &op);
270 if (!conn || conn->fd == -1) goto end;
272 how &= CF_CLOSEMASK&~conn->f;
274 fprintf(stderr, ";; closing %u\n", how);
275 if ((conn->f&CF_CLOSEMASK) == CF_CLOSEMASK) {
279 if (how&CF_CLOSERD) shutdown(conn->fd, SHUT_RD);
280 if (how&CF_CLOSEWR) shutdown(conn->fd, SHUT_WR);
284 if (conn) close_struct(jni, &op);