1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* 2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * you may not use this file except in compliance with the License. 6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * You may obtain a copy of the License at 7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * See the License for the specific language governing permissions and 14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * limitations under the License. 15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define LOG_TAG "mq" 18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <assert.h> 20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h> 21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <fcntl.h> 22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <pthread.h> 23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h> 24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h> 25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h> 26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/socket.h> 28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/types.h> 29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/un.h> 30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/uio.h> 31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/array.h> 33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/hashmap.h> 34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/selector.h> 35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "loghack.h" 37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "buffer.h" 38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Number of dead peers to remember. */ 40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define PEER_HISTORY (16) 41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttypedef struct sockaddr SocketAddress; 43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttypedef struct sockaddr_un UnixAddress; 44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Process/user/group ID. We don't use ucred directly because it's only 47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * available on Linux. 48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttypedef struct { 50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pid_t pid; 51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project uid_t uid; 52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project gid_t gid; 53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} Credentials; 54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Listens for bytes coming from remote peers. */ 56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttypedef void BytesListener(Credentials credentials, char* bytes, size_t size); 57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Listens for the deaths of remote peers. */ 59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttypedef void DeathListener(pid_t pid); 60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Types of packets. */ 62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttypedef enum { 63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** Request for a connection to another peer. */ 64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project CONNECTION_REQUEST, 65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** A connection to another peer. */ 67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project CONNECTION, 68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** Reports a failed connection attempt. */ 70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project CONNECTION_ERROR, 71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** A generic packet of bytes. */ 73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project BYTES, 74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} PacketType; 75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttypedef enum { 77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** Reading a packet header. */ 78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project READING_HEADER, 79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** Waiting for a connection from the master. */ 81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ACCEPTING_CONNECTION, 82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** Reading bytes. */ 84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project READING_BYTES, 85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} InputState; 86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** A packet header. */ 88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// TODO: Use custom headers for master->peer, peer->master, peer->peer. 89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttypedef struct { 90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project PacketType type; 91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project union { 92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** Packet size. Used for BYTES. */ 93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project size_t size; 94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** Credentials. Used for CONNECTION and CONNECTION_REQUEST. */ 96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Credentials credentials; 97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project }; 98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} Header; 99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** A packet which will be sent to a peer. */ 101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttypedef struct OutgoingPacket OutgoingPacket; 102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct OutgoingPacket { 103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** Packet header. */ 104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Header header; 105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project union { 107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** Connection to peer. Used with CONNECTION. */ 108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int socket; 109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** Buffer of bytes. Used with BYTES. */ 111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Buffer* bytes; 112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project }; 113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** Frees all resources associated with this packet. */ 115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project void (*free)(OutgoingPacket* packet); 116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** Optional context. */ 118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project void* context; 119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** Next packet in the queue. */ 121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project OutgoingPacket* nextPacket; 122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}; 123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Represents a remote peer. */ 125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttypedef struct PeerProxy PeerProxy; 126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Local peer state. You typically have one peer per process. */ 128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttypedef struct { 129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** This peer's PID. */ 130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pid_t pid; 131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** 133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Map from pid to peer proxy. The peer has a peer proxy for each remote 134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * peer it's connected to. 135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Acquire mutex before use. 137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Hashmap* peerProxies; 139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** Manages I/O. */ 141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Selector* selector; 142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** Used to synchronize operations with the selector thread. */ 144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pthread_mutex_t mutex; 145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** Is this peer the master? */ 147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bool master; 148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** Peer proxy for the master. */ 150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project PeerProxy* masterProxy; 151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** Listens for packets from remote peers. */ 153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project BytesListener* onBytes; 154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** Listens for deaths of remote peers. */ 156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project DeathListener* onDeath; 157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** Keeps track of recently dead peers. Requires mutex. */ 159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pid_t deadPeers[PEER_HISTORY]; 160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project size_t deadPeerCursor; 161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} Peer; 162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct PeerProxy { 164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** Credentials of the remote process. */ 165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Credentials credentials; 166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** Keeps track of data coming in from the remote peer. */ 168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project InputState inputState; 169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Buffer* inputBuffer; 170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project PeerProxy* connecting; 171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** File descriptor for this peer. */ 173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project SelectableFd* fd; 174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** 176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Queue of packets to be written out to the remote peer. 177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Requires mutex. 179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // TODO: Limit queue length. 181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project OutgoingPacket* currentPacket; 182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project OutgoingPacket* lastPacket; 183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** Used to write outgoing header. */ 185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Buffer outgoingHeader; 186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** True if this is the master's proxy. */ 188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bool master; 189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** Reference back to the local peer. */ 191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Peer* peer; 192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /** 194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Used in master only. Maps this peer proxy to other peer proxies to 195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * which the peer has been connected to. Maps pid to PeerProxy. Helps 196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * keep track of which connections we've sent to whom. 197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Hashmap* connections; 199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}; 200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Server socket path. */ 202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic const char* MASTER_PATH = "/master.peer"; 203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Credentials of the master peer. */ 205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic const Credentials MASTER_CREDENTIALS = {0, 0, 0}; 206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Creates a peer proxy and adds it to the peer proxy map. */ 208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic PeerProxy* peerProxyCreate(Peer* peer, Credentials credentials); 209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Sets the non-blocking flag on a descriptor. */ 211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void setNonBlocking(int fd) { 212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int flags; 213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if ((flags = fcntl(fd, F_GETFL, 0)) < 0) { 214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("fcntl() error: %s", strerror(errno)); 215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) { 217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("fcntl() error: %s", strerror(errno)); 218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Closes a fd and logs a warning if the close fails. */ 222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void closeWithWarning(int fd) { 223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int result = close(fd); 224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (result == -1) { 225ae8b56c0d17a97aff0b98e6405c7cc9811bbbc3dSteve Block ALOGW("close() error: %s", strerror(errno)); 226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Hashes pid_t keys. */ 230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int pidHash(void* key) { 231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pid_t* pid = (pid_t*) key; 232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return (int) (*pid); 233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Compares pid_t keys. */ 236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic bool pidEquals(void* keyA, void* keyB) { 237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pid_t* a = (pid_t*) keyA; 238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pid_t* b = (pid_t*) keyB; 239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return *a == *b; 240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Gets the master address. Not thread safe. */ 243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic UnixAddress* getMasterAddress() { 244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project static UnixAddress masterAddress; 245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project static bool initialized = false; 246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (initialized == false) { 247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project masterAddress.sun_family = AF_LOCAL; 248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project strcpy(masterAddress.sun_path, MASTER_PATH); 249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project initialized = true; 250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return &masterAddress; 252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Gets exclusive access to the peer for this thread. */ 255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void peerLock(Peer* peer) { 256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pthread_mutex_lock(&peer->mutex); 257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Releases exclusive access to the peer. */ 260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void peerUnlock(Peer* peer) { 261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pthread_mutex_unlock(&peer->mutex); 262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Frees a simple, i.e. header-only, outgoing packet. */ 265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void outgoingPacketFree(OutgoingPacket* packet) { 2668d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("Freeing outgoing packet."); 267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project free(packet); 268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Prepare to read a new packet from the peer. 272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void peerProxyExpectHeader(PeerProxy* peerProxy) { 274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxy->inputState = READING_HEADER; 275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bufferPrepareForRead(peerProxy->inputBuffer, sizeof(Header)); 276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Sets up the buffer for the outgoing header. */ 279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void peerProxyPrepareOutgoingHeader(PeerProxy* peerProxy) { 280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxy->outgoingHeader.data 281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project = (char*) &(peerProxy->currentPacket->header); 282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxy->outgoingHeader.size = sizeof(Header); 283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bufferPrepareForWrite(&peerProxy->outgoingHeader); 284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Adds a packet to the end of the queue. Callers must have the mutex. */ 287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void peerProxyEnqueueOutgoingPacket(PeerProxy* peerProxy, 288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project OutgoingPacket* newPacket) { 289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project newPacket->nextPacket = NULL; // Just in case. 290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (peerProxy->currentPacket == NULL) { 291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // The queue is empty. 292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxy->currentPacket = newPacket; 293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxy->lastPacket = newPacket; 294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyPrepareOutgoingHeader(peerProxy); 296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxy->lastPacket->nextPacket = newPacket; 298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Takes the peer lock and enqueues the given packet. */ 302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void peerProxyLockAndEnqueueOutgoingPacket(PeerProxy* peerProxy, 303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project OutgoingPacket* newPacket) { 304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Peer* peer = peerProxy->peer; 305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerLock(peer); 306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyEnqueueOutgoingPacket(peerProxy, newPacket); 307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerUnlock(peer); 308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Frees current packet and moves to the next one. Returns true if there is 312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * a next packet or false if the queue is empty. 313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic bool peerProxyNextPacket(PeerProxy* peerProxy) { 315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Peer* peer = peerProxy->peer; 316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerLock(peer); 317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project OutgoingPacket* current = peerProxy->currentPacket; 319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (current == NULL) { 321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // The queue is already empty. 322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerUnlock(peer); 323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return false; 324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project OutgoingPacket* next = current->nextPacket; 327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxy->currentPacket = next; 328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project current->nextPacket = NULL; 329dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project current->free(current); 330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (next == NULL) { 331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // The queue is empty. 332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxy->lastPacket = NULL; 333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerUnlock(peer); 334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return false; 335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerUnlock(peer); 337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyPrepareOutgoingHeader(peerProxy); 338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // TODO: Start writing next packet? It would reduce the number of 340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // system calls, but we could also starve other peers. 341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return true; 342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 345dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Checks whether a peer died recently. 347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic bool peerIsDead(Peer* peer, pid_t pid) { 349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project size_t i; 350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project for (i = 0; i < PEER_HISTORY; i++) { 351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pid_t deadPeer = peer->deadPeers[i]; 352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (deadPeer == 0) { 353dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return false; 354dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 355dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (deadPeer == pid) { 356dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return true; 357dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 359dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return false; 360dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 361dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 362dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 363dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Cleans up connection information. 364dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic bool peerProxyRemoveConnection(void* key, void* value, void* context) { 366dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project PeerProxy* deadPeer = (PeerProxy*) context; 367dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project PeerProxy* otherPeer = (PeerProxy*) value; 368dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project hashmapRemove(otherPeer->connections, &(deadPeer->credentials.pid)); 369dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return true; 370dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 371dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 373dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Called when the peer dies. 374dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 375dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void peerProxyKill(PeerProxy* peerProxy, bool errnoIsSet) { 376dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (errnoIsSet) { 377fe71a61e5b0cb666675900d206251a7c18ed944bSteve Block ALOGI("Peer %d died. errno: %s", peerProxy->credentials.pid, 378dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project strerror(errno)); 379dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 380fe71a61e5b0cb666675900d206251a7c18ed944bSteve Block ALOGI("Peer %d died.", peerProxy->credentials.pid); 381dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 382dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 383dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // If we lost the master, we're up a creek. We can't let this happen. 384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (peerProxy->master) { 385dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("Lost connection to master."); 386dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 387dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 388dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Peer* localPeer = peerProxy->peer; 389dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pid_t pid = peerProxy->credentials.pid; 390dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 391dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerLock(localPeer); 392dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 393dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Remember for awhile that the peer died. 394dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project localPeer->deadPeers[localPeer->deadPeerCursor] 395dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project = peerProxy->credentials.pid; 396dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project localPeer->deadPeerCursor++; 397dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (localPeer->deadPeerCursor == PEER_HISTORY) { 398dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project localPeer->deadPeerCursor = 0; 399dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 400dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 401dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Remove from peer map. 402dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project hashmapRemove(localPeer->peerProxies, &pid); 403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 404dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // External threads can no longer get to this peer proxy, so we don't 405dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // need the lock anymore. 406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerUnlock(localPeer); 407dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 408dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Remove the fd from the selector. 409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (peerProxy->fd != NULL) { 410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxy->fd->remove = true; 411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 413dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Clear outgoing packet queue. 414dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while (peerProxyNextPacket(peerProxy)) {} 415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 416dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bufferFree(peerProxy->inputBuffer); 417dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 418dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // This only applies to the master. 419dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (peerProxy->connections != NULL) { 420dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // We can't leave these other maps pointing to freed memory. 421dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project hashmapForEach(peerProxy->connections, &peerProxyRemoveConnection, 422dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxy); 423dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project hashmapFree(peerProxy->connections); 424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 425dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Invoke death listener. 427dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project localPeer->onDeath(pid); 428dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 429dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Free the peer proxy itself. 430dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project free(peerProxy); 431dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 432dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 433dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void peerProxyHandleError(PeerProxy* peerProxy, char* functionName) { 434dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (errno == EINTR) { 435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Log interruptions but otherwise ignore them. 436ae8b56c0d17a97aff0b98e6405c7cc9811bbbc3dSteve Block ALOGW("%s() interrupted.", functionName); 437dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else if (errno == EAGAIN) { 4388d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("EWOULDBLOCK"); 439dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Ignore. 440dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 441ae8b56c0d17a97aff0b98e6405c7cc9811bbbc3dSteve Block ALOGW("Error returned by %s().", functionName); 442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyKill(peerProxy, true); 443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 445dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 447dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Buffers output sent to a peer. May be called multiple times until the entire 448dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * buffer is filled. Returns true when the buffer is empty. 449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic bool peerProxyWriteFromBuffer(PeerProxy* peerProxy, Buffer* outgoing) { 451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ssize_t size = bufferWrite(outgoing, peerProxy->fd->fd); 452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (size < 0) { 453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyHandleError(peerProxy, "write"); 454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return false; 455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return bufferWriteComplete(outgoing); 457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Writes packet bytes to peer. */ 461dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void peerProxyWriteBytes(PeerProxy* peerProxy) { 462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Buffer* buffer = peerProxy->currentPacket->bytes; 463dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (peerProxyWriteFromBuffer(peerProxy, buffer)) { 4648d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("Bytes written."); 465dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyNextPacket(peerProxy); 466dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 467dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 469dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Sends a socket to the peer. */ 470dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void peerProxyWriteConnection(PeerProxy* peerProxy) { 471dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int socket = peerProxy->currentPacket->socket; 472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 473dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Why does sending and receiving fds have to be such a PITA? 474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct msghdr msg; 475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct iovec iov[1]; 476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project union { 478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct cmsghdr cm; 479dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char control[CMSG_SPACE(sizeof(int))]; 480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } control_un; 481dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct cmsghdr *cmptr; 483dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 484dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project msg.msg_control = control_un.control; 485dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project msg.msg_controllen = sizeof(control_un.control); 486dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project cmptr = CMSG_FIRSTHDR(&msg); 487dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project cmptr->cmsg_len = CMSG_LEN(sizeof(int)); 488dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project cmptr->cmsg_level = SOL_SOCKET; 489dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project cmptr->cmsg_type = SCM_RIGHTS; 490dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 491dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Store the socket in the message. 492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *((int *) CMSG_DATA(cmptr)) = peerProxy->currentPacket->socket; 493dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 494dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project msg.msg_name = NULL; 495dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project msg.msg_namelen = 0; 496dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project iov[0].iov_base = ""; 497dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project iov[0].iov_len = 1; 498dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project msg.msg_iov = iov; 499dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project msg.msg_iovlen = 1; 500dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 501dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ssize_t result = sendmsg(peerProxy->fd->fd, &msg, 0); 502dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 503dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (result < 0) { 504dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyHandleError(peerProxy, "sendmsg"); 505dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 506dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Success. Queue up the next packet. 507dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyNextPacket(peerProxy); 508dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 509dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 510dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 511dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 512dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 513dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Writes some outgoing data. 514dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 515dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void peerProxyWrite(SelectableFd* fd) { 516dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // TODO: Try to write header and body with one system call. 517dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 518dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project PeerProxy* peerProxy = (PeerProxy*) fd->data; 519dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project OutgoingPacket* current = peerProxy->currentPacket; 520dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 521dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (current == NULL) { 522dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // We have nothing left to write. 523dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return; 524dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 525dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 526dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Write the header. 527dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Buffer* outgoingHeader = &peerProxy->outgoingHeader; 528dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bool headerWritten = bufferWriteComplete(outgoingHeader); 529dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (!headerWritten) { 5308d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("Writing header..."); 531dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project headerWritten = peerProxyWriteFromBuffer(peerProxy, outgoingHeader); 532dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (headerWritten) { 5338d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("Header written."); 534dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 535dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 536dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 537dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Write body. 538dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (headerWritten) { 539dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project PacketType type = current->header.type; 540dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project switch (type) { 541dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case CONNECTION: 542dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyWriteConnection(peerProxy); 543dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 544dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case BYTES: 545dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyWriteBytes(peerProxy); 546dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 547dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case CONNECTION_REQUEST: 548dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case CONNECTION_ERROR: 549dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // These packets consist solely of a header. 550dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyNextPacket(peerProxy); 551dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 552dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project default: 553dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("Unknown packet type: %d", type); 554dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 555dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 556dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 557dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 558dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 559dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Sets up a peer proxy's fd before we try to select() it. 560dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 561dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void peerProxyBeforeSelect(SelectableFd* fd) { 5628d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("Before select..."); 563dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 564dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project PeerProxy* peerProxy = (PeerProxy*) fd->data; 565dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 566dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerLock(peerProxy->peer); 567dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bool hasPackets = peerProxy->currentPacket != NULL; 568dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerUnlock(peerProxy->peer); 569dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 570dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (hasPackets) { 5718d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("Packets found. Setting onWritable()."); 572dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 573dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd->onWritable = &peerProxyWrite; 574dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 575dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // We have nothing to write. 576dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd->onWritable = NULL; 577dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 578dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 579dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 580dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Prepare to read bytes from the peer. */ 581dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void peerProxyExpectBytes(PeerProxy* peerProxy, Header* header) { 5828d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("Expecting %d bytes.", header->size); 5838d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block 5848d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block peerProxy->inputState = READING_BYTES; 585dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (bufferPrepareForRead(peerProxy->inputBuffer, header->size) == -1) { 586ae8b56c0d17a97aff0b98e6405c7cc9811bbbc3dSteve Block ALOGW("Couldn't allocate memory for incoming data. Size: %u", 587dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project (unsigned int) header->size); 588dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 589dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // TODO: Ignore the packet and log a warning? 590dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyKill(peerProxy, false); 591dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 592dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 593dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 594dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 595dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Gets a peer proxy for the given ID. Creates a peer proxy if necessary. 596dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Sends a connection request to the master if desired. 597dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 598dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Returns NULL if an error occurs. Sets errno to EHOSTDOWN if the peer died 599dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * or ENOMEM if memory couldn't be allocated. 600dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 601dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic PeerProxy* peerProxyGetOrCreate(Peer* peer, pid_t pid, 602dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bool requestConnection) { 603dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (pid == peer->pid) { 604dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project errno = EINVAL; 605dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return NULL; 606dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 607dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 608dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (peerIsDead(peer, pid)) { 609dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project errno = EHOSTDOWN; 610dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return NULL; 611dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 612dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 613dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project PeerProxy* peerProxy = hashmapGet(peer->peerProxies, &pid); 614dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (peerProxy != NULL) { 615dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return peerProxy; 616dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 617dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 618dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // If this is the master peer, we already know about all peers. 619dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (peer->master) { 620dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project errno = EHOSTDOWN; 621dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return NULL; 622dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 623dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 624dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Try to create a peer proxy. 625dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Credentials credentials; 626dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project credentials.pid = pid; 627dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 628dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Fake gid and uid until we have the real thing. The real creds are 629dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // filled in by masterProxyExpectConnection(). These fake creds will 630dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // never be exposed to the user. 631dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project credentials.uid = 0; 632dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project credentials.gid = 0; 633dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 634dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Make sure we can allocate the connection request packet. 635dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project OutgoingPacket* packet = NULL; 636dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (requestConnection) { 637dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet = calloc(1, sizeof(OutgoingPacket)); 638dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (packet == NULL) { 639dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project errno = ENOMEM; 640dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return NULL; 641dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 642dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 643dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet->header.type = CONNECTION_REQUEST; 644dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet->header.credentials = credentials; 645dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet->free = &outgoingPacketFree; 646dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 647dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 648dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxy = peerProxyCreate(peer, credentials); 649dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (peerProxy == NULL) { 650dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project free(packet); 651dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project errno = ENOMEM; 652dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return NULL; 653dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 654dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Send a connection request to the master. 655dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (requestConnection) { 656dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project PeerProxy* masterProxy = peer->masterProxy; 657dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyEnqueueOutgoingPacket(masterProxy, packet); 658dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 659dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 660dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return peerProxy; 661dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 662dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 663dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 664dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 665dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Switches the master peer proxy into a state where it's waiting for a 666dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * connection from the master. 667dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 668dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void masterProxyExpectConnection(PeerProxy* masterProxy, 669dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Header* header) { 670dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // TODO: Restructure things so we don't need this check. 671dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Verify that this really is the master. 672dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (!masterProxy->master) { 673ae8b56c0d17a97aff0b98e6405c7cc9811bbbc3dSteve Block ALOGW("Non-master process %d tried to send us a connection.", 674dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project masterProxy->credentials.pid); 675dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Kill off the evil peer. 676dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyKill(masterProxy, false); 677dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return; 678dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 679dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 680dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project masterProxy->inputState = ACCEPTING_CONNECTION; 681dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Peer* localPeer = masterProxy->peer; 682dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 683dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Create a peer proxy so we have somewhere to stash the creds. 684dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // See if we already have a proxy set up. 685dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pid_t pid = header->credentials.pid; 686dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerLock(localPeer); 687dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project PeerProxy* peerProxy = peerProxyGetOrCreate(localPeer, pid, false); 688dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (peerProxy == NULL) { 689ae8b56c0d17a97aff0b98e6405c7cc9811bbbc3dSteve Block ALOGW("Peer proxy creation failed: %s", strerror(errno)); 690dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 691dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Fill in full credentials. 692dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxy->credentials = header->credentials; 693dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 694dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerUnlock(localPeer); 695dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 696dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Keep track of which peer proxy we're accepting a connection for. 697dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project masterProxy->connecting = peerProxy; 698dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 699dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 700dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 701dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Reads input from a peer process. 702dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 703dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void peerProxyRead(SelectableFd* fd); 704dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 705dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Sets up fd callbacks. */ 706dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void peerProxySetFd(PeerProxy* peerProxy, SelectableFd* fd) { 707dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxy->fd = fd; 708dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd->data = peerProxy; 709dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd->onReadable = &peerProxyRead; 710dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd->beforeSelect = &peerProxyBeforeSelect; 711dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 712dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Make the socket non-blocking. 713dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project setNonBlocking(fd->fd); 714dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 715dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 716dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 717dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Accepts a connection sent by the master proxy. 718dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 719dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void masterProxyAcceptConnection(PeerProxy* masterProxy) { 720dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct msghdr msg; 721dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct iovec iov[1]; 722dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ssize_t size; 723dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char ignored; 724dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int incomingFd; 725dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 726dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // TODO: Reuse code which writes the connection. Who the heck designed 727dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // this API anyway? 728dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project union { 729dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct cmsghdr cm; 730dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char control[CMSG_SPACE(sizeof(int))]; 731dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } control_un; 732dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct cmsghdr *cmptr; 733dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project msg.msg_control = control_un.control; 734dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project msg.msg_controllen = sizeof(control_un.control); 735dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 736dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project msg.msg_name = NULL; 737dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project msg.msg_namelen = 0; 738dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 739dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // We sent 1 byte of data so we can detect EOF. 740dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project iov[0].iov_base = &ignored; 741dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project iov[0].iov_len = 1; 742dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project msg.msg_iov = iov; 743dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project msg.msg_iovlen = 1; 744dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 745dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project size = recvmsg(masterProxy->fd->fd, &msg, 0); 746dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (size < 0) { 747dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (errno == EINTR) { 748dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Log interruptions but otherwise ignore them. 749ae8b56c0d17a97aff0b98e6405c7cc9811bbbc3dSteve Block ALOGW("recvmsg() interrupted."); 750dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return; 751dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else if (errno == EAGAIN) { 752dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Keep waiting for the connection. 753dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return; 754dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 755dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("Error reading connection from master: %s", 756dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project strerror(errno)); 757dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 758dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else if (size == 0) { 759dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // EOF. 760dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("Received EOF from master."); 761dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 762dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 763dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Extract fd from message. 764dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if ((cmptr = CMSG_FIRSTHDR(&msg)) != NULL 765dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project && cmptr->cmsg_len == CMSG_LEN(sizeof(int))) { 766dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (cmptr->cmsg_level != SOL_SOCKET) { 767dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("Expected SOL_SOCKET."); 768dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 769dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (cmptr->cmsg_type != SCM_RIGHTS) { 770dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("Expected SCM_RIGHTS."); 771dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 772dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project incomingFd = *((int*) CMSG_DATA(cmptr)); 773dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 774dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("Expected fd."); 775dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 776dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 777dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // The peer proxy this connection is for. 778dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project PeerProxy* peerProxy = masterProxy->connecting; 779dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (peerProxy == NULL) { 780ae8b56c0d17a97aff0b98e6405c7cc9811bbbc3dSteve Block ALOGW("Received connection for unknown peer."); 781dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project closeWithWarning(incomingFd); 782dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 783dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Peer* peer = masterProxy->peer; 784dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 785dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project SelectableFd* selectableFd = selectorAdd(peer->selector, incomingFd); 786dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (selectableFd == NULL) { 787ae8b56c0d17a97aff0b98e6405c7cc9811bbbc3dSteve Block ALOGW("Error adding fd to selector for %d.", 788dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxy->credentials.pid); 789dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project closeWithWarning(incomingFd); 790dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyKill(peerProxy, false); 791dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 792dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 793dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxySetFd(peerProxy, selectableFd); 794dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 795dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 796dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyExpectHeader(masterProxy); 797dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 798dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 799dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 800dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Frees an outgoing packet containing a connection. 801dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 802dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void outgoingPacketFreeSocket(OutgoingPacket* packet) { 803dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project closeWithWarning(packet->socket); 804dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project outgoingPacketFree(packet); 805dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 806dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 807dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 808dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Connects two known peers. 809dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 810dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void masterConnectPeers(PeerProxy* peerA, PeerProxy* peerB) { 811dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int sockets[2]; 812dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int result = socketpair(AF_LOCAL, SOCK_STREAM, 0, sockets); 813dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (result == -1) { 814ae8b56c0d17a97aff0b98e6405c7cc9811bbbc3dSteve Block ALOGW("socketpair() error: %s", strerror(errno)); 815dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // TODO: Send CONNECTION_FAILED packets to peers. 816dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return; 817dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 818dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 819dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project OutgoingPacket* packetA = calloc(1, sizeof(OutgoingPacket)); 820dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project OutgoingPacket* packetB = calloc(1, sizeof(OutgoingPacket)); 821dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (packetA == NULL || packetB == NULL) { 822dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project free(packetA); 823dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project free(packetB); 824ae8b56c0d17a97aff0b98e6405c7cc9811bbbc3dSteve Block ALOGW("malloc() error. Failed to tell process %d that process %d is" 825dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project " dead.", peerA->credentials.pid, peerB->credentials.pid); 826dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return; 827dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 828dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 829dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packetA->header.type = CONNECTION; 830dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packetB->header.type = CONNECTION; 831dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 832dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packetA->header.credentials = peerB->credentials; 833dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packetB->header.credentials = peerA->credentials; 834dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 835dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packetA->socket = sockets[0]; 836dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packetB->socket = sockets[1]; 837dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 838dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packetA->free = &outgoingPacketFreeSocket; 839dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packetB->free = &outgoingPacketFreeSocket; 840dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 841dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerLock(peerA->peer); 842dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyEnqueueOutgoingPacket(peerA, packetA); 843dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyEnqueueOutgoingPacket(peerB, packetB); 844dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerUnlock(peerA->peer); 845dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 846dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 847dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 848dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Informs a peer that the peer they're trying to connect to couldn't be 849dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * found. 850dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 851dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void masterReportConnectionError(PeerProxy* peerProxy, 852dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Credentials credentials) { 853dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project OutgoingPacket* packet = calloc(1, sizeof(OutgoingPacket)); 854dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (packet == NULL) { 855ae8b56c0d17a97aff0b98e6405c7cc9811bbbc3dSteve Block ALOGW("malloc() error. Failed to tell process %d that process %d is" 856dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project " dead.", peerProxy->credentials.pid, credentials.pid); 857dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return; 858dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 859dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 860dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet->header.type = CONNECTION_ERROR; 861dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet->header.credentials = credentials; 862dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet->free = &outgoingPacketFree; 863dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 864dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyLockAndEnqueueOutgoingPacket(peerProxy, packet); 865dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 866dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 867dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 868dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Handles a request to be connected to another peer. 869dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 870dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void masterHandleConnectionRequest(PeerProxy* peerProxy, 871dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Header* header) { 872dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Peer* master = peerProxy->peer; 873dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pid_t targetPid = header->credentials.pid; 874dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (!hashmapContainsKey(peerProxy->connections, &targetPid)) { 875dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // We haven't connected these peers yet. 876dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project PeerProxy* targetPeer 877dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project = (PeerProxy*) hashmapGet(master->peerProxies, &targetPid); 878dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (targetPeer == NULL) { 879dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Unknown process. 880dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project masterReportConnectionError(peerProxy, header->credentials); 881dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 882dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project masterConnectPeers(peerProxy, targetPeer); 883dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 884dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 885dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 886dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // This packet is complete. Get ready for the next one. 887dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyExpectHeader(peerProxy); 888dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 889dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 890dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 891dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * The master told us this peer is dead. 892dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 893dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void masterProxyHandleConnectionError(PeerProxy* masterProxy, 894dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Header* header) { 895dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Peer* peer = masterProxy->peer; 896dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 897dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Look up the peer proxy. 898dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pid_t pid = header->credentials.pid; 899dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project PeerProxy* peerProxy = NULL; 900dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerLock(peer); 901dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxy = hashmapGet(peer->peerProxies, &pid); 902dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerUnlock(peer); 903dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 904dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (peerProxy != NULL) { 905fe71a61e5b0cb666675900d206251a7c18ed944bSteve Block ALOGI("Couldn't connect to %d.", pid); 906dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyKill(peerProxy, false); 907dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 908ae8b56c0d17a97aff0b98e6405c7cc9811bbbc3dSteve Block ALOGW("Peer proxy for %d not found. This shouldn't happen.", pid); 909dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 910dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 911dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyExpectHeader(masterProxy); 912dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 913dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 914dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 915dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Handles a packet header. 916dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 917dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void peerProxyHandleHeader(PeerProxy* peerProxy, Header* header) { 918dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project switch (header->type) { 919dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case CONNECTION_REQUEST: 920dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project masterHandleConnectionRequest(peerProxy, header); 921dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 922dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case CONNECTION: 923dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project masterProxyExpectConnection(peerProxy, header); 924dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 925dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case CONNECTION_ERROR: 926dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project masterProxyHandleConnectionError(peerProxy, header); 927dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 928dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case BYTES: 929dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyExpectBytes(peerProxy, header); 930dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 931dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project default: 932ae8b56c0d17a97aff0b98e6405c7cc9811bbbc3dSteve Block ALOGW("Invalid packet type from %d: %d", peerProxy->credentials.pid, 933dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project header->type); 934dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyKill(peerProxy, false); 935dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 936dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 937dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 938dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 939dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Buffers input sent by peer. May be called multiple times until the entire 940dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * buffer is filled. Returns true when the buffer is full. 941dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 942dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic bool peerProxyBufferInput(PeerProxy* peerProxy) { 943dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Buffer* in = peerProxy->inputBuffer; 944dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ssize_t size = bufferRead(in, peerProxy->fd->fd); 945dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (size < 0) { 946dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyHandleError(peerProxy, "read"); 947dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return false; 948dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else if (size == 0) { 949dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // EOF. 950fe71a61e5b0cb666675900d206251a7c18ed944bSteve Block ALOGI("EOF"); 951dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyKill(peerProxy, false); 952dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return false; 953dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else if (bufferReadComplete(in)) { 954dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // We're done! 955dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return true; 956dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 957dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Continue reading. 958dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return false; 959dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 960dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 961dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 962dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 963dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Reads input from a peer process. 964dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 965dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void peerProxyRead(SelectableFd* fd) { 9668d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("Reading..."); 967dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project PeerProxy* peerProxy = (PeerProxy*) fd->data; 968dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int state = peerProxy->inputState; 969dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Buffer* in = peerProxy->inputBuffer; 970dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project switch (state) { 971dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case READING_HEADER: 972dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (peerProxyBufferInput(peerProxy)) { 9738d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("Header read."); 974dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // We've read the complete header. 975dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Header* header = (Header*) in->data; 976dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyHandleHeader(peerProxy, header); 977dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 978dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 979dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case READING_BYTES: 9808d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("Reading bytes..."); 981dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (peerProxyBufferInput(peerProxy)) { 9828d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("Bytes read."); 983dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // We have the complete packet. Notify bytes listener. 984dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxy->peer->onBytes(peerProxy->credentials, 985dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in->data, in->size); 986dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 987dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Get ready for the next packet. 988dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyExpectHeader(peerProxy); 989dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 990dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 991dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case ACCEPTING_CONNECTION: 992dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project masterProxyAcceptConnection(peerProxy); 993dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 994dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project default: 995dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("Unknown state: %d", state); 996dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 997dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 998dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 999dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic PeerProxy* peerProxyCreate(Peer* peer, Credentials credentials) { 1000dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project PeerProxy* peerProxy = calloc(1, sizeof(PeerProxy)); 1001dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (peerProxy == NULL) { 1002dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return NULL; 1003dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1004dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1005dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxy->inputBuffer = bufferCreate(sizeof(Header)); 1006dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (peerProxy->inputBuffer == NULL) { 1007dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project free(peerProxy); 1008dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return NULL; 1009dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1010dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1011dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxy->peer = peer; 1012dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxy->credentials = credentials; 1013dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1014dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Initial state == expecting a header. 1015dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyExpectHeader(peerProxy); 1016dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1017dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Add this proxy to the map. Make sure the key points to the stable memory 1018dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // inside of the peer proxy itself. 1019dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pid_t* pid = &(peerProxy->credentials.pid); 1020dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project hashmapPut(peer->peerProxies, pid, peerProxy); 1021dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return peerProxy; 1022dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 1023dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1024dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Accepts a connection to the master peer. */ 1025dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void masterAcceptConnection(SelectableFd* listenerFd) { 1026dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Accept connection. 1027dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int socket = accept(listenerFd->fd, NULL, NULL); 1028dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (socket == -1) { 1029ae8b56c0d17a97aff0b98e6405c7cc9811bbbc3dSteve Block ALOGW("accept() error: %s", strerror(errno)); 1030dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return; 1031dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1032dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 10338d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("Accepted connection as fd %d.", socket); 1034dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1035dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Get credentials. 1036dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Credentials credentials; 1037dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ucred ucredentials; 1038dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project socklen_t credentialsSize = sizeof(struct ucred); 1039dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int result = getsockopt(socket, SOL_SOCKET, SO_PEERCRED, 1040dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project &ucredentials, &credentialsSize); 1041dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // We might want to verify credentialsSize. 1042dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (result == -1) { 1043ae8b56c0d17a97aff0b98e6405c7cc9811bbbc3dSteve Block ALOGW("getsockopt() error: %s", strerror(errno)); 1044dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project closeWithWarning(socket); 1045dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return; 1046dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1047dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1048dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Copy values into our own structure so we know we have the types right. 1049dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project credentials.pid = ucredentials.pid; 1050dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project credentials.uid = ucredentials.uid; 1051dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project credentials.gid = ucredentials.gid; 1052dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1053fe71a61e5b0cb666675900d206251a7c18ed944bSteve Block ALOGI("Accepted connection from process %d.", credentials.pid); 1054dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1055dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Peer* masterPeer = (Peer*) listenerFd->data; 1056dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1057dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerLock(masterPeer); 1058dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1059dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Make sure we don't already have a connection from that process. 1060dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project PeerProxy* peerProxy 1061dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project = hashmapGet(masterPeer->peerProxies, &credentials.pid); 1062dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (peerProxy != NULL) { 1063dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerUnlock(masterPeer); 1064ae8b56c0d17a97aff0b98e6405c7cc9811bbbc3dSteve Block ALOGW("Alread connected to process %d.", credentials.pid); 1065dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project closeWithWarning(socket); 1066dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return; 1067dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1068dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1069dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Add connection to the selector. 1070dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project SelectableFd* socketFd = selectorAdd(masterPeer->selector, socket); 1071dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (socketFd == NULL) { 1072dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerUnlock(masterPeer); 1073ae8b56c0d17a97aff0b98e6405c7cc9811bbbc3dSteve Block ALOGW("malloc() failed."); 1074dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project closeWithWarning(socket); 1075dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return; 1076dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1077dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1078dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Create a peer proxy. 1079dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxy = peerProxyCreate(masterPeer, credentials); 1080dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerUnlock(masterPeer); 1081dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (peerProxy == NULL) { 1082ae8b56c0d17a97aff0b98e6405c7cc9811bbbc3dSteve Block ALOGW("malloc() failed."); 1083dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project socketFd->remove = true; 1084dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project closeWithWarning(socket); 1085dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1086dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxy->connections = hashmapCreate(10, &pidHash, &pidEquals); 1087dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxySetFd(peerProxy, socketFd); 1088dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 1089dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1090dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 1091dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Creates the local peer. 1092dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 1093dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic Peer* peerCreate() { 1094dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Peer* peer = calloc(1, sizeof(Peer)); 1095dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (peer == NULL) { 1096dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("malloc() error."); 1097dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1098dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peer->peerProxies = hashmapCreate(10, &pidHash, &pidEquals); 1099dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peer->selector = selectorCreate(); 1100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pthread_mutexattr_t attributes; 1102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (pthread_mutexattr_init(&attributes) != 0) { 1103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("pthread_mutexattr_init() error."); 1104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_RECURSIVE) != 0) { 1106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("pthread_mutexattr_settype() error."); 1107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (pthread_mutex_init(&peer->mutex, &attributes) != 0) { 1109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("pthread_mutex_init() error."); 1110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peer->pid = getpid(); 1113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return peer; 1114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 1115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** The local peer. */ 1117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic Peer* localPeer; 1118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Frees a packet of bytes. */ 1120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void outgoingPacketFreeBytes(OutgoingPacket* packet) { 11218d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("Freeing outgoing packet."); 1122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bufferFree(packet->bytes); 1123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project free(packet); 1124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 1125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 1127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Sends a packet of bytes to a remote peer. Returns 0 on success. 1128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 1129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Returns -1 if an error occurs. Sets errno to ENOMEM if memory couldn't be 1130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * allocated. Sets errno to EHOSTDOWN if the peer died recently. Sets errno 1131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * to EINVAL if pid is the same as the local pid. 1132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 1133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint peerSendBytes(pid_t pid, const char* bytes, size_t size) { 1134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Peer* peer = localPeer; 1135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project assert(peer != NULL); 1136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project OutgoingPacket* packet = calloc(1, sizeof(OutgoingPacket)); 1138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (packet == NULL) { 1139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project errno = ENOMEM; 1140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 1141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Buffer* copy = bufferCreate(size); 1144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (copy == NULL) { 1145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project free(packet); 1146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project errno = ENOMEM; 1147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 1148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Copy data. 1151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memcpy(copy->data, bytes, size); 1152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project copy->size = size; 1153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet->bytes = copy; 1155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet->header.type = BYTES; 1156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet->header.size = size; 1157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet->free = outgoingPacketFreeBytes; 1158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bufferPrepareForWrite(packet->bytes); 1159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerLock(peer); 1161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project PeerProxy* peerProxy = peerProxyGetOrCreate(peer, pid, true); 1163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (peerProxy == NULL) { 1164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // The peer is already dead or we couldn't alloc memory. Either way, 1165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // errno is set. 1166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerUnlock(peer); 1167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet->free(packet); 1168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 1169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 1170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyEnqueueOutgoingPacket(peerProxy, packet); 1171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerUnlock(peer); 1172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project selectorWakeUp(peer->selector); 1173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 1174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 1176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Keeps track of how to free shared bytes. */ 1178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttypedef struct { 1179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project void (*free)(void* context); 1180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project void* context; 1181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} SharedBytesFreer; 1182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Frees shared bytes. */ 1184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void outgoingPacketFreeSharedBytes(OutgoingPacket* packet) { 1185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project SharedBytesFreer* sharedBytesFreer 1186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project = (SharedBytesFreer*) packet->context; 1187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sharedBytesFreer->free(sharedBytesFreer->context); 1188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project free(sharedBytesFreer); 1189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project free(packet); 1190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 1191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 1193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Sends a packet of bytes to a remote peer without copying the bytes. Calls 1194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * free() with context after the bytes have been sent. 1195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 1196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Returns -1 if an error occurs. Sets errno to ENOMEM if memory couldn't be 1197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * allocated. Sets errno to EHOSTDOWN if the peer died recently. Sets errno 1198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * to EINVAL if pid is the same as the local pid. 1199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 1200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint peerSendSharedBytes(pid_t pid, char* bytes, size_t size, 1201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project void (*free)(void* context), void* context) { 1202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Peer* peer = localPeer; 1203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project assert(peer != NULL); 1204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project OutgoingPacket* packet = calloc(1, sizeof(OutgoingPacket)); 1206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (packet == NULL) { 1207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project errno = ENOMEM; 1208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 1209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Buffer* wrapper = bufferWrap(bytes, size, size); 1212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (wrapper == NULL) { 1213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project free(packet); 1214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project errno = ENOMEM; 1215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 1216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project SharedBytesFreer* sharedBytesFreer = malloc(sizeof(SharedBytesFreer)); 1219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (sharedBytesFreer == NULL) { 1220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project free(packet); 1221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project free(wrapper); 1222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project errno = ENOMEM; 1223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 1224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sharedBytesFreer->free = free; 1226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sharedBytesFreer->context = context; 1227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet->bytes = wrapper; 1229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet->context = sharedBytesFreer; 1230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet->header.type = BYTES; 1231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet->header.size = size; 1232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet->free = &outgoingPacketFreeSharedBytes; 1233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bufferPrepareForWrite(packet->bytes); 1234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerLock(peer); 1236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project PeerProxy* peerProxy = peerProxyGetOrCreate(peer, pid, true); 1238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (peerProxy == NULL) { 1239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // The peer is already dead or we couldn't alloc memory. Either way, 1240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // errno is set. 1241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerUnlock(peer); 1242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project packet->free(packet); 1243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 1244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 1245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxyEnqueueOutgoingPacket(peerProxy, packet); 1246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerUnlock(peer); 1247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project selectorWakeUp(peer->selector); 1248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 1249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 1251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 1253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Starts the master peer. The master peer differs from other peers in that 1254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * it is responsible for connecting the other peers. You can only have one 1255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * master peer. 1256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 1257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Goes into an I/O loop and does not return. 1258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 1259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid masterPeerInitialize(BytesListener* bytesListener, 1260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project DeathListener* deathListener) { 1261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Create and bind socket. 1262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int listenerSocket = socket(AF_LOCAL, SOCK_STREAM, 0); 1263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (listenerSocket == -1) { 1264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("socket() error: %s", strerror(errno)); 1265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unlink(MASTER_PATH); 1267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int result = bind(listenerSocket, (SocketAddress*) getMasterAddress(), 1268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sizeof(UnixAddress)); 1269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (result == -1) { 1270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("bind() error: %s", strerror(errno)); 1271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 12738d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("Listener socket: %d", listenerSocket); 1274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Queue up to 16 connections. 1276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project result = listen(listenerSocket, 16); 1277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (result != 0) { 1278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("listen() error: %s", strerror(errno)); 1279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Make socket non-blocking. 1282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project setNonBlocking(listenerSocket); 1283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Create the peer for this process. Fail if we already have one. 1285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (localPeer != NULL) { 1286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("Peer is already initialized."); 1287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project localPeer = peerCreate(); 1289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (localPeer == NULL) { 1290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("malloc() failed."); 1291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project localPeer->master = true; 1293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project localPeer->onBytes = bytesListener; 1294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project localPeer->onDeath = deathListener; 1295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Make listener socket selectable. 1297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project SelectableFd* listenerFd = selectorAdd(localPeer->selector, listenerSocket); 1298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (listenerFd == NULL) { 1299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("malloc() error."); 1300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project listenerFd->data = localPeer; 1302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project listenerFd->onReadable = &masterAcceptConnection; 1303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 1304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 1306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Starts a local peer. 1307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 1308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Goes into an I/O loop and does not return. 1309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 1310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid peerInitialize(BytesListener* bytesListener, 1311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project DeathListener* deathListener) { 1312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Connect to master peer. 1313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int masterSocket = socket(AF_LOCAL, SOCK_STREAM, 0); 1314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (masterSocket == -1) { 1315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("socket() error: %s", strerror(errno)); 1316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int result = connect(masterSocket, (SocketAddress*) getMasterAddress(), 1318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sizeof(UnixAddress)); 1319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (result != 0) { 1320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("connect() error: %s", strerror(errno)); 1321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Create the peer for this process. Fail if we already have one. 1324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (localPeer != NULL) { 1325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("Peer is already initialized."); 1326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project localPeer = peerCreate(); 1328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (localPeer == NULL) { 1329dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("malloc() failed."); 1330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project localPeer->onBytes = bytesListener; 1332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project localPeer->onDeath = deathListener; 1333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Make connection selectable. 1335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project SelectableFd* masterFd = selectorAdd(localPeer->selector, masterSocket); 1336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (masterFd == NULL) { 1337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("malloc() error."); 1338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Create a peer proxy for the master peer. 1341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project PeerProxy* masterProxy = peerProxyCreate(localPeer, MASTER_CREDENTIALS); 1342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (masterProxy == NULL) { 1343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("malloc() error."); 1344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 1345dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project peerProxySetFd(masterProxy, masterFd); 1346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project masterProxy->master = true; 1347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project localPeer->masterProxy = masterProxy; 1348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 1349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Starts the master peer I/O loop. Doesn't return. */ 1351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid peerLoop() { 1352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project assert(localPeer != NULL); 1353dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1354dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Start selector. 1355dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project selectorLoop(localPeer->selector); 1356dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 1357dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1358