PageRenderTime 52ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/Runtime/src/sunjdk/java.net/java_net_PlainDatagramSocketImpl.c

https://github.com/cscott/Harpoon
C | 428 lines | 252 code | 52 blank | 124 comment | 42 complexity | 69916603204c34fe362a3bd735206aa0 MD5 | raw file
  1. /* Implementation for class java_net_PlainDatagramSocketImpl */
  2. #include <jni.h>
  3. #include "java_net_PlainDatagramSocketImpl.h"
  4. #include <assert.h>
  5. #include <errno.h> /* for errno */
  6. #include <netinet/in.h> /* for AF_INET, SOCK_DGRAM, etc */
  7. #include <sys/socket.h> /* for socket(2), send(2) */
  8. #include <string.h> /* for strerror(3) */
  9. #include <unistd.h> /* for close(2) */
  10. #include "flexthread.h" /* for mutex ops */
  11. #include "../java.io/javaio.h" /* for getfd/setfd */
  12. static jfieldID DSI_fdObjID = 0; /* The field ID of DatagramSocketImpl.fd */
  13. static jfieldID DSI_localPortID = 0; /* The field ID of DSocketImpl.localPort*/
  14. static jfieldID DP_bufID = 0; /* The field ID of DatagramPacket.buf */
  15. static jfieldID DP_offsetID = 0; /* The field ID of DatagramPacket.offset */
  16. static jfieldID DP_lengthID = 0; /* The field ID of DatagramPacket.length */
  17. static jfieldID DP_addressID = 0; /* The field ID of DatagramPacket.address */
  18. static jfieldID DP_portID = 0; /* The field ID of DatagramPacket.port */
  19. static jfieldID IA_addrID = 0; /* The field ID of InetAddress.address */
  20. static jfieldID IA_familyID= 0; /* The field ID of InetAddress.family */
  21. static jmethodID IA_consID = 0; /* no-arg constructor for InetAddress */
  22. static jclass IACls = 0; /* The java/net/InetAddress class object */
  23. static jclass IOExcCls = 0; /* The java/io/IOException class object */
  24. static jint jSO_BINDADDR, jSO_REUSEADDR, jSO_LINGER, jSO_TIMEOUT;
  25. static jint jTCP_NODELAY, jIP_MULTICAST_IF;
  26. static int inited = 0; /* whether the above variables have been initialized */
  27. FLEX_MUTEX_DECLARE_STATIC(init_mutex);
  28. static int initializePDSI(JNIEnv *env) {
  29. jclass PDSICls, DPCls;
  30. FLEX_MUTEX_LOCK(&init_mutex);
  31. // other thread may win race to lock and init before we do.
  32. if (inited) goto done;
  33. PDSICls = (*env)->FindClass(env, "java/net/PlainDatagramSocketImpl");
  34. if ((*env)->ExceptionOccurred(env)) goto done;
  35. DSI_fdObjID = (*env)->GetFieldID(env, PDSICls,
  36. "fd","Ljava/io/FileDescriptor;");
  37. if ((*env)->ExceptionOccurred(env)) goto done;
  38. DSI_localPortID = (*env)->GetFieldID(env, PDSICls, "localPort", "I");
  39. if ((*env)->ExceptionOccurred(env)) goto done;
  40. DPCls = (*env)->FindClass(env, "java/net/DatagramPacket");
  41. if ((*env)->ExceptionOccurred(env)) goto done;
  42. DP_bufID = (*env)->GetFieldID(env, DPCls, "buf", "[B");
  43. if ((*env)->ExceptionOccurred(env)) goto done;
  44. DP_offsetID = (*env)->GetFieldID(env, DPCls, "offset", "I");
  45. if ((*env)->ExceptionOccurred(env)) {
  46. /* this field not present before JDK1.2! */
  47. DP_offsetID=0;
  48. (*env)->ExceptionClear(env);
  49. }
  50. DP_lengthID = (*env)->GetFieldID(env, DPCls, "length", "I");
  51. if ((*env)->ExceptionOccurred(env)) goto done;
  52. DP_addressID = (*env)->GetFieldID(env, DPCls, "address",
  53. "Ljava/net/InetAddress;");
  54. if ((*env)->ExceptionOccurred(env)) goto done;
  55. DP_portID = (*env)->GetFieldID(env, DPCls, "port", "I");
  56. if ((*env)->ExceptionOccurred(env)) goto done;
  57. IACls = (*env)->FindClass(env, "java/net/InetAddress");
  58. /* make IACls into a global reference for future use */
  59. IACls = (*env)->NewGlobalRef(env, IACls);
  60. if ((*env)->ExceptionOccurred(env)) goto done;
  61. IA_consID = (*env)->GetMethodID(env, IACls, "<init>", "()V");
  62. if ((*env)->ExceptionOccurred(env)) {
  63. /* not entirely unexpected that this method might not be present. */
  64. IA_consID = 0;
  65. (*env)->ExceptionClear(env);
  66. fprintf(stderr, "WARNING: constructor InetAddress() not found.\n");
  67. }
  68. IA_addrID = (*env)->GetFieldID(env, IACls, "address", "I");
  69. if ((*env)->ExceptionOccurred(env)) goto done;
  70. IA_familyID= (*env)->GetFieldID(env, IACls, "family", "I");
  71. if ((*env)->ExceptionOccurred(env)) goto done;
  72. IOExcCls = (*env)->FindClass(env, "java/io/IOException");
  73. if ((*env)->ExceptionOccurred(env)) goto done;
  74. /* make IOExcCls into a global reference for future use */
  75. IOExcCls = (*env)->NewGlobalRef(env, IOExcCls);
  76. /* initialize socket option values. copied from source file at
  77. * at the moment; will work on being able to read these from the binary.*/
  78. jTCP_NODELAY=0x0001; jIP_MULTICAST_IF=0x10;
  79. jSO_BINDADDR=0x000F; jSO_REUSEADDR=0x04;
  80. jSO_LINGER=0x0080; jSO_TIMEOUT=0x1006;
  81. /* done. */
  82. inited = 1;
  83. done:
  84. FLEX_MUTEX_UNLOCK(&init_mutex);
  85. return inited;
  86. }
  87. /*
  88. * Class: java_net_PlainDatagramSocketImpl
  89. * Method: init
  90. * Signature: ()V
  91. */
  92. /* perform class load-time initialization */
  93. JNIEXPORT void JNICALL Java_java_net_PlainDatagramSocketImpl_init
  94. (JNIEnv *env, jclass _plaindatagramsocketimpl) {
  95. /* do nothing */
  96. }
  97. /*
  98. * Class: java_net_PlainDatagramSocketImpl
  99. * Method: datagramSocketCreate
  100. * Signature: ()V
  101. */
  102. /* creates a datagram socket */
  103. JNIEXPORT void JNICALL Java_java_net_PlainDatagramSocketImpl_datagramSocketCreate
  104. (JNIEnv *env, jobject _this) {
  105. jobject fdObj;
  106. int fd;
  107. /* If static data has not been loaded, load it now */
  108. if (!inited && !initializePDSI(env)) return; /* exception occurred; bail */
  109. fd = socket(AF_INET, SOCK_DGRAM, 0);
  110. fdObj = (*env)->GetObjectField(env, _this, DSI_fdObjID);
  111. Java_java_io_FileDescriptor_setfd(env, fdObj, fd);
  112. /* Check for error condition */
  113. if (fd==-1)
  114. (*env)->ThrowNew(env, IOExcCls, strerror(errno));
  115. }
  116. /*
  117. * Class: java_net_PlainDatagramSocketImpl
  118. * Method: datagramSocketClose
  119. * Signature: ()V
  120. */
  121. /* close the socket */
  122. JNIEXPORT void JNICALL Java_java_net_PlainDatagramSocketImpl_datagramSocketClose
  123. (JNIEnv *env, jobject _this) {
  124. int fd, rc;
  125. jobject fdObj;
  126. assert(inited && _this);
  127. fdObj = (*env)->GetObjectField(env, _this, DSI_fdObjID);
  128. fd = Java_java_io_FileDescriptor_getfd(env, fdObj);
  129. rc = close(fd);
  130. if (rc<0)
  131. (*env)->ThrowNew(env, IOExcCls, strerror(errno));
  132. }
  133. /*
  134. * Class: java_net_PlainDatagramSocketImpl
  135. * Method: bind
  136. * Signature: (ILjava/net/InetAddress;)V
  137. */
  138. /* binds a datagram socket to a local port */
  139. JNIEXPORT void JNICALL Java_java_net_PlainDatagramSocketImpl_bind
  140. (JNIEnv *env, jobject _this, jint lport, jobject laddr/*InetAddress*/) {
  141. struct sockaddr_in sa;
  142. jobject fdObj;
  143. int fd, rc, sa_size;
  144. assert(inited && _this && laddr);
  145. memset(&sa, 0, sizeof(sa));
  146. sa.sin_family = (*env)->GetIntField(env, laddr, IA_familyID);
  147. sa.sin_addr.s_addr = htonl((*env)->GetIntField(env, laddr, IA_addrID));
  148. sa.sin_port = htons(lport);
  149. fdObj = (*env)->GetObjectField(env, _this, DSI_fdObjID);
  150. fd = Java_java_io_FileDescriptor_getfd(env, fdObj);
  151. rc = bind(fd, (struct sockaddr *) &sa, sizeof(sa));
  152. /* Check for error condition */
  153. if (rc<0) goto error;
  154. /* update instance variables */
  155. sa_size = sizeof(sa);
  156. rc = getsockname(fd, (struct sockaddr *) &sa, &sa_size);
  157. if (rc<0) goto error;
  158. (*env)->SetIntField(env, _this, DSI_localPortID, (int)ntohs(sa.sin_port));
  159. /* done! */
  160. return;
  161. error:
  162. (*env)->ThrowNew(env, IOExcCls, strerror(errno));
  163. return;
  164. }
  165. #if 0
  166. /*
  167. * Class: java_net_PlainDatagramSocketImpl
  168. * Method: getTTL
  169. * Signature: ()B
  170. */
  171. /* get the TTL (time-to-live) option */
  172. JNIEXPORT jbyte JNICALL Java_java_net_PlainDatagramSocketImpl_getTTL
  173. (JNIEnv *env, jobject _this) {
  174. assert(inited && _this);
  175. assert(0/*unimplemented*/);
  176. }
  177. /*
  178. * Class: java_net_PlainDatagramSocketImpl
  179. * Method: getTimeToLive
  180. * Signature: ()I
  181. */
  182. /* get the TTL (time-to-live) option */
  183. JNIEXPORT jint JNICALL Java_java_net_PlainDatagramSocketImpl_getTimeToLive
  184. (JNIEnv *env, jobject _this) {
  185. assert(inited && _this);
  186. assert(0/*unimplemented*/);
  187. }
  188. /*
  189. * Class: java_net_PlainDatagramSocketImpl
  190. * Method: join
  191. * Signature: (Ljava/net/InetAddress;)V
  192. */
  193. /* join the multicast group */
  194. JNIEXPORT void JNICALL Java_java_net_PlainDatagramSocketImpl_join
  195. (JNIEnv *env, jobject _this, jobject inetaddr /*InetAddress*/) {
  196. assert(inited && _this);
  197. assert(0/*unimplemented*/);
  198. }
  199. /*
  200. * Class: java_net_PlainDatagramSocketImpl
  201. * Method: leave
  202. * Signature: (Ljava/net/InetAddress;)V
  203. */
  204. /* leave the multicast group */
  205. JNIEXPORT void JNICALL Java_java_net_PlainDatagramSocketImpl_leave
  206. (JNIEnv *env, jobject _this, jobject inetaddr /*InetAddress*/) {
  207. assert(0/*unimplemented*/);
  208. }
  209. #endif
  210. /*
  211. * Class: java_net_PlainDatagramSocketImpl
  212. * Method: peek
  213. * Signature: (Ljava/net/InetAddress;)I
  214. */
  215. /* peek at the packet to see who it is from. */
  216. /* fills the inetaddress and returns the port number */
  217. JNIEXPORT jint JNICALL Java_java_net_PlainDatagramSocketImpl_peek
  218. (JNIEnv *env, jobject _this, jobject addrObj/*InetAddress*/) {
  219. struct sockaddr_in sa;
  220. int salen = sizeof(sa);
  221. jobject fdObj;
  222. char buf[1];
  223. int fd, rc;
  224. /* oh, this is ugly */
  225. assert(inited && addrObj);
  226. fdObj = (*env)->GetObjectField(env, _this, DSI_fdObjID);
  227. fd = Java_java_io_FileDescriptor_getfd(env, fdObj);
  228. do {
  229. rc = recvfrom(fd, buf, 0, MSG_PEEK, (struct sockaddr *) &sa, &salen);
  230. } while (rc<0 && errno==EINTR); /* repeat if interrupted */
  231. /* Check for error condition */
  232. if (rc<0) {
  233. (*env)->ThrowNew(env, IOExcCls, strerror(errno));
  234. return 0;
  235. }
  236. /* fill in inetaddress/extract port */
  237. (*env)->SetIntField(env, addrObj, IA_familyID, sa.sin_family);
  238. (*env)->SetIntField(env, addrObj, IA_addrID, ntohl(sa.sin_addr.s_addr));
  239. return ntohs(sa.sin_port);
  240. }
  241. /*
  242. * Class: java_net_PlainDatagramSocketImpl
  243. * Method: receive
  244. * Signature: (Ljava/net/DatagramPacket;)V
  245. */
  246. /* receive the datagram packet */
  247. JNIEXPORT void JNICALL Java_java_net_PlainDatagramSocketImpl_receive
  248. (JNIEnv *env, jobject _this, jobject p /*DatagramPacket*/) {
  249. struct sockaddr_in sa;
  250. int salen = sizeof(sa);
  251. jobject fdObj, addrObj, bufObj;
  252. jbyte *bufp;
  253. jint len, off;
  254. int fd, rc;
  255. /* oh, this is ugly */
  256. assert(inited && p);
  257. /* get file descriptor */
  258. fdObj = (*env)->GetObjectField(env, _this, DSI_fdObjID);
  259. fd = Java_java_io_FileDescriptor_getfd(env, fdObj);
  260. /* get inetaddress object */
  261. addrObj = (*env)->GetObjectField(env, p, DP_addressID);
  262. /* if null, create a new inetaddr object */
  263. if (addrObj==NULL) {
  264. if (IA_consID)
  265. addrObj = (*env)->NewObject(env, IACls, IA_consID);
  266. else
  267. addrObj = (*env)->AllocObject(env, IACls); /* RISKY! */
  268. (*env)->SetObjectField(env, p, DP_addressID, addrObj);
  269. }
  270. assert(addrObj);
  271. /* get message buffer */
  272. bufObj = (*env)->GetObjectField(env, p, DP_bufID);
  273. bufp = (*env)->GetByteArrayElements(env, (jbyteArray) bufObj, NULL);
  274. off = DP_offsetID ? (*env)->GetIntField(env, p, DP_offsetID) : 0;
  275. len = (*env)->GetIntField(env, p, DP_lengthID);
  276. do {
  277. rc = recvfrom
  278. (fd, bufp+off, len, MSG_WAITALL, (struct sockaddr *) &sa, &salen);
  279. } while (rc<0 && errno==EINTR); /* repeat if interrupted */
  280. (*env)->ReleaseByteArrayElements(env, (jbyteArray)bufObj, bufp,
  281. rc < 0 ? JNI_ABORT : 0);
  282. /* Check for error condition */
  283. if (rc<0) {
  284. (*env)->ThrowNew(env, IOExcCls, strerror(errno));
  285. return;
  286. }
  287. /* fill in inetaddress/extract port */
  288. (*env)->SetIntField(env, addrObj, IA_familyID, sa.sin_family);
  289. (*env)->SetIntField(env, addrObj, IA_addrID, ntohl(sa.sin_addr.s_addr));
  290. (*env)->SetIntField(env, p, DP_portID, ntohs(sa.sin_port));
  291. /* set length of received datagram */
  292. (*env)->SetIntField(env, p, DP_lengthID, rc);
  293. return;
  294. }
  295. /*
  296. * Class: java_net_PlainDatagramSocketImpl
  297. * Method: send
  298. * Signature: (Ljava/net/DatagramPacket;)V
  299. */
  300. /* sends a datagram packet. the packet contains the data and the
  301. * destination address to send the packet to. */
  302. JNIEXPORT void JNICALL Java_java_net_PlainDatagramSocketImpl_send
  303. (JNIEnv *env, jobject _this, jobject p/*DatagramPacket*/) {
  304. struct sockaddr_in sa;
  305. jobject fdObj, addrObj, bufObj;
  306. jbyte *bufp;
  307. jint len, off;
  308. int fd, rc;
  309. assert(inited && _this && p);
  310. /* get file descriptor */
  311. fdObj = (*env)->GetObjectField(env, _this, DSI_fdObjID);
  312. fd = Java_java_io_FileDescriptor_getfd(env, fdObj);
  313. /* get inetaddress and port from datagrampacket */
  314. addrObj = (*env)->GetObjectField(env, p, DP_addressID);
  315. memset(&sa, 0, sizeof(sa));
  316. sa.sin_family = (*env)->GetIntField(env, addrObj, IA_familyID);
  317. sa.sin_addr.s_addr = htonl((*env)->GetIntField(env, addrObj, IA_addrID));
  318. sa.sin_port = htons((*env)->GetIntField(env, p, DP_portID));
  319. /* get message buffer */
  320. bufObj = (*env)->GetObjectField(env, p, DP_bufID);
  321. bufp = (*env)->GetByteArrayElements(env, (jbyteArray) bufObj, NULL);
  322. off = DP_offsetID ? (*env)->GetIntField(env, p, DP_offsetID) : 0;
  323. len = (*env)->GetIntField(env, p, DP_lengthID);
  324. /* actually send data gram */
  325. do {
  326. rc = sendto
  327. (fd, bufp+off, len, 0/*no flags*/, (struct sockaddr *)&sa, sizeof(sa));
  328. } while (rc<0 && errno==EINTR); /* repeat if interrupted */
  329. /* free buffers */
  330. (*env)->ReleaseByteArrayElements(env, (jbyteArray)bufObj, bufp, JNI_ABORT);
  331. if (rc<0)
  332. (*env)->ThrowNew(env, IOExcCls, strerror(errno));
  333. }
  334. #if 0
  335. /*
  336. * Class: java_net_PlainDatagramSocketImpl
  337. * Method: setTTL
  338. * Signature: (B)V
  339. */
  340. /* set the TTL (time-to-live) option */
  341. JNIEXPORT void JNICALL Java_java_net_PlainDatagramSocketImpl_setTTL
  342. (JNIEnv *env, jobject _this, jbyte ttl) {
  343. assert(0/*unimplemented*/);
  344. }
  345. /*
  346. * Class: java_net_PlainDatagramSocketImpl
  347. * Method: setTimeToLive
  348. * Signature: (I)V
  349. */
  350. /* set the TTL (time-to-live) option */
  351. JNIEXPORT void JNICALL Java_java_net_PlainDatagramSocketImpl_setTimeToLive
  352. (JNIEnv *env, jobject _this, jint ttl) {
  353. assert(0/*unimplemented*/);
  354. }
  355. /*
  356. * Class: java_net_PlainDatagramSocketImpl
  357. * Method: socketGetOption
  358. * Signature: (I)I
  359. */
  360. /* get option's state - set or not */
  361. JNIEXPORT jint JNICALL Java_java_net_PlainDatagramSocketImpl_socketGetOption
  362. (JNIEnv *env, jobject _this, jint optID) {
  363. assert(0/*unimplemented*/);
  364. }
  365. /*
  366. * Class: java_net_PlainDatagramSocketImpl
  367. * Method: socketSetOption
  368. * Signature: (ILjava/lang/Object;)V
  369. */
  370. /* set a value -- since we only support (setting) binary options here,
  371. * o must be a Boolean */
  372. JNIEXPORT void JNICALL Java_java_net_PlainDatagramSocketImpl_socketSetOption
  373. (JNIEnv *env, jobject _this, jint optID, jobject o) {
  374. assert(0/*unimplemented*/);
  375. }
  376. #endif