| 159 | } |
| 160 | |
| 161 | int ConnectToServer(ConnectionOption ConnectionOption) { |
| 162 | auto ServerSocketName = GetServerSocketName(); |
| 163 | |
| 164 | // Create the initial unix socket |
| 165 | int SocketFD = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); |
| 166 | if (SocketFD == -1) { |
| 167 | LogMan::Msg::EFmt("Couldn't open AF_UNIX socket {}", errno); |
| 168 | return -1; |
| 169 | } |
| 170 | |
| 171 | // AF_UNIX has a special feature for named socket paths. |
| 172 | // If the name of the socket begins with `\0` then it is an "abstract" socket address. |
| 173 | // The entirety of the name is used as a path to a socket that doesn't have any filesystem backing. |
| 174 | struct sockaddr_un addr {}; |
| 175 | addr.sun_family = AF_UNIX; |
| 176 | size_t SizeOfSocketString = std::min(ServerSocketName.size() + 1, sizeof(addr.sun_path) - 1); |
| 177 | addr.sun_path[0] = 0; // Abstract AF_UNIX sockets start with \0 |
| 178 | strncpy(addr.sun_path + 1, ServerSocketName.data(), SizeOfSocketString); |
| 179 | // Include final null character. |
| 180 | size_t SizeOfAddr = sizeof(addr.sun_family) + SizeOfSocketString; |
| 181 | |
| 182 | if (connect(SocketFD, reinterpret_cast<struct sockaddr*>(&addr), SizeOfAddr) == -1) { |
| 183 | if (ConnectionOption == ConnectionOption::Default || errno != ECONNREFUSED) { |
| 184 | LogMan::Msg::EFmt("Couldn't connect to FEXServer socket {} {}", ServerSocketName, errno); |
| 185 | } |
| 186 | } else { |
| 187 | return SocketFD; |
| 188 | } |
| 189 | |
| 190 | // Try again with a path-based socket, since abstract sockets will fail if we have been |
| 191 | // placed in a new netns as part of a sandbox. |
| 192 | auto ServerSocketPath = GetServerSocketPath(); |
| 193 | |
| 194 | SizeOfSocketString = std::min(ServerSocketPath.size(), sizeof(addr.sun_path) - 1); |
| 195 | strncpy(addr.sun_path, ServerSocketPath.data(), SizeOfSocketString); |
| 196 | SizeOfAddr = sizeof(addr.sun_family) + SizeOfSocketString; |
| 197 | if (connect(SocketFD, reinterpret_cast<struct sockaddr*>(&addr), SizeOfAddr) == -1) { |
| 198 | if (ConnectionOption == ConnectionOption::Default || (errno != ECONNREFUSED && errno != ENOENT)) { |
| 199 | LogMan::Msg::EFmt("Couldn't connect to FEXServer socket {} {}", ServerSocketPath, errno); |
| 200 | } |
| 201 | } else { |
| 202 | return SocketFD; |
| 203 | } |
| 204 | |
| 205 | close(SocketFD); |
| 206 | return -1; |
| 207 | } |
| 208 | |
| 209 | bool SetupClient(std::string_view InterpreterPath) { |
| 210 | ServerFD = FEXServerClient::ConnectToAndStartServer(InterpreterPath); |
no test coverage detected