android_net_LocalSocketImpl.cpp revision 76f6a86de25e1bf74717e047e55fd44b089673f3
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 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "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> 38092eb8d43baffd7723bc7847c180a32fb5269481You Kim#include <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 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = recvmsg(fd, &msg, MSG_NOSIGNAL); 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (ret < 0 && errno == EINTR); 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret < 0 && errno == EPIPE) { 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Treat this as an end of stream 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret < 0) { 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, errno); 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((msg.msg_flags & (MSG_CTRUNC | MSG_OOB | MSG_ERRQUEUE)) != 0) { 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // To us, any of the above flags are a fatal error 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 22269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jniThrowException(env, "java/io/IOException", 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unexpected error or truncation during recvmsg()"); 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret >= 0) { 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project socket_process_cmsg(env, thisJ, &msg); 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret; 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Writes all the data in the specified buffer to the specified socket. 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns 0 on success or -1 if an exception was thrown. 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int socket_write_all(JNIEnv *env, jobject object, int fd, 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void *buf, size_t len) 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ssize_t ret; 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct msghdr msg; 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned char *buffer = (unsigned char *)buf; 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(&msg, 0, sizeof(msg)); 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 24869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jobjectArray outboundFds 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project = (jobjectArray)env->GetObjectField( 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project object, field_outboundFileDescriptors); 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 25298671c34fa00a79c62ff0d9d874428bed1f86e92Mathieu Chartier if (env->ExceptionCheck()) { 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct cmsghdr *cmsg; 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int countFds = outboundFds == NULL ? 0 : env->GetArrayLength(outboundFds); 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fds[countFds]; 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char msgbuf[CMSG_SPACE(countFds)]; 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Add any pending outbound file descriptors to the message 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (outboundFds != NULL) { 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 26498671c34fa00a79c62ff0d9d874428bed1f86e92Mathieu Chartier if (env->ExceptionCheck()) { 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < countFds; i++) { 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jobject fdObject = env->GetObjectArrayElement(outboundFds, i); 27098671c34fa00a79c62ff0d9d874428bed1f86e92Mathieu Chartier if (env->ExceptionCheck()) { 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fds[i] = jniGetFDFromFileDescriptor(env, fdObject); 27598671c34fa00a79c62ff0d9d874428bed1f86e92Mathieu Chartier if (env->ExceptionCheck()) { 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // See "man cmsg" really 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg.msg_control = msgbuf; 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg.msg_controllen = sizeof msgbuf; 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cmsg = CMSG_FIRSTHDR(&msg); 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cmsg->cmsg_level = SOL_SOCKET; 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cmsg->cmsg_type = SCM_RIGHTS; 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cmsg->cmsg_len = CMSG_LEN(sizeof fds); 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memcpy(CMSG_DATA(cmsg), fds, sizeof fds); 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We only write our msg_control during the first write 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (len > 0) { 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct iovec iv; 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(&iv, 0, sizeof(iv)); 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project iv.iov_base = buffer; 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project iv.iov_len = len; 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg.msg_iov = &iv; 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg.msg_iovlen = 1; 30069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = sendmsg(fd, &msg, MSG_NOSIGNAL); 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (ret < 0 && errno == EINTR); 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret < 0) { 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, errno); 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buffer += ret; 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project len -= ret; 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Wipes out any msg_control too 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(&msg, 0, sizeof(msg)); 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint socket_read (JNIEnv *env, jobject object, jobject fileDescriptor) 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int err; 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fileDescriptor == NULL) { 32669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jniThrowNullPointerException(env, NULL); 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)-1; 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33298671c34fa00a79c62ff0d9d874428bed1f86e92Mathieu Chartier if (env->ExceptionCheck()) { 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)0; 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned char buf; 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = socket_read_all(env, object, fd, &buf, 1); 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err < 0) { 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, errno); 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)0; 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err == 0) { 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // end of file 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)-1; 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)buf; 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 35369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughesstatic jint socket_readba (JNIEnv *env, jobject object, 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyteArray buffer, jint off, jint len, jobject fileDescriptor) 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyte* byteBuffer; 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ret; 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fileDescriptor == NULL || buffer == NULL) { 36169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jniThrowNullPointerException(env, NULL); 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)-1; 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (off < 0 || len < 0 || (off + len) > env->GetArrayLength(buffer)) { 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL); 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)-1; 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (len == 0) { 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // because socket_read_all returns 0 on EOF 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 37798671c34fa00a79c62ff0d9d874428bed1f86e92Mathieu Chartier if (env->ExceptionCheck()) { 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)-1; 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project byteBuffer = env->GetByteArrayElements(buffer, NULL); 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (NULL == byteBuffer) { 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // an exception will have been thrown 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)-1; 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 38869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes ret = socket_read_all(env, object, 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd, byteBuffer + off, len); 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // A return of -1 above means an exception is pending 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ReleaseByteArrayElements(buffer, byteBuffer, 0); 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint) ((ret == 0) ? -1 : ret); 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 39869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughesstatic void socket_write (JNIEnv *env, jobject object, 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint b, jobject fileDescriptor) 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int err; 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fileDescriptor == NULL) { 40569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jniThrowNullPointerException(env, NULL); 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 41198671c34fa00a79c62ff0d9d874428bed1f86e92Mathieu Chartier if (env->ExceptionCheck()) { 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = socket_write_all(env, object, fd, &b, 1); 4160f0b4919667f418b249c497f5ad3e83fdf4437e5Andreas Gampe UNUSED(err); 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // A return of -1 above means an exception is pending 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 42069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughesstatic void socket_writeba (JNIEnv *env, jobject object, 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyteArray buffer, jint off, jint len, jobject fileDescriptor) 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int err; 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyte* byteBuffer; 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fileDescriptor == NULL || buffer == NULL) { 42869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jniThrowNullPointerException(env, NULL); 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (off < 0 || len < 0 || (off + len) > env->GetArrayLength(buffer)) { 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL); 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 43998671c34fa00a79c62ff0d9d874428bed1f86e92Mathieu Chartier if (env->ExceptionCheck()) { 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project byteBuffer = env->GetByteArrayElements(buffer,NULL); 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (NULL == byteBuffer) { 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // an exception will have been thrown 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 45069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes err = socket_write_all(env, object, fd, 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project byteBuffer + off, len); 4520f0b4919667f418b249c497f5ad3e83fdf4437e5Andreas Gampe UNUSED(err); 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // A return of -1 above means an exception is pending 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ReleaseByteArrayElements(buffer, byteBuffer, JNI_ABORT); 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 45869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughesstatic jobject socket_get_peer_credentials(JNIEnv *env, 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jobject object, jobject fileDescriptor) 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int err; 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fileDescriptor == NULL) { 46569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jniThrowNullPointerException(env, NULL); 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 47198671c34fa00a79c62ff0d9d874428bed1f86e92Mathieu Chartier if (env->ExceptionCheck()) { 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct ucred creds; 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(&creds, 0, sizeof(creds)); 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project socklen_t szCreds = sizeof(creds); 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 48069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes err = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds); 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err < 0) { 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, errno); 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (szCreds == 0) { 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 49169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes return env->NewObject(class_Credentials, method_CredentialsInit, 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project creds.pid, creds.uid, creds.gid); 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * JNI registration. 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 49876f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gMethods[] = { 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* name, signature, funcPtr */ 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"connectLocal", "(Ljava/io/FileDescriptor;Ljava/lang/String;I)V", 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void*)socket_connect_local}, 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"bindLocal", "(Ljava/io/FileDescriptor;Ljava/lang/String;I)V", (void*)socket_bind_local}, 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"read_native", "(Ljava/io/FileDescriptor;)I", (void*) socket_read}, 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"readba_native", "([BIILjava/io/FileDescriptor;)I", (void*) socket_readba}, 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"writeba_native", "([BIILjava/io/FileDescriptor;)V", (void*) socket_writeba}, 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"write_native", "(ILjava/io/FileDescriptor;)V", (void*) socket_write}, 50769a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes {"getPeerCredentials_native", 50869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes "(Ljava/io/FileDescriptor;)Landroid/net/Credentials;", 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void*) socket_get_peer_credentials} 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_net_LocalSocketImpl(JNIEnv *env) 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jclass clazz; 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project clazz = env->FindClass("android/net/LocalSocketImpl"); 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (clazz == NULL) { 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto error; 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 52269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes field_inboundFileDescriptors = env->GetFieldID(clazz, 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "inboundFileDescriptors", "[Ljava/io/FileDescriptor;"); 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (field_inboundFileDescriptors == NULL) { 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto error; 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 52969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes field_outboundFileDescriptors = env->GetFieldID(clazz, 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "outboundFileDescriptors", "[Ljava/io/FileDescriptor;"); 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (field_outboundFileDescriptors == NULL) { 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto error; 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project class_Credentials = env->FindClass("android/net/Credentials"); 53769a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (class_Credentials == NULL) { 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto error; 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project class_Credentials = (jclass)env->NewGlobalRef(class_Credentials); 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project class_FileDescriptor = env->FindClass("java/io/FileDescriptor"); 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (class_FileDescriptor == NULL) { 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto error; 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project class_FileDescriptor = (jclass)env->NewGlobalRef(class_FileDescriptor); 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 55269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes method_CredentialsInit 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project = env->GetMethodID(class_Credentials, "<init>", "(III)V"); 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (method_CredentialsInit == NULL) { 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto error; 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return jniRegisterNativeMethods(env, 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "android/net/LocalSocketImpl", gMethods, NELEM(gMethods)); 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecterror: 5633762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Error registering android.net.LocalSocketImpl"); 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 568