Home | History | Annotate | Download | only in adb
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "adb_listeners.h"
     18 
     19 #include <stdio.h>
     20 #include <stdlib.h>
     21 
     22 #include <android-base/stringprintf.h>
     23 #include <android-base/strings.h>
     24 #include <cutils/sockets.h>
     25 
     26 #include "socket_spec.h"
     27 #include "sysdeps.h"
     28 #include "transport.h"
     29 
     30 // A listener is an entity which binds to a local port and, upon receiving a connection on that
     31 // port, creates an asocket to connect the new local connection to a specific remote service.
     32 //
     33 // TODO: some listeners read from the new connection to determine what exact service to connect to
     34 // on the far side.
     35 class alistener {
     36   public:
     37     alistener(const std::string& _local_name, const std::string& _connect_to);
     38     ~alistener();
     39 
     40     fdevent fde;
     41     int fd = -1;
     42 
     43     std::string local_name;
     44     std::string connect_to;
     45     atransport* transport = nullptr;
     46     adisconnect disconnect;
     47 
     48   private:
     49     DISALLOW_COPY_AND_ASSIGN(alistener);
     50 };
     51 
     52 alistener::alistener(const std::string& _local_name, const std::string& _connect_to)
     53     : local_name(_local_name), connect_to(_connect_to) {
     54 }
     55 
     56 alistener::~alistener() {
     57     // Closes the corresponding fd.
     58     fdevent_remove(&fde);
     59 
     60     if (transport) {
     61         transport->RemoveDisconnect(&disconnect);
     62     }
     63 }
     64 
     65 // listener_list retains ownership of all created alistener objects. Removing an alistener from
     66 // this list will cause it to be deleted.
     67 typedef std::list<std::unique_ptr<alistener>> ListenerList;
     68 static ListenerList& listener_list = *new ListenerList();
     69 
     70 static void ss_listener_event_func(int _fd, unsigned ev, void *_l) {
     71     if (ev & FDE_READ) {
     72         int fd = adb_socket_accept(_fd, nullptr, nullptr);
     73         if (fd < 0) return;
     74 
     75         int rcv_buf_size = CHUNK_SIZE;
     76         adb_setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcv_buf_size, sizeof(rcv_buf_size));
     77 
     78         asocket* s = create_local_socket(fd);
     79         if (s) {
     80             connect_to_smartsocket(s);
     81             return;
     82         }
     83 
     84         adb_close(fd);
     85     }
     86 }
     87 
     88 static void listener_event_func(int _fd, unsigned ev, void* _l)
     89 {
     90     alistener* listener = reinterpret_cast<alistener*>(_l);
     91     asocket *s;
     92 
     93     if (ev & FDE_READ) {
     94         int fd = adb_socket_accept(_fd, nullptr, nullptr);
     95         if (fd < 0) {
     96             return;
     97         }
     98 
     99         s = create_local_socket(fd);
    100         if (s) {
    101             s->transport = listener->transport;
    102             connect_to_remote(s, listener->connect_to.c_str());
    103             return;
    104         }
    105 
    106         adb_close(fd);
    107     }
    108 }
    109 
    110 // Called as a transport disconnect function. |arg| is the raw alistener*.
    111 static void listener_disconnect(void* arg, atransport*) {
    112     for (auto iter = listener_list.begin(); iter != listener_list.end(); ++iter) {
    113         if (iter->get() == arg) {
    114             (*iter)->transport = nullptr;
    115             listener_list.erase(iter);
    116             return;
    117         }
    118     }
    119 }
    120 
    121 // Write the list of current listeners (network redirections) into a string.
    122 std::string format_listeners() {
    123     std::string result;
    124     for (auto& l : listener_list) {
    125         // Ignore special listeners like those for *smartsocket*
    126         if (l->connect_to[0] == '*') {
    127             continue;
    128         }
    129         //  <device-serial> " " <local-name> " " <remote-name> "\n"
    130         // Entries from "adb reverse" have no serial.
    131         android::base::StringAppendF(&result, "%s %s %s\n",
    132                                      l->transport->serial ? l->transport->serial : "(reverse)",
    133                                      l->local_name.c_str(), l->connect_to.c_str());
    134     }
    135     return result;
    136 }
    137 
    138 InstallStatus remove_listener(const char* local_name, atransport* transport) {
    139     for (auto iter = listener_list.begin(); iter != listener_list.end(); ++iter) {
    140         if (local_name == (*iter)->local_name) {
    141             listener_list.erase(iter);
    142             return INSTALL_STATUS_OK;
    143         }
    144     }
    145     return INSTALL_STATUS_LISTENER_NOT_FOUND;
    146 }
    147 
    148 void remove_all_listeners() {
    149     auto iter = listener_list.begin();
    150     while (iter != listener_list.end()) {
    151         // Never remove smart sockets.
    152         if ((*iter)->connect_to[0] == '*') {
    153             ++iter;
    154         } else {
    155             iter = listener_list.erase(iter);
    156         }
    157     }
    158 }
    159 
    160 InstallStatus install_listener(const std::string& local_name, const char* connect_to,
    161                                atransport* transport, int no_rebind, int* resolved_tcp_port,
    162                                std::string* error) {
    163     for (auto& l : listener_list) {
    164         if (local_name == l->local_name) {
    165             // Can't repurpose a smartsocket.
    166             if(l->connect_to[0] == '*') {
    167                 *error = "cannot repurpose smartsocket";
    168                 return INSTALL_STATUS_INTERNAL_ERROR;
    169             }
    170 
    171             // Can't repurpose a listener if 'no_rebind' is true.
    172             if (no_rebind) {
    173                 *error = "cannot rebind";
    174                 return INSTALL_STATUS_CANNOT_REBIND;
    175             }
    176 
    177             l->connect_to = connect_to;
    178             if (l->transport != transport) {
    179                 l->transport->RemoveDisconnect(&l->disconnect);
    180                 l->transport = transport;
    181                 l->transport->AddDisconnect(&l->disconnect);
    182             }
    183             return INSTALL_STATUS_OK;
    184         }
    185     }
    186 
    187     std::unique_ptr<alistener> listener(new alistener(local_name, connect_to));
    188 
    189     int resolved = 0;
    190     listener->fd = socket_spec_listen(listener->local_name, error, &resolved);
    191     if (listener->fd < 0) {
    192         return INSTALL_STATUS_CANNOT_BIND;
    193     }
    194 
    195     // If the caller requested port 0, update the listener name with the resolved port.
    196     if (resolved != 0) {
    197         listener->local_name = android::base::StringPrintf("tcp:%d", resolved);
    198         if (resolved_tcp_port) {
    199             *resolved_tcp_port = resolved;
    200         }
    201     }
    202 
    203     close_on_exec(listener->fd);
    204     if (listener->connect_to == "*smartsocket*") {
    205         fdevent_install(&listener->fde, listener->fd, ss_listener_event_func, listener.get());
    206     } else {
    207         fdevent_install(&listener->fde, listener->fd, listener_event_func, listener.get());
    208     }
    209     fdevent_set(&listener->fde, FDE_READ);
    210 
    211     listener->transport = transport;
    212 
    213     if (transport) {
    214         listener->disconnect.opaque = listener.get();
    215         listener->disconnect.func   = listener_disconnect;
    216         transport->AddDisconnect(&listener->disconnect);
    217     }
    218 
    219     listener_list.push_back(std::move(listener));
    220     return INSTALL_STATUS_OK;
    221 }
    222