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