19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "LocalSocketImpl" 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 192279b2534272282a5b5152723235da397e49195cSteven Moreland#include <nativehelper/JNIHelp.h> 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "jni.h" 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "utils/Log.h" 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "utils/misc.h" 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h> 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <string.h> 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/types.h> 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/socket.h> 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/un.h> 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <arpa/inet.h> 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <netinet/in.h> 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdlib.h> 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <errno.h> 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <unistd.h> 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/ioctl.h> 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <cutils/sockets.h> 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <netinet/tcp.h> 382279b2534272282a5b5152723235da397e49195cSteven Moreland#include <nativehelper/ScopedUtfChars.h> 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android { 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 420f0b4919667f418b249c497f5ad3e83fdf4437e5Andreas Gampetemplate <typename T> 430f0b4919667f418b249c497f5ad3e83fdf4437e5Andreas Gampevoid UNUSED(T t) {} 440f0b4919667f418b249c497f5ad3e83fdf4437e5Andreas Gampe 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID field_inboundFileDescriptors; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID field_outboundFileDescriptors; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jclass class_Credentials; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jclass class_FileDescriptor; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jmethodID method_CredentialsInit; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* private native void connectLocal(FileDescriptor fd, 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * String name, int namespace) throws IOException 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectsocket_connect_local(JNIEnv *env, jobject object, 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jobject fileDescriptor, jstring name, jint namespaceId) 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ret; 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6398671c34fa00a79c62ff0d9d874428bed1f86e92Mathieu Chartier if (env->ExceptionCheck()) { 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 67092eb8d43baffd7723bc7847c180a32fb5269481You Kim ScopedUtfChars nameUtf8(env, name); 68092eb8d43baffd7723bc7847c180a32fb5269481You Kim 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = socket_local_client_connect( 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd, 71092eb8d43baffd7723bc7847c180a32fb5269481You Kim nameUtf8.c_str(), 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project namespaceId, 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SOCK_STREAM); 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret < 0) { 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, errno); 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define DEFAULT_BACKLOG 4 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes/* private native void bindLocal(FileDescriptor fd, String name, namespace) 8469a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes * throws IOException; 8569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes */ 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectsocket_bind_local (JNIEnv *env, jobject object, jobject fileDescriptor, 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jstring name, jint namespaceId) 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ret; 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (name == NULL) { 9569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jniThrowNullPointerException(env, NULL); 96092eb8d43baffd7723bc7847c180a32fb5269481You Kim return; 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10198671c34fa00a79c62ff0d9d874428bed1f86e92Mathieu Chartier if (env->ExceptionCheck()) { 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 105092eb8d43baffd7723bc7847c180a32fb5269481You Kim ScopedUtfChars nameUtf8(env, name); 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 107092eb8d43baffd7723bc7847c180a32fb5269481You Kim ret = socket_local_server_bind(fd, nameUtf8.c_str(), namespaceId); 10869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret < 0) { 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, errno); 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 11669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes * Processes ancillary data, handling only 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * SCM_RIGHTS. Creates appropriate objects and sets appropriate 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * fields in the LocalSocketImpl object. Returns 0 on success 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * or -1 if an exception was thrown. 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int socket_process_cmsg(JNIEnv *env, jobject thisJ, struct msghdr * pMsg) 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct cmsghdr *cmsgptr; 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes for (cmsgptr = CMSG_FIRSTHDR(pMsg); 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(pMsg, cmsgptr)) { 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cmsgptr->cmsg_level != SOL_SOCKET) { 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cmsgptr->cmsg_type == SCM_RIGHTS) { 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int *pDescriptors = (int *)CMSG_DATA(cmsgptr); 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jobjectArray fdArray; 13569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes int count 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project = ((cmsgptr->cmsg_len - CMSG_LEN(0)) / sizeof(int)); 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count < 0) { 13969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jniThrowException(env, "java/io/IOException", 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "invalid cmsg length"); 141092eb8d43baffd7723bc7847c180a32fb5269481You Kim return -1; 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fdArray = env->NewObjectArray(count, class_FileDescriptor, NULL); 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fdArray == NULL) { 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 15169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jobject fdObject 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project = jniCreateFileDescriptor(env, pDescriptors[i]); 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15498671c34fa00a79c62ff0d9d874428bed1f86e92Mathieu Chartier if (env->ExceptionCheck()) { 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetObjectArrayElement(fdArray, i, fdObject); 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16098671c34fa00a79c62ff0d9d874428bed1f86e92Mathieu Chartier if (env->ExceptionCheck()) { 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetObjectField(thisJ, field_inboundFileDescriptors, fdArray); 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16798671c34fa00a79c62ff0d9d874428bed1f86e92Mathieu Chartier if (env->ExceptionCheck()) { 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Reads data from a socket into buf, processing any ancillary data 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and adding it to thisJ. 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the length of normal data read, or -1 if an exception has 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * been thrown in this function. 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 18369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughesstatic ssize_t socket_read_all(JNIEnv *env, jobject thisJ, int fd, 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void *buffer, size_t len) 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ssize_t ret; 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct msghdr msg; 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct iovec iv; 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned char *buf = (unsigned char *)buffer; 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Enough buffer for a pile of fd's. We throw an exception if 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // this buffer is too small. 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct cmsghdr cmsgbuf[2*sizeof(cmsghdr) + 0x100]; 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(&msg, 0, sizeof(msg)); 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(&iv, 0, sizeof(iv)); 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project iv.iov_base = buf; 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project iv.iov_len = len; 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg.msg_iov = &iv; 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg.msg_iovlen = 1; 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg.msg_control = cmsgbuf; 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg.msg_controllen = sizeof(cmsgbuf); 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 205b0e5079b5dc37641741c3ea370376261aa06667fNick Kralevich ret = TEMP_FAILURE_RETRY(recvmsg(fd, &msg, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC)); 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret < 0 && errno == EPIPE) { 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Treat this as an end of stream 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret < 0) { 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, errno); 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((msg.msg_flags & (MSG_CTRUNC | MSG_OOB | MSG_ERRQUEUE)) != 0) { 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // To us, any of the above flags are a fatal error 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 22069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jniThrowException(env, "java/io/IOException", 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unexpected error or truncation during recvmsg()"); 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret >= 0) { 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project socket_process_cmsg(env, thisJ, &msg); 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret; 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Writes all the data in the specified buffer to the specified socket. 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns 0 on success or -1 if an exception was thrown. 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int socket_write_all(JNIEnv *env, jobject object, int fd, 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void *buf, size_t len) 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ssize_t ret; 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct msghdr msg; 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned char *buffer = (unsigned char *)buf; 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(&msg, 0, sizeof(msg)); 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 24669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jobjectArray outboundFds 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project = (jobjectArray)env->GetObjectField( 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project object, field_outboundFileDescriptors); 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 25098671c34fa00a79c62ff0d9d874428bed1f86e92Mathieu Chartier if (env->ExceptionCheck()) { 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct cmsghdr *cmsg; 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int countFds = outboundFds == NULL ? 0 : env->GetArrayLength(outboundFds); 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fds[countFds]; 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char msgbuf[CMSG_SPACE(countFds)]; 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Add any pending outbound file descriptors to the message 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (outboundFds != NULL) { 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 26298671c34fa00a79c62ff0d9d874428bed1f86e92Mathieu Chartier if (env->ExceptionCheck()) { 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < countFds; i++) { 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jobject fdObject = env->GetObjectArrayElement(outboundFds, i); 26898671c34fa00a79c62ff0d9d874428bed1f86e92Mathieu Chartier if (env->ExceptionCheck()) { 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fds[i] = jniGetFDFromFileDescriptor(env, fdObject); 27398671c34fa00a79c62ff0d9d874428bed1f86e92Mathieu Chartier if (env->ExceptionCheck()) { 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // See "man cmsg" really 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg.msg_control = msgbuf; 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg.msg_controllen = sizeof msgbuf; 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cmsg = CMSG_FIRSTHDR(&msg); 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cmsg->cmsg_level = SOL_SOCKET; 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cmsg->cmsg_type = SCM_RIGHTS; 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cmsg->cmsg_len = CMSG_LEN(sizeof fds); 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memcpy(CMSG_DATA(cmsg), fds, sizeof fds); 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We only write our msg_control during the first write 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (len > 0) { 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct iovec iv; 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(&iv, 0, sizeof(iv)); 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project iv.iov_base = buffer; 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project iv.iov_len = len; 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg.msg_iov = &iv; 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg.msg_iovlen = 1; 29869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = sendmsg(fd, &msg, MSG_NOSIGNAL); 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (ret < 0 && errno == EINTR); 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret < 0) { 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, errno); 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buffer += ret; 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project len -= ret; 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Wipes out any msg_control too 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(&msg, 0, sizeof(msg)); 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint socket_read (JNIEnv *env, jobject object, jobject fileDescriptor) 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int err; 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fileDescriptor == NULL) { 32469a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jniThrowNullPointerException(env, NULL); 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)-1; 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33098671c34fa00a79c62ff0d9d874428bed1f86e92Mathieu Chartier if (env->ExceptionCheck()) { 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)0; 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned char buf; 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = socket_read_all(env, object, fd, &buf, 1); 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err < 0) { 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, errno); 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)0; 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err == 0) { 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // end of file 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)-1; 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)buf; 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 35169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughesstatic jint socket_readba (JNIEnv *env, jobject object, 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyteArray buffer, jint off, jint len, jobject fileDescriptor) 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyte* byteBuffer; 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ret; 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fileDescriptor == NULL || buffer == NULL) { 35969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jniThrowNullPointerException(env, NULL); 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)-1; 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (off < 0 || len < 0 || (off + len) > env->GetArrayLength(buffer)) { 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL); 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)-1; 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (len == 0) { 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // because socket_read_all returns 0 on EOF 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 37598671c34fa00a79c62ff0d9d874428bed1f86e92Mathieu Chartier if (env->ExceptionCheck()) { 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)-1; 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project byteBuffer = env->GetByteArrayElements(buffer, NULL); 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (NULL == byteBuffer) { 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // an exception will have been thrown 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)-1; 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 38669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes ret = socket_read_all(env, object, 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd, byteBuffer + off, len); 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // A return of -1 above means an exception is pending 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ReleaseByteArrayElements(buffer, byteBuffer, 0); 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint) ((ret == 0) ? -1 : ret); 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 39669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughesstatic void socket_write (JNIEnv *env, jobject object, 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint b, jobject fileDescriptor) 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int err; 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fileDescriptor == NULL) { 40369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jniThrowNullPointerException(env, NULL); 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 40998671c34fa00a79c62ff0d9d874428bed1f86e92Mathieu Chartier if (env->ExceptionCheck()) { 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = socket_write_all(env, object, fd, &b, 1); 4140f0b4919667f418b249c497f5ad3e83fdf4437e5Andreas Gampe UNUSED(err); 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // A return of -1 above means an exception is pending 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 41869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughesstatic void socket_writeba (JNIEnv *env, jobject object, 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyteArray buffer, jint off, jint len, jobject fileDescriptor) 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int err; 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyte* byteBuffer; 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fileDescriptor == NULL || buffer == NULL) { 42669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jniThrowNullPointerException(env, NULL); 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (off < 0 || len < 0 || (off + len) > env->GetArrayLength(buffer)) { 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL); 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 43798671c34fa00a79c62ff0d9d874428bed1f86e92Mathieu Chartier if (env->ExceptionCheck()) { 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project byteBuffer = env->GetByteArrayElements(buffer,NULL); 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (NULL == byteBuffer) { 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // an exception will have been thrown 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 44869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes err = socket_write_all(env, object, fd, 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project byteBuffer + off, len); 4500f0b4919667f418b249c497f5ad3e83fdf4437e5Andreas Gampe UNUSED(err); 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // A return of -1 above means an exception is pending 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ReleaseByteArrayElements(buffer, byteBuffer, JNI_ABORT); 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 45669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughesstatic jobject socket_get_peer_credentials(JNIEnv *env, 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jobject object, jobject fileDescriptor) 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int err; 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fileDescriptor == NULL) { 46369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jniThrowNullPointerException(env, NULL); 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 46998671c34fa00a79c62ff0d9d874428bed1f86e92Mathieu Chartier if (env->ExceptionCheck()) { 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct ucred creds; 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(&creds, 0, sizeof(creds)); 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project socklen_t szCreds = sizeof(creds); 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 47869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes err = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds); 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err < 0) { 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, errno); 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (szCreds == 0) { 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 48969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes return env->NewObject(class_Credentials, method_CredentialsInit, 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project creds.pid, creds.uid, creds.gid); 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * JNI registration. 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 49676f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gMethods[] = { 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* name, signature, funcPtr */ 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"connectLocal", "(Ljava/io/FileDescriptor;Ljava/lang/String;I)V", 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void*)socket_connect_local}, 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"bindLocal", "(Ljava/io/FileDescriptor;Ljava/lang/String;I)V", (void*)socket_bind_local}, 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"read_native", "(Ljava/io/FileDescriptor;)I", (void*) socket_read}, 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"readba_native", "([BIILjava/io/FileDescriptor;)I", (void*) socket_readba}, 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"writeba_native", "([BIILjava/io/FileDescriptor;)V", (void*) socket_writeba}, 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"write_native", "(ILjava/io/FileDescriptor;)V", (void*) socket_write}, 50569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes {"getPeerCredentials_native", 50669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes "(Ljava/io/FileDescriptor;)Landroid/net/Credentials;", 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void*) socket_get_peer_credentials} 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_net_LocalSocketImpl(JNIEnv *env) 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jclass clazz; 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project clazz = env->FindClass("android/net/LocalSocketImpl"); 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (clazz == NULL) { 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto error; 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 52069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes field_inboundFileDescriptors = env->GetFieldID(clazz, 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "inboundFileDescriptors", "[Ljava/io/FileDescriptor;"); 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (field_inboundFileDescriptors == NULL) { 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto error; 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 52769a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes field_outboundFileDescriptors = env->GetFieldID(clazz, 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "outboundFileDescriptors", "[Ljava/io/FileDescriptor;"); 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (field_outboundFileDescriptors == NULL) { 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto error; 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project class_Credentials = env->FindClass("android/net/Credentials"); 53569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (class_Credentials == NULL) { 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto error; 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project class_Credentials = (jclass)env->NewGlobalRef(class_Credentials); 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project class_FileDescriptor = env->FindClass("java/io/FileDescriptor"); 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (class_FileDescriptor == NULL) { 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto error; 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project class_FileDescriptor = (jclass)env->NewGlobalRef(class_FileDescriptor); 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 55069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes method_CredentialsInit 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project = env->GetMethodID(class_Credentials, "<init>", "(III)V"); 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (method_CredentialsInit == NULL) { 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto error; 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return jniRegisterNativeMethods(env, 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "android/net/LocalSocketImpl", gMethods, NELEM(gMethods)); 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecterror: 5613762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Error registering android.net.LocalSocketImpl"); 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 566