android_net_LocalSocketImpl.cpp revision 69a017bc1d1649350f830dfada5c6ed5eac0b770
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> 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android { 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID field_inboundFileDescriptors; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID field_outboundFileDescriptors; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jclass class_Credentials; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jclass class_FileDescriptor; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jmethodID method_CredentialsInit; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * private native FileDescriptor 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * create_native(boolean stream) 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * throws IOException; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jobject 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectsocket_create (JNIEnv *env, jobject object, jboolean stream) 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ret; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = socket(PF_LOCAL, stream ? SOCK_STREAM : SOCK_DGRAM, 0); 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret < 0) { 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, errno); 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return jniCreateFileDescriptor(env,ret); 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* private native void connectLocal(FileDescriptor fd, 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * String name, int namespace) throws IOException 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectsocket_connect_local(JNIEnv *env, jobject object, 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jobject fileDescriptor, jstring name, jint namespaceId) 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ret; 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char *nameUtf8; 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nameUtf8 = env->GetStringUTFChars(name, NULL); 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionOccurred() != NULL) { 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = socket_local_client_connect( 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd, 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nameUtf8, 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project namespaceId, 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SOCK_STREAM); 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ReleaseStringUTFChars(name, nameUtf8); 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret < 0) { 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, errno); 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define DEFAULT_BACKLOG 4 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes/* private native void bindLocal(FileDescriptor fd, String name, namespace) 10369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes * throws IOException; 10469a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes */ 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectsocket_bind_local (JNIEnv *env, jobject object, jobject fileDescriptor, 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jstring name, jint namespaceId) 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ret; 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char *nameUtf8; 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (name == NULL) { 11669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jniThrowNullPointerException(env, NULL); 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionOccurred() != NULL) { 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nameUtf8 = env->GetStringUTFChars(name, NULL); 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = socket_local_server_bind(fd, nameUtf8, namespaceId); 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ReleaseStringUTFChars(name, nameUtf8); 13069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret < 0) { 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, errno); 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* private native void listen_native(int fd, int backlog) throws IOException; */ 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectsocket_listen (JNIEnv *env, jobject object, jobject fileDescriptor, int backlog) 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ret; 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionOccurred() != NULL) { 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = listen(fd, backlog); 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret < 0) { 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, errno); 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* private native FileDescriptor 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** accept (FileDescriptor fd, LocalSocketImpl s) 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** throws IOException; 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project*/ 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jobject 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectsocket_accept (JNIEnv *env, jobject object, jobject fileDescriptor, jobject s) 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project union { 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct sockaddr address; 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct sockaddr_un un_address; 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } sa; 16969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ret; 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int retFD; 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project socklen_t addrlen; 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (s == NULL) { 17669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jniThrowNullPointerException(env, NULL); 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionOccurred() != NULL) { 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project addrlen = sizeof(sa); 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = accept(fd, &(sa.address), &addrlen); 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (ret < 0 && errno == EINTR); 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret < 0) { 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, errno); 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project retFD = ret; 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return jniCreateFileDescriptor(env, retFD); 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* private native void shutdown(FileDescriptor fd, boolean shutdownInput) */ 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectsocket_shutdown (JNIEnv *env, jobject object, jobject fileDescriptor, 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jboolean shutdownInput) 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ret; 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionOccurred() != NULL) { 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = shutdown(fd, shutdownInput ? SHUT_RD : SHUT_WR); 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret < 0) { 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, errno); 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic bool 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectjava_opt_to_real(int optID, int* opt, int* level) 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (optID) 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case 4098: 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *opt = SO_RCVBUF; 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *level = SOL_SOCKET; 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case 4097: 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *opt = SO_SNDBUF; 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *level = SOL_SOCKET; 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case 4102: 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *opt = SO_SNDTIMEO; 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *level = SOL_SOCKET; 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case 128: 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *opt = SO_LINGER; 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *level = SOL_SOCKET; 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case 1: 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *opt = TCP_NODELAY; 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *level = IPPROTO_TCP; 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case 4: 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *opt = SO_REUSEADDR; 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *level = SOL_SOCKET; 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectsocket_getOption(JNIEnv *env, jobject object, jobject fileDescriptor, int optID) 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ret, value; 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int opt, level; 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project socklen_t size = sizeof(int); 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!java_opt_to_real(optID, &opt, &level)) { 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, -1); 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionOccurred() != NULL) { 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (opt) 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case SO_LINGER: 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct linger lingr; 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size = sizeof(lingr); 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = getsockopt(fd, level, opt, &lingr, &size); 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!lingr.l_onoff) { 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project value = -1; 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project value = lingr.l_linger; 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = getsockopt(fd, level, opt, &value, &size); 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret != 0) { 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, errno); 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return value; 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void socket_setOption( 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project JNIEnv *env, jobject object, jobject fileDescriptor, int optID, 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint boolValue, jint intValue) { 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ret; 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int optname; 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int level; 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!java_opt_to_real(optID, &optname, &level)) { 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, -1); 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionOccurred() != NULL) { 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (optname) { 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case SO_LINGER: { 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * SO_LINGER is special because it needs to use a special 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * "linger" struct as well as use the incoming boolean 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * argument specially. 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct linger lingr; 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lingr.l_onoff = boolValue ? 1 : 0; // Force it to be 0 or 1. 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lingr.l_linger = intValue; 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = setsockopt(fd, level, optname, &lingr, sizeof(lingr)); 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case SO_SNDTIMEO: { 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * SO_TIMEOUT from the core library gets converted to 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * SO_SNDTIMEO, but the option is supposed to set both 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * send and receive timeouts. Note: The incoming timeout 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * value is in milliseconds. 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct timeval timeout; 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project timeout.tv_sec = intValue / 1000; 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project timeout.tv_usec = (intValue % 1000) * 1000; 34869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void *)&timeout, sizeof(timeout)); 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret == 0) { 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void *)&timeout, sizeof(timeout)); 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: { 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * In all other cases, the translated option level and 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * optname may be used directly for a call to setsockopt(). 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = setsockopt(fd, level, optname, &intValue, sizeof(intValue)); 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret != 0) { 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, errno); 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 37569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughesstatic jint socket_available (JNIEnv *env, jobject object, 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jobject fileDescriptor) 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionOccurred() != NULL) { 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)-1; 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if 1 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int avail; 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ret = ioctl(fd, FIONREAD, &avail); 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If this were a non-socket fd, there would be other cases to worry 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // about... 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret < 0) { 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, errno); 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint) 0; 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)avail; 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// there appears to be a bionic bug that prevents this version from working. 40169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ssize_t ret; 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct msghdr msg; 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(&msg, 0, sizeof(msg)); 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = recvmsg(fd, &msg, MSG_PEEK | MSG_DONTWAIT | MSG_NOSIGNAL); 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (ret < 0 && errno == EINTR); 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 41169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // MSG_PEEK returns 0 on EOF and EWOULDBLOCK on none available 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret < 0 && errno == EWOULDBLOCK) { 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } if (ret < 0) { 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, errno); 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)ret; 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void socket_close (JNIEnv *env, jobject object, jobject fileDescriptor) 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int err; 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fileDescriptor == NULL) { 43069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jniThrowNullPointerException(env, NULL); 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionOccurred() != NULL) { 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = close(fd); 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (err < 0 && errno == EINTR); 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err < 0) { 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, errno); 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 45169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes * Processes ancillary data, handling only 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * SCM_RIGHTS. Creates appropriate objects and sets appropriate 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * fields in the LocalSocketImpl object. Returns 0 on success 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * or -1 if an exception was thrown. 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int socket_process_cmsg(JNIEnv *env, jobject thisJ, struct msghdr * pMsg) 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct cmsghdr *cmsgptr; 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 46069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes for (cmsgptr = CMSG_FIRSTHDR(pMsg); 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(pMsg, cmsgptr)) { 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cmsgptr->cmsg_level != SOL_SOCKET) { 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cmsgptr->cmsg_type == SCM_RIGHTS) { 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int *pDescriptors = (int *)CMSG_DATA(cmsgptr); 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jobjectArray fdArray; 47069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes int count 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project = ((cmsgptr->cmsg_len - CMSG_LEN(0)) / sizeof(int)); 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count < 0) { 47469a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jniThrowException(env, "java/io/IOException", 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "invalid cmsg length"); 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fdArray = env->NewObjectArray(count, class_FileDescriptor, NULL); 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fdArray == NULL) { 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 48569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jobject fdObject 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project = jniCreateFileDescriptor(env, pDescriptors[i]); 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionOccurred() != NULL) { 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetObjectArrayElement(fdArray, i, fdObject); 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionOccurred() != NULL) { 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetObjectField(thisJ, field_inboundFileDescriptors, fdArray); 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionOccurred() != NULL) { 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Reads data from a socket into buf, processing any ancillary data 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and adding it to thisJ. 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the length of normal data read, or -1 if an exception has 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * been thrown in this function. 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 51769a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughesstatic ssize_t socket_read_all(JNIEnv *env, jobject thisJ, int fd, 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void *buffer, size_t len) 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ssize_t ret; 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ssize_t bytesread = 0; 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct msghdr msg; 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct iovec iv; 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned char *buf = (unsigned char *)buffer; 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Enough buffer for a pile of fd's. We throw an exception if 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // this buffer is too small. 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct cmsghdr cmsgbuf[2*sizeof(cmsghdr) + 0x100]; 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(&msg, 0, sizeof(msg)); 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(&iv, 0, sizeof(iv)); 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project iv.iov_base = buf; 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project iv.iov_len = len; 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg.msg_iov = &iv; 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg.msg_iovlen = 1; 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg.msg_control = cmsgbuf; 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg.msg_controllen = sizeof(cmsgbuf); 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = recvmsg(fd, &msg, MSG_NOSIGNAL); 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (ret < 0 && errno == EINTR); 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret < 0 && errno == EPIPE) { 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Treat this as an end of stream 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret < 0) { 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, errno); 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((msg.msg_flags & (MSG_CTRUNC | MSG_OOB | MSG_ERRQUEUE)) != 0) { 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // To us, any of the above flags are a fatal error 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 55769a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jniThrowException(env, "java/io/IOException", 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unexpected error or truncation during recvmsg()"); 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret >= 0) { 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project socket_process_cmsg(env, thisJ, &msg); 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret; 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Writes all the data in the specified buffer to the specified socket. 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns 0 on success or -1 if an exception was thrown. 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int socket_write_all(JNIEnv *env, jobject object, int fd, 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void *buf, size_t len) 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ssize_t ret; 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct msghdr msg; 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned char *buffer = (unsigned char *)buf; 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(&msg, 0, sizeof(msg)); 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 58369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jobjectArray outboundFds 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project = (jobjectArray)env->GetObjectField( 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project object, field_outboundFileDescriptors); 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionOccurred() != NULL) { 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct cmsghdr *cmsg; 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int countFds = outboundFds == NULL ? 0 : env->GetArrayLength(outboundFds); 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fds[countFds]; 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char msgbuf[CMSG_SPACE(countFds)]; 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Add any pending outbound file descriptors to the message 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (outboundFds != NULL) { 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionOccurred() != NULL) { 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < countFds; i++) { 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jobject fdObject = env->GetObjectArrayElement(outboundFds, i); 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionOccurred() != NULL) { 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fds[i] = jniGetFDFromFileDescriptor(env, fdObject); 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionOccurred() != NULL) { 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // See "man cmsg" really 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg.msg_control = msgbuf; 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg.msg_controllen = sizeof msgbuf; 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cmsg = CMSG_FIRSTHDR(&msg); 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cmsg->cmsg_level = SOL_SOCKET; 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cmsg->cmsg_type = SCM_RIGHTS; 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cmsg->cmsg_len = CMSG_LEN(sizeof fds); 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memcpy(CMSG_DATA(cmsg), fds, sizeof fds); 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We only write our msg_control during the first write 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (len > 0) { 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct iovec iv; 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(&iv, 0, sizeof(iv)); 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project iv.iov_base = buffer; 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project iv.iov_len = len; 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg.msg_iov = &iv; 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg.msg_iovlen = 1; 63569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = sendmsg(fd, &msg, MSG_NOSIGNAL); 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (ret < 0 && errno == EINTR); 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret < 0) { 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, errno); 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buffer += ret; 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project len -= ret; 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Wipes out any msg_control too 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(&msg, 0, sizeof(msg)); 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint socket_read (JNIEnv *env, jobject object, jobject fileDescriptor) 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int err; 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fileDescriptor == NULL) { 66169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jniThrowNullPointerException(env, NULL); 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)-1; 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionOccurred() != NULL) { 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)0; 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned char buf; 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = socket_read_all(env, object, fd, &buf, 1); 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err < 0) { 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, errno); 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)0; 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err == 0) { 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // end of file 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)-1; 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)buf; 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 68869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughesstatic jint socket_readba (JNIEnv *env, jobject object, 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyteArray buffer, jint off, jint len, jobject fileDescriptor) 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyte* byteBuffer; 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ret; 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fileDescriptor == NULL || buffer == NULL) { 69669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jniThrowNullPointerException(env, NULL); 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)-1; 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (off < 0 || len < 0 || (off + len) > env->GetArrayLength(buffer)) { 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL); 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)-1; 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (len == 0) { 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // because socket_read_all returns 0 on EOF 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionOccurred() != NULL) { 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)-1; 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project byteBuffer = env->GetByteArrayElements(buffer, NULL); 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (NULL == byteBuffer) { 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // an exception will have been thrown 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint)-1; 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 72369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes ret = socket_read_all(env, object, 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd, byteBuffer + off, len); 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // A return of -1 above means an exception is pending 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ReleaseByteArrayElements(buffer, byteBuffer, 0); 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (jint) ((ret == 0) ? -1 : ret); 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 73369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughesstatic void socket_write (JNIEnv *env, jobject object, 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint b, jobject fileDescriptor) 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int err; 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fileDescriptor == NULL) { 74069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jniThrowNullPointerException(env, NULL); 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionOccurred() != NULL) { 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = socket_write_all(env, object, fd, &b, 1); 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // A return of -1 above means an exception is pending 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 75569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughesstatic void socket_writeba (JNIEnv *env, jobject object, 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyteArray buffer, jint off, jint len, jobject fileDescriptor) 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int err; 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyte* byteBuffer; 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fileDescriptor == NULL || buffer == NULL) { 76369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jniThrowNullPointerException(env, NULL); 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (off < 0 || len < 0 || (off + len) > env->GetArrayLength(buffer)) { 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL); 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionOccurred() != NULL) { 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project byteBuffer = env->GetByteArrayElements(buffer,NULL); 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (NULL == byteBuffer) { 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // an exception will have been thrown 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 78569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes err = socket_write_all(env, object, fd, 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project byteBuffer + off, len); 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // A return of -1 above means an exception is pending 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ReleaseByteArrayElements(buffer, byteBuffer, JNI_ABORT); 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 79369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughesstatic jobject socket_get_peer_credentials(JNIEnv *env, 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jobject object, jobject fileDescriptor) 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int err; 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fileDescriptor == NULL) { 80069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jniThrowNullPointerException(env, NULL); 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionOccurred() != NULL) { 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct ucred creds; 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(&creds, 0, sizeof(creds)); 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project socklen_t szCreds = sizeof(creds); 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 81569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes err = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds); 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err < 0) { 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, errno); 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (szCreds == 0) { 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 82669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes return env->NewObject(class_Credentials, method_CredentialsInit, 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project creds.pid, creds.uid, creds.gid); 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if 0 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//TODO change this to return an instance of LocalSocketAddress 83269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughesstatic jobject socket_getSockName(JNIEnv *env, 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jobject object, jobject fileDescriptor) 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int err; 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fileDescriptor == NULL) { 83969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes jniThrowNullPointerException(env, NULL); 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionOccurred() != NULL) { 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project union { 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct sockaddr address; 8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct sockaddr_un un_address; 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } sa; 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(&sa, 0, sizeof(sa)); 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project socklen_t namelen = sizeof(sa); 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = getsockname(fd, &(sa.address), &namelen); 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err < 0) { 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, errno); 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sa.address.sa_family != AF_UNIX) { 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We think we're an impl only for AF_UNIX, so this should never happen. 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowIOException(env, EINVAL); 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sa.un_address.sun_path[0] == '\0') { 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * JNI registration. 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gMethods[] = { 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* name, signature, funcPtr */ 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"getOption_native", "(Ljava/io/FileDescriptor;I)I", (void*)socket_getOption}, 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"setOption_native", "(Ljava/io/FileDescriptor;III)V", (void*)socket_setOption}, 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"create_native", "(Z)Ljava/io/FileDescriptor;", (void*)socket_create}, 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"connectLocal", "(Ljava/io/FileDescriptor;Ljava/lang/String;I)V", 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void*)socket_connect_local}, 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"bindLocal", "(Ljava/io/FileDescriptor;Ljava/lang/String;I)V", (void*)socket_bind_local}, 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"listen_native", "(Ljava/io/FileDescriptor;I)V", (void*)socket_listen}, 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"accept", "(Ljava/io/FileDescriptor;Landroid/net/LocalSocketImpl;)Ljava/io/FileDescriptor;", (void*)socket_accept}, 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"shutdown", "(Ljava/io/FileDescriptor;Z)V", (void*)socket_shutdown}, 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"available_native", "(Ljava/io/FileDescriptor;)I", (void*) socket_available}, 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"close_native", "(Ljava/io/FileDescriptor;)V", (void*) socket_close}, 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"read_native", "(Ljava/io/FileDescriptor;)I", (void*) socket_read}, 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"readba_native", "([BIILjava/io/FileDescriptor;)I", (void*) socket_readba}, 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"writeba_native", "([BIILjava/io/FileDescriptor;)V", (void*) socket_writeba}, 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"write_native", "(ILjava/io/FileDescriptor;)V", (void*) socket_write}, 90169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes {"getPeerCredentials_native", 90269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes "(Ljava/io/FileDescriptor;)Landroid/net/Credentials;", 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void*) socket_get_peer_credentials} 90469a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes //,{"getSockName_native", "(Ljava/io/FileDescriptor;)Ljava/lang/String;", 9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // (void *) socket_getSockName} 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_net_LocalSocketImpl(JNIEnv *env) 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jclass clazz; 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project clazz = env->FindClass("android/net/LocalSocketImpl"); 9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (clazz == NULL) { 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto error; 9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 91969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes field_inboundFileDescriptors = env->GetFieldID(clazz, 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "inboundFileDescriptors", "[Ljava/io/FileDescriptor;"); 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (field_inboundFileDescriptors == NULL) { 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto error; 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 92669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes field_outboundFileDescriptors = env->GetFieldID(clazz, 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "outboundFileDescriptors", "[Ljava/io/FileDescriptor;"); 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (field_outboundFileDescriptors == NULL) { 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto error; 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project class_Credentials = env->FindClass("android/net/Credentials"); 93469a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (class_Credentials == NULL) { 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto error; 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project class_Credentials = (jclass)env->NewGlobalRef(class_Credentials); 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project class_FileDescriptor = env->FindClass("java/io/FileDescriptor"); 9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (class_FileDescriptor == NULL) { 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto error; 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project class_FileDescriptor = (jclass)env->NewGlobalRef(class_FileDescriptor); 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 94969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes method_CredentialsInit 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project = env->GetMethodID(class_Credentials, "<init>", "(III)V"); 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (method_CredentialsInit == NULL) { 9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto error; 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return jniRegisterNativeMethods(env, 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "android/net/LocalSocketImpl", gMethods, NELEM(gMethods)); 9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecterror: 9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Error registering android.net.LocalSocketImpl"); 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 965