1 // Copyright 2022 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #if defined(_WIN32)
16 #include <msvc-getopt.h>
17 #else
18 #include <getopt.h>
19 #endif
20
21 #if defined(__linux__)
22 #include <execinfo.h>
23 #include <signal.h>
24 #include <unistd.h>
25
26 #include <cstdio>
27 #endif
28
29 #ifndef NETSIM_ANDROID_EMULATOR
30 #include "backend/fd_startup.h"
31 #endif
32 #include "core/server.h"
33 #include "frontend/frontend_client_stub.h"
34 #include "hci/bluetooth_facade.h"
35 #include "netsim-cxx/src/lib.rs.h"
36
37 // Wireless network simulator for android (and other) emulated devices.
38
39 #if defined(__linux__)
40 // Signal handler to print backtraces and then terminate the program.
SignalHandler(int sig)41 void SignalHandler(int sig) {
42 size_t buffer_size = 20; // Number of entries in that array.
43 void *buffer[buffer_size];
44
45 auto size = backtrace(buffer, buffer_size);
46 fprintf(stderr,
47 "netsim error: interrupt by signal %d. Obtained %d stack frames:\n",
48 sig, size);
49 backtrace_symbols_fd(buffer, size, STDERR_FILENO);
50 exit(sig);
51 }
52 #endif
53
ArgError(char * argv[],int c)54 void ArgError(char *argv[], int c) {
55 std::cerr << argv[0] << ": invalid option -- " << (char)c << "\n";
56 std::cerr << "Try `" << argv[0] << " --help' for more information.\n";
57 }
58
main(int argc,char * argv[])59 int main(int argc, char *argv[]) {
60 #if defined(__linux__)
61 signal(SIGSEGV, SignalHandler);
62 #endif
63 const char *kShortOpt = "s:dg";
64 const option kLongOptions[] = {
65 {"rootcanal_default_commands_file", required_argument, 0, 'c'},
66 {"rootcanal_controller_properties_file", required_argument, 0, 'p'},
67 };
68
69 bool debug = false;
70 bool grpc_startup = false;
71 std::string fd_startup_str;
72 std::string rootcanal_default_commands_file;
73 std::string rootcanal_controller_properties_file;
74
75 int c;
76
77 while ((c = getopt_long(argc, argv, kShortOpt, kLongOptions, nullptr)) !=
78 -1) {
79 switch (c) {
80 #ifdef NETSIM_ANDROID_EMULATOR
81 case 'g':
82 grpc_startup = true;
83 break;
84 #else
85 case 's':
86 fd_startup_str = std::string(optarg);
87 break;
88 #endif
89 case 'd':
90 debug = true;
91 break;
92
93 case 'c':
94 rootcanal_default_commands_file = std::string(optarg);
95 break;
96
97 case 'p':
98 rootcanal_controller_properties_file = std::string(optarg);
99 break;
100
101 default:
102 ArgError(argv, c);
103 return (-2);
104 }
105 }
106
107 // Daemon mode -- start radio managers
108 if (!fd_startup_str.empty() || grpc_startup) {
109 netsim::hci::facade::Start();
110 }
111
112 #ifdef NETSIM_ANDROID_EMULATOR
113 // get netsim daemon, starting if it doesn't exist
114 // Create a frontend grpc client to check if a netsimd is already running.
115 auto frontend_stub = netsim::frontend::NewFrontendClient();
116 if (frontend_stub == nullptr) {
117 // starts netsim in vhci connection mode
118 netsim::server::Run();
119 }
120 #else
121 if (!fd_startup_str.empty()) {
122 netsim::RunFdTransport(fd_startup_str);
123 netsim::server::Run();
124 return -1;
125 }
126 #endif
127
128 return (0);
129 }
130