PageRenderTime 34ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/jni/OSNetworkSystem.cpp

https://github.com/sortir/sipdroid
C++ | 3670 lines | 2373 code | 615 blank | 682 comment | 576 complexity | da45757e245a55287e2e260bd4d1362e MD5 | raw file
Possible License(s): GPL-3.0, BSD-3-Clause
  1. /*
  2. * Copyright (C) 2009 The Sipdroid Open Source Project
  3. * Copyright (C) 2007 The Android Open Source Project
  4. *
  5. * This file is part of Sipdroid (http://www.sipdroid.org)
  6. *
  7. * Sipdroid is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This source code is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this source code; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. */
  21. #define LOG_TAG "OSNetworkSystem"
  22. //#include "JNIHelp.h"
  23. #include "jni.h"
  24. #include "errno.h"
  25. #include <unistd.h>
  26. #include <stdio.h>
  27. #include <sys/socket.h>
  28. #include <netinet/in.h>
  29. #include <netinet/tcp.h>
  30. #include <netdb.h>
  31. #include <sys/time.h>
  32. #include <stdlib.h>
  33. #include <sys/ioctl.h>
  34. #include <sys/un.h>
  35. //#include <cutils/properties.h>
  36. //#include <cutils/adb_networking.h>
  37. //#include <utils/LogSocket.h>
  38. //#include "AndroidSystemNatives.h"
  39. /**
  40. * @name Socket Errors
  41. * Error codes for socket operations
  42. *
  43. * @internal SOCKERR* range from -200 to -299 avoid overlap
  44. */
  45. #define SOCKERR_BADSOCKET -200 /* generic error */
  46. #define SOCKERR_NOTINITIALIZED -201 /* socket library uninitialized */
  47. #define SOCKERR_BADAF -202 /* bad address family */
  48. #define SOCKERR_BADPROTO -203 /* bad protocol */
  49. #define SOCKERR_BADTYPE -204 /* bad type */
  50. #define SOCKERR_SYSTEMBUSY -205 /* system busy handling requests */
  51. #define SOCKERR_SYSTEMFULL -206 /* too many sockets */
  52. #define SOCKERR_NOTCONNECTED -207 /* socket is not connected */
  53. #define SOCKERR_INTERRUPTED -208 /* the call was cancelled */
  54. #define SOCKERR_TIMEOUT -209 /* the operation timed out */
  55. #define SOCKERR_CONNRESET -210 /* the connection was reset */
  56. #define SOCKERR_WOULDBLOCK -211 /* the socket is marked as nonblocking operation would block */
  57. #define SOCKERR_ADDRNOTAVAIL -212 /* address not available */
  58. #define SOCKERR_ADDRINUSE -213 /* address already in use */
  59. #define SOCKERR_NOTBOUND -214 /* the socket is not bound */
  60. #define SOCKERR_UNKNOWNSOCKET -215 /* resolution of fileDescriptor to socket failed */
  61. #define SOCKERR_INVALIDTIMEOUT -216 /* the specified timeout is invalid */
  62. #define SOCKERR_FDSETFULL -217 /* Unable to create an FDSET */
  63. #define SOCKERR_TIMEVALFULL -218 /* Unable to create a TIMEVAL */
  64. #define SOCKERR_REMSOCKSHUTDOWN -219 /* The remote socket has shutdown gracefully */
  65. #define SOCKERR_NOTLISTENING -220 /* listen() was not invoked prior to accept() */
  66. #define SOCKERR_NOTSTREAMSOCK -221 /* The socket does not support connection-oriented service */
  67. #define SOCKERR_ALREADYBOUND -222 /* The socket is already bound to an address */
  68. #define SOCKERR_NBWITHLINGER -223 /* The socket is marked non-blocking & SO_LINGER is non-zero */
  69. #define SOCKERR_ISCONNECTED -224 /* The socket is already connected */
  70. #define SOCKERR_NOBUFFERS -225 /* No buffer space is available */
  71. #define SOCKERR_HOSTNOTFOUND -226 /* Authoritative Answer Host not found */
  72. #define SOCKERR_NODATA -227 /* Valid name, no data record of requested type */
  73. #define SOCKERR_BOUNDORCONN -228 /* The socket has not been bound or is already connected */
  74. #define SOCKERR_OPNOTSUPP -229 /* The socket does not support the operation */
  75. #define SOCKERR_OPTUNSUPP -230 /* The socket option is not supported */
  76. #define SOCKERR_OPTARGSINVALID -231 /* The socket option arguments are invalid */
  77. #define SOCKERR_SOCKLEVELINVALID -232 /* The socket level is invalid */
  78. #define SOCKERR_TIMEOUTFAILURE -233
  79. #define SOCKERR_SOCKADDRALLOCFAIL -234 /* Unable to allocate the sockaddr structure */
  80. #define SOCKERR_FDSET_SIZEBAD -235 /* The calculated maximum size of the file descriptor set is bad */
  81. #define SOCKERR_UNKNOWNFLAG -236 /* The flag is unknown */
  82. #define SOCKERR_MSGSIZE -237 /* The datagram was too big to fit the specified buffer & was truncated. */
  83. #define SOCKERR_NORECOVERY -238 /* The operation failed with no recovery possible */
  84. #define SOCKERR_ARGSINVALID -239 /* The arguments are invalid */
  85. #define SOCKERR_BADDESC -240 /* The socket argument is not a valid file descriptor */
  86. #define SOCKERR_NOTSOCK -241 /* The socket argument is not a socket */
  87. #define SOCKERR_HOSTENTALLOCFAIL -242 /* Unable to allocate the hostent structure */
  88. #define SOCKERR_TIMEVALALLOCFAIL -243 /* Unable to allocate the timeval structure */
  89. #define SOCKERR_LINGERALLOCFAIL -244 /* Unable to allocate the linger structure */
  90. #define SOCKERR_IPMREQALLOCFAIL -245 /* Unable to allocate the ipmreq structure */
  91. #define SOCKERR_FDSETALLOCFAIL -246 /* Unable to allocate the fdset structure */
  92. #define SOCKERR_OPFAILED -247 /* Operation failed */
  93. #define SOCKERR_VALUE_NULL -248 /* The value indexed was NULL */
  94. #define SOCKERR_CONNECTION_REFUSED -249 /* connection was refused */
  95. #define SOCKERR_ENETUNREACH -250 /* network is not reachable */
  96. #define SOCKERR_EACCES -251 /* permissions do not allow action on socket */
  97. #define SOCKERR_EHOSTUNREACH -252 /* no route to host */
  98. #define SOCKERR_EPIPE -253 /* broken pipe */
  99. #define JAVASOCKOPT_TCP_NODELAY 1
  100. #define JAVASOCKOPT_IP_TOS 3
  101. #define JAVASOCKOPT_SO_REUSEADDR 4
  102. #define JAVASOCKOPT_SO_KEEPALIVE 8
  103. #define JAVASOCKOPT_MCAST_TIME_TO_LIVE 10 /* Currently unused */
  104. #define JAVASOCKOPT_SO_BINDADDR 15
  105. #define JAVASOCKOPT_MCAST_INTERFACE 16
  106. #define JAVASOCKOPT_MCAST_TTL 17
  107. #define JAVASOCKOPT_IP_MULTICAST_LOOP 18
  108. #define JAVASOCKOPT_MCAST_ADD_MEMBERSHIP 19
  109. #define JAVASOCKOPT_MCAST_DROP_MEMBERSHIP 20
  110. #define JAVASOCKOPT_IP_MULTICAST_IF2 31
  111. #define JAVASOCKOPT_SO_BROADCAST 32
  112. #define JAVASOCKOPT_SO_LINGER 128
  113. #define JAVASOCKOPT_REUSEADDR_AND_REUSEPORT 10001
  114. #define JAVASOCKOPT_SO_SNDBUF 4097
  115. #define JAVASOCKOPT_SO_RCVBUF 4098
  116. #define JAVASOCKOPT_SO_RCVTIMEOUT 4102
  117. #define JAVASOCKOPT_SO_OOBINLINE 4099
  118. /* constants for calling multi-call functions */
  119. #define SOCKET_STEP_START 10
  120. #define SOCKET_STEP_CHECK 20
  121. #define SOCKET_STEP_DONE 30
  122. #define BROKEN_MULTICAST_IF 1
  123. #define BROKEN_MULTICAST_TTL 2
  124. #define BROKEN_TCP_NODELAY 4
  125. #define SOCKET_CONNECT_STEP_START 0
  126. #define SOCKET_CONNECT_STEP_CHECK 1
  127. #define SOCKET_OP_NONE 0
  128. #define SOCKET_OP_READ 1
  129. #define SOCKET_OP_WRITE 2
  130. #define SOCKET_READ_WRITE 3
  131. #define SOCKET_MSG_PEEK 1
  132. #define SOCKET_MSG_OOB 2
  133. #define SOCKET_NOFLAGS 0
  134. #undef BUFFERSIZE
  135. #define BUFFERSIZE 2048
  136. // wait for 500000 usec = 0.5 second
  137. #define SEND_RETRY_TIME 500000
  138. struct CachedFields {
  139. jfieldID fd_descriptor;
  140. jclass iaddr_class;
  141. jmethodID iaddr_class_init;
  142. jmethodID iaddr_getbyaddress;
  143. jfieldID iaddr_ipaddress;
  144. jclass genericipmreq_class;
  145. jclass integer_class;
  146. jmethodID integer_class_init;
  147. jfieldID integer_class_value;
  148. jclass boolean_class;
  149. jmethodID boolean_class_init;
  150. jfieldID boolean_class_value;
  151. jclass byte_class;
  152. jmethodID byte_class_init;
  153. jfieldID byte_class_value;
  154. jclass string_class;
  155. jmethodID string_class_init;
  156. jfieldID socketimpl_address;
  157. jfieldID socketimpl_port;
  158. jclass dpack_class;
  159. jfieldID dpack_address;
  160. jfieldID dpack_port;
  161. jfieldID dpack_length;
  162. jclass fd_class;
  163. jfieldID descriptor;
  164. } gCachedFields;
  165. static int useAdbNetworking = 0;
  166. /* needed for connecting with timeout */
  167. typedef struct selectFDSet {
  168. int nfds;
  169. int sock;
  170. fd_set writeSet;
  171. fd_set readSet;
  172. fd_set exceptionSet;
  173. } selectFDSet;
  174. static const char * netLookupErrorString(int anErrorNum);
  175. #define log_socket_close(a,b)
  176. #define log_socket_connect(a,b,c)
  177. #define add_send_stats(a,b)
  178. #define add_recv_stats(a,b)
  179. #define adb_networking_connect_fd(a,b) 0
  180. #define adb_networking_gethostbyname(a,b) 0
  181. #define PROPERTY_VALUE_MAX 1
  182. #define property_get(a,b,c)
  183. #define assert(a)
  184. /*
  185. * Throw an exception with the specified class and an optional message.
  186. */
  187. int jniThrowException(JNIEnv* env, const char* className, const char* msg)
  188. {
  189. jclass exceptionClass;
  190. exceptionClass = env->FindClass(className);
  191. if (exceptionClass == NULL) {
  192. // LOGE("Unable to find exception class %s\n", className);
  193. assert(0); /* fatal during dev; should always be fatal? */
  194. return -1;
  195. }
  196. if (env->ThrowNew(exceptionClass, msg) != JNI_OK) {
  197. // LOGE("Failed throwing '%s' '%s'\n", className, msg);
  198. assert(!"failed to throw");
  199. }
  200. return 0;
  201. }
  202. /*
  203. * Internal helper function.
  204. *
  205. * Get the file descriptor.
  206. */
  207. static inline int getFd(JNIEnv* env, jobject obj)
  208. {
  209. return env->GetIntField(obj, gCachedFields.descriptor);
  210. }
  211. /*
  212. * Internal helper function.
  213. *
  214. * Set the file descriptor.
  215. */
  216. static inline void setFd(JNIEnv* env, jobject obj, jint value)
  217. {
  218. env->SetIntField(obj, gCachedFields.descriptor, value);
  219. }
  220. /*
  221. * For JNIHelp.c
  222. * Get an int file descriptor from a java.io.FileDescriptor
  223. */
  224. static int jniGetFDFromFileDescriptor (JNIEnv* env, jobject fileDescriptor) {
  225. return getFd(env, fileDescriptor);
  226. }
  227. /*
  228. * For JNIHelp.c
  229. * Set the descriptor of a java.io.FileDescriptor
  230. */
  231. static void jniSetFileDescriptorOfFD (JNIEnv* env, jobject fileDescriptor, int value) {
  232. setFd(env, fileDescriptor, value);
  233. }
  234. /**
  235. * Throws an SocketException with the message affiliated with the errorCode.
  236. */
  237. static void throwSocketException(JNIEnv *env, int errorCode) {
  238. jniThrowException(env, "java/net/SocketException",
  239. netLookupErrorString(errorCode));
  240. }
  241. /**
  242. * Throws an IOException with the given message.
  243. */
  244. static void throwIOExceptionStr(JNIEnv *env, const char *message) {
  245. jniThrowException(env, "java/io/IOException", message);
  246. }
  247. /**
  248. * Throws a NullPointerException.
  249. */
  250. static void throwNullPointerException(JNIEnv *env) {
  251. jniThrowException(env, "java/lang/NullPointerException", NULL);
  252. }
  253. /**
  254. * Converts a 4-byte array to a native address structure. Throws a
  255. * NullPointerException or an IOException in case of error. This is
  256. * signaled by a return value of -1. The normal return value is 0.
  257. */
  258. static int javaAddressToStructIn(
  259. JNIEnv *env, jbyteArray java_address, struct in_addr *address) {
  260. memset(address, 0, sizeof(address));
  261. if (java_address == NULL) {
  262. return -1;
  263. }
  264. if (env->GetArrayLength(java_address) != sizeof(address->s_addr)) {
  265. return -1;
  266. }
  267. jbyte * java_address_bytes
  268. = env->GetByteArrayElements(java_address, NULL);
  269. memcpy(&(address->s_addr),
  270. java_address_bytes,
  271. sizeof(address->s_addr));
  272. env->ReleaseByteArrayElements(java_address, java_address_bytes, JNI_ABORT);
  273. return 0;
  274. }
  275. /**
  276. * Converts a native address structure to a 4-byte array. Throws a
  277. * NullPointerException or an IOException in case of error. This is
  278. * signaled by a return value of -1. The normal return value is 0.
  279. */
  280. static int structInToJavaAddress(
  281. JNIEnv *env, struct in_addr *address, jbyteArray java_address) {
  282. if (java_address == NULL) {
  283. return -1;
  284. }
  285. if (env->GetArrayLength(java_address) != sizeof(address->s_addr)) {
  286. return -1;
  287. }
  288. jbyte *java_address_bytes;
  289. java_address_bytes = env->GetByteArrayElements(java_address, NULL);
  290. memcpy(java_address_bytes, &(address->s_addr), sizeof(address->s_addr));
  291. env->ReleaseByteArrayElements(java_address, java_address_bytes, 0);
  292. return 0;
  293. }
  294. /**
  295. * Converts a native address structure to an InetAddress object.
  296. * Throws a NullPointerException or an IOException in case of
  297. * error. This is signaled by a return value of -1. The normal
  298. * return value is 0.
  299. */
  300. static int socketAddressToInetAddress(JNIEnv *env,
  301. struct sockaddr_in *sockaddress, jobject inetaddress, int *port) {
  302. jbyteArray ipaddress;
  303. int result;
  304. ipaddress = (jbyteArray)env->GetObjectField(inetaddress,
  305. gCachedFields.iaddr_ipaddress);
  306. if (structInToJavaAddress(env, &sockaddress->sin_addr, ipaddress) < 0) {
  307. return -1;
  308. }
  309. *port = ntohs(sockaddress->sin_port);
  310. return 0;
  311. }
  312. /**
  313. * Converts an InetAddress object to a native address structure.
  314. * Throws a NullPointerException or an IOException in case of
  315. * error. This is signaled by a return value of -1. The normal
  316. * return value is 0.
  317. */
  318. static int inetAddressToSocketAddress(JNIEnv *env,
  319. jobject inetaddress, int port, struct sockaddr_in *sockaddress) {
  320. jbyteArray ipaddress;
  321. int result;
  322. ipaddress = (jbyteArray)env->GetObjectField(inetaddress,
  323. gCachedFields.iaddr_ipaddress);
  324. memset(sockaddress, 0, sizeof(sockaddress));
  325. sockaddress->sin_family = AF_INET;
  326. sockaddress->sin_port = htons(port);
  327. if (javaAddressToStructIn(env, ipaddress, &(sockaddress->sin_addr)) < 0) {
  328. return -1;
  329. }
  330. return 0;
  331. }
  332. static jobject structInToInetAddress(JNIEnv *env, struct in_addr *address) {
  333. jbyteArray bytes;
  334. int success;
  335. bytes = env->NewByteArray(4);
  336. if (bytes == NULL) {
  337. return NULL;
  338. }
  339. if (structInToJavaAddress(env, address, bytes) < 0) {
  340. return NULL;
  341. }
  342. return env->CallStaticObjectMethod(gCachedFields.iaddr_class,
  343. gCachedFields.iaddr_getbyaddress, bytes);
  344. }
  345. /**
  346. * Answer a new java.lang.Boolean object.
  347. *
  348. * @param env pointer to the JNI library
  349. * @param anInt the Boolean constructor argument
  350. *
  351. * @return the new Boolean
  352. */
  353. static jobject newJavaLangBoolean(JNIEnv * env, jint anInt) {
  354. jclass tempClass;
  355. jmethodID tempMethod;
  356. tempClass = gCachedFields.boolean_class;
  357. tempMethod = gCachedFields.boolean_class_init;
  358. return env->NewObject(tempClass, tempMethod, (jboolean) (anInt != 0));
  359. }
  360. /**
  361. * Answer a new java.lang.Byte object.
  362. *
  363. * @param env pointer to the JNI library
  364. * @param anInt the Byte constructor argument
  365. *
  366. * @return the new Byte
  367. */
  368. static jobject newJavaLangByte(JNIEnv * env, jbyte val) {
  369. jclass tempClass;
  370. jmethodID tempMethod;
  371. tempClass = gCachedFields.byte_class;
  372. tempMethod = gCachedFields.byte_class_init;
  373. return env->NewObject(tempClass, tempMethod, val);
  374. }
  375. /**
  376. * Answer a new java.lang.Integer object.
  377. *
  378. * @param env pointer to the JNI library
  379. * @param anInt the Integer constructor argument
  380. *
  381. * @return the new Integer
  382. */
  383. static jobject newJavaLangInteger(JNIEnv * env, jint anInt) {
  384. jclass tempClass;
  385. jmethodID tempMethod;
  386. tempClass = gCachedFields.integer_class;
  387. tempMethod = gCachedFields.integer_class_init;
  388. return env->NewObject(tempClass, tempMethod, anInt);
  389. }
  390. /**
  391. * Answer a new java.lang.String object.
  392. *
  393. * @param env pointer to the JNI library
  394. * @param anInt the byte[] constructor argument
  395. *
  396. * @return the new String
  397. */
  398. static jobject newJavaLangString(JNIEnv * env, jbyteArray bytes) {
  399. jclass tempClass;
  400. jmethodID tempMethod;
  401. tempClass = gCachedFields.string_class;
  402. tempMethod = gCachedFields.string_class_init;
  403. return env->NewObject(tempClass, tempMethod, (jbyteArray) bytes);
  404. }
  405. /**
  406. * Query OS for timestamp.
  407. * Retrieve the current value of system clock and convert to milliseconds.
  408. *
  409. * @param[in] portLibrary The port library.
  410. *
  411. * @return 0 on failure, time value in milliseconds on success.
  412. * @deprecated Use @ref time_hires_clock and @ref time_hires_delta
  413. *
  414. * technically, this should return I_64 since both timeval.tv_sec and
  415. * timeval.tv_usec are long
  416. */
  417. static int time_msec_clock() {
  418. struct timeval tp;
  419. struct timezone tzp;
  420. gettimeofday(&tp, &tzp);
  421. return (tp.tv_sec * 1000) + (tp.tv_usec / 1000);
  422. }
  423. /**
  424. * check if the passed sockaddr_in struct contains a localhost address
  425. *
  426. * @param[in] address pointer to the address to check
  427. *
  428. * @return 0 if the passed address isn't a localhost address
  429. */
  430. static int isLocalhost(struct sockaddr_in *address) {
  431. // return address == 127.0.0.1
  432. return (unsigned int) address->sin_addr.s_addr == 16777343;
  433. }
  434. /**
  435. * Answer the errorString corresponding to the errorNumber, if available.
  436. * This function will answer a default error string, if the errorNumber is not
  437. * recognized.
  438. *
  439. * This function will have to be reworked to handle internationalization
  440. * properly, removing the explicit strings.
  441. *
  442. * @param anErrorNum the error code to resolve to a human readable string
  443. *
  444. * @return a human readable error string
  445. */
  446. static const char * netLookupErrorString(int anErrorNum) {
  447. switch (anErrorNum) {
  448. case SOCKERR_BADSOCKET:
  449. return "Bad socket";
  450. case SOCKERR_NOTINITIALIZED:
  451. return "Socket library uninitialized";
  452. case SOCKERR_BADAF:
  453. return "Bad address family";
  454. case SOCKERR_BADPROTO:
  455. return "Bad protocol";
  456. case SOCKERR_BADTYPE:
  457. return "Bad type";
  458. case SOCKERR_SYSTEMBUSY:
  459. return "System busy handling requests";
  460. case SOCKERR_SYSTEMFULL:
  461. return "Too many sockets allocated";
  462. case SOCKERR_NOTCONNECTED:
  463. return "Socket is not connected";
  464. case SOCKERR_INTERRUPTED:
  465. return "The system call was cancelled";
  466. case SOCKERR_TIMEOUT:
  467. return "The operation timed out";
  468. case SOCKERR_CONNRESET:
  469. return "The connection was reset";
  470. case SOCKERR_WOULDBLOCK:
  471. return "The nonblocking operation would block";
  472. case SOCKERR_ADDRNOTAVAIL:
  473. return "The address is not available";
  474. case SOCKERR_ADDRINUSE:
  475. return "The address is already in use";
  476. case SOCKERR_NOTBOUND:
  477. return "The socket is not bound";
  478. case SOCKERR_UNKNOWNSOCKET:
  479. return "Resolution of the FileDescriptor to socket failed";
  480. case SOCKERR_INVALIDTIMEOUT:
  481. return "The specified timeout is invalid";
  482. case SOCKERR_FDSETFULL:
  483. return "Unable to create an FDSET";
  484. case SOCKERR_TIMEVALFULL:
  485. return "Unable to create a TIMEVAL";
  486. case SOCKERR_REMSOCKSHUTDOWN:
  487. return "The remote socket has shutdown gracefully";
  488. case SOCKERR_NOTLISTENING:
  489. return "Listen() was not invoked prior to accept()";
  490. case SOCKERR_NOTSTREAMSOCK:
  491. return "The socket does not support connection-oriented service";
  492. case SOCKERR_ALREADYBOUND:
  493. return "The socket is already bound to an address";
  494. case SOCKERR_NBWITHLINGER:
  495. return "The socket is marked non-blocking & SO_LINGER is non-zero";
  496. case SOCKERR_ISCONNECTED:
  497. return "The socket is already connected";
  498. case SOCKERR_NOBUFFERS:
  499. return "No buffer space is available";
  500. case SOCKERR_HOSTNOTFOUND:
  501. return "Authoritative Answer Host not found";
  502. case SOCKERR_NODATA:
  503. return "Valid name, no data record of requested type";
  504. case SOCKERR_BOUNDORCONN:
  505. return "The socket has not been bound or is already connected";
  506. case SOCKERR_OPNOTSUPP:
  507. return "The socket does not support the operation";
  508. case SOCKERR_OPTUNSUPP:
  509. return "The socket option is not supported";
  510. case SOCKERR_OPTARGSINVALID:
  511. return "The socket option arguments are invalid";
  512. case SOCKERR_SOCKLEVELINVALID:
  513. return "The socket level is invalid";
  514. case SOCKERR_TIMEOUTFAILURE:
  515. return "The timeout operation failed";
  516. case SOCKERR_SOCKADDRALLOCFAIL:
  517. return "Failed to allocate address structure";
  518. case SOCKERR_FDSET_SIZEBAD:
  519. return "The calculated maximum size of the file descriptor set is bad";
  520. case SOCKERR_UNKNOWNFLAG:
  521. return "The flag is unknown";
  522. case SOCKERR_MSGSIZE:
  523. return "The datagram was too big to fit the specified buffer, so truncated";
  524. case SOCKERR_NORECOVERY:
  525. return "The operation failed with no recovery possible";
  526. case SOCKERR_ARGSINVALID:
  527. return "The arguments are invalid";
  528. case SOCKERR_BADDESC:
  529. return "The socket argument is not a valid file descriptor";
  530. case SOCKERR_NOTSOCK:
  531. return "The socket argument is not a socket";
  532. case SOCKERR_HOSTENTALLOCFAIL:
  533. return "Unable to allocate the hostent structure";
  534. case SOCKERR_TIMEVALALLOCFAIL:
  535. return "Unable to allocate the timeval structure";
  536. case SOCKERR_LINGERALLOCFAIL:
  537. return "Unable to allocate the linger structure";
  538. case SOCKERR_IPMREQALLOCFAIL:
  539. return "Unable to allocate the ipmreq structure";
  540. case SOCKERR_FDSETALLOCFAIL:
  541. return "Unable to allocate the fdset structure";
  542. case SOCKERR_OPFAILED:
  543. return "Operation failed";
  544. case SOCKERR_CONNECTION_REFUSED:
  545. return "Connection refused";
  546. case SOCKERR_ENETUNREACH:
  547. return "Network unreachable";
  548. case SOCKERR_EHOSTUNREACH:
  549. return "No route to host";
  550. case SOCKERR_EPIPE:
  551. return "Broken pipe";
  552. case SOCKERR_EACCES:
  553. return "Permission denied (maybe missing INTERNET permission)";
  554. default:
  555. // LOGE("unknown socket error %d", anErrorNum);
  556. return "unknown error";
  557. }
  558. }
  559. static int convertError(int errorCode) {
  560. switch (errorCode) {
  561. case EBADF:
  562. return SOCKERR_BADDESC;
  563. case ENOBUFS:
  564. return SOCKERR_NOBUFFERS;
  565. case EOPNOTSUPP:
  566. return SOCKERR_OPNOTSUPP;
  567. case ENOPROTOOPT:
  568. return SOCKERR_OPTUNSUPP;
  569. case EINVAL:
  570. return SOCKERR_SOCKLEVELINVALID;
  571. case ENOTSOCK:
  572. return SOCKERR_NOTSOCK;
  573. case EINTR:
  574. return SOCKERR_INTERRUPTED;
  575. case ENOTCONN:
  576. return SOCKERR_NOTCONNECTED;
  577. case EAFNOSUPPORT:
  578. return SOCKERR_BADAF;
  579. /* note: CONNRESET not included because it has the same
  580. * value as ECONNRESET and they both map to SOCKERR_CONNRESET */
  581. case ECONNRESET:
  582. return SOCKERR_CONNRESET;
  583. case EAGAIN:
  584. return SOCKERR_WOULDBLOCK;
  585. case EPROTONOSUPPORT:
  586. return SOCKERR_BADPROTO;
  587. case EFAULT:
  588. return SOCKERR_ARGSINVALID;
  589. case ETIMEDOUT:
  590. return SOCKERR_TIMEOUT;
  591. case ECONNREFUSED:
  592. return SOCKERR_CONNECTION_REFUSED;
  593. case ENETUNREACH:
  594. return SOCKERR_ENETUNREACH;
  595. case EACCES:
  596. return SOCKERR_EACCES;
  597. case EPIPE:
  598. return SOCKERR_EPIPE;
  599. case EHOSTUNREACH:
  600. return SOCKERR_EHOSTUNREACH;
  601. case EADDRINUSE:
  602. return SOCKERR_ADDRINUSE;
  603. case EADDRNOTAVAIL:
  604. return SOCKERR_ADDRNOTAVAIL;
  605. case EMSGSIZE:
  606. return SOCKERR_MSGSIZE;
  607. default:
  608. // LOGE("unclassified errno %d (%s)", errorCode, strerror(errorCode));
  609. return SOCKERR_OPFAILED;
  610. }
  611. }
  612. static int sockSelect(int nfds, fd_set *readfds, fd_set *writefds,
  613. fd_set *exceptfds, struct timeval *timeout) {
  614. int result = select(nfds, readfds, writefds, exceptfds, timeout);
  615. if (result < 0) {
  616. if (errno == EINTR) {
  617. result = SOCKERR_INTERRUPTED;
  618. } else {
  619. result = SOCKERR_OPFAILED;
  620. }
  621. } else if (result == 0) {
  622. result = SOCKERR_TIMEOUT;
  623. }
  624. return result;
  625. }
  626. #define SELECT_READ_TYPE 0
  627. #define SELECT_WRITE_TYPE 1
  628. static int selectWait(int handle, int uSecTime, int type) {
  629. fd_set fdset;
  630. struct timeval time, *timePtr;
  631. int result = 0;
  632. int size = handle + 1;
  633. FD_ZERO(&fdset);
  634. FD_SET(handle, &fdset);
  635. if (0 <= uSecTime) {
  636. /* Use a timeout if uSecTime >= 0 */
  637. memset(&time, 0, sizeof(time));
  638. time.tv_usec = uSecTime;
  639. timePtr = &time;
  640. } else {
  641. /* Infinite timeout if uSecTime < 0 */
  642. timePtr = NULL;
  643. }
  644. if (type == SELECT_READ_TYPE) {
  645. result = sockSelect(size, &fdset, NULL, NULL, timePtr);
  646. } else {
  647. result = sockSelect(size, NULL, &fdset, NULL, timePtr);
  648. }
  649. return result;
  650. }
  651. static int pollSelectWait(JNIEnv *env, jobject fileDescriptor, int timeout, int type) {
  652. /* now try reading the socket for the timespan timeout.
  653. * if timeout is 0 try forever until the soclets gets ready or until an
  654. * exception occurs.
  655. */
  656. int pollTimeoutUSec = 100000, pollMsec = 100;
  657. int finishTime = 0;
  658. int timeLeft = timeout;
  659. int hasTimeout = timeout > 0 ? 1 : 0;
  660. int result = 0;
  661. int handle;
  662. if (hasTimeout) {
  663. finishTime = time_msec_clock() + timeout;
  664. }
  665. int poll = 1;
  666. while (poll) { /* begin polling loop */
  667. /*
  668. * Fetch the handle every time in case the socket is closed.
  669. */
  670. handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
  671. if (handle == 0 || handle == -1) {
  672. throwSocketException(env, SOCKERR_INTERRUPTED);
  673. return -1;
  674. }
  675. if (hasTimeout) {
  676. if (timeLeft - 10 < pollMsec) {
  677. pollTimeoutUSec = timeLeft <= 0 ? 0 : (timeLeft * 1000);
  678. }
  679. result = selectWait(handle, pollTimeoutUSec, type);
  680. /*
  681. * because we are polling at a time smaller than timeout
  682. * (presumably) lets treat an interrupt and timeout the same - go
  683. * see if we're done timewise, and then just try again if not.
  684. */
  685. if (SOCKERR_TIMEOUT == result ||
  686. SOCKERR_INTERRUPTED == result) {
  687. timeLeft = finishTime - time_msec_clock();
  688. if (timeLeft <= 0) {
  689. /*
  690. * Always throw the "timeout" message because that is
  691. * effectively what has happened, even if we happen to
  692. * have been interrupted.
  693. */
  694. jniThrowException(env, "java/net/SocketTimeoutException",
  695. netLookupErrorString(SOCKERR_TIMEOUT));
  696. } else {
  697. continue; // try again
  698. }
  699. } else if (0 > result) {
  700. log_socket_close(handle, result);
  701. throwSocketException(env, result);
  702. }
  703. poll = 0;
  704. } else { /* polling with no timeout (why would you do this?)*/
  705. result = selectWait(handle, pollTimeoutUSec, type);
  706. /*
  707. * if interrupted (or a timeout) just retry
  708. */
  709. if (SOCKERR_TIMEOUT == result ||
  710. SOCKERR_INTERRUPTED == result) {
  711. continue; // try again
  712. } else if (0 > result) {
  713. log_socket_close(handle, result);
  714. throwSocketException(env, result);
  715. }
  716. poll = 0;
  717. }
  718. } /* end polling loop */
  719. return result;
  720. }
  721. /**
  722. * A helper method, to set the connect context to a Long object.
  723. *
  724. * @param env pointer to the JNI library
  725. * @param longclass Java Long Object
  726. */
  727. void setConnectContext(JNIEnv *env,jobject longclass,jbyte * context) {
  728. jclass descriptorCLS;
  729. jfieldID descriptorFID;
  730. descriptorCLS = env->FindClass("java/lang/Long");
  731. descriptorFID = env->GetFieldID(descriptorCLS, "value", "J");
  732. env->SetLongField(longclass, descriptorFID, (jlong)((jint)context));
  733. };
  734. /**
  735. * A helper method, to get the connect context.
  736. *
  737. * @param env pointer to the JNI library
  738. * @param longclass Java Long Object
  739. */
  740. jbyte *getConnectContext(JNIEnv *env, jobject longclass) {
  741. jclass descriptorCLS;
  742. jfieldID descriptorFID;
  743. descriptorCLS = env->FindClass("java/lang/Long");
  744. descriptorFID = env->GetFieldID(descriptorCLS, "value", "J");
  745. return (jbyte*) ((jint)env->GetLongField(longclass, descriptorFID));
  746. };
  747. // typical ip checksum
  748. unsigned short ip_checksum(unsigned short* buffer, int size) {
  749. register unsigned short * buf = buffer;
  750. register int bufleft = size;
  751. register unsigned long sum = 0;
  752. while (bufleft > 1) {
  753. sum = sum + (*buf++);
  754. bufleft = bufleft - sizeof(unsigned short );
  755. }
  756. if (bufleft) {
  757. sum = sum + (*(unsigned char*)buf);
  758. }
  759. sum = (sum >> 16) + (sum & 0xffff);
  760. sum += (sum >> 16);
  761. return (unsigned short )(~sum);
  762. }
  763. /**
  764. * Establish a connection to a peer with a timeout. This function is called
  765. * repeatedly in order to carry out the connect and to allow other tasks to
  766. * proceed on certain platforms. The caller must first call with
  767. * step = SOCKET_STEP_START, if the result is SOCKERR_NOTCONNECTED it will then
  768. * call it with step = CHECK until either another error or 0 is returned to
  769. * indicate the connect is complete. Each time the function should sleep for no
  770. * more than timeout milliseconds. If the connect succeeds or an error occurs,
  771. * the caller must always end the process by calling the function with
  772. * step = SOCKET_STEP_DONE
  773. *
  774. * @param[in] portLibrary The port library.
  775. * @param[in] sock pointer to the unconnected local socket.
  776. * @param[in] addr pointer to the sockaddr, specifying remote host/port.
  777. * @param[in] timeout the timeout in milliseconds. If timeout is negative,
  778. * perform a block operation.
  779. * @param[in,out] pointer to context pointer. Filled in on first call and then
  780. * to be passed into each subsequent call.
  781. *
  782. * @return 0, if no errors occurred, otherwise the (negative) error code.
  783. */
  784. static int sockConnectWithTimeout(int handle, struct sockaddr_in addr,
  785. unsigned int timeout, unsigned int step, jbyte *ctxt) {
  786. int rc = 0;
  787. struct timeval passedTimeout;
  788. int errorVal;
  789. socklen_t errorValLen = sizeof(int);
  790. struct selectFDSet *context = NULL;
  791. if (SOCKET_STEP_START == step) {
  792. context = (struct selectFDSet *) ctxt;
  793. context->sock = handle;
  794. context->nfds = handle + 1;
  795. if (useAdbNetworking && !isLocalhost(&addr)) {
  796. // LOGD("+connect to address 0x%08x (via adb)",
  797. // addr.sin_addr.s_addr);
  798. rc = adb_networking_connect_fd(handle, &addr);
  799. // LOGD("-connect ret %d errno %d (via adb)", rc, errno);
  800. } else {
  801. log_socket_connect(handle, ntohl(addr.sin_addr.s_addr),
  802. ntohs(addr.sin_port));
  803. /* set the socket to non-blocking */
  804. int block = JNI_TRUE;
  805. rc = ioctl(handle, FIONBIO, &block);
  806. if (0 != rc) {
  807. return convertError(rc);
  808. }
  809. // LOGD("+connect to address 0x%08x (via normal) on handle %d",
  810. // addr.sin_addr.s_addr, handle);
  811. do {
  812. rc = connect(handle, (struct sockaddr *) &addr,
  813. sizeof(struct sockaddr));
  814. } while (rc < 0 && errno == EINTR);
  815. // LOGD("-connect to address 0x%08x (via normal) returned %d",
  816. // addr.sin_addr.s_addr, (int) rc);
  817. }
  818. if (rc == -1) {
  819. rc = errno;
  820. switch (rc) {
  821. case EINTR:
  822. return SOCKERR_ALREADYBOUND;
  823. case EAGAIN:
  824. case EINPROGRESS:
  825. return SOCKERR_NOTCONNECTED;
  826. default:
  827. return convertError(rc);
  828. }
  829. }
  830. /* we connected right off the bat so just return */
  831. return rc;
  832. } else if (SOCKET_STEP_CHECK == step) {
  833. /* now check if we have connected yet */
  834. context = (struct selectFDSet *) ctxt;
  835. /*
  836. * set the timeout value to be used. Because on some unix platforms we
  837. * don't get notified when a socket is closed we only sleep for 100ms
  838. * at a time
  839. */
  840. passedTimeout.tv_sec = 0;
  841. if (timeout > 100) {
  842. passedTimeout.tv_usec = 100 * 1000;
  843. } else if ((int)timeout >= 0) {
  844. passedTimeout.tv_usec = timeout * 1000;
  845. }
  846. /* initialize the FD sets for the select */
  847. FD_ZERO(&(context->exceptionSet));
  848. FD_ZERO(&(context->writeSet));
  849. FD_ZERO(&(context->readSet));
  850. FD_SET(context->sock, &(context->writeSet));
  851. FD_SET(context->sock, &(context->readSet));
  852. FD_SET(context->sock, &(context->exceptionSet));
  853. rc = select(context->nfds,
  854. &(context->readSet),
  855. &(context->writeSet),
  856. &(context->exceptionSet),
  857. (int)timeout >= 0 ? &passedTimeout : NULL);
  858. /* if there is at least one descriptor ready to be checked */
  859. if (0 < rc) {
  860. /* if the descriptor is in the write set we connected or failed */
  861. if (FD_ISSET(context->sock, &(context->writeSet))) {
  862. if (!FD_ISSET(context->sock, &(context->readSet))) {
  863. /* ok we have connected ok */
  864. return 0;
  865. } else {
  866. /* ok we have more work to do to figure it out */
  867. if (getsockopt(context->sock, SOL_SOCKET, SO_ERROR,
  868. &errorVal, &errorValLen) >= 0) {
  869. return errorVal ? convertError(errorVal) : 0;
  870. } else {
  871. return convertError(errno);
  872. }
  873. }
  874. }
  875. /* if the descriptor is in the exception set the connect failed */
  876. if (FD_ISSET(context->sock, &(context->exceptionSet))) {
  877. if (getsockopt(context->sock, SOL_SOCKET, SO_ERROR, &errorVal,
  878. &errorValLen) >= 0) {
  879. return errorVal ? convertError(errorVal) : 0;
  880. }
  881. rc = errno;
  882. return convertError(rc);
  883. }
  884. } else if (rc < 0) {
  885. /* something went wrong with the select call */
  886. rc = errno;
  887. /* if it was EINTR we can just try again. Return not connected */
  888. if (EINTR == rc) {
  889. return SOCKERR_NOTCONNECTED;
  890. }
  891. /* some other error occured so look it up and return */
  892. return convertError(rc);
  893. }
  894. /*
  895. * if we get here the timeout expired or the connect had not yet
  896. * completed just indicate that the connect is not yet complete
  897. */
  898. return SOCKERR_NOTCONNECTED;
  899. } else if (SOCKET_STEP_DONE == step) {
  900. /* we are done the connect or an error occured so clean up */
  901. if (handle != -1) {
  902. int block = JNI_FALSE;
  903. ioctl(handle, FIONBIO, &block);
  904. }
  905. return 0;
  906. }
  907. return SOCKERR_ARGSINVALID;
  908. }
  909. /**
  910. * Join/Leave the nominated multicast group on the specified socket.
  911. * Implemented by setting the multicast 'add membership'/'drop membership'
  912. * option at the HY_IPPROTO_IP level on the socket.
  913. *
  914. * Implementation note for multicast sockets in general:
  915. *
  916. * - This code is untested, because at the time of this writing multicast can't
  917. * be properly tested on Android due to GSM routing restrictions. So it might
  918. * or might not work.
  919. *
  920. * - The REUSEPORT socket option that Harmony employs is not supported on Linux
  921. * and thus also not supported on Android. It's is not needed for multicast
  922. * to work anyway (REUSEADDR should suffice).
  923. *
  924. * @param env pointer to the JNI library.
  925. * @param socketP pointer to the hysocket to join/leave on.
  926. * @param optVal pointer to the InetAddress, the multicast group to join/drop.
  927. *
  928. * @exception SocketException if an error occurs during the call
  929. */
  930. static void mcastAddDropMembership (JNIEnv * env, int handle, jobject optVal,
  931. int ignoreIF, int setSockOptVal) {
  932. int result;
  933. struct ip_mreq ipmreqP;
  934. struct sockaddr_in sockaddrP;
  935. int length = sizeof(struct ip_mreq);
  936. socklen_t lengthIF = sizeof(struct sockaddr_in);
  937. /*
  938. * JNI objects needed to access the information in the optVal oject
  939. * passed in. The object passed in is a GenericIPMreq object
  940. */
  941. jclass cls;
  942. jfieldID multiaddrID;
  943. jfieldID interfaceAddrID;
  944. jobject multiaddr;
  945. jobject interfaceAddr;
  946. /*
  947. * check whether we are getting an InetAddress or an Generic IPMreq, for now
  948. * we support both so that we will not break the tests
  949. */
  950. if (env->IsInstanceOf (optVal, gCachedFields.iaddr_class)) {
  951. ipmreqP.imr_interface.s_addr = htonl(INADDR_ANY);
  952. if (!ignoreIF) {
  953. result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF, &sockaddrP,
  954. &lengthIF);
  955. if (0 != result) {
  956. throwSocketException (env, convertError(errno));
  957. return;
  958. }
  959. memcpy(&(ipmreqP.imr_interface.s_addr), &(sockaddrP.sin_addr), 4);
  960. }
  961. result = inetAddressToSocketAddress(env, optVal, 0, &sockaddrP);
  962. if (result < 0) {
  963. throwSocketException(env, SOCKERR_BADSOCKET);
  964. return;
  965. }
  966. memcpy(&(ipmreqP.imr_multiaddr.s_addr), &(sockaddrP.sin_addr), 4);
  967. result = setsockopt(handle, IPPROTO_IP, setSockOptVal, &ipmreqP, length);
  968. if (0 != result) {
  969. throwSocketException (env, convertError(errno));
  970. return;
  971. }
  972. } else {
  973. /* we need the multicast address regardless of the type of address */
  974. cls = env->GetObjectClass(optVal);
  975. multiaddrID = env->GetFieldID(cls, "multiaddr", "Ljava/net/InetAddress;");
  976. multiaddr = env->GetObjectField(optVal, multiaddrID);
  977. result = inetAddressToSocketAddress(env, multiaddr, 0, &sockaddrP);
  978. if (result < 0) {
  979. throwSocketException(env, SOCKERR_BADSOCKET);
  980. return;
  981. }
  982. memcpy(&(ipmreqP.imr_multiaddr.s_addr), &(sockaddrP.sin_addr), 4);
  983. /* we need to use an IP_MREQ as it is an IPV4 address */
  984. interfaceAddrID = env->GetFieldID(cls, "interfaceAddr",
  985. "Ljava/net/InetAddress;");
  986. interfaceAddr = env->GetObjectField(optVal, interfaceAddrID);
  987. ipmreqP.imr_interface.s_addr = htonl(INADDR_ANY);
  988. /*
  989. * if an interfaceAddr was passed then use that value, otherwise set the
  990. * interface to all 0 to indicate the system should select the interface
  991. * used
  992. */
  993. if (!ignoreIF) {
  994. if (NULL != interfaceAddr) {
  995. result = inetAddressToSocketAddress(env, interfaceAddr, 0,
  996. &sockaddrP);
  997. if (result < 0) {
  998. throwSocketException(env, SOCKERR_BADSOCKET);
  999. return;
  1000. }
  1001. memcpy(&(ipmreqP.imr_interface.s_addr), &(sockaddrP.sin_addr), 4);
  1002. }
  1003. }
  1004. /* join/drop the multicast address */
  1005. result = setsockopt(handle, IPPROTO_IP, setSockOptVal, &ipmreqP, length);
  1006. if (0 != result) {
  1007. throwSocketException (env, convertError(errno));
  1008. return;
  1009. }
  1010. }
  1011. }
  1012. extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_oneTimeInitializationImpl(JNIEnv* env, jobject obj,
  1013. jboolean jcl_supports_ipv6) {
  1014. // LOGD("ENTER oneTimeInitializationImpl of OSNetworkSystem");
  1015. char useAdbNetworkingProperty[PROPERTY_VALUE_MAX];
  1016. char adbConnectedProperty[PROPERTY_VALUE_MAX];
  1017. property_get("android.net.use-adb-networking", useAdbNetworkingProperty, "");
  1018. property_get("adb.connected", adbConnectedProperty, "");
  1019. if (strlen((char *)useAdbNetworkingProperty) > 0
  1020. && strlen((char *)adbConnectedProperty) > 0) {
  1021. useAdbNetworking = 1;
  1022. }
  1023. memset(&gCachedFields, 0, sizeof(gCachedFields));
  1024. // initializing InetAddress
  1025. jclass iaddrclass = env->FindClass("java/net/InetAddress");
  1026. if (iaddrclass == NULL) {
  1027. jniThrowException(env, "java/lang/ClassNotFoundException",
  1028. "java.net.InetAddress");
  1029. return;
  1030. }
  1031. gCachedFields.iaddr_class = (jclass) env->NewGlobalRef(iaddrclass);
  1032. jmethodID iaddrclassinit = env->GetMethodID(iaddrclass, "<init>", "()V");
  1033. if (iaddrclassinit == NULL) {
  1034. jniThrowException(env, "java/lang/NoSuchMethodError", "InetAddress.<init>()");
  1035. return;
  1036. }
  1037. gCachedFields.iaddr_class_init = iaddrclassinit;
  1038. jmethodID iaddrgetbyaddress = env->GetStaticMethodID(iaddrclass,
  1039. "getByAddress", "([B)Ljava/net/InetAddress;");
  1040. if (iaddrgetbyaddress == NULL) {
  1041. jniThrowException(env, "java/lang/NoSuchMethodError",
  1042. "InetAddress.getByAddress(byte[] val)");
  1043. return;
  1044. }
  1045. gCachedFields.iaddr_getbyaddress = iaddrgetbyaddress;
  1046. jfieldID iaddripaddress = env->GetFieldID(iaddrclass, "ipaddress", "[B");
  1047. if (iaddripaddress == NULL) {
  1048. jniThrowException(env, "java/lang/NoSuchFieldError",
  1049. "Can't find field InetAddress.ipaddress");
  1050. return;
  1051. }
  1052. gCachedFields.iaddr_ipaddress = iaddripaddress;
  1053. // get the GenericIPMreq class
  1054. jclass genericipmreqclass = env->FindClass("org/apache/harmony/luni/net/GenericIPMreq");
  1055. if (genericipmreqclass == NULL) {
  1056. jniThrowException(env, "java/lang/ClassNotFoundException",
  1057. "org.apache.harmony.luni.net.GenericIPMreq");
  1058. return;
  1059. }
  1060. gCachedFields.genericipmreq_class = (jclass) env->NewGlobalRef(genericipmreqclass);
  1061. // initializing Integer
  1062. jclass integerclass = env->FindClass("java/lang/Integer");
  1063. if (integerclass == NULL) {
  1064. jniThrowException(env, "java/lang/ClassNotFoundException",
  1065. "java.lang.Integer");
  1066. return;
  1067. }
  1068. jmethodID integerclassinit = env->GetMethodID(integerclass, "<init>", "(I)V");
  1069. if (integerclassinit == NULL) {
  1070. jniThrowException(env, "java/lang/NoSuchMethodError",
  1071. "Integer.<init>(int val)");
  1072. return;
  1073. }
  1074. jfieldID integerclassvalue = env->GetFieldID(integerclass, "value", "I");
  1075. if (integerclassvalue == NULL) {
  1076. jniThrowException(env, "java/lang/NoSuchMethodError", "Integer.value");
  1077. return;
  1078. }
  1079. gCachedFields.integer_class = (jclass) env->NewGlobalRef(integerclass);
  1080. gCachedFields.integer_class_init = integerclassinit;
  1081. gCachedFields.integer_class_value = integerclassvalue;
  1082. // initializing Boolean
  1083. jclass booleanclass = env->FindClass("java/lang/Boolean");
  1084. if (booleanclass == NULL) {
  1085. jniThrowException(env, "java/lang/ClassNotFoundException",
  1086. "java.lang.Boolean");
  1087. return;
  1088. }
  1089. jmethodID booleanclassinit = env->GetMethodID(booleanclass, "<init>", "(Z)V");
  1090. if (booleanclassinit == NULL) {
  1091. jniThrowException(env, "java/lang/NoSuchMethodError",
  1092. "Boolean.<init>(boolean val)");
  1093. return;
  1094. }
  1095. jfieldID booleanclassvalue = env->GetFieldID(booleanclass, "value", "Z");
  1096. if (booleanclassvalue == NULL) {
  1097. jniThrowException(env, "java/lang/NoSuchMethodError", "Boolean.value");
  1098. return;
  1099. }
  1100. gCachedFields.boolean_class = (jclass) env->NewGlobalRef(booleanclass);
  1101. gCachedFields.boolean_class_init = booleanclassinit;
  1102. gCachedFields.boolean_class_value = booleanclassvalue;
  1103. // initializing Byte
  1104. jclass byteclass = env->FindClass("java/lang/Byte");
  1105. if (byteclass == NULL) {
  1106. jniThrowException(env, "java/lang/ClassNotFoundException",
  1107. "java.lang.Byte");
  1108. return;
  1109. }
  1110. jmethodID byteclassinit = env->GetMethodID(byteclass, "<init>", "(B)V");
  1111. if (byteclassinit == NULL) {
  1112. jniThrowException(env, "java/lang/NoSuchMethodError",
  1113. "Byte.<init>(byte val)");
  1114. return;
  1115. }
  1116. jfieldID byteclassvalue = env->GetFieldID(byteclass, "value", "B");
  1117. if (byteclassvalue == NULL) {
  1118. jniThrowException(env, "java/lang/NoSuchMethodError", "Byte.value");
  1119. return;
  1120. }
  1121. gCachedFields.byte_class = (jclass) env->NewGlobalRef(byteclass);
  1122. gCachedFields.byte_class_init = byteclassinit;
  1123. gCachedFields.byte_class_value = byteclassvalue;
  1124. // initializing String
  1125. jclass stringclass = env->FindClass("java/lang/String");
  1126. if (stringclass == NULL) {
  1127. jniThrowException(env, "java/lang/ClassNotFoundException",
  1128. "java.lang.String");
  1129. return;
  1130. }
  1131. jmethodID stringclassinit = env->GetMethodID(stringclass, "<init>", "([B)V");
  1132. if (stringclassinit == NULL) {
  1133. jniThrowException(env, "java/lang/NoSuchMethodError",
  1134. "String.<init>(byte[] val)");
  1135. return;
  1136. }
  1137. gCachedFields.string_class = (jclass) env->NewGlobalRef(stringclass);
  1138. gCachedFields.string_class_init = stringclassinit;
  1139. // initializing ScoketImpl
  1140. jclass socketimplclass = env->FindClass("java/net/SocketImpl");
  1141. if (socketimplclass == NULL) {
  1142. jniThrowException(env, "java/lang/ClassNotFoundException",
  1143. "java.net.SocketImpl");
  1144. return;
  1145. }
  1146. jfieldID socketimplport = env->GetFieldID(socketimplclass, "port", "I");
  1147. if (socketimplport == NULL) {
  1148. jniThrowException(env, "java/lang/NoSuchFieldError", "SocketImpl.port");
  1149. return;
  1150. }
  1151. jfieldID socketimpladdress = env->GetFieldID(socketimplclass, "address",
  1152. "Ljava/net/InetAddress;");
  1153. if (socketimpladdress == NULL) {
  1154. jniThrowException(env, "java/lang/NoSuchFieldError",
  1155. "SocketImpl.address");
  1156. return;
  1157. }
  1158. gCachedFields.socketimpl_address = socketimpladdress;
  1159. gCachedFields.socketimpl_port = socketimplport;
  1160. gCachedFields.dpack_class = env->FindClass("java/net/DatagramPacket");
  1161. if (gCachedFields.dpack_class == NULL) {
  1162. jniThrowException(env, "java/lang/ClassNotFoundException",
  1163. "java.net.DatagramPacket");
  1164. return;
  1165. }
  1166. gCachedFields.dpack_address = env->GetFieldID(gCachedFields.dpack_class,
  1167. "address", "Ljava/net/InetAddress;");
  1168. if (gCachedFields.dpack_address == NULL) {
  1169. jniThrowException(env, "java/lang/NoSuchFieldError",
  1170. "DatagramPacket.address");
  1171. return;
  1172. }
  1173. gCachedFields.dpack_port = env->GetFieldID(gCachedFields.dpack_class,
  1174. "port", "I");
  1175. if (gCachedFields.dpack_port == NULL) {
  1176. jniThrowException(env, "java/lang/NoSuchFieldError",
  1177. "DatagramPacket.port");
  1178. return;
  1179. }
  1180. gCachedFields.dpack_length = env->GetFieldID(gCachedFields.dpack_class,
  1181. "length", "I");
  1182. if (gCachedFields.dpack_length == NULL) {
  1183. jniThrowException(env, "java/lang/NoSuchFieldError",
  1184. "DatagramPacket.length");
  1185. return;
  1186. }
  1187. gCachedFields.fd_class = env->FindClass("java/io/FileDescriptor");
  1188. if (gCachedFields.fd_class == NULL) {
  1189. jniThrowException(env, "java/lang/ClassNotFoundException",
  1190. "java.io.FileDescriptor");
  1191. return;
  1192. }
  1193. gCachedFields.descriptor = env->GetFieldID(gCachedFields.fd_class, "descriptor", "I");
  1194. if (gCachedFields.descriptor == NULL) {
  1195. jniThrowException(env, "java/lang/NoSuchFieldError",
  1196. "FileDescriptor.descriptor");
  1197. return;
  1198. }
  1199. }
  1200. extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_createSocketImpl(JNIEnv* env, jclass clazz,
  1201. jobject fileDescriptor, jboolean preferIPv4Stack) {
  1202. // LOGD("ENTER createSocketImpl");
  1203. int ret = socket(PF_INET, SOCK_STREAM, 0);
  1204. if (ret < 0) {
  1205. int err = convertError(errno);
  1206. throwSocketException(env, err);
  1207. return;
  1208. }
  1209. jniSetFileDescriptorOfFD(env, fileDescriptor, ret);
  1210. return;
  1211. }
  1212. extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_createDatagramSocketImpl(JNIEnv* env, jclass clazz,
  1213. jobject fileDescriptor, jboolean preferIPv4Stack) {
  1214. // LOGD("ENTER createDatagramSocketImpl");
  1215. int ret = socket(PF_INET, SOCK_DGRAM, 0);
  1216. if (ret < 0) {
  1217. int err = convertError(errno);
  1218. throwSocketException(env, err);
  1219. return;
  1220. }
  1221. jniSetFileDescriptorOfFD(env, fileDescriptor, ret);
  1222. return;
  1223. }
  1224. extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_readSocketDirectImpl(JNIEnv* env, jclass clazz,
  1225. jobject fileDescriptor, jint address, jint offset, jint count,
  1226. jint timeout) {
  1227. // LOGD("ENTER readSocketDirectImpl");
  1228. int handle;
  1229. jbyte *message = (jbyte *)address;
  1230. int result, ret, localCount;
  1231. handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
  1232. if (handle == 0 || handle == -1) {
  1233. throwSocketException(env, SOCKERR_BADSOCKET);
  1234. return 0;
  1235. }
  1236. result = selectWait(handle, timeout, SELECT_READ_TYPE);
  1237. if (0 > result) {
  1238. return 0;
  1239. }
  1240. localCount = (count < 65536) ? count : 65536;
  1241. do {
  1242. ret = recv(handle, (jbyte *) message, localCount, SOCKET_NOFLAGS);
  1243. } while (ret < 0 && errno == EINTR);
  1244. if (0 == ret) {
  1245. return -1;
  1246. } else if (ret == -1) {
  1247. int err = convertError(errno);
  1248. log_socket_close(handle, err);
  1249. throwSocketException(env, err);
  1250. return 0;
  1251. }
  1252. add_recv_stats(handle, ret);
  1253. return ret;
  1254. }
  1255. extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_readSocketImpl(JNIEnv* env, jclass clazz,
  1256. jobject fileDescriptor, jbyteArray data, jint offset, jint count,
  1257. jint timeout) {
  1258. // LOGD("ENTER readSocketImpl");
  1259. jbyte *message;
  1260. int result, localCount;
  1261. jbyte internalBuffer[BUFFERSIZE];
  1262. localCount = (count < 65536) ? count : 65536;
  1263. if (localCount > BUFFERSIZE) {
  1264. message = (jbyte*)malloc(localCount * sizeof(jbyte));
  1265. if (message == NULL) {
  1266. jniThrowException(env, "java/lang/OutOfMemoryError",
  1267. "couldn't allocate enough memory for readSocket");
  1268. return 0;
  1269. }
  1270. } else {
  1271. message = (jbyte *)internalBuffer;
  1272. }
  1273. result = Java_org_sipdroid_net_impl_OSNetworkSystem_readSocketDirectImpl(env, clazz, fileDescriptor,
  1274. (jint) message, offset, count, timeout);
  1275. if (result > 0) {
  1276. env->SetByteArrayRegion(data, offset, result, (jbyte *)message);
  1277. }
  1278. if (((jbyte *)message) != internalBuffer) {
  1279. free(( jbyte *)message);
  1280. }
  1281. return result;
  1282. }
  1283. extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_writeSocketDirectImpl(JNIEnv* env, jclass clazz,
  1284. jobject fileDescriptor, jint address, jint offset, jint count) {
  1285. // LOGD("ENTER writeSocketDirectImpl");
  1286. int handle;
  1287. jbyte *message = (jbyte *)address;
  1288. int result = 0, sent = 0;
  1289. if (count <= 0) {
  1290. return 0;
  1291. }
  1292. handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
  1293. if (handle == 0 || handle == -1) {
  1294. throwSocketException(env, SOCKERR_BADSOCKET);
  1295. return 0;
  1296. }
  1297. result = send(handle, (jbyte *) message, (int) count, SOCKET_NOFLAGS);
  1298. if (result < 0) {
  1299. int err = convertError(errno);
  1300. log_socket_close(handle, err);
  1301. if (SOCKERR_WOULDBLOCK == err){
  1302. jclass socketExClass,errorCodeExClass;
  1303. jmethodID errorCodeExConstructor, socketExConstructor,socketExCauseMethod;
  1304. jobject errorCodeEx, socketEx;
  1305. const char* errorMessage = netLookupErrorString(err);
  1306. jstring errorMessageString = env->NewStringUTF(errorMessage);
  1307. errorCodeExClass = env->FindClass("org/apache/harmony/luni/util/ErrorCodeException");
  1308. if (!errorCodeExClass){
  1309. return 0;
  1310. }
  1311. errorCodeExConstructor = env->GetMethodID(errorCodeExClass,"<init>","(I)V");
  1312. if (!errorCodeExConstructor){
  1313. return 0;
  1314. }
  1315. errorCodeEx = env->NewObject(errorCodeExClass,errorCodeExConstructor,err);
  1316. socketExClass = env->FindClass("java/net/SocketException");
  1317. if (!socketExClass) {
  1318. return 0;
  1319. }
  1320. socketExConstructor = env->GetMethodID(socketExClass,"<init>","(Ljava/lang/String;)V");
  1321. if (!socketExConstructor) {
  1322. return 0;
  1323. }
  1324. socketEx = env->NewObject(socketExClass, socketExConstructor, errorMessageString);
  1325. socketExCauseMethod = env->GetMethodID(socketExClass,"initCause","(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
  1326. env->CallObjectMethod(socketEx,socketExCauseMethod,errorCodeEx);
  1327. env->Throw((jthrowable)socketEx);
  1328. return 0;
  1329. }
  1330. throwSocketException(env, err);
  1331. return 0;
  1332. }
  1333. add_send_stats(handle, result);
  1334. return result;
  1335. }
  1336. extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_writeSocketImpl(JNIEnv* env, jclass clazz,
  1337. jobject fileDescriptor, jbyteArray data, jint offset, jint count) {
  1338. // LOGD("ENTER writeSocketImpl");
  1339. jbyte *message;
  1340. int sent = 0;
  1341. jint result = 0;
  1342. /* TODO: ARRAY PINNING */
  1343. #define INTERNAL_SEND_BUFFER_MAX 512
  1344. jbyte internalBuffer[INTERNAL_SEND_BUFFER_MAX];
  1345. if (count > INTERNAL_SEND_BUFFER_MAX) {
  1346. message = (jbyte*)malloc(count * sizeof( jbyte));
  1347. if (message == NULL) {
  1348. jniThrowException(env, "java/lang/OutOfMemoryError",
  1349. "couldn't allocate enough memory for writeSocket");
  1350. return 0;
  1351. }
  1352. } else {
  1353. message = (jbyte *)internalBuffer;
  1354. }
  1355. env->GetByteArrayRegion(data, offset, count, message);
  1356. result = Java_org_sipdroid_net_impl_OSNetworkSystem_writeSocketDirectImpl(env, clazz, fileDescriptor,
  1357. (jint) message, offset, count);
  1358. if (( jbyte *)message != internalBuffer) {
  1359. free(( jbyte *)message);
  1360. }
  1361. #undef INTERNAL_SEND_BUFFER_MAX
  1362. return result;
  1363. }
  1364. extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_setNonBlockingImpl(JNIEnv* env, jclass clazz,
  1365. jobject fileDescriptor, jboolean nonblocking) {
  1366. // LOGD("ENTER setNonBlockingImpl");
  1367. int handle;
  1368. int result;
  1369. handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
  1370. if (handle == 0 || handle == -1) {
  1371. throwSocketException(env, SOCKERR_BADSOCKET);
  1372. return;
  1373. }
  1374. int block = nonblocking;
  1375. result = ioctl(handle, FIONBIO, &block);
  1376. if (result == -1) {
  1377. throwSocketException(env, convertError(errno));
  1378. }
  1379. }
  1380. extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_connectSocketImpl(JNIEnv* env, jclass clazz,
  1381. jobject fileDescriptor, jint trafficClass, jobject inetAddr, jint port);
  1382. extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_connectWithTimeoutSocketImpl(JNIEnv* env,
  1383. jclass clazz, jobject fileDescriptor, jint timeout, jint trafficClass,
  1384. jobject inetAddr, jint port, jint step, jbyteArray passContext) {
  1385. // LOGD("ENTER connectWithTimeoutSocketImpl");
  1386. int handle;
  1387. int result = 0;
  1388. struct sockaddr_in address;
  1389. jbyte *context = NULL;
  1390. memset(&address, 0, sizeof(address));
  1391. address.sin_family = AF_INET;
  1392. result = inetAddressToSocketAddress(env, inetAddr, port,
  1393. (struct sockaddr_in *) &address);
  1394. if (result < 0) {
  1395. throwSocketException(env, SOCKERR_BADSOCKET);
  1396. return result;
  1397. }
  1398. // Check if we're using adb networking and redirect in case it is used.
  1399. if (useAdbNetworking && !isLocalhost(&address)) {
  1400. return Java_org_sipdroid_net_impl_OSNetworkSystem_connectSocketImpl(env, clazz, fileDescriptor,
  1401. trafficClass, inetAddr, port);
  1402. }
  1403. handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
  1404. if (handle == 0 || handle == -1) {
  1405. throwSocketException(env, SOCKERR_BADSOCKET);
  1406. return -1;
  1407. }
  1408. address.sin_port = htons(port);
  1409. context = (jbyte *)env->GetPrimitiveArrayCritical(passContext, NULL);
  1410. switch (step) {
  1411. case SOCKET_CONNECT_STEP_START:
  1412. result = sockConnectWithTimeout(handle, address, 0,
  1413. SOCKET_STEP_START, context);
  1414. break;
  1415. case SOCKET_CONNECT_STEP_CHECK:
  1416. result = sockConnectWithTimeout(handle, address, timeout,
  1417. SOCKET_STEP_CHECK, context);
  1418. break;
  1419. }
  1420. env->ReleasePrimitiveArrayCritical(passContext, context, JNI_ABORT);
  1421. if (0 == result) {
  1422. /* connected , so stop here */
  1423. sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE, NULL);
  1424. } else if (result != SOCKERR_NOTCONNECTED) {
  1425. /* can not connect... */
  1426. sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE, NULL);
  1427. if (result == SOCKERR_EACCES) {
  1428. jniThrowException(env, "java/lang/SecurityException",
  1429. netLookupErrorString(result));
  1430. } else {
  1431. jniThrowException(env, "java/net/ConnectException",
  1432. netLookupErrorString(result));
  1433. }
  1434. }
  1435. return result;
  1436. }
  1437. extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_connectStreamWithTimeoutSocketImpl(JNIEnv* env,
  1438. jclass clazz, jobject fileDescriptor, jint remotePort, jint timeout,
  1439. jint trafficClass, jobject inetAddr) {
  1440. // LOGD("ENTER connectStreamWithTimeoutSocketImpl");
  1441. int result = 0;
  1442. int handle;
  1443. struct sockaddr_in address;
  1444. jbyte *context = NULL;
  1445. int remainingTimeout = timeout;
  1446. int passedTimeout = 0;
  1447. int finishTime = 0;
  1448. int blocking = 0;
  1449. char hasTimeout = timeout > 0;
  1450. /* if a timeout was specified calculate the finish time value */
  1451. if (hasTimeout) {
  1452. finishTime = time_msec_clock() + (int) timeout;
  1453. }
  1454. handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
  1455. if (handle == 0 || handle == -1) {
  1456. throwSocketException(env, SOCKERR_BADSOCKET);
  1457. return;
  1458. } else {
  1459. result = inetAddressToSocketAddress(env, inetAddr, remotePort,
  1460. (struct sockaddr_in *) &address);
  1461. if (result < 0) {
  1462. throwSocketException(env, SOCKERR_BADSOCKET);
  1463. return;
  1464. }
  1465. // Check if we're using adb networking and redirect in case it is used.
  1466. if (useAdbNetworking && !isLocalhost(&address)) {
  1467. int retVal = Java_org_sipdroid_net_impl_OSNetworkSystem_connectSocketImpl(env, clazz,
  1468. fileDescriptor, trafficClass, inetAddr, remotePort);
  1469. if (retVal != 0) {
  1470. throwSocketException(env, SOCKERR_BADSOCKET);
  1471. }
  1472. return;
  1473. }
  1474. /*
  1475. * we will be looping checking for when we are connected so allocate
  1476. * the descriptor sets that we will use
  1477. */
  1478. context =(jbyte *) malloc(sizeof(struct selectFDSet));
  1479. if (NULL == context) {
  1480. throwSocketException(env, SOCKERR_NOBUFFERS);
  1481. return;
  1482. }
  1483. result = sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_START, context);
  1484. if (0 == result) {
  1485. /* ok we connected right away so we are done */
  1486. sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE, context);
  1487. goto bail;
  1488. } else if (result != SOCKERR_NOTCONNECTED) {
  1489. log_socket_close(handle, result);
  1490. sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE,
  1491. context);
  1492. /* we got an error other than NOTCONNECTED so we cannot continue */
  1493. if (SOCKERR_EACCES == result) {
  1494. jniThrowException(env, "java/lang/SecurityException",
  1495. netLookupErrorString(result));
  1496. } else {
  1497. throwSocketException(env, result);
  1498. }
  1499. goto bail;
  1500. }
  1501. while (SOCKERR_NOTCONNECTED == result) {
  1502. passedTimeout = remainingTimeout;
  1503. /*
  1504. * ok now try and connect. Depending on the platform this may sleep
  1505. * for up to passedTimeout milliseconds
  1506. */
  1507. result = sockConnectWithTimeout(handle, address, passedTimeout,
  1508. SOCKET_STEP_CHECK, context);
  1509. /*
  1510. * now check if the socket is still connected.
  1511. * Do it here as some platforms seem to think they
  1512. * are connected if the socket is closed on them.
  1513. */
  1514. handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
  1515. if (handle == 0 || handle == -1) {
  1516. sockConnectWithTimeout(handle, address, 0,
  1517. SOCKET_STEP_DONE, context);
  1518. throwSocketException(env, SOCKERR_BADSOCKET);
  1519. goto bail;
  1520. }
  1521. /*
  1522. * check if we are now connected,
  1523. * if so we can finish the process and return
  1524. */
  1525. if (0 == result) {
  1526. sockConnectWithTimeout(handle, address, 0,
  1527. SOCKET_STEP_DONE, context);
  1528. goto bail;
  1529. }
  1530. /*
  1531. * if the error is SOCKERR_NOTCONNECTED then we have not yet
  1532. * connected and we may not be done yet
  1533. */
  1534. if (SOCKERR_NOTCONNECTED == result) {
  1535. /* check if the timeout has expired */
  1536. if (hasTimeout) {
  1537. remainingTimeout = finishTime - time_msec_clock();
  1538. if (remainingTimeout <= 0) {
  1539. log_socket_close(handle, result);
  1540. sockConnectWithTimeout(handle, address, 0,
  1541. SOCKET_STEP_DONE, context);
  1542. jniThrowException(env,
  1543. "java/net/SocketTimeoutException",
  1544. netLookupErrorString(result));
  1545. goto bail;
  1546. }
  1547. } else {
  1548. remainingTimeout = 100;
  1549. }
  1550. } else {
  1551. log_socket_close(handle, result);
  1552. sockConnectWithTimeout(handle, address, remainingTimeout,
  1553. SOCKET_STEP_DONE, context);
  1554. if ((SOCKERR_CONNRESET == result) ||
  1555. (SOCKERR_CONNECTION_REFUSED == result) ||
  1556. (SOCKERR_ADDRNOTAVAIL == result) ||
  1557. (SOCKERR_ADDRINUSE == result) ||
  1558. (SOCKERR_ENETUNREACH == result)) {
  1559. jniThrowException(env, "java/net/ConnectException",
  1560. netLookupErrorString(result));
  1561. } else if (SOCKERR_EACCES == result) {
  1562. jniThrowException(env, "java/lang/SecurityException",
  1563. netLookupErrorString(result));
  1564. } else {
  1565. throwSocketException(env, result);
  1566. }
  1567. goto bail;
  1568. }
  1569. }
  1570. }
  1571. bail:
  1572. /* free the memory for the FD set */
  1573. if (context != NULL) {
  1574. free(context);
  1575. }
  1576. }
  1577. extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_connectSocketImpl(JNIEnv* env, jclass clazz,
  1578. jobject fileDescriptor, jint trafficClass, jobject inetAddr, jint port) {
  1579. //LOGD("ENTER direct-call connectSocketImpl\n");
  1580. struct sockaddr_in address;
  1581. int ret;
  1582. int handle;
  1583. jbyteArray java_in_addr;
  1584. memset(&address, 0, sizeof(address));
  1585. address.sin_family = AF_INET;
  1586. ret = inetAddressToSocketAddress(env, inetAddr, port,
  1587. (struct sockaddr_in *) &address);
  1588. if (ret < 0) {
  1589. throwSocketException(env, SOCKERR_BADSOCKET);
  1590. return ret;
  1591. }
  1592. handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
  1593. if (handle == 0 || handle == -1) {
  1594. throwSocketException(env, SOCKERR_BADSOCKET);
  1595. return -1;
  1596. }
  1597. address.sin_port = htons(port);
  1598. if (useAdbNetworking && !isLocalhost(&address)) {
  1599. // LOGD("+connect to address 0x%08x port %d (via adb)",
  1600. // address.sin_addr.s_addr, (int) port);
  1601. ret = adb_networking_connect_fd(handle, &address);
  1602. // LOGD("-connect ret %d errno %d (via adb)", ret, errno);
  1603. } else {
  1604. // call this method with a timeout of zero
  1605. Java_org_sipdroid_net_impl_OSNetworkSystem_connectStreamWithTimeoutSocketImpl(env, clazz,
  1606. fileDescriptor, port, 0, trafficClass, inetAddr);
  1607. if (env->ExceptionOccurred() != 0) {
  1608. return -1;
  1609. } else {
  1610. return 0;
  1611. }
  1612. }
  1613. if (ret < 0) {
  1614. jniThrowException(env, "java/net/ConnectException",
  1615. netLookupErrorString(convertError(errno)));
  1616. return ret;
  1617. }
  1618. return ret;
  1619. }
  1620. extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_socketBindImpl(JNIEnv* env, jclass clazz,
  1621. jobject fileDescriptor, jint port, jobject inetAddress) {
  1622. // LOGD("ENTER socketBindImpl");
  1623. struct sockaddr_in sockaddress;
  1624. int ret;
  1625. int handle;
  1626. ret = inetAddressToSocketAddress(env, inetAddress, port,
  1627. (struct sockaddr_in *) &sockaddress);
  1628. if (ret < 0) {
  1629. throwSocketException(env, SOCKERR_BADSOCKET);
  1630. return;
  1631. }
  1632. handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
  1633. if (handle == 0 || handle == -1) {
  1634. throwSocketException(env, SOCKERR_BADSOCKET);
  1635. return;
  1636. }
  1637. ret = bind(handle, (const sockaddr*)&sockaddress, sizeof(sockaddress));
  1638. if (ret < 0) {
  1639. jniThrowException(env, "java/net/BindException",
  1640. netLookupErrorString(convertError(errno)));
  1641. return;
  1642. }
  1643. }
  1644. extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_listenStreamSocketImpl(JNIEnv* env, jclass clazz,
  1645. jobject fileDescriptor, jint backlog) {
  1646. // LOGD("ENTER listenStreamSocketImpl");
  1647. int ret;
  1648. int handle;
  1649. handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
  1650. if (handle == 0 || handle == -1) {
  1651. throwSocketException(env, SOCKERR_BADSOCKET);
  1652. return;
  1653. }
  1654. ret = listen(handle, backlog);
  1655. if (ret < 0) {
  1656. int err = convertError(errno);
  1657. log_socket_close(handle, err);
  1658. throwSocketException(env, err);
  1659. return;
  1660. }
  1661. }
  1662. extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_availableStreamImpl(JNIEnv* env, jclass clazz,
  1663. jobject fileDescriptor) {
  1664. // LOGD("ENTER availableStreamImpl");
  1665. int handle;
  1666. char message[BUFFERSIZE];
  1667. int result;
  1668. handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
  1669. if (handle == 0 || handle == -1) {
  1670. throwSocketException(env, SOCKERR_BADSOCKET);
  1671. return 0;
  1672. }
  1673. do {
  1674. result = selectWait(handle, 1, SELECT_READ_TYPE);
  1675. if (SOCKERR_TIMEOUT == result) {
  1676. // The read operation timed out, so answer 0 bytes available
  1677. return 0;
  1678. } else if (SOCKERR_INTERRUPTED == result) {
  1679. continue;
  1680. } else if (0 > result) {
  1681. log_socket_close(handle, result);
  1682. throwSocketException(env, result);
  1683. return 0;
  1684. }
  1685. } while (SOCKERR_INTERRUPTED == result);
  1686. result = recv(handle, (jbyte *) message, BUFFERSIZE, MSG_PEEK);
  1687. if (0 > result) {
  1688. int err = convertError(errno);
  1689. log_socket_close(handle, err);
  1690. throwSocketException(env, err);
  1691. return 0;
  1692. }
  1693. add_recv_stats(handle, result);
  1694. return result;
  1695. }
  1696. extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_acceptSocketImpl(JNIEnv* env, jclass clazz,
  1697. jobject fdServer, jobject newSocket, jobject fdnewSocket, jint timeout) {
  1698. // LOGD("ENTER acceptSocketImpl");
  1699. union {
  1700. struct sockaddr address;
  1701. struct sockaddr_in in_address;
  1702. } sa;
  1703. int ret;
  1704. int retFD;
  1705. int result;
  1706. int handle;
  1707. socklen_t addrlen;
  1708. if (newSocket == NULL) {
  1709. throwNullPointerException(env);
  1710. return;
  1711. }
  1712. result = pollSelectWait(env, fdServer, timeout, SELECT_READ_TYPE);
  1713. if (0 > result) {
  1714. return;
  1715. }
  1716. handle = jniGetFDFromFileDescriptor(env, fdServer);
  1717. if (handle == 0 || handle == -1) {
  1718. throwSocketException(env, SOCKERR_BADSOCKET);
  1719. return;
  1720. }
  1721. do {
  1722. addrlen = sizeof(sa);
  1723. ret = accept(handle, &(sa.address), &addrlen);
  1724. } while (ret < 0 && errno == EINTR);
  1725. if (ret < 0) {
  1726. int err = convertError(errno);
  1727. log_socket_close(handle, err);
  1728. throwSocketException(env, err);
  1729. return;
  1730. }
  1731. retFD = ret;
  1732. /* For AF_INET / inetOrLocal == true only: put
  1733. * peer address and port in instance variables
  1734. * We don't bother for UNIX domain sockets, since most peers are
  1735. * anonymous anyway
  1736. */
  1737. if (sa.address.sa_family == AF_INET) {
  1738. // inetOrLocal should also be true
  1739. jobject inetAddress;
  1740. inetAddress = structInToInetAddress(env, &(sa.in_address.sin_addr));
  1741. if (inetAddress == NULL) {
  1742. close(retFD);
  1743. newSocket = NULL;
  1744. return;
  1745. }
  1746. env->SetObjectField(newSocket,
  1747. gCachedFields.socketimpl_address, inetAddress);
  1748. env->SetIntField(newSocket, gCachedFields.socketimpl_port,
  1749. ntohs(sa.in_address.sin_port));
  1750. }
  1751. jniSetFileDescriptorOfFD(env, fdnewSocket, retFD);
  1752. }
  1753. extern "C" jboolean Java_org_sipdroid_net_impl_OSNetworkSystem_supportsUrgentDataImpl(JNIEnv* env,
  1754. jclass clazz, jobject fileDescriptor) {
  1755. // LOGD("ENTER supportsUrgentDataImpl");
  1756. int handle;
  1757. handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
  1758. if (handle == 0 || handle == -1) {
  1759. return JNI_FALSE;
  1760. }
  1761. return JNI_TRUE;
  1762. }
  1763. extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_sendUrgentDataImpl(JNIEnv* env, jclass clazz,
  1764. jobject fileDescriptor, jbyte value) {
  1765. // LOGD("ENTER sendUrgentDataImpl");
  1766. int handle;
  1767. int result;
  1768. handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
  1769. if (handle == 0 || handle == -1) {
  1770. throwSocketException(env, SOCKERR_BADSOCKET);
  1771. return;
  1772. }
  1773. result = send(handle, (jbyte *) &value, 1, MSG_OOB);
  1774. if (result < 0) {
  1775. int err = convertError(errno);
  1776. log_socket_close(handle, err);
  1777. throwSocketException(env, err);
  1778. }
  1779. }
  1780. extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_connectDatagramImpl2(JNIEnv* env, jclass clazz,
  1781. jobject fd, jint port, jint trafficClass, jobject inetAddress) {
  1782. // LOGD("ENTER connectDatagramImpl2");
  1783. int handle = jniGetFDFromFileDescriptor(env, fd);
  1784. struct sockaddr_in sockAddr;
  1785. int ret;
  1786. ret = inetAddressToSocketAddress(env, inetAddress, port, &sockAddr);
  1787. if (ret < 0) {
  1788. throwSocketException(env, SOCKERR_BADSOCKET);
  1789. return;
  1790. }
  1791. log_socket_connect(handle, ntohl(sockAddr.sin_addr.s_addr), port);
  1792. int result = connect(handle, (struct sockaddr *)&sockAddr, sizeof(sockAddr));
  1793. if (result < 0) {
  1794. int err = convertError(errno);
  1795. log_socket_close(handle, err);
  1796. throwSocketException(env, err);
  1797. }
  1798. }
  1799. extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_disconnectDatagramImpl(JNIEnv* env, jclass clazz,
  1800. jobject fd) {
  1801. // LOGD("ENTER disconnectDatagramImpl");
  1802. int handle = jniGetFDFromFileDescriptor(env, fd);
  1803. struct sockaddr_in *sockAddr;
  1804. socklen_t sockAddrLen = sizeof(struct sockaddr_in);
  1805. sockAddr = (struct sockaddr_in *) malloc(sockAddrLen);
  1806. memset(sockAddr, 0, sockAddrLen);
  1807. sockAddr->sin_family = AF_UNSPEC;
  1808. int result = connect(handle, (struct sockaddr *)sockAddr, sockAddrLen);
  1809. free(sockAddr);
  1810. if (result < 0) {
  1811. int err = convertError(errno);
  1812. log_socket_close(handle, err);
  1813. throwSocketException(env, err);
  1814. }
  1815. }
  1816. extern "C" jboolean Java_org_sipdroid_net_impl_OSNetworkSystem_socketBindImpl2(JNIEnv* env, jclass clazz,
  1817. jobject fileDescriptor, jint port, jboolean bindToDevice,
  1818. jobject inetAddress) {
  1819. // LOGD("ENTER socketBindImpl2");
  1820. struct sockaddr_in sockaddress;
  1821. int ret;
  1822. int handle;
  1823. ret = inetAddressToSocketAddress(env, inetAddress, port,
  1824. (struct sockaddr_in *) &sockaddress);
  1825. if (ret < 0) {
  1826. throwSocketException(env, SOCKERR_BADSOCKET);
  1827. return 0;
  1828. }
  1829. handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
  1830. if (handle == 0 || handle == -1) {
  1831. throwSocketException(env, SOCKERR_BADSOCKET);
  1832. return 0;
  1833. }
  1834. ret = bind(handle, (const sockaddr*)&sockaddress, sizeof(sockaddress));
  1835. if (ret < 0) {
  1836. int err = convertError(errno);
  1837. log_socket_close(handle, err);
  1838. jniThrowException(env, "java/net/BindException", netLookupErrorString(err));
  1839. return 0;
  1840. }
  1841. return 0;
  1842. }
  1843. extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_peekDatagramImpl(JNIEnv* env, jclass clazz,
  1844. jobject fd, jobject sender, jint receiveTimeout) {
  1845. // LOGD("ENTER peekDatagramImpl");
  1846. int port = -1;
  1847. int result = pollSelectWait (env, fd, receiveTimeout, SELECT_READ_TYPE);
  1848. if (0> result) {
  1849. return (jint) 0;
  1850. }
  1851. int handle = jniGetFDFromFileDescriptor(env, fd);
  1852. if (handle == 0 || handle == -1) {
  1853. throwSocketException(env, SOCKERR_BADSOCKET);
  1854. return 0;
  1855. }
  1856. struct sockaddr_in sockAddr;
  1857. socklen_t sockAddrLen = sizeof(sockAddr);
  1858. int length = recvfrom(handle, NULL, 0, MSG_PEEK,
  1859. (struct sockaddr *)&sockAddr, &sockAddrLen);
  1860. if (length < 0) {
  1861. int err = convertError(errno);
  1862. log_socket_close(handle, err);
  1863. throwSocketException(env, err);
  1864. return 0;
  1865. }
  1866. if (socketAddressToInetAddress(env, &sockAddr, sender, &port) < 0) {
  1867. throwIOExceptionStr(env, "Address conversion failed");
  1868. return -1;
  1869. }
  1870. add_recv_stats(handle, length);
  1871. return port;
  1872. }
  1873. extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_receiveDatagramDirectImpl(JNIEnv* env, jclass clazz,
  1874. jobject fd, jobject packet, jint address, jint offset, jint length,
  1875. jint receiveTimeout, jboolean peek) {
  1876. // LOGD("ENTER receiveDatagramDirectImpl");
  1877. int result = pollSelectWait (env, fd, receiveTimeout, SELECT_READ_TYPE);
  1878. if (0 > result) {
  1879. return (jint) 0;
  1880. }
  1881. int handle = jniGetFDFromFileDescriptor(env, fd);
  1882. if (handle == 0 || handle == -1) {
  1883. throwSocketException(env, SOCKERR_BADSOCKET);
  1884. return 0;
  1885. }
  1886. struct sockaddr_in sockAddr;
  1887. socklen_t sockAddrLen = sizeof(sockAddr);
  1888. int mode = peek ? MSG_PEEK : 0;
  1889. int actualLength = recvfrom(handle, (char*)(address + offset), length, mode,
  1890. (struct sockaddr *)&sockAddr, &sockAddrLen);
  1891. if (actualLength < 0) {
  1892. int err = convertError(errno);
  1893. log_socket_close(handle, err);
  1894. throwSocketException(env, err);
  1895. return 0;
  1896. }
  1897. if (packet != NULL) {
  1898. /*
  1899. int port = ntohs(sockAddr.sin_port);
  1900. jbyteArray addr = env->NewByteArray(sizeof(struct in_addr));
  1901. if ((structInToJavaAddress(env, &sockAddr.sin_addr, addr)) < 0) {
  1902. jniThrowException(env, "java/net/SocketException",
  1903. "Could not set address of packet.");
  1904. return 0;
  1905. }
  1906. jobject sender = env->CallStaticObjectMethod(
  1907. gCachedFields.iaddr_class, gCachedFields.iaddr_getbyaddress,
  1908. addr);
  1909. env->SetObjectField(packet, gCachedFields.dpack_address, sender);
  1910. env->SetIntField(packet, gCachedFields.dpack_port, port);
  1911. */
  1912. env->SetIntField(packet, gCachedFields.dpack_length, actualLength);
  1913. }
  1914. add_recv_stats(handle, actualLength);
  1915. return actualLength;
  1916. }
  1917. extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_receiveDatagramImpl(JNIEnv* env, jclass clazz,
  1918. jobject fd, jobject packet, jbyteArray data, jint offset, jint length,
  1919. jint receiveTimeout, jboolean peek) {
  1920. // LOGD("ENTER receiveDatagramImpl");
  1921. int localLength = (length < 65536) ? length : 65536;
  1922. jbyte *bytes = (jbyte*) malloc(localLength);
  1923. if (bytes == NULL) {
  1924. jniThrowException(env, "java/lang/OutOfMemoryError",
  1925. "couldn't allocate enough memory for receiveDatagram");
  1926. return 0;
  1927. }
  1928. int actualLength = Java_org_sipdroid_net_impl_OSNetworkSystem_receiveDatagramDirectImpl(env, clazz, fd,
  1929. packet, (jint)bytes, offset, localLength, receiveTimeout, peek);
  1930. if (actualLength > 0) {
  1931. env->SetByteArrayRegion(data, offset, actualLength, bytes);
  1932. }
  1933. free(bytes);
  1934. return actualLength;
  1935. }
  1936. extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_recvConnectedDatagramDirectImpl(JNIEnv* env,
  1937. jclass clazz, jobject fd, jobject packet, jint address, jint offset,
  1938. jint length, jint receiveTimeout, jboolean peek) {
  1939. // LOGD("ENTER receiveConnectedDatagramDirectImpl");
  1940. int result = pollSelectWait (env, fd, receiveTimeout, SELECT_READ_TYPE);
  1941. if (0 > result) {
  1942. return 0;
  1943. }
  1944. int handle = jniGetFDFromFileDescriptor(env, fd);
  1945. if (handle == 0 || handle == -1) {
  1946. throwSocketException(env, SOCKERR_BADSOCKET);
  1947. return 0;
  1948. }
  1949. int mode = peek ? MSG_PEEK : 0;
  1950. int actualLength = recvfrom(handle,
  1951. (char*)(address + offset), length, mode, NULL, NULL);
  1952. if (actualLength < 0) {
  1953. jniThrowException(env, "java/net/PortUnreachableException", "");
  1954. return 0;
  1955. }
  1956. if ( packet != NULL) {
  1957. env->SetIntField(packet, gCachedFields.dpack_length, actualLength);
  1958. }
  1959. add_recv_stats(handle, actualLength);
  1960. return actualLength;
  1961. }
  1962. extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_recvConnectedDatagramImpl(JNIEnv* env, jclass clazz,
  1963. jobject fd, jobject packet, jbyteArray data, jint offset, jint length,
  1964. jint receiveTimeout, jboolean peek) {
  1965. // LOGD("ENTER receiveConnectedDatagramImpl");
  1966. int localLength = (length < 65536) ? length : 65536;
  1967. jbyte *bytes = (jbyte*) malloc(localLength);
  1968. if (bytes == NULL) {
  1969. jniThrowException(env, "java/lang/OutOfMemoryError",
  1970. "couldn't allocate enough memory for recvConnectedDatagram");
  1971. return 0;
  1972. }
  1973. int actualLength = Java_org_sipdroid_net_impl_OSNetworkSystem_recvConnectedDatagramDirectImpl(env,
  1974. clazz, fd, packet, (jint)bytes, offset, localLength,
  1975. receiveTimeout, peek);
  1976. if (actualLength > 0) {
  1977. env->SetByteArrayRegion(data, offset, actualLength, bytes);
  1978. }
  1979. free(bytes);
  1980. return actualLength;
  1981. }
  1982. extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_sendDatagramDirectImpl(JNIEnv* env, jclass clazz,
  1983. jobject fd, jint address, jint offset, jint length, jint port,
  1984. jboolean bindToDevice, jint trafficClass, jobject inetAddress) {
  1985. // LOGD("ENTER sendDatagramDirectImpl");
  1986. int result = 0;
  1987. int handle = jniGetFDFromFileDescriptor(env, fd);
  1988. if (handle == 0 || handle == -1) {
  1989. throwSocketException(env, SOCKERR_BADSOCKET);
  1990. return 0;
  1991. }
  1992. struct sockaddr_in receiver;
  1993. if (inetAddressToSocketAddress(env, inetAddress, port, &receiver) < 0) {
  1994. throwSocketException(env, SOCKERR_BADSOCKET);
  1995. return 0;
  1996. }
  1997. result = sendto(handle, (char*)(address + offset), length, SOCKET_NOFLAGS,
  1998. (struct sockaddr*)&receiver, sizeof(receiver));
  1999. if (result < 0) {
  2000. int err = convertError(errno);
  2001. if ((SOCKERR_CONNRESET == err)
  2002. || (SOCKERR_CONNECTION_REFUSED == err)) {
  2003. return 0;
  2004. } else {
  2005. log_socket_close(handle, err);
  2006. throwSocketException(env, err);
  2007. return 0;
  2008. }
  2009. }
  2010. add_send_stats(handle, result);
  2011. return result;
  2012. }
  2013. extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_sendDatagramImpl(JNIEnv* env, jclass clazz,
  2014. jobject fd, jbyteArray data, jint offset, jint length, jint port,
  2015. jboolean bindToDevice, jint trafficClass, jobject inetAddress) {
  2016. // LOGD("ENTER sendDatagramImpl");
  2017. jbyte *bytes = env->GetByteArrayElements(data, NULL);
  2018. int actualLength = Java_org_sipdroid_net_impl_OSNetworkSystem_sendDatagramDirectImpl(env, clazz, fd,
  2019. (jint)bytes, offset, length, port, bindToDevice, trafficClass,
  2020. inetAddress);
  2021. env->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
  2022. return actualLength;
  2023. }
  2024. extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_sendConnectedDatagramDirectImpl(JNIEnv* env,
  2025. jclass clazz, jobject fd, jint address, jint offset, jint length,
  2026. jboolean bindToDevice) {
  2027. // LOGD("ENTER sendConnectedDatagramDirectImpl");
  2028. int handle = jniGetFDFromFileDescriptor(env, fd);
  2029. if (handle == 0 || handle == -1) {
  2030. throwSocketException(env, SOCKERR_BADSOCKET);
  2031. return 0;
  2032. }
  2033. int result = send(handle, (char*)(address + offset), length, 0);
  2034. if (result < 0) {
  2035. int err = convertError(errno);
  2036. if ((SOCKERR_CONNRESET == err) || (SOCKERR_CONNECTION_REFUSED == err)) {
  2037. return 0;
  2038. } else {
  2039. log_socket_close(handle, err);
  2040. throwSocketException(env, err);
  2041. return 0;
  2042. }
  2043. }
  2044. add_send_stats(handle, length);
  2045. return result;
  2046. }
  2047. extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_sendConnectedDatagramImpl(JNIEnv* env, jclass clazz,
  2048. jobject fd, jbyteArray data, jint offset, jint length,
  2049. jboolean bindToDevice) {
  2050. // LOGD("ENTER sendConnectedDatagramImpl");
  2051. jbyte *bytes = env->GetByteArrayElements(data, NULL);
  2052. int actualLength = Java_org_sipdroid_net_impl_OSNetworkSystem_sendConnectedDatagramDirectImpl(env,
  2053. clazz, fd, (jint)bytes, offset, length, bindToDevice);
  2054. env->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
  2055. return actualLength;
  2056. }
  2057. extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_createServerStreamSocketImpl(JNIEnv* env,
  2058. jclass clazz, jobject fileDescriptor, jboolean preferIPv4Stack) {
  2059. // LOGD("ENTER createServerStreamSocketImpl");
  2060. if (fileDescriptor == NULL) {
  2061. throwNullPointerException(env);
  2062. return;
  2063. }
  2064. int handle = socket(PF_INET, SOCK_STREAM, 0);
  2065. if (handle < 0) {
  2066. int err = convertError(errno);
  2067. throwSocketException(env, err);
  2068. return;
  2069. }
  2070. jniSetFileDescriptorOfFD(env, fileDescriptor, handle);
  2071. int value = 1;
  2072. setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int));
  2073. }
  2074. extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_createMulticastSocketImpl(JNIEnv* env,
  2075. jclass clazz, jobject fileDescriptor, jboolean preferIPv4Stack) {
  2076. // LOGD("ENTER createMulticastSocketImpl");
  2077. int handle = socket(PF_INET, SOCK_DGRAM, 0);
  2078. if (handle < 0) {
  2079. int err = convertError(errno);
  2080. throwSocketException(env, err);
  2081. return;
  2082. }
  2083. jniSetFileDescriptorOfFD(env, fileDescriptor, handle);
  2084. int value = 1;
  2085. // setsockopt(handle, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(jbyte));
  2086. setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int));
  2087. }
  2088. /*
  2089. * @param timeout in milliseconds. If zero, block until data received
  2090. */
  2091. extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_receiveStreamImpl(JNIEnv* env, jclass clazz,
  2092. jobject fileDescriptor, jbyteArray data, jint offset, jint count,
  2093. jint timeout) {
  2094. // LOGD("ENTER receiveStreamImpl");
  2095. int result;
  2096. int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
  2097. if (handle == 0 || handle == -1) {
  2098. throwSocketException(env, SOCKERR_BADSOCKET);
  2099. return 0;
  2100. }
  2101. // Cap read length to available buf size
  2102. int spaceAvailable = env->GetArrayLength(data) - offset;
  2103. int localCount = count < spaceAvailable? count : spaceAvailable;
  2104. jboolean isCopy;
  2105. jbyte *body = env->GetByteArrayElements(data, &isCopy);
  2106. // set timeout
  2107. struct timeval tv;
  2108. tv.tv_sec = timeout / 1000;
  2109. tv.tv_usec = (timeout % 1000) * 1000;
  2110. setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv,
  2111. sizeof(struct timeval));
  2112. do {
  2113. result = recv(handle, body + offset, localCount, SOCKET_NOFLAGS);
  2114. } while (result < 0 && errno == EINTR);
  2115. env->ReleaseByteArrayElements(data, body, 0);
  2116. /*
  2117. * If no bytes are read, return -1 to signal 'endOfFile'
  2118. * to the Java input stream
  2119. */
  2120. if (0 < result) {
  2121. add_recv_stats(handle, result);
  2122. return result;
  2123. } else if (0 == result) {
  2124. return -1;
  2125. } else {
  2126. // If EAGAIN or EWOULDBLOCK, read timed out
  2127. if (errno == EAGAIN || errno == EWOULDBLOCK) {
  2128. jniThrowException(env, "java/net/SocketTimeoutException",
  2129. netLookupErrorString(SOCKERR_TIMEOUT));
  2130. } else {
  2131. int err = convertError(errno);
  2132. log_socket_close(handle, err);
  2133. throwSocketException(env, err);
  2134. }
  2135. return 0;
  2136. }
  2137. }
  2138. extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_sendStreamImpl(JNIEnv* env, jclass clazz,
  2139. jobject fileDescriptor, jbyteArray data, jint offset, jint count) {
  2140. // LOGD("ENTER sendStreamImpl");
  2141. int handle = 0;
  2142. int result = 0, sent = 0;
  2143. jboolean isCopy;
  2144. jbyte *message = env->GetByteArrayElements(data, &isCopy);
  2145. // Cap write length to available buf size
  2146. int spaceAvailable = env->GetArrayLength(data) - offset;
  2147. if (count > spaceAvailable) count = spaceAvailable;
  2148. while (sent < count) {
  2149. handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
  2150. if (handle == 0 || handle == -1) {
  2151. throwSocketException(env,
  2152. sent == 0 ? SOCKERR_BADSOCKET : SOCKERR_INTERRUPTED);
  2153. env->ReleaseByteArrayElements(data, message, 0);
  2154. return 0;
  2155. }
  2156. // LOGD("before select %d", count);
  2157. selectWait(handle, SEND_RETRY_TIME, SELECT_WRITE_TYPE);
  2158. result = send(handle, (jbyte *)message + offset + sent,
  2159. (int) count - sent, SOCKET_NOFLAGS);
  2160. if (result < 0) {
  2161. result = errno;
  2162. if (result == EAGAIN ||result == EWOULDBLOCK) {
  2163. // LOGD("write blocked %d", sent);
  2164. continue;
  2165. }
  2166. env->ReleaseByteArrayElements(data, message, 0);
  2167. int err = convertError(result);
  2168. log_socket_close(handle, err);
  2169. throwSocketException(env, err);
  2170. return 0;
  2171. }
  2172. sent += result;
  2173. }
  2174. env->ReleaseByteArrayElements(data, message, 0);
  2175. add_send_stats(handle, sent);
  2176. return sent;
  2177. }
  2178. extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_shutdownInputImpl(JNIEnv* env, jobject obj,
  2179. jobject fileDescriptor) {
  2180. // LOGD("ENTER shutdownInputImpl");
  2181. int ret;
  2182. int handle;
  2183. handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
  2184. if (handle == 0 || handle == -1) {
  2185. throwSocketException(env, SOCKERR_BADSOCKET);
  2186. return;
  2187. }
  2188. ret = shutdown(handle, SHUT_RD);
  2189. if (ret < 0) {
  2190. int err = convertError(errno);
  2191. log_socket_close(handle, err);
  2192. throwSocketException(env, err);
  2193. return;
  2194. }
  2195. }
  2196. extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_shutdownOutputImpl(JNIEnv* env, jobject obj,
  2197. jobject fileDescriptor) {
  2198. // LOGD("ENTER shutdownOutputImpl");
  2199. int ret;
  2200. int handle;
  2201. handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
  2202. if (handle == 0 || handle == -1) {
  2203. return;
  2204. }
  2205. ret = shutdown(handle, SHUT_WR);
  2206. if (ret < 0) {
  2207. int err = convertError(errno);
  2208. log_socket_close(handle, err);
  2209. throwSocketException(env, err);
  2210. return;
  2211. }
  2212. }
  2213. extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_sendDatagramImpl2(JNIEnv* env, jclass clazz,
  2214. jobject fd, jbyteArray data, jint offset, jint length, jint port,
  2215. jobject inetAddress) {
  2216. // LOGD("ENTER sendDatagramImpl2");
  2217. jbyte *message;
  2218. jbyte nhostAddrBytes[4];
  2219. unsigned short nPort;
  2220. int result = 0, sent = 0;
  2221. int handle = 0;
  2222. struct sockaddr_in sockaddrP;
  2223. if (inetAddress != NULL) {
  2224. result = inetAddressToSocketAddress(env, inetAddress, port,
  2225. (struct sockaddr_in *) &sockaddrP);
  2226. if (result < 0) {
  2227. throwSocketException(env, SOCKERR_BADSOCKET);
  2228. return 0;
  2229. }
  2230. handle = jniGetFDFromFileDescriptor(env, fd);
  2231. if (handle == 0 || handle == -1) {
  2232. throwSocketException(env, SOCKERR_BADSOCKET);
  2233. return 0;
  2234. }
  2235. }
  2236. message = (jbyte*) malloc(length * sizeof(jbyte));
  2237. if (message == NULL) {
  2238. jniThrowException(env, "java/lang/OutOfMemoryError",
  2239. "couldn't allocate enough memory for readSocket");
  2240. return 0;
  2241. }
  2242. env->GetByteArrayRegion(data, offset, length, message);
  2243. while (sent < length) {
  2244. handle = jniGetFDFromFileDescriptor(env, fd);
  2245. if (handle == 0 || handle == -1) {
  2246. throwSocketException(env,
  2247. sent == 0 ? SOCKERR_BADSOCKET : SOCKERR_INTERRUPTED);
  2248. free(message);
  2249. return 0;
  2250. }
  2251. result = sendto(handle, (char *) (message + sent),
  2252. (int) (length - sent), SOCKET_NOFLAGS,
  2253. (struct sockaddr *) &sockaddrP, sizeof(sockaddrP));
  2254. if (result < 0) {
  2255. int err = convertError(errno);
  2256. log_socket_close(handle, err);
  2257. throwSocketException(env, err);
  2258. free(message);
  2259. return 0;
  2260. }
  2261. sent += result;
  2262. }
  2263. free(message);
  2264. add_send_stats(handle, sent);
  2265. return sent;
  2266. }
  2267. extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_selectImpl(JNIEnv* env, jclass clazz,
  2268. jobjectArray readFDArray, jobjectArray writeFDArray, jint countReadC,
  2269. jint countWriteC, jintArray outFlags, jlong timeout) {
  2270. // LOGD("ENTER selectImpl");
  2271. struct timeval timeP;
  2272. int result = 0;
  2273. int size = 0;
  2274. jobject gotFD;
  2275. fd_set *fdset_read,*fdset_write;
  2276. int handle;
  2277. jboolean isCopy ;
  2278. jint *flagArray;
  2279. int val;
  2280. unsigned int time_sec = (unsigned int)timeout/1000;
  2281. unsigned int time_msec = (unsigned int)(timeout%1000);
  2282. fdset_read = (fd_set *)malloc(sizeof(fd_set));
  2283. fdset_write = (fd_set *)malloc(sizeof(fd_set));
  2284. FD_ZERO(fdset_read);
  2285. FD_ZERO(fdset_write);
  2286. for (val = 0; val<countReadC; val++) {
  2287. gotFD = env->GetObjectArrayElement(readFDArray,val);
  2288. handle = jniGetFDFromFileDescriptor(env, gotFD);
  2289. FD_SET(handle, fdset_read);
  2290. if (0 > (size - handle)) {
  2291. size = handle;
  2292. }
  2293. }
  2294. for (val = 0; val<countWriteC; val++) {
  2295. gotFD = env->GetObjectArrayElement(writeFDArray,val);
  2296. handle = jniGetFDFromFileDescriptor(env, gotFD);
  2297. FD_SET(handle, fdset_write);
  2298. if (0 > (size - handle)) {
  2299. size = handle;
  2300. }
  2301. }
  2302. /* the size is the max_fd + 1 */
  2303. size =size + 1;
  2304. if (0 > size) {
  2305. result = SOCKERR_FDSET_SIZEBAD;
  2306. } else {
  2307. /* only set when timeout >= 0 (non-block)*/
  2308. if (0 <= timeout) {
  2309. timeP.tv_sec = time_sec;
  2310. timeP.tv_usec = time_msec*1000;
  2311. result = sockSelect(size, fdset_read, fdset_write, NULL, &timeP);
  2312. } else {
  2313. result = sockSelect(size, fdset_read, fdset_write, NULL, NULL);
  2314. }
  2315. }
  2316. if (0 < result) {
  2317. /*output the result to a int array*/
  2318. flagArray = env->GetIntArrayElements(outFlags, &isCopy);
  2319. for (val=0; val<countReadC; val++) {
  2320. gotFD = env->GetObjectArrayElement(readFDArray,val);
  2321. handle = jniGetFDFromFileDescriptor(env, gotFD);
  2322. if (FD_ISSET(handle,fdset_read)) {
  2323. flagArray[val] = SOCKET_OP_READ;
  2324. } else {
  2325. flagArray[val] = SOCKET_OP_NONE;
  2326. }
  2327. }
  2328. for (val=0; val<countWriteC; val++) {
  2329. gotFD = env->GetObjectArrayElement(writeFDArray,val);
  2330. handle = jniGetFDFromFileDescriptor(env, gotFD);
  2331. if (FD_ISSET(handle,fdset_write)) {
  2332. flagArray[val+countReadC] = SOCKET_OP_WRITE;
  2333. } else {
  2334. flagArray[val+countReadC] = SOCKET_OP_NONE;
  2335. }
  2336. }
  2337. env->ReleaseIntArrayElements(outFlags, flagArray, 0);
  2338. }
  2339. free(fdset_write);
  2340. free(fdset_read);
  2341. /* return both correct and error result, let java handle the exception*/
  2342. return result;
  2343. }
  2344. extern "C" jobject Java_org_sipdroid_net_impl_OSNetworkSystem_getSocketLocalAddressImpl(JNIEnv* env,
  2345. jclass clazz, jobject fileDescriptor, jboolean preferIPv6Addresses) {
  2346. // LOGD("ENTER getSocketLocalAddressImpl");
  2347. struct sockaddr_in addr;
  2348. socklen_t addrLen = sizeof(addr);
  2349. memset(&addr, 0, addrLen);
  2350. int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
  2351. int result;
  2352. if (handle == 0 || handle == -1) {
  2353. throwSocketException(env, SOCKERR_UNKNOWNSOCKET);
  2354. return NULL;
  2355. }
  2356. result = getsockname(handle, (struct sockaddr *)&addr, &addrLen);
  2357. // Spec says ignore all errors
  2358. return structInToInetAddress(env, &(addr.sin_addr));
  2359. }
  2360. extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_getSocketLocalPortImpl(JNIEnv* env, jclass clazz,
  2361. jobject fileDescriptor, jboolean preferIPv6Addresses) {
  2362. // LOGD("ENTER getSocketLocalPortImpl");
  2363. struct sockaddr_in addr;
  2364. socklen_t addrLen = sizeof(addr);
  2365. int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
  2366. int result;
  2367. if (handle == 0 || handle == -1) {
  2368. throwSocketException(env, SOCKERR_UNKNOWNSOCKET);
  2369. return 0;
  2370. }
  2371. result = getsockname(handle, (struct sockaddr *)&addr, &addrLen);
  2372. if (0 != result) {
  2373. // The java spec does not indicate any exceptions on this call
  2374. return 0;
  2375. } else {
  2376. return ntohs(addr.sin_port);
  2377. }
  2378. }
  2379. extern "C" jobject Java_org_sipdroid_net_impl_OSNetworkSystem_getSocketOptionImpl(JNIEnv* env, jclass clazz,
  2380. jobject fileDescriptor, jint anOption) {
  2381. // LOGD("ENTER getSocketOptionImpl");
  2382. int handle;
  2383. int intValue = 0;
  2384. socklen_t intSize = sizeof(int);
  2385. unsigned char byteValue = 0;
  2386. socklen_t byteSize = sizeof(unsigned char);
  2387. int result;
  2388. struct sockaddr_in sockVal;
  2389. socklen_t sockSize = sizeof(sockVal);
  2390. handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
  2391. if (handle == 0 || handle == -1) {
  2392. throwSocketException(env, SOCKERR_BADSOCKET);
  2393. return NULL;
  2394. }
  2395. switch ((int) anOption & 0xffff) {
  2396. case JAVASOCKOPT_SO_LINGER: {
  2397. struct linger lingr;
  2398. socklen_t size = sizeof(struct linger);
  2399. result = getsockopt(handle, SOL_SOCKET, SO_LINGER, &lingr, &size);
  2400. if (0 != result) {
  2401. throwSocketException(env, convertError(errno));
  2402. return NULL;
  2403. }
  2404. if (!lingr.l_onoff) {
  2405. intValue = -1;
  2406. } else {
  2407. intValue = lingr.l_linger;
  2408. }
  2409. return newJavaLangInteger(env, intValue);
  2410. }
  2411. case JAVASOCKOPT_TCP_NODELAY: {
  2412. if ((anOption >> 16) & BROKEN_TCP_NODELAY) {
  2413. return NULL;
  2414. }
  2415. result = getsockopt(handle, IPPROTO_TCP, TCP_NODELAY, &intValue, &intSize);
  2416. if (0 != result) {
  2417. throwSocketException(env, convertError(errno));
  2418. return NULL;
  2419. }
  2420. return newJavaLangBoolean(env, intValue);
  2421. }
  2422. case JAVASOCKOPT_MCAST_TTL: {
  2423. if ((anOption >> 16) & BROKEN_MULTICAST_TTL) {
  2424. return newJavaLangByte(env, 0);
  2425. }
  2426. result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_TTL, &byteValue, &byteSize);
  2427. if (0 != result) {
  2428. throwSocketException(env, convertError(errno));
  2429. return NULL;
  2430. }
  2431. return newJavaLangByte(env, (jbyte)(byteValue & 0xFF));
  2432. }
  2433. case JAVASOCKOPT_MCAST_INTERFACE: {
  2434. if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
  2435. return NULL;
  2436. }
  2437. result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF, &sockVal, &sockSize);
  2438. if (0 != result) {
  2439. throwSocketException(env, convertError(errno));
  2440. return NULL;
  2441. }
  2442. return structInToInetAddress(env, &(sockVal.sin_addr));
  2443. }
  2444. case JAVASOCKOPT_SO_SNDBUF: {
  2445. result = getsockopt(handle, SOL_SOCKET, SO_SNDBUF, &intValue, &intSize);
  2446. if (0 != result) {
  2447. throwSocketException(env, convertError(errno));
  2448. return NULL;
  2449. }
  2450. return newJavaLangInteger(env, intValue);
  2451. }
  2452. case JAVASOCKOPT_SO_RCVBUF: {
  2453. result = getsockopt(handle, SOL_SOCKET, SO_RCVBUF, &intValue, &intSize);
  2454. if (0 != result) {
  2455. throwSocketException(env, convertError(errno));
  2456. return NULL;
  2457. }
  2458. return newJavaLangInteger(env, intValue);
  2459. }
  2460. case JAVASOCKOPT_SO_BROADCAST: {
  2461. result = getsockopt(handle, SOL_SOCKET, SO_BROADCAST, &intValue, &intSize);
  2462. if (0 != result) {
  2463. throwSocketException(env, convertError(errno));
  2464. return NULL;
  2465. }
  2466. return newJavaLangBoolean(env, intValue);
  2467. }
  2468. case JAVASOCKOPT_SO_REUSEADDR: {
  2469. result = getsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intValue, &intSize);
  2470. if (0 != result) {
  2471. throwSocketException(env, convertError(errno));
  2472. return NULL;
  2473. }
  2474. return newJavaLangBoolean(env, intValue);
  2475. }
  2476. case JAVASOCKOPT_SO_KEEPALIVE: {
  2477. result = getsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &intValue, &intSize);
  2478. if (0 != result) {
  2479. throwSocketException(env, convertError(errno));
  2480. return NULL;
  2481. }
  2482. return newJavaLangBoolean(env, intValue);
  2483. }
  2484. case JAVASOCKOPT_SO_OOBINLINE: {
  2485. result = getsockopt(handle, SOL_SOCKET, SO_OOBINLINE, &intValue, &intSize);
  2486. if (0 != result) {
  2487. throwSocketException(env, convertError(errno));
  2488. return NULL;
  2489. }
  2490. return newJavaLangBoolean(env, intValue);
  2491. }
  2492. case JAVASOCKOPT_IP_MULTICAST_LOOP: {
  2493. result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_LOOP, &intValue, &intSize);
  2494. if (0 != result) {
  2495. throwSocketException(env, convertError(errno));
  2496. return NULL;
  2497. }
  2498. return newJavaLangBoolean(env, intValue);
  2499. }
  2500. case JAVASOCKOPT_IP_TOS: {
  2501. result = getsockopt(handle, IPPROTO_IP, IP_TOS, &intValue, &intSize);
  2502. if (0 != result) {
  2503. throwSocketException(env, convertError(errno));
  2504. return NULL;
  2505. }
  2506. return newJavaLangInteger(env, intValue);
  2507. }
  2508. case JAVASOCKOPT_SO_RCVTIMEOUT: {
  2509. struct timeval timeout;
  2510. socklen_t size = sizeof(timeout);
  2511. result = getsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, &timeout, &size);
  2512. if (0 != result) {
  2513. throwSocketException(env, convertError(errno));
  2514. return NULL;
  2515. }
  2516. return newJavaLangInteger(env, timeout.tv_sec * 1000 + timeout.tv_usec/1000);
  2517. }
  2518. default: {
  2519. throwSocketException(env, SOCKERR_OPTUNSUPP);
  2520. return NULL;
  2521. }
  2522. }
  2523. }
  2524. extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_setSocketOptionImpl(JNIEnv* env, jclass clazz,
  2525. jobject fileDescriptor, jint anOption, jobject optVal) {
  2526. // LOGD("ENTER setSocketOptionImpl");
  2527. int handle, result;
  2528. int intVal, intSize = sizeof(int);
  2529. unsigned char byteVal, byteSize = sizeof(unsigned char);
  2530. struct sockaddr_in sockVal;
  2531. int sockSize = sizeof(sockVal);
  2532. if (env->IsInstanceOf(optVal, gCachedFields.integer_class)) {
  2533. intVal = (int) env->GetIntField(optVal, gCachedFields.integer_class_value);
  2534. } else if (env->IsInstanceOf(optVal, gCachedFields.boolean_class)) {
  2535. intVal = (int) env->GetBooleanField(optVal, gCachedFields.boolean_class_value);
  2536. } else if (env->IsInstanceOf(optVal, gCachedFields.byte_class)) {
  2537. byteVal = (int) env->GetByteField(optVal, gCachedFields.byte_class_value);
  2538. } else if (env->IsInstanceOf(optVal, gCachedFields.iaddr_class)) {
  2539. if (inetAddressToSocketAddress(env, optVal, 0, &sockVal) < 0) {
  2540. throwSocketException(env, SOCKERR_BADSOCKET);
  2541. return;
  2542. }
  2543. } else if (env->IsInstanceOf(optVal, gCachedFields.genericipmreq_class)) {
  2544. // we'll use optVal directly
  2545. } else {
  2546. throwSocketException(env, SOCKERR_OPTUNSUPP);
  2547. return;
  2548. }
  2549. handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
  2550. if (handle == 0 || handle == -1) {
  2551. throwSocketException(env, SOCKERR_BADSOCKET);
  2552. return;
  2553. }
  2554. switch ((int) anOption & 0xffff) {
  2555. case JAVASOCKOPT_SO_LINGER: {
  2556. struct linger lingr;
  2557. lingr.l_onoff = intVal > 0 ? 1 : 0;
  2558. lingr.l_linger = intVal;
  2559. result = setsockopt(handle, SOL_SOCKET, SO_LINGER, &lingr,
  2560. sizeof(struct linger));
  2561. if (0 != result) {
  2562. throwSocketException(env, convertError(errno));
  2563. return;
  2564. }
  2565. break;
  2566. }
  2567. case JAVASOCKOPT_TCP_NODELAY: {
  2568. if ((anOption >> 16) & BROKEN_TCP_NODELAY) {
  2569. return;
  2570. }
  2571. result = setsockopt(handle, IPPROTO_TCP, TCP_NODELAY, &intVal, intSize);
  2572. if (0 != result) {
  2573. throwSocketException(env, convertError(errno));
  2574. return;
  2575. }
  2576. break;
  2577. }
  2578. case JAVASOCKOPT_MCAST_TTL: {
  2579. if ((anOption >> 16) & BROKEN_MULTICAST_TTL) {
  2580. return;
  2581. }
  2582. result = setsockopt(handle, IPPROTO_IP, IP_MULTICAST_TTL, &byteVal, byteSize);
  2583. if (0 != result) {
  2584. throwSocketException(env, convertError(errno));
  2585. return;
  2586. }
  2587. break;
  2588. }
  2589. case JAVASOCKOPT_MCAST_ADD_MEMBERSHIP: {
  2590. mcastAddDropMembership(env, handle, optVal,
  2591. (anOption >> 16) & BROKEN_MULTICAST_IF, IP_ADD_MEMBERSHIP);
  2592. return;
  2593. }
  2594. case JAVASOCKOPT_MCAST_DROP_MEMBERSHIP: {
  2595. mcastAddDropMembership(env, handle, optVal,
  2596. (anOption >> 16) & BROKEN_MULTICAST_IF, IP_DROP_MEMBERSHIP);
  2597. return;
  2598. }
  2599. case JAVASOCKOPT_MCAST_INTERFACE: {
  2600. if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
  2601. return;
  2602. }
  2603. result = setsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF, &sockVal, sockSize);
  2604. if (0 != result) {
  2605. throwSocketException(env, convertError(errno));
  2606. return;
  2607. }
  2608. break;
  2609. }
  2610. case JAVASOCKOPT_SO_SNDBUF: {
  2611. result = setsockopt(handle, SOL_SOCKET, SO_SNDBUF, &intVal, intSize);
  2612. if (0 != result) {
  2613. throwSocketException(env, convertError(errno));
  2614. return;
  2615. }
  2616. break;
  2617. }
  2618. case JAVASOCKOPT_SO_RCVBUF: {
  2619. result = setsockopt(handle, SOL_SOCKET, SO_RCVBUF, &intVal, intSize);
  2620. if (0 != result) {
  2621. throwSocketException(env, convertError(errno));
  2622. return;
  2623. }
  2624. break;
  2625. }
  2626. case JAVASOCKOPT_SO_BROADCAST: {
  2627. result = setsockopt(handle, SOL_SOCKET, SO_BROADCAST, &intVal, intSize);
  2628. if (0 != result) {
  2629. throwSocketException(env, convertError(errno));
  2630. return;
  2631. }
  2632. break;
  2633. }
  2634. case JAVASOCKOPT_SO_REUSEADDR: {
  2635. result = setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intVal, intSize);
  2636. if (0 != result) {
  2637. throwSocketException(env, convertError(errno));
  2638. return;
  2639. }
  2640. break;
  2641. }
  2642. case JAVASOCKOPT_SO_KEEPALIVE: {
  2643. result = setsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &intVal, intSize);
  2644. if (0 != result) {
  2645. throwSocketException(env, convertError(errno));
  2646. return;
  2647. }
  2648. break;
  2649. }
  2650. case JAVASOCKOPT_SO_OOBINLINE: {
  2651. result = setsockopt(handle, SOL_SOCKET, SO_OOBINLINE, &intVal, intSize);
  2652. if (0 != result) {
  2653. throwSocketException(env, convertError(errno));
  2654. return;
  2655. }
  2656. break;
  2657. }
  2658. case JAVASOCKOPT_IP_MULTICAST_LOOP: {
  2659. result = setsockopt(handle, IPPROTO_IP, IP_MULTICAST_LOOP, &intVal, intSize);
  2660. if (0 != result) {
  2661. throwSocketException(env, convertError(errno));
  2662. return;
  2663. }
  2664. break;
  2665. }
  2666. case JAVASOCKOPT_IP_TOS: {
  2667. result = setsockopt(handle, IPPROTO_IP, IP_TOS, &intVal, intSize);
  2668. if (0 != result) {
  2669. throwSocketException(env, convertError(errno));
  2670. return;
  2671. }
  2672. break;
  2673. }
  2674. case JAVASOCKOPT_REUSEADDR_AND_REUSEPORT: {
  2675. // SO_REUSEPORT doesn't need to get set on this System
  2676. result = setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &intVal, intSize);
  2677. if (0 != result) {
  2678. throwSocketException(env, convertError(errno));
  2679. return;
  2680. }
  2681. break;
  2682. }
  2683. case JAVASOCKOPT_SO_RCVTIMEOUT: {
  2684. struct timeval timeout;
  2685. timeout.tv_sec = intVal / 1000;
  2686. timeout.tv_usec = (intVal % 1000) * 1000;
  2687. result = setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, &timeout,
  2688. sizeof(struct timeval));
  2689. if (0 != result) {
  2690. throwSocketException(env, convertError(errno));
  2691. return;
  2692. }
  2693. break;
  2694. }
  2695. default: {
  2696. throwSocketException(env, SOCKERR_OPTUNSUPP);
  2697. }
  2698. }
  2699. }
  2700. extern "C" jint Java_org_sipdroid_net_impl_OSNetworkSystem_getSocketFlagsImpl(JNIEnv* env, jclass clazz) {
  2701. // LOGD("ENTER getSocketFlagsImpl");
  2702. // Not implemented by harmony
  2703. return 0;
  2704. }
  2705. extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_socketCloseImpl(JNIEnv* env, jclass clazz,
  2706. jobject fileDescriptor) {
  2707. // LOGD("ENTER socketCloseImpl");
  2708. int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
  2709. if (handle == 0 || handle == -1) {
  2710. throwSocketException(env, SOCKERR_BADSOCKET);
  2711. return;
  2712. }
  2713. log_socket_close(handle, SOCKET_CLOSE_LOCAL);
  2714. jniSetFileDescriptorOfFD(env, fileDescriptor, -1);
  2715. close(handle);
  2716. }
  2717. extern "C" jobject Java_org_sipdroid_net_impl_OSNetworkSystem_getHostByAddrImpl(JNIEnv* env, jclass clazz,
  2718. jbyteArray addrStr) {
  2719. // LOGD("ENTER getHostByAddrImpl");
  2720. if (addrStr == NULL) {
  2721. throwNullPointerException(env);
  2722. return JNI_FALSE;
  2723. }
  2724. jstring address = (jstring)newJavaLangString(env, addrStr);
  2725. jstring result;
  2726. const char* addr = env->GetStringUTFChars(address, NULL);
  2727. struct hostent* ent = gethostbyaddr(addr, strlen(addr), AF_INET);
  2728. if (ent != NULL && ent->h_name != NULL) {
  2729. result = env->NewStringUTF(ent->h_name);
  2730. } else {
  2731. result = NULL;
  2732. }
  2733. env->ReleaseStringUTFChars(address, addr);
  2734. return result;
  2735. }
  2736. extern "C" jobject Java_org_sipdroid_net_impl_OSNetworkSystem_getHostByNameImpl(JNIEnv* env, jclass clazz,
  2737. jstring nameStr, jboolean preferIPv6Addresses) {
  2738. // LOGD("ENTER getHostByNameImpl");
  2739. if (nameStr == NULL) {
  2740. throwNullPointerException(env);
  2741. return NULL;
  2742. }
  2743. const char* name = env->GetStringUTFChars(nameStr, NULL);
  2744. if (useAdbNetworking) {
  2745. union {
  2746. struct in_addr a;
  2747. jbyte j[4];
  2748. } outaddr;
  2749. // LOGD("ADB networking: +gethostbyname '%s'", name);
  2750. int err;
  2751. err = adb_networking_gethostbyname(name, &(outaddr.a));
  2752. env->ReleaseStringUTFChars(nameStr, name);
  2753. #if 0
  2754. LOGD("ADB networking: -gethostbyname err %d addr 0x%08x %u.%u.%u.%u",
  2755. err, (unsigned int)outaddr.a.s_addr,
  2756. outaddr.j[0],outaddr.j[1],
  2757. outaddr.j[2],outaddr.j[3]);
  2758. #endif
  2759. if (err < 0) {
  2760. return NULL;
  2761. } else {
  2762. jbyteArray addr = env->NewByteArray(4);
  2763. env->SetByteArrayRegion(addr, 0, 4, outaddr.j);
  2764. return addr;
  2765. }
  2766. } else {
  2767. // normal case...no adb networking
  2768. struct hostent* ent = gethostbyname(name);
  2769. env->ReleaseStringUTFChars(nameStr, name);
  2770. if (ent != NULL && ent->h_length > 0) {
  2771. jbyteArray addr = env->NewByteArray(4);
  2772. jbyte v[4];
  2773. memcpy(v, ent->h_addr, 4);
  2774. env->SetByteArrayRegion(addr, 0, 4, v);
  2775. return addr;
  2776. } else {
  2777. return NULL;
  2778. }
  2779. }
  2780. }
  2781. extern "C" void Java_org_sipdroid_net_impl_OSNetworkSystem_setInetAddressImpl(JNIEnv* env, jobject obj,
  2782. jobject sender, jbyteArray address) {
  2783. // LOGD("ENTER setInetAddressImpl");
  2784. env->SetObjectField(sender, gCachedFields.iaddr_ipaddress, address);
  2785. }
  2786. /*
  2787. extern "C" jobject Java_org_sipdroid_net_impl_OSNetworkSystem_inheritedChannelImpl(JNIEnv* env, jobject obj) {
  2788. // LOGD("ENTER inheritedChannelImpl");
  2789. int socket = 0;
  2790. int opt;
  2791. socklen_t length = sizeof(opt);
  2792. int socket_type;
  2793. struct sockaddr_in local_addr;
  2794. struct sockaddr_in remote_addr;
  2795. jclass channel_class, socketaddr_class, serverSocket_class, socketImpl_class;
  2796. jobject channel_object = NULL, socketaddr_object, serverSocket_object;
  2797. jobject fd_object, addr_object, localAddr_object, socketImpl_object;
  2798. jfieldID port_field, socketaddr_field, bound_field, fd_field;
  2799. jfieldID serverSocket_field, socketImpl_field, addr_field, localAddr_field;
  2800. jmethodID channel_new;
  2801. jbyteArray addr_array;
  2802. struct sockaddr_in *sock;
  2803. jbyte * address;
  2804. jbyte * localAddr;
  2805. jboolean jtrue = JNI_TRUE;
  2806. if (0 != getsockopt(socket, SOL_SOCKET, SO_TYPE, &opt, &length)) {
  2807. return NULL;
  2808. }
  2809. if (SOCK_STREAM !=opt && SOCK_DGRAM !=opt) {
  2810. return NULL;
  2811. }
  2812. socket_type = opt;
  2813. length = sizeof(struct sockaddr);
  2814. if (0 != getsockname(socket, (struct sockaddr *)&local_addr, &length)) {
  2815. return NULL;
  2816. } else {
  2817. if (AF_INET != local_addr.sin_family || length != sizeof(struct sockaddr)) {
  2818. return NULL;
  2819. }
  2820. localAddr = (jbyte*) malloc(sizeof(jbyte)*4);
  2821. if (NULL == localAddr) {
  2822. return NULL;
  2823. }
  2824. memcpy (localAddr, &(local_addr.sin_addr.s_addr), 4);
  2825. }
  2826. if (0 != getpeername(socket, (struct sockaddr *)&remote_addr, &length)) {
  2827. remote_addr.sin_port = 0;
  2828. remote_addr.sin_addr.s_addr = 0;
  2829. address = (jbyte*) malloc(sizeof(jbyte)*4);
  2830. bzero(address, sizeof(jbyte)*4);
  2831. } else {
  2832. if (AF_INET != remote_addr.sin_family
  2833. || length != sizeof(struct sockaddr)) {
  2834. return NULL;
  2835. }
  2836. address = (jbyte*) malloc(sizeof(jbyte)*4);
  2837. memcpy (address, &(remote_addr.sin_addr.s_addr), 4);
  2838. }
  2839. // analysis end, begin pack to java
  2840. if (SOCK_STREAM == opt) {
  2841. if (remote_addr.sin_port!=0) {
  2842. //socket
  2843. channel_class = env->FindClass(
  2844. "org/apache/harmony/nio/internal/SocketChannelImpl");
  2845. if (NULL == channel_class) {
  2846. goto clean;
  2847. }
  2848. channel_new = env->GetMethodID(channel_class, "<init>", "()V");
  2849. if (NULL == channel_new) {
  2850. goto clean;
  2851. }
  2852. channel_object = env->NewObject(channel_class, channel_new);
  2853. if (NULL == channel_object) {
  2854. goto clean;
  2855. }
  2856. // new and set FileDescript
  2857. fd_field = env->GetFieldID(channel_class, "fd",
  2858. "java/io/FielDescriptor");
  2859. fd_object = env->GetObjectField(channel_object, fd_field);
  2860. if (NULL == fd_object) {
  2861. goto clean;
  2862. }
  2863. jniSetFileDescriptorOfFD(env, fd_object, socket);
  2864. // local port
  2865. port_field = env->GetFieldID(channel_class, "localPort", "I");
  2866. env->SetIntField(channel_object, port_field,
  2867. ntohs(local_addr.sin_port));
  2868. // new and set remote addr
  2869. addr_object = env->NewObject(gCachedFields.iaddr_class,
  2870. gCachedFields.iaddr_class_init);
  2871. if (NULL == addr_object) {
  2872. goto clean;
  2873. }
  2874. socketaddr_class = env->FindClass("java/net/InetSocketAddress");
  2875. socketaddr_field = env->GetFieldID(channel_class, "connectAddress",
  2876. "Ljava/net/InetSocketAddress;");
  2877. socketaddr_object = env->GetObjectField(channel_object,
  2878. socketaddr_field);
  2879. if (NULL == socketaddr_object) {
  2880. goto clean;
  2881. }
  2882. addr_field = env->GetFieldID(socketaddr_class, "addr",
  2883. "Ljava/net/InetAddress;");
  2884. env->SetObjectField(socketaddr_object, addr_field, addr_object);
  2885. addr_array = env->NewByteArray((jsize)4);
  2886. env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, address);
  2887. env->SetObjectField(addr_object, gCachedFields.iaddr_ipaddress,
  2888. addr_array);
  2889. // localAddr
  2890. socketaddr_class = env->FindClass("java/net/InetSocketAddress");
  2891. socketaddr_field = env->GetFieldID(channel_class, "connectAddress",
  2892. "Ljava/net/InetSocketAddress;");
  2893. socketaddr_object = env->GetObjectField(channel_object,
  2894. socketaddr_field);
  2895. localAddr_field = env->GetFieldID(channel_class, "localAddress",
  2896. "Ljava/net/InetAddress;");
  2897. localAddr_object = env->NewObject(gCachedFields.iaddr_class,
  2898. gCachedFields.iaddr_class_init);
  2899. jfieldID socketaddr_field = env->GetFieldID(channel_class,
  2900. "connectAddress", "Ljava/net/InetSocketAddress;");
  2901. jobject socketaddr_object = env->GetObjectField(channel_object,
  2902. socketaddr_field);
  2903. env->SetObjectField(socketaddr_object, localAddr_field,
  2904. localAddr_object);
  2905. if (NULL == localAddr_object) {
  2906. goto clean;
  2907. }
  2908. addr_array = env->NewByteArray((jsize)4);
  2909. env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, localAddr);
  2910. env->SetObjectField(localAddr_object, gCachedFields.iaddr_ipaddress,
  2911. addr_array);
  2912. // set port
  2913. port_field = env->GetFieldID(socketaddr_class, "port", "I");
  2914. env->SetIntField(socketaddr_object, port_field,
  2915. ntohs(remote_addr.sin_port));
  2916. // set bound
  2917. if (0 != local_addr.sin_port) {
  2918. bound_field = env->GetFieldID(channel_class, "isBound", "Z");
  2919. env->SetBooleanField(channel_object, bound_field, jtrue);
  2920. }
  2921. } else {
  2922. //serverSocket
  2923. channel_class = env->FindClass(
  2924. "org/apache/harmony/nio/internal/ServerSocketChannelImpl");
  2925. if (NULL == channel_class) {
  2926. goto clean;
  2927. }
  2928. channel_new = env->GetMethodID(channel_class, "<init>", "()V");
  2929. if (NULL == channel_new) {
  2930. goto clean;
  2931. }
  2932. channel_object = env->NewObject(channel_class, channel_new);
  2933. if (NULL == channel_object) {
  2934. goto clean;
  2935. }
  2936. serverSocket_field = env->GetFieldID(channel_class, "socket",
  2937. "Ljava/net/ServerSocket;");
  2938. serverSocket_class = env->FindClass("Ljava/net/ServerSocket;");
  2939. serverSocket_object = env->GetObjectField(channel_object,
  2940. serverSocket_field);
  2941. // set bound
  2942. if (0 != local_addr.sin_port) {
  2943. bound_field = env->GetFieldID(channel_class, "isBound", "Z");
  2944. env->SetBooleanField(channel_object, bound_field, jtrue);
  2945. bound_field = env->GetFieldID(serverSocket_class, "isBound", "Z");
  2946. env->SetBooleanField(serverSocket_object, bound_field, jtrue);
  2947. }
  2948. // localAddr
  2949. socketImpl_class = env->FindClass("java/net/SocketImpl");
  2950. socketImpl_field = env->GetFieldID(channel_class, "impl",
  2951. "Ljava/net/SocketImpl;");
  2952. socketImpl_object = env->GetObjectField(channel_object,
  2953. socketImpl_field);
  2954. if (NULL == socketImpl_object) {
  2955. goto clean;
  2956. }
  2957. localAddr_field = env->GetFieldID(channel_class, "localAddress",
  2958. "Ljava/net/InetAddress;");
  2959. localAddr_object = env->NewObject(gCachedFields.iaddr_class,
  2960. gCachedFields.iaddr_class_init);
  2961. if (NULL == localAddr_object) {
  2962. goto clean;
  2963. }
  2964. env->SetObjectField(socketImpl_object, localAddr_field,
  2965. localAddr_object);
  2966. addr_array = env->NewByteArray((jsize)4);
  2967. env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, localAddr);
  2968. env->SetObjectField(localAddr_object,
  2969. gCachedFields.iaddr_ipaddress, addr_array);
  2970. // set port
  2971. port_field = env->GetFieldID(socketImpl_class, "localport", "I");
  2972. env->SetIntField(socketImpl_object, port_field,
  2973. ntohs(local_addr.sin_port));
  2974. }
  2975. } else {
  2976. //Datagram Socket
  2977. // new DatagramChannel
  2978. channel_class = env->FindClass(
  2979. "org/apache/harmony/nio/internal/DatagramChannelImpl");
  2980. if (NULL == channel_class) {
  2981. goto clean;
  2982. }
  2983. channel_new = env->GetMethodID(channel_class, "<init>", "()V");
  2984. if (NULL == channel_new) {
  2985. goto clean;
  2986. }
  2987. channel_object = env->NewObject(channel_class, channel_new);
  2988. if (NULL == channel_object) {
  2989. goto clean;
  2990. }
  2991. // new and set FileDescript
  2992. fd_field = env->GetFieldID(channel_class, "fd", "java/io/FileDescriptor");
  2993. fd_object = env->GetObjectField(channel_object, fd_field);
  2994. if (NULL == fd_object) {
  2995. goto clean;
  2996. }
  2997. jniSetFileDescriptorOfFD(env, fd_object, socket);
  2998. port_field = env->GetFieldID(channel_class, "localPort", "I");
  2999. env->SetIntField(channel_object, port_field, ntohs(local_addr.sin_port));
  3000. // new and set remote addr
  3001. addr_object = env->NewObject(gCachedFields.iaddr_class,
  3002. gCachedFields.iaddr_class_init);
  3003. if (NULL == addr_object) {
  3004. goto clean;
  3005. }
  3006. socketaddr_class = env->FindClass("java/net/InetSocketAddress");
  3007. socketaddr_field = env->GetFieldID(channel_class, "connectAddress",
  3008. "Ljava/net/InetSocketAddress;");
  3009. socketaddr_object = env->GetObjectField(channel_object, socketaddr_field);
  3010. if (NULL == socketaddr_object) {
  3011. goto clean;
  3012. }
  3013. addr_field = env->GetFieldID(socketaddr_class, "addr",
  3014. "Ljava/net/InetAddress;");
  3015. env->SetObjectField(socketaddr_object, addr_field, addr_object);
  3016. addr_array = env->NewByteArray((jsize)4);
  3017. env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, address);
  3018. env->SetObjectField(addr_object, gCachedFields.iaddr_ipaddress, addr_array);
  3019. // set bound
  3020. if (0 != local_addr.sin_port) {
  3021. bound_field = env->GetFieldID(channel_class, "isBound", "Z");
  3022. env->SetBooleanField(channel_object, bound_field, jtrue);
  3023. }
  3024. }
  3025. clean:
  3026. free(address);
  3027. free(localAddr);
  3028. return channel_object;
  3029. }
  3030. */