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
);