PageRenderTime 52ms CodeModel.GetById 11ms 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

Large files files are truncated, but you can click here to view the full file

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

Large files files are truncated, but you can click here to view the full file