1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "LocalSocketImpl" 18 19 #include "JNIHelp.h" 20 #include "jni.h" 21 #include "utils/Log.h" 22 #include "utils/misc.h" 23 24 #include <stdio.h> 25 #include <string.h> 26 #include <sys/types.h> 27 #include <sys/socket.h> 28 #include <sys/un.h> 29 #include <arpa/inet.h> 30 #include <netinet/in.h> 31 #include <stdlib.h> 32 #include <errno.h> 33 #include <unistd.h> 34 #include <sys/ioctl.h> 35 36 #include <cutils/sockets.h> 37 #include <netinet/tcp.h> 38 39 namespace android { 40 41 static jfieldID field_inboundFileDescriptors; 42 static jfieldID field_outboundFileDescriptors; 43 static jclass class_Credentials; 44 static jclass class_FileDescriptor; 45 static jmethodID method_CredentialsInit; 46 47 /* 48 * private native FileDescriptor 49 * create_native(boolean stream) 50 * throws IOException; 51 */ 52 static jobject 53 socket_create (JNIEnv *env, jobject object, jboolean stream) 54 { 55 int ret; 56 57 ret = socket(PF_LOCAL, stream ? SOCK_STREAM : SOCK_DGRAM, 0); 58 59 if (ret < 0) { 60 jniThrowIOException(env, errno); 61 return NULL; 62 } 63 64 return jniCreateFileDescriptor(env,ret); 65 } 66 67 /* private native void connectLocal(FileDescriptor fd, 68 * String name, int namespace) throws IOException 69 */ 70 static void 71 socket_connect_local(JNIEnv *env, jobject object, 72 jobject fileDescriptor, jstring name, jint namespaceId) 73 { 74 int ret; 75 const char *nameUtf8; 76 int fd; 77 78 nameUtf8 = env->GetStringUTFChars(name, NULL); 79 80 fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 81 82 if (env->ExceptionOccurred() != NULL) { 83 return; 84 } 85 86 ret = socket_local_client_connect( 87 fd, 88 nameUtf8, 89 namespaceId, 90 SOCK_STREAM); 91 92 env->ReleaseStringUTFChars(name, nameUtf8); 93 94 if (ret < 0) { 95 jniThrowIOException(env, errno); 96 return; 97 } 98 } 99 100 #define DEFAULT_BACKLOG 4 101 102 /* private native void bindLocal(FileDescriptor fd, String name, namespace) 103 * throws IOException; 104 */ 105 106 static void 107 socket_bind_local (JNIEnv *env, jobject object, jobject fileDescriptor, 108 jstring name, jint namespaceId) 109 { 110 int ret; 111 int fd; 112 const char *nameUtf8; 113 114 115 if (name == NULL) { 116 jniThrowNullPointerException(env, NULL); 117 } 118 119 fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 120 121 if (env->ExceptionOccurred() != NULL) { 122 return; 123 } 124 125 nameUtf8 = env->GetStringUTFChars(name, NULL); 126 127 ret = socket_local_server_bind(fd, nameUtf8, namespaceId); 128 129 env->ReleaseStringUTFChars(name, nameUtf8); 130 131 if (ret < 0) { 132 jniThrowIOException(env, errno); 133 return; 134 } 135 } 136 137 /* private native void listen_native(int fd, int backlog) throws IOException; */ 138 static void 139 socket_listen (JNIEnv *env, jobject object, jobject fileDescriptor, int backlog) 140 { 141 int ret; 142 int fd; 143 144 fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 145 146 if (env->ExceptionOccurred() != NULL) { 147 return; 148 } 149 150 ret = listen(fd, backlog); 151 152 if (ret < 0) { 153 jniThrowIOException(env, errno); 154 return; 155 } 156 } 157 158 /* private native FileDescriptor 159 ** accept (FileDescriptor fd, LocalSocketImpl s) 160 ** throws IOException; 161 */ 162 static jobject 163 socket_accept (JNIEnv *env, jobject object, jobject fileDescriptor, jobject s) 164 { 165 union { 166 struct sockaddr address; 167 struct sockaddr_un un_address; 168 } sa; 169 170 int ret; 171 int retFD; 172 int fd; 173 socklen_t addrlen; 174 175 if (s == NULL) { 176 jniThrowNullPointerException(env, NULL); 177 return NULL; 178 } 179 180 fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 181 182 if (env->ExceptionOccurred() != NULL) { 183 return NULL; 184 } 185 186 do { 187 addrlen = sizeof(sa); 188 ret = accept(fd, &(sa.address), &addrlen); 189 } while (ret < 0 && errno == EINTR); 190 191 if (ret < 0) { 192 jniThrowIOException(env, errno); 193 return NULL; 194 } 195 196 retFD = ret; 197 198 return jniCreateFileDescriptor(env, retFD); 199 } 200 201 /* private native void shutdown(FileDescriptor fd, boolean shutdownInput) */ 202 203 static void 204 socket_shutdown (JNIEnv *env, jobject object, jobject fileDescriptor, 205 jboolean shutdownInput) 206 { 207 int ret; 208 int fd; 209 210 fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 211 212 if (env->ExceptionOccurred() != NULL) { 213 return; 214 } 215 216 ret = shutdown(fd, shutdownInput ? SHUT_RD : SHUT_WR); 217 218 if (ret < 0) { 219 jniThrowIOException(env, errno); 220 return; 221 } 222 } 223 224 static bool 225 java_opt_to_real(int optID, int* opt, int* level) 226 { 227 switch (optID) 228 { 229 case 4098: 230 *opt = SO_RCVBUF; 231 *level = SOL_SOCKET; 232 return true; 233 case 4097: 234 *opt = SO_SNDBUF; 235 *level = SOL_SOCKET; 236 return true; 237 case 4102: 238 *opt = SO_SNDTIMEO; 239 *level = SOL_SOCKET; 240 return true; 241 case 128: 242 *opt = SO_LINGER; 243 *level = SOL_SOCKET; 244 return true; 245 case 1: 246 *opt = TCP_NODELAY; 247 *level = IPPROTO_TCP; 248 return true; 249 case 4: 250 *opt = SO_REUSEADDR; 251 *level = SOL_SOCKET; 252 return true; 253 254 } 255 return false; 256 } 257 258 static jint 259 socket_getOption(JNIEnv *env, jobject object, jobject fileDescriptor, int optID) 260 { 261 int ret, value; 262 int opt, level; 263 int fd; 264 265 socklen_t size = sizeof(int); 266 267 if (!java_opt_to_real(optID, &opt, &level)) { 268 jniThrowIOException(env, -1); 269 return 0; 270 } 271 272 fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 273 274 if (env->ExceptionOccurred() != NULL) { 275 return 0; 276 } 277 278 switch (opt) 279 { 280 case SO_LINGER: 281 { 282 struct linger lingr; 283 size = sizeof(lingr); 284 ret = getsockopt(fd, level, opt, &lingr, &size); 285 if (!lingr.l_onoff) { 286 value = -1; 287 } else { 288 value = lingr.l_linger; 289 } 290 break; 291 } 292 default: 293 ret = getsockopt(fd, level, opt, &value, &size); 294 break; 295 } 296 297 298 if (ret != 0) { 299 jniThrowIOException(env, errno); 300 return 0; 301 } 302 303 return value; 304 } 305 306 static void socket_setOption( 307 JNIEnv *env, jobject object, jobject fileDescriptor, int optID, 308 jint boolValue, jint intValue) { 309 int ret; 310 int optname; 311 int level; 312 int fd; 313 314 if (!java_opt_to_real(optID, &optname, &level)) { 315 jniThrowIOException(env, -1); 316 return; 317 } 318 319 fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 320 321 if (env->ExceptionOccurred() != NULL) { 322 return; 323 } 324 325 switch (optname) { 326 case SO_LINGER: { 327 /* 328 * SO_LINGER is special because it needs to use a special 329 * "linger" struct as well as use the incoming boolean 330 * argument specially. 331 */ 332 struct linger lingr; 333 lingr.l_onoff = boolValue ? 1 : 0; // Force it to be 0 or 1. 334 lingr.l_linger = intValue; 335 ret = setsockopt(fd, level, optname, &lingr, sizeof(lingr)); 336 break; 337 } 338 case SO_SNDTIMEO: { 339 /* 340 * SO_TIMEOUT from the core library gets converted to 341 * SO_SNDTIMEO, but the option is supposed to set both 342 * send and receive timeouts. Note: The incoming timeout 343 * value is in milliseconds. 344 */ 345 struct timeval timeout; 346 timeout.tv_sec = intValue / 1000; 347 timeout.tv_usec = (intValue % 1000) * 1000; 348 349 ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, 350 (void *)&timeout, sizeof(timeout)); 351 352 if (ret == 0) { 353 ret = setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, 354 (void *)&timeout, sizeof(timeout)); 355 } 356 357 break; 358 } 359 default: { 360 /* 361 * In all other cases, the translated option level and 362 * optname may be used directly for a call to setsockopt(). 363 */ 364 ret = setsockopt(fd, level, optname, &intValue, sizeof(intValue)); 365 break; 366 } 367 } 368 369 if (ret != 0) { 370 jniThrowIOException(env, errno); 371 return; 372 } 373 } 374 static jint socket_pending (JNIEnv *env, jobject object, 375 jobject fileDescriptor) 376 { 377 int fd; 378 379 fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 380 381 if (env->ExceptionOccurred() != NULL) { 382 return (jint)-1; 383 } 384 385 int pending; 386 int ret = ioctl(fd, TIOCOUTQ, &pending); 387 388 // If this were a non-socket fd, there would be other cases to worry 389 // about... 390 391 //ALOGD("socket_pending, ioctl ret:%d, pending:%d", ret, pending); 392 if (ret < 0) { 393 jniThrowIOException(env, errno); 394 return (jint) 0; 395 } 396 397 return (jint)pending; 398 } 399 static jint socket_available (JNIEnv *env, jobject object, 400 jobject fileDescriptor) 401 { 402 int fd; 403 404 fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 405 406 if (env->ExceptionOccurred() != NULL) { 407 return (jint)-1; 408 } 409 410 #if 1 411 int avail; 412 int ret = ioctl(fd, FIONREAD, &avail); 413 414 // If this were a non-socket fd, there would be other cases to worry 415 // about... 416 417 if (ret < 0) { 418 jniThrowIOException(env, errno); 419 return (jint) 0; 420 } 421 422 return (jint)avail; 423 #else 424 // there appears to be a bionic bug that prevents this version from working. 425 426 ssize_t ret; 427 struct msghdr msg; 428 429 memset(&msg, 0, sizeof(msg)); 430 431 do { 432 ret = recvmsg(fd, &msg, MSG_PEEK | MSG_DONTWAIT | MSG_NOSIGNAL); 433 } while (ret < 0 && errno == EINTR); 434 435 436 // MSG_PEEK returns 0 on EOF and EWOULDBLOCK on none available 437 if (ret < 0 && errno == EWOULDBLOCK) { 438 return 0; 439 } if (ret < 0) { 440 jniThrowIOException(env, errno); 441 return -1; 442 } 443 444 return (jint)ret; 445 #endif 446 } 447 448 static void socket_close (JNIEnv *env, jobject object, jobject fileDescriptor) 449 { 450 int fd; 451 int err; 452 453 if (fileDescriptor == NULL) { 454 jniThrowNullPointerException(env, NULL); 455 return; 456 } 457 458 fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 459 460 if (env->ExceptionOccurred() != NULL) { 461 return; 462 } 463 464 do { 465 err = close(fd); 466 } while (err < 0 && errno == EINTR); 467 468 if (err < 0) { 469 jniThrowIOException(env, errno); 470 return; 471 } 472 } 473 474 /** 475 * Processes ancillary data, handling only 476 * SCM_RIGHTS. Creates appropriate objects and sets appropriate 477 * fields in the LocalSocketImpl object. Returns 0 on success 478 * or -1 if an exception was thrown. 479 */ 480 static int socket_process_cmsg(JNIEnv *env, jobject thisJ, struct msghdr * pMsg) 481 { 482 struct cmsghdr *cmsgptr; 483 484 for (cmsgptr = CMSG_FIRSTHDR(pMsg); 485 cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(pMsg, cmsgptr)) { 486 487 if (cmsgptr->cmsg_level != SOL_SOCKET) { 488 continue; 489 } 490 491 if (cmsgptr->cmsg_type == SCM_RIGHTS) { 492 int *pDescriptors = (int *)CMSG_DATA(cmsgptr); 493 jobjectArray fdArray; 494 int count 495 = ((cmsgptr->cmsg_len - CMSG_LEN(0)) / sizeof(int)); 496 497 if (count < 0) { 498 jniThrowException(env, "java/io/IOException", 499 "invalid cmsg length"); 500 } 501 502 fdArray = env->NewObjectArray(count, class_FileDescriptor, NULL); 503 504 if (fdArray == NULL) { 505 return -1; 506 } 507 508 for (int i = 0; i < count; i++) { 509 jobject fdObject 510 = jniCreateFileDescriptor(env, pDescriptors[i]); 511 512 if (env->ExceptionOccurred() != NULL) { 513 return -1; 514 } 515 516 env->SetObjectArrayElement(fdArray, i, fdObject); 517 518 if (env->ExceptionOccurred() != NULL) { 519 return -1; 520 } 521 } 522 523 env->SetObjectField(thisJ, field_inboundFileDescriptors, fdArray); 524 525 if (env->ExceptionOccurred() != NULL) { 526 return -1; 527 } 528 } 529 } 530 531 return 0; 532 } 533 534 /** 535 * Reads data from a socket into buf, processing any ancillary data 536 * and adding it to thisJ. 537 * 538 * Returns the length of normal data read, or -1 if an exception has 539 * been thrown in this function. 540 */ 541 static ssize_t socket_read_all(JNIEnv *env, jobject thisJ, int fd, 542 void *buffer, size_t len) 543 { 544 ssize_t ret; 545 ssize_t bytesread = 0; 546 struct msghdr msg; 547 struct iovec iv; 548 unsigned char *buf = (unsigned char *)buffer; 549 // Enough buffer for a pile of fd's. We throw an exception if 550 // this buffer is too small. 551 struct cmsghdr cmsgbuf[2*sizeof(cmsghdr) + 0x100]; 552 553 memset(&msg, 0, sizeof(msg)); 554 memset(&iv, 0, sizeof(iv)); 555 556 iv.iov_base = buf; 557 iv.iov_len = len; 558 559 msg.msg_iov = &iv; 560 msg.msg_iovlen = 1; 561 msg.msg_control = cmsgbuf; 562 msg.msg_controllen = sizeof(cmsgbuf); 563 564 do { 565 ret = recvmsg(fd, &msg, MSG_NOSIGNAL); 566 } while (ret < 0 && errno == EINTR); 567 568 if (ret < 0 && errno == EPIPE) { 569 // Treat this as an end of stream 570 return 0; 571 } 572 573 if (ret < 0) { 574 jniThrowIOException(env, errno); 575 return -1; 576 } 577 578 if ((msg.msg_flags & (MSG_CTRUNC | MSG_OOB | MSG_ERRQUEUE)) != 0) { 579 // To us, any of the above flags are a fatal error 580 581 jniThrowException(env, "java/io/IOException", 582 "Unexpected error or truncation during recvmsg()"); 583 584 return -1; 585 } 586 587 if (ret >= 0) { 588 socket_process_cmsg(env, thisJ, &msg); 589 } 590 591 return ret; 592 } 593 594 /** 595 * Writes all the data in the specified buffer to the specified socket. 596 * 597 * Returns 0 on success or -1 if an exception was thrown. 598 */ 599 static int socket_write_all(JNIEnv *env, jobject object, int fd, 600 void *buf, size_t len) 601 { 602 ssize_t ret; 603 struct msghdr msg; 604 unsigned char *buffer = (unsigned char *)buf; 605 memset(&msg, 0, sizeof(msg)); 606 607 jobjectArray outboundFds 608 = (jobjectArray)env->GetObjectField( 609 object, field_outboundFileDescriptors); 610 611 if (env->ExceptionOccurred() != NULL) { 612 return -1; 613 } 614 615 struct cmsghdr *cmsg; 616 int countFds = outboundFds == NULL ? 0 : env->GetArrayLength(outboundFds); 617 int fds[countFds]; 618 char msgbuf[CMSG_SPACE(countFds)]; 619 620 // Add any pending outbound file descriptors to the message 621 if (outboundFds != NULL) { 622 623 if (env->ExceptionOccurred() != NULL) { 624 return -1; 625 } 626 627 for (int i = 0; i < countFds; i++) { 628 jobject fdObject = env->GetObjectArrayElement(outboundFds, i); 629 if (env->ExceptionOccurred() != NULL) { 630 return -1; 631 } 632 633 fds[i] = jniGetFDFromFileDescriptor(env, fdObject); 634 if (env->ExceptionOccurred() != NULL) { 635 return -1; 636 } 637 } 638 639 // See "man cmsg" really 640 msg.msg_control = msgbuf; 641 msg.msg_controllen = sizeof msgbuf; 642 cmsg = CMSG_FIRSTHDR(&msg); 643 cmsg->cmsg_level = SOL_SOCKET; 644 cmsg->cmsg_type = SCM_RIGHTS; 645 cmsg->cmsg_len = CMSG_LEN(sizeof fds); 646 memcpy(CMSG_DATA(cmsg), fds, sizeof fds); 647 } 648 649 // We only write our msg_control during the first write 650 while (len > 0) { 651 struct iovec iv; 652 memset(&iv, 0, sizeof(iv)); 653 654 iv.iov_base = buffer; 655 iv.iov_len = len; 656 657 msg.msg_iov = &iv; 658 msg.msg_iovlen = 1; 659 660 do { 661 ret = sendmsg(fd, &msg, MSG_NOSIGNAL); 662 } while (ret < 0 && errno == EINTR); 663 664 if (ret < 0) { 665 jniThrowIOException(env, errno); 666 return -1; 667 } 668 669 buffer += ret; 670 len -= ret; 671 672 // Wipes out any msg_control too 673 memset(&msg, 0, sizeof(msg)); 674 } 675 676 return 0; 677 } 678 679 static jint socket_read (JNIEnv *env, jobject object, jobject fileDescriptor) 680 { 681 int fd; 682 int err; 683 684 if (fileDescriptor == NULL) { 685 jniThrowNullPointerException(env, NULL); 686 return (jint)-1; 687 } 688 689 fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 690 691 if (env->ExceptionOccurred() != NULL) { 692 return (jint)0; 693 } 694 695 unsigned char buf; 696 697 err = socket_read_all(env, object, fd, &buf, 1); 698 699 if (err < 0) { 700 jniThrowIOException(env, errno); 701 return (jint)0; 702 } 703 704 if (err == 0) { 705 // end of file 706 return (jint)-1; 707 } 708 709 return (jint)buf; 710 } 711 712 static jint socket_readba (JNIEnv *env, jobject object, 713 jbyteArray buffer, jint off, jint len, jobject fileDescriptor) 714 { 715 int fd; 716 jbyte* byteBuffer; 717 int ret; 718 719 if (fileDescriptor == NULL || buffer == NULL) { 720 jniThrowNullPointerException(env, NULL); 721 return (jint)-1; 722 } 723 724 if (off < 0 || len < 0 || (off + len) > env->GetArrayLength(buffer)) { 725 jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL); 726 return (jint)-1; 727 } 728 729 if (len == 0) { 730 // because socket_read_all returns 0 on EOF 731 return 0; 732 } 733 734 fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 735 736 if (env->ExceptionOccurred() != NULL) { 737 return (jint)-1; 738 } 739 740 byteBuffer = env->GetByteArrayElements(buffer, NULL); 741 742 if (NULL == byteBuffer) { 743 // an exception will have been thrown 744 return (jint)-1; 745 } 746 747 ret = socket_read_all(env, object, 748 fd, byteBuffer + off, len); 749 750 // A return of -1 above means an exception is pending 751 752 env->ReleaseByteArrayElements(buffer, byteBuffer, 0); 753 754 return (jint) ((ret == 0) ? -1 : ret); 755 } 756 757 static void socket_write (JNIEnv *env, jobject object, 758 jint b, jobject fileDescriptor) 759 { 760 int fd; 761 int err; 762 763 if (fileDescriptor == NULL) { 764 jniThrowNullPointerException(env, NULL); 765 return; 766 } 767 768 fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 769 770 if (env->ExceptionOccurred() != NULL) { 771 return; 772 } 773 774 err = socket_write_all(env, object, fd, &b, 1); 775 776 // A return of -1 above means an exception is pending 777 } 778 779 static void socket_writeba (JNIEnv *env, jobject object, 780 jbyteArray buffer, jint off, jint len, jobject fileDescriptor) 781 { 782 int fd; 783 int err; 784 jbyte* byteBuffer; 785 786 if (fileDescriptor == NULL || buffer == NULL) { 787 jniThrowNullPointerException(env, NULL); 788 return; 789 } 790 791 if (off < 0 || len < 0 || (off + len) > env->GetArrayLength(buffer)) { 792 jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL); 793 return; 794 } 795 796 fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 797 798 if (env->ExceptionOccurred() != NULL) { 799 return; 800 } 801 802 byteBuffer = env->GetByteArrayElements(buffer,NULL); 803 804 if (NULL == byteBuffer) { 805 // an exception will have been thrown 806 return; 807 } 808 809 err = socket_write_all(env, object, fd, 810 byteBuffer + off, len); 811 812 // A return of -1 above means an exception is pending 813 814 env->ReleaseByteArrayElements(buffer, byteBuffer, JNI_ABORT); 815 } 816 817 static jobject socket_get_peer_credentials(JNIEnv *env, 818 jobject object, jobject fileDescriptor) 819 { 820 int err; 821 int fd; 822 823 if (fileDescriptor == NULL) { 824 jniThrowNullPointerException(env, NULL); 825 return NULL; 826 } 827 828 fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 829 830 if (env->ExceptionOccurred() != NULL) { 831 return NULL; 832 } 833 834 struct ucred creds; 835 836 memset(&creds, 0, sizeof(creds)); 837 socklen_t szCreds = sizeof(creds); 838 839 err = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds); 840 841 if (err < 0) { 842 jniThrowIOException(env, errno); 843 return NULL; 844 } 845 846 if (szCreds == 0) { 847 return NULL; 848 } 849 850 return env->NewObject(class_Credentials, method_CredentialsInit, 851 creds.pid, creds.uid, creds.gid); 852 } 853 854 #if 0 855 //TODO change this to return an instance of LocalSocketAddress 856 static jobject socket_getSockName(JNIEnv *env, 857 jobject object, jobject fileDescriptor) 858 { 859 int err; 860 int fd; 861 862 if (fileDescriptor == NULL) { 863 jniThrowNullPointerException(env, NULL); 864 return NULL; 865 } 866 867 fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 868 869 if (env->ExceptionOccurred() != NULL) { 870 return NULL; 871 } 872 873 union { 874 struct sockaddr address; 875 struct sockaddr_un un_address; 876 } sa; 877 878 memset(&sa, 0, sizeof(sa)); 879 880 socklen_t namelen = sizeof(sa); 881 err = getsockname(fd, &(sa.address), &namelen); 882 883 if (err < 0) { 884 jniThrowIOException(env, errno); 885 return NULL; 886 } 887 888 if (sa.address.sa_family != AF_UNIX) { 889 // We think we're an impl only for AF_UNIX, so this should never happen. 890 891 jniThrowIOException(env, EINVAL); 892 return NULL; 893 } 894 895 if (sa.un_address.sun_path[0] == '\0') { 896 } else { 897 } 898 899 900 901 902 } 903 #endif 904 905 /* 906 * JNI registration. 907 */ 908 static JNINativeMethod gMethods[] = { 909 /* name, signature, funcPtr */ 910 {"getOption_native", "(Ljava/io/FileDescriptor;I)I", (void*)socket_getOption}, 911 {"setOption_native", "(Ljava/io/FileDescriptor;III)V", (void*)socket_setOption}, 912 {"create_native", "(Z)Ljava/io/FileDescriptor;", (void*)socket_create}, 913 {"connectLocal", "(Ljava/io/FileDescriptor;Ljava/lang/String;I)V", 914 (void*)socket_connect_local}, 915 {"bindLocal", "(Ljava/io/FileDescriptor;Ljava/lang/String;I)V", (void*)socket_bind_local}, 916 {"listen_native", "(Ljava/io/FileDescriptor;I)V", (void*)socket_listen}, 917 {"accept", "(Ljava/io/FileDescriptor;Landroid/net/LocalSocketImpl;)Ljava/io/FileDescriptor;", (void*)socket_accept}, 918 {"shutdown", "(Ljava/io/FileDescriptor;Z)V", (void*)socket_shutdown}, 919 {"available_native", "(Ljava/io/FileDescriptor;)I", (void*) socket_available}, 920 {"pending_native", "(Ljava/io/FileDescriptor;)I", (void*) socket_pending}, 921 {"close_native", "(Ljava/io/FileDescriptor;)V", (void*) socket_close}, 922 {"read_native", "(Ljava/io/FileDescriptor;)I", (void*) socket_read}, 923 {"readba_native", "([BIILjava/io/FileDescriptor;)I", (void*) socket_readba}, 924 {"writeba_native", "([BIILjava/io/FileDescriptor;)V", (void*) socket_writeba}, 925 {"write_native", "(ILjava/io/FileDescriptor;)V", (void*) socket_write}, 926 {"getPeerCredentials_native", 927 "(Ljava/io/FileDescriptor;)Landroid/net/Credentials;", 928 (void*) socket_get_peer_credentials} 929 //,{"getSockName_native", "(Ljava/io/FileDescriptor;)Ljava/lang/String;", 930 // (void *) socket_getSockName} 931 932 }; 933 934 int register_android_net_LocalSocketImpl(JNIEnv *env) 935 { 936 jclass clazz; 937 938 clazz = env->FindClass("android/net/LocalSocketImpl"); 939 940 if (clazz == NULL) { 941 goto error; 942 } 943 944 field_inboundFileDescriptors = env->GetFieldID(clazz, 945 "inboundFileDescriptors", "[Ljava/io/FileDescriptor;"); 946 947 if (field_inboundFileDescriptors == NULL) { 948 goto error; 949 } 950 951 field_outboundFileDescriptors = env->GetFieldID(clazz, 952 "outboundFileDescriptors", "[Ljava/io/FileDescriptor;"); 953 954 if (field_outboundFileDescriptors == NULL) { 955 goto error; 956 } 957 958 class_Credentials = env->FindClass("android/net/Credentials"); 959 960 if (class_Credentials == NULL) { 961 goto error; 962 } 963 964 class_Credentials = (jclass)env->NewGlobalRef(class_Credentials); 965 966 class_FileDescriptor = env->FindClass("java/io/FileDescriptor"); 967 968 if (class_FileDescriptor == NULL) { 969 goto error; 970 } 971 972 class_FileDescriptor = (jclass)env->NewGlobalRef(class_FileDescriptor); 973 974 method_CredentialsInit 975 = env->GetMethodID(class_Credentials, "<init>", "(III)V"); 976 977 if (method_CredentialsInit == NULL) { 978 goto error; 979 } 980 981 return jniRegisterNativeMethods(env, 982 "android/net/LocalSocketImpl", gMethods, NELEM(gMethods)); 983 984 error: 985 ALOGE("Error registering android.net.LocalSocketImpl"); 986 return -1; 987 } 988 989 }; 990