am 6dca1987: am cf4dba5a: Merge "adb: win32: initial IPv6 support and improved Winsock error reporting"
* commit '6dca19875325a2ed25f9b55d736a9f6d17afeaad': adb: win32: initial IPv6 support and improved Winsock error reporting
This commit is contained in:
commit
c0d738f331
13 changed files with 372 additions and 201 deletions
|
|
@ -801,11 +801,13 @@ int handle_forward_request(const char* service, TransportType type, const char*
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string error;
|
||||||
InstallStatus r;
|
InstallStatus r;
|
||||||
if (kill_forward) {
|
if (kill_forward) {
|
||||||
r = remove_listener(pieces[0].c_str(), transport);
|
r = remove_listener(pieces[0].c_str(), transport);
|
||||||
} else {
|
} else {
|
||||||
r = install_listener(pieces[0], pieces[1].c_str(), transport, no_rebind);
|
r = install_listener(pieces[0], pieces[1].c_str(), transport,
|
||||||
|
no_rebind, &error);
|
||||||
}
|
}
|
||||||
if (r == INSTALL_STATUS_OK) {
|
if (r == INSTALL_STATUS_OK) {
|
||||||
#if ADB_HOST
|
#if ADB_HOST
|
||||||
|
|
@ -821,7 +823,8 @@ int handle_forward_request(const char* service, TransportType type, const char*
|
||||||
case INSTALL_STATUS_OK: message = "success (!)"; break;
|
case INSTALL_STATUS_OK: message = "success (!)"; break;
|
||||||
case INSTALL_STATUS_INTERNAL_ERROR: message = "internal error"; break;
|
case INSTALL_STATUS_INTERNAL_ERROR: message = "internal error"; break;
|
||||||
case INSTALL_STATUS_CANNOT_BIND:
|
case INSTALL_STATUS_CANNOT_BIND:
|
||||||
message = android::base::StringPrintf("cannot bind to socket: %s", strerror(errno));
|
message = android::base::StringPrintf("cannot bind to socket: %s",
|
||||||
|
error.c_str());
|
||||||
break;
|
break;
|
||||||
case INSTALL_STATUS_CANNOT_REBIND:
|
case INSTALL_STATUS_CANNOT_REBIND:
|
||||||
message = android::base::StringPrintf("cannot rebind existing socket");
|
message = android::base::StringPrintf("cannot rebind existing socket");
|
||||||
|
|
|
||||||
|
|
@ -153,8 +153,8 @@ int _adb_connect(const std::string& service, std::string* error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int fd;
|
int fd;
|
||||||
|
std::string reason;
|
||||||
if (__adb_server_name) {
|
if (__adb_server_name) {
|
||||||
std::string reason;
|
|
||||||
fd = network_connect(__adb_server_name, __adb_server_port, SOCK_STREAM, 0, &reason);
|
fd = network_connect(__adb_server_name, __adb_server_port, SOCK_STREAM, 0, &reason);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
*error = android::base::StringPrintf("can't connect to %s:%d: %s",
|
*error = android::base::StringPrintf("can't connect to %s:%d: %s",
|
||||||
|
|
@ -163,9 +163,10 @@ int _adb_connect(const std::string& service, std::string* error) {
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fd = socket_loopback_client(__adb_server_port, SOCK_STREAM);
|
fd = network_loopback_client(__adb_server_port, SOCK_STREAM, &reason);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
*error = perror_str("cannot connect to daemon");
|
*error = android::base::StringPrintf("cannot connect to daemon: %s",
|
||||||
|
reason.c_str());
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -110,27 +110,30 @@ static void listener_disconnect(void* listener, atransport* t) {
|
||||||
free_listener(reinterpret_cast<alistener*>(listener));
|
free_listener(reinterpret_cast<alistener*>(listener));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int local_name_to_fd(const char* name) {
|
static int local_name_to_fd(const char* name, std::string* error) {
|
||||||
if (!strncmp("tcp:", name, 4)) {
|
if (!strncmp("tcp:", name, 4)) {
|
||||||
int port = atoi(name + 4);
|
int port = atoi(name + 4);
|
||||||
if (gListenAll > 0) {
|
if (gListenAll > 0) {
|
||||||
return socket_inaddr_any_server(port, SOCK_STREAM);
|
return network_inaddr_any_server(port, SOCK_STREAM, error);
|
||||||
} else {
|
} else {
|
||||||
return socket_loopback_server(port, SOCK_STREAM);
|
return network_loopback_server(port, SOCK_STREAM, error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if !defined(_WIN32) // No Unix-domain sockets on Windows.
|
#if !defined(_WIN32) // No Unix-domain sockets on Windows.
|
||||||
// It's nonsensical to support the "reserved" space on the adb host side
|
// It's nonsensical to support the "reserved" space on the adb host side
|
||||||
if (!strncmp(name, "local:", 6)) {
|
if (!strncmp(name, "local:", 6)) {
|
||||||
return socket_local_server(name + 6, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
|
return network_local_server(name + 6,
|
||||||
|
ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM, error);
|
||||||
} else if (!strncmp(name, "localabstract:", 14)) {
|
} else if (!strncmp(name, "localabstract:", 14)) {
|
||||||
return socket_local_server(name + 14, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
|
return network_local_server(name + 14,
|
||||||
|
ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM, error);
|
||||||
} else if (!strncmp(name, "localfilesystem:", 16)) {
|
} else if (!strncmp(name, "localfilesystem:", 16)) {
|
||||||
return socket_local_server(name + 16, ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
|
return network_local_server(name + 16,
|
||||||
|
ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
printf("unknown local portname '%s'\n", name);
|
*error = android::base::StringPrintf("unknown local portname '%s'", name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -178,7 +181,8 @@ void remove_all_listeners(void)
|
||||||
InstallStatus install_listener(const std::string& local_name,
|
InstallStatus install_listener(const std::string& local_name,
|
||||||
const char *connect_to,
|
const char *connect_to,
|
||||||
atransport* transport,
|
atransport* transport,
|
||||||
int no_rebind)
|
int no_rebind,
|
||||||
|
std::string* error)
|
||||||
{
|
{
|
||||||
for (alistener* l = listener_list.next; l != &listener_list; l = l->next) {
|
for (alistener* l = listener_list.next; l != &listener_list; l = l->next) {
|
||||||
if (local_name == l->local_name) {
|
if (local_name == l->local_name) {
|
||||||
|
|
@ -226,9 +230,9 @@ InstallStatus install_listener(const std::string& local_name,
|
||||||
goto nomem;
|
goto nomem;
|
||||||
}
|
}
|
||||||
|
|
||||||
listener->fd = local_name_to_fd(listener->local_name);
|
listener->fd = local_name_to_fd(listener->local_name, error);
|
||||||
if (listener->fd < 0) {
|
if (listener->fd < 0) {
|
||||||
printf("cannot bind '%s': %s\n", listener->local_name, strerror(errno));
|
printf("cannot bind '%s': %s\n", listener->local_name, error->c_str());
|
||||||
free(listener->local_name);
|
free(listener->local_name);
|
||||||
free(listener->connect_to);
|
free(listener->connect_to);
|
||||||
free(listener);
|
free(listener);
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,8 @@ enum InstallStatus {
|
||||||
InstallStatus install_listener(const std::string& local_name,
|
InstallStatus install_listener(const std::string& local_name,
|
||||||
const char* connect_to,
|
const char* connect_to,
|
||||||
atransport* transport,
|
atransport* transport,
|
||||||
int no_rebind);
|
int no_rebind,
|
||||||
|
std::string* error);
|
||||||
|
|
||||||
std::string format_listeners();
|
std::string format_listeners();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,17 +28,10 @@
|
||||||
#include <base/logging.h>
|
#include <base/logging.h>
|
||||||
#include <base/stringprintf.h>
|
#include <base/stringprintf.h>
|
||||||
#include <base/strings.h>
|
#include <base/strings.h>
|
||||||
#include <cutils/sockets.h>
|
|
||||||
|
|
||||||
#include "adb_trace.h"
|
#include "adb_trace.h"
|
||||||
#include "sysdeps.h"
|
#include "sysdeps.h"
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#include <ws2tcpip.h>
|
|
||||||
#else
|
|
||||||
#include <netdb.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool getcwd(std::string* s) {
|
bool getcwd(std::string* s) {
|
||||||
char* cwd = getcwd(nullptr, 0);
|
char* cwd = getcwd(nullptr, 0);
|
||||||
if (cwd != nullptr) *s = cwd;
|
if (cwd != nullptr) *s = cwd;
|
||||||
|
|
@ -178,18 +171,3 @@ bool parse_host_and_port(const std::string& address,
|
||||||
<< " (" << *canonical_address << ")";
|
<< " (" << *canonical_address << ")";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int network_connect(const std::string& host, int port, int type, int timeout, std::string* error) {
|
|
||||||
int getaddrinfo_error = 0;
|
|
||||||
int fd = socket_network_client_timeout(host.c_str(), port, type, timeout, &getaddrinfo_error);
|
|
||||||
if (fd != -1) {
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
if (getaddrinfo_error != 0) {
|
|
||||||
// TODO: gai_strerror is not thread safe on Win32.
|
|
||||||
*error = gai_strerror(getaddrinfo_error);
|
|
||||||
} else {
|
|
||||||
*error = strerror(errno);
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,4 @@ bool parse_host_and_port(const std::string& address,
|
||||||
std::string* host, int* port,
|
std::string* host, int* port,
|
||||||
std::string* error);
|
std::string* error);
|
||||||
|
|
||||||
int network_connect(const std::string& host, int port, int type, int timeout, std::string* error);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -150,9 +150,10 @@ int adb_main(int is_daemon, int server_port) {
|
||||||
local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
|
local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
|
||||||
adb_auth_init();
|
adb_auth_init();
|
||||||
|
|
||||||
|
std::string error;
|
||||||
std::string local_name = android::base::StringPrintf("tcp:%d", server_port);
|
std::string local_name = android::base::StringPrintf("tcp:%d", server_port);
|
||||||
if (install_listener(local_name, "*smartsocket*", nullptr, 0)) {
|
if (install_listener(local_name, "*smartsocket*", nullptr, 0, &error)) {
|
||||||
LOG(FATAL) << "Could not install *smartsocket* listener";
|
LOG(FATAL) << "Could not install *smartsocket* listener: " << error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_daemon) {
|
if (is_daemon) {
|
||||||
|
|
|
||||||
|
|
@ -71,9 +71,11 @@ static int connect_to_console(const char* serial) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fd = socket_loopback_client(port, SOCK_STREAM);
|
std::string error;
|
||||||
|
int fd = network_loopback_client(port, SOCK_STREAM, &error);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
fprintf(stderr, "error: could not connect to TCP port %d\n", port);
|
fprintf(stderr, "error: could not connect to TCP port %d: %s\n", port,
|
||||||
|
error.c_str());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return fd;
|
return fd;
|
||||||
|
|
|
||||||
|
|
@ -177,10 +177,13 @@ int adbd_main(int server_port) {
|
||||||
LOG(FATAL) << "Could not set selinux context";
|
LOG(FATAL) << "Could not set selinux context";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std::string error;
|
||||||
std::string local_name =
|
std::string local_name =
|
||||||
android::base::StringPrintf("tcp:%d", server_port);
|
android::base::StringPrintf("tcp:%d", server_port);
|
||||||
if (install_listener(local_name, "*smartsocket*", nullptr, 0)) {
|
if (install_listener(local_name, "*smartsocket*", nullptr, 0,
|
||||||
LOG(FATAL) << "Could not install *smartsocket* listener";
|
&error)) {
|
||||||
|
LOG(FATAL) << "Could not install *smartsocket* listener: "
|
||||||
|
<< error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -432,7 +432,8 @@ int service_to_fd(const char *name)
|
||||||
int port = atoi(name + 4);
|
int port = atoi(name + 4);
|
||||||
name = strchr(name + 4, ':');
|
name = strchr(name + 4, ':');
|
||||||
if(name == 0) {
|
if(name == 0) {
|
||||||
ret = socket_loopback_client(port, SOCK_STREAM);
|
std::string error;
|
||||||
|
ret = network_loopback_client(port, SOCK_STREAM, &error);
|
||||||
if (ret >= 0)
|
if (ret >= 0)
|
||||||
disable_tcp_nagle(ret);
|
disable_tcp_nagle(ret);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TEMP_FAILURE_RETRY is defined by some, but not all, versions of
|
* TEMP_FAILURE_RETRY is defined by some, but not all, versions of
|
||||||
* <unistd.h>. (Alas, it is not as standard as we'd hoped!) So, if it's
|
* <unistd.h>. (Alas, it is not as standard as we'd hoped!) So, if it's
|
||||||
|
|
@ -212,6 +214,12 @@ static __inline__ void adb_sleep_ms( int mseconds )
|
||||||
Sleep( mseconds );
|
Sleep( mseconds );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int network_loopback_client(int port, int type, std::string* error);
|
||||||
|
int network_loopback_server(int port, int type, std::string* error);
|
||||||
|
int network_inaddr_any_server(int port, int type, std::string* error);
|
||||||
|
int network_connect(const std::string& host, int port, int type, int timeout,
|
||||||
|
std::string* error);
|
||||||
|
|
||||||
extern int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrlen);
|
extern int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrlen);
|
||||||
|
|
||||||
#undef accept
|
#undef accept
|
||||||
|
|
@ -240,10 +248,14 @@ static __inline__ int adb_is_absolute_host_path(const char* path) {
|
||||||
return isalpha(path[0]) && path[1] == ':' && path[2] == '\\';
|
return isalpha(path[0]) && path[1] == ':' && path[2] == '\\';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Like strerror(), but for Win32 error codes.
|
||||||
|
std::string SystemErrorCodeToString(DWORD error_code);
|
||||||
|
|
||||||
#else /* !_WIN32 a.k.a. Unix */
|
#else /* !_WIN32 a.k.a. Unix */
|
||||||
|
|
||||||
#include "fdevent.h"
|
#include "fdevent.h"
|
||||||
#include <cutils/misc.h>
|
#include <cutils/misc.h>
|
||||||
|
#include <cutils/sockets.h>
|
||||||
#include <cutils/threads.h>
|
#include <cutils/threads.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
@ -254,6 +266,7 @@ static __inline__ int adb_is_absolute_host_path(const char* path) {
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <netdb.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
@ -404,6 +417,48 @@ static __inline__ int adb_creat(const char* path, int mode)
|
||||||
#undef creat
|
#undef creat
|
||||||
#define creat ___xxx_creat
|
#define creat ___xxx_creat
|
||||||
|
|
||||||
|
// Helper for network_* functions.
|
||||||
|
inline int _fd_set_error_str(int fd, std::string* error) {
|
||||||
|
if (fd == -1) {
|
||||||
|
*error = strerror(errno);
|
||||||
|
}
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int network_loopback_client(int port, int type, std::string* error) {
|
||||||
|
return _fd_set_error_str(socket_loopback_client(port, type), error);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int network_loopback_server(int port, int type, std::string* error) {
|
||||||
|
return _fd_set_error_str(socket_loopback_server(port, type), error);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int network_inaddr_any_server(int port, int type, std::string* error) {
|
||||||
|
return _fd_set_error_str(socket_inaddr_any_server(port, type), error);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int network_local_server(const char *name, int namespace_id, int type,
|
||||||
|
std::string* error) {
|
||||||
|
return _fd_set_error_str(socket_local_server(name, namespace_id, type),
|
||||||
|
error);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int network_connect(const std::string& host, int port, int type,
|
||||||
|
int timeout, std::string* error) {
|
||||||
|
int getaddrinfo_error = 0;
|
||||||
|
int fd = socket_network_client_timeout(host.c_str(), port, type, timeout,
|
||||||
|
&getaddrinfo_error);
|
||||||
|
if (fd != -1) {
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
if (getaddrinfo_error != 0) {
|
||||||
|
*error = gai_strerror(getaddrinfo_error);
|
||||||
|
} else {
|
||||||
|
*error = strerror(errno);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static __inline__ int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrlen)
|
static __inline__ int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrlen)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,15 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <cutils/sockets.h>
|
#include <cutils/sockets.h>
|
||||||
|
|
||||||
|
#include <base/logging.h>
|
||||||
|
#include <base/stringprintf.h>
|
||||||
|
#include <base/strings.h>
|
||||||
|
|
||||||
#include "adb.h"
|
#include "adb.h"
|
||||||
|
|
||||||
extern void fatal(const char *fmt, ...);
|
extern void fatal(const char *fmt, ...);
|
||||||
|
|
@ -80,6 +87,29 @@ static const FHClassRec _fh_socket_class = {
|
||||||
|
|
||||||
#define assert(cond) do { if (!(cond)) fatal( "assertion failed '%s' on %s:%ld\n", #cond, __FILE__, __LINE__ ); } while (0)
|
#define assert(cond) do { if (!(cond)) fatal( "assertion failed '%s' on %s:%ld\n", #cond, __FILE__, __LINE__ ); } while (0)
|
||||||
|
|
||||||
|
std::string SystemErrorCodeToString(const DWORD error_code) {
|
||||||
|
const int kErrorMessageBufferSize = 256;
|
||||||
|
char msgbuf[kErrorMessageBufferSize];
|
||||||
|
DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
|
||||||
|
DWORD len = FormatMessageA(flags, nullptr, error_code, 0, msgbuf,
|
||||||
|
arraysize(msgbuf), nullptr);
|
||||||
|
if (len == 0) {
|
||||||
|
return android::base::StringPrintf(
|
||||||
|
"Error (%lu) while retrieving error. (%lu)", GetLastError(),
|
||||||
|
error_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string msg(msgbuf);
|
||||||
|
// Messages returned by the system end with line breaks.
|
||||||
|
msg = android::base::Trim(msg);
|
||||||
|
// There are many Windows error messages compared to POSIX, so include the
|
||||||
|
// numeric error code for easier, quicker, accurate identification. Use
|
||||||
|
// decimal instead of hex because there are decimal ranges like 10000-11999
|
||||||
|
// for Winsock.
|
||||||
|
android::base::StringAppendF(&msg, " (%lu)", error_code);
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/***** *****/
|
/***** *****/
|
||||||
|
|
@ -253,6 +283,23 @@ _fh_close( FH f )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deleter for unique_fh.
|
||||||
|
class fh_deleter {
|
||||||
|
public:
|
||||||
|
void operator()(struct FHRec_* fh) {
|
||||||
|
// We're called from a destructor and destructors should not overwrite
|
||||||
|
// errno because callers may do:
|
||||||
|
// errno = EBLAH;
|
||||||
|
// return -1; // calls destructor, which should not overwrite errno
|
||||||
|
const int saved_errno = errno;
|
||||||
|
_fh_close(fh);
|
||||||
|
errno = saved_errno;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Like std::unique_ptr, but calls _fh_close() instead of operator delete().
|
||||||
|
typedef std::unique_ptr<struct FHRec_, fh_deleter> unique_fh;
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/***** *****/
|
/***** *****/
|
||||||
|
|
@ -467,21 +514,6 @@ int adb_lseek(int fd, int pos, int where)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int adb_shutdown(int fd)
|
|
||||||
{
|
|
||||||
FH f = _fh_from_int(fd, __func__);
|
|
||||||
|
|
||||||
if (!f || f->clazz != &_fh_socket_class) {
|
|
||||||
D("adb_shutdown: invalid fd %d\n", fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
D( "adb_shutdown: %s\n", f->name);
|
|
||||||
shutdown( f->fh_socket, SD_BOTH );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int adb_close(int fd)
|
int adb_close(int fd)
|
||||||
{
|
{
|
||||||
FH f = _fh_from_int(fd, __func__);
|
FH f = _fh_from_int(fd, __func__);
|
||||||
|
|
@ -505,29 +537,63 @@ int adb_close(int fd)
|
||||||
|
|
||||||
#undef setsockopt
|
#undef setsockopt
|
||||||
|
|
||||||
static void _socket_set_errno( void ) {
|
static void _socket_set_errno( const DWORD err ) {
|
||||||
switch (WSAGetLastError()) {
|
// The Windows C Runtime (MSVCRT.DLL) strerror() does not support a lot of
|
||||||
|
// POSIX and socket error codes, so this can only meaningfully map so much.
|
||||||
|
switch ( err ) {
|
||||||
case 0: errno = 0; break;
|
case 0: errno = 0; break;
|
||||||
case WSAEWOULDBLOCK: errno = EAGAIN; break;
|
case WSAEWOULDBLOCK: errno = EAGAIN; break;
|
||||||
case WSAEINTR: errno = EINTR; break;
|
case WSAEINTR: errno = EINTR; break;
|
||||||
|
case WSAEFAULT: errno = EFAULT; break;
|
||||||
|
case WSAEINVAL: errno = EINVAL; break;
|
||||||
|
case WSAEMFILE: errno = EMFILE; break;
|
||||||
default:
|
default:
|
||||||
D( "_socket_set_errno: unhandled value %d\n", WSAGetLastError() );
|
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
|
D( "_socket_set_errno: mapping Windows error code %lu to errno %d\n",
|
||||||
|
err, errno );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _fh_socket_init( FH f ) {
|
static void _fh_socket_init( FH f ) {
|
||||||
f->fh_socket = INVALID_SOCKET;
|
f->fh_socket = INVALID_SOCKET;
|
||||||
f->event = WSACreateEvent();
|
f->event = WSACreateEvent();
|
||||||
|
if (f->event == WSA_INVALID_EVENT) {
|
||||||
|
D("WSACreateEvent failed: %s\n",
|
||||||
|
SystemErrorCodeToString(WSAGetLastError()).c_str());
|
||||||
|
|
||||||
|
// _event_socket_start assumes that this field is INVALID_HANDLE_VALUE
|
||||||
|
// on failure, instead of NULL which is what Windows really returns on
|
||||||
|
// error. It might be better to change all the other code to look for
|
||||||
|
// NULL, but that is a much riskier change.
|
||||||
|
f->event = INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
f->mask = 0;
|
f->mask = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _fh_socket_close( FH f ) {
|
static int _fh_socket_close( FH f ) {
|
||||||
/* gently tell any peer that we're closing the socket */
|
if (f->fh_socket != INVALID_SOCKET) {
|
||||||
shutdown( f->fh_socket, SD_BOTH );
|
/* gently tell any peer that we're closing the socket */
|
||||||
closesocket( f->fh_socket );
|
if (shutdown(f->fh_socket, SD_BOTH) == SOCKET_ERROR) {
|
||||||
f->fh_socket = INVALID_SOCKET;
|
// If the socket is not connected, this returns an error. We want to
|
||||||
CloseHandle( f->event );
|
// minimize logging spam, so don't log these errors for now.
|
||||||
|
#if 0
|
||||||
|
D("socket shutdown failed: %s\n",
|
||||||
|
SystemErrorCodeToString(WSAGetLastError()).c_str());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (closesocket(f->fh_socket) == SOCKET_ERROR) {
|
||||||
|
D("closesocket failed: %s\n",
|
||||||
|
SystemErrorCodeToString(WSAGetLastError()).c_str());
|
||||||
|
}
|
||||||
|
f->fh_socket = INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
if (f->event != NULL) {
|
||||||
|
if (!CloseHandle(f->event)) {
|
||||||
|
D("CloseHandle failed: %s\n",
|
||||||
|
SystemErrorCodeToString(GetLastError()).c_str());
|
||||||
|
}
|
||||||
|
f->event = NULL;
|
||||||
|
}
|
||||||
f->mask = 0;
|
f->mask = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -540,7 +606,10 @@ static int _fh_socket_lseek( FH f, int pos, int origin ) {
|
||||||
static int _fh_socket_read(FH f, void* buf, int len) {
|
static int _fh_socket_read(FH f, void* buf, int len) {
|
||||||
int result = recv(f->fh_socket, reinterpret_cast<char*>(buf), len, 0);
|
int result = recv(f->fh_socket, reinterpret_cast<char*>(buf), len, 0);
|
||||||
if (result == SOCKET_ERROR) {
|
if (result == SOCKET_ERROR) {
|
||||||
_socket_set_errno();
|
const DWORD err = WSAGetLastError();
|
||||||
|
D("recv fd %d failed: %s\n", _fh_to_int(f),
|
||||||
|
SystemErrorCodeToString(err).c_str());
|
||||||
|
_socket_set_errno(err);
|
||||||
result = -1;
|
result = -1;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -549,7 +618,10 @@ static int _fh_socket_read(FH f, void* buf, int len) {
|
||||||
static int _fh_socket_write(FH f, const void* buf, int len) {
|
static int _fh_socket_write(FH f, const void* buf, int len) {
|
||||||
int result = send(f->fh_socket, reinterpret_cast<const char*>(buf), len, 0);
|
int result = send(f->fh_socket, reinterpret_cast<const char*>(buf), len, 0);
|
||||||
if (result == SOCKET_ERROR) {
|
if (result == SOCKET_ERROR) {
|
||||||
_socket_set_errno();
|
const DWORD err = WSAGetLastError();
|
||||||
|
D("send fd %d failed: %s\n", _fh_to_int(f),
|
||||||
|
SystemErrorCodeToString(err).c_str());
|
||||||
|
_socket_set_errno(err);
|
||||||
result = -1;
|
result = -1;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -570,31 +642,39 @@ static int _winsock_init;
|
||||||
static void
|
static void
|
||||||
_cleanup_winsock( void )
|
_cleanup_winsock( void )
|
||||||
{
|
{
|
||||||
|
// TODO: WSAStartup() might be called multiple times and this won't properly
|
||||||
|
// cleanup the right number of times. Plus, WSACleanup() probably doesn't
|
||||||
|
// make sense since it might interrupt other threads using Winsock (since
|
||||||
|
// our various threads are not explicitly cleanly shutdown at process exit).
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_init_winsock( void )
|
_init_winsock( void )
|
||||||
{
|
{
|
||||||
|
// TODO: Multiple threads calling this may potentially cause multiple calls
|
||||||
|
// to WSAStartup() and multiple atexit() calls.
|
||||||
if (!_winsock_init) {
|
if (!_winsock_init) {
|
||||||
WSADATA wsaData;
|
WSADATA wsaData;
|
||||||
int rc = WSAStartup( MAKEWORD(2,2), &wsaData);
|
int rc = WSAStartup( MAKEWORD(2,2), &wsaData);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
fatal( "adb: could not initialize Winsock\n" );
|
fatal( "adb: could not initialize Winsock: %s",
|
||||||
|
SystemErrorCodeToString( rc ).c_str());
|
||||||
}
|
}
|
||||||
atexit( _cleanup_winsock );
|
atexit( _cleanup_winsock );
|
||||||
_winsock_init = 1;
|
_winsock_init = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int socket_loopback_client(int port, int type)
|
int network_loopback_client(int port, int type, std::string* error) {
|
||||||
{
|
|
||||||
FH f = _fh_alloc( &_fh_socket_class );
|
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
SOCKET s;
|
SOCKET s;
|
||||||
|
|
||||||
if (!f)
|
unique_fh f(_fh_alloc(&_fh_socket_class));
|
||||||
|
if (!f) {
|
||||||
|
*error = strerror(errno);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (!_winsock_init)
|
if (!_winsock_init)
|
||||||
_init_winsock();
|
_init_winsock();
|
||||||
|
|
@ -606,32 +686,40 @@ int socket_loopback_client(int port, int type)
|
||||||
|
|
||||||
s = socket(AF_INET, type, 0);
|
s = socket(AF_INET, type, 0);
|
||||||
if(s == INVALID_SOCKET) {
|
if(s == INVALID_SOCKET) {
|
||||||
D("socket_loopback_client: could not create socket\n" );
|
*error = SystemErrorCodeToString(WSAGetLastError());
|
||||||
_fh_close(f);
|
D("could not create socket: %s\n", error->c_str());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
f->fh_socket = s;
|
||||||
|
|
||||||
|
if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) == SOCKET_ERROR) {
|
||||||
|
*error = SystemErrorCodeToString(WSAGetLastError());
|
||||||
|
D("could not connect to %s:%d: %s\n",
|
||||||
|
type != SOCK_STREAM ? "udp" : "tcp", port, error->c_str());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
f->fh_socket = s;
|
const int fd = _fh_to_int(f.get());
|
||||||
if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
snprintf( f->name, sizeof(f->name), "%d(lo-client:%s%d)", fd,
|
||||||
D("socket_loopback_client: could not connect to %s:%d\n", type != SOCK_STREAM ? "udp" : "tcp", port );
|
type != SOCK_STREAM ? "udp:" : "", port );
|
||||||
_fh_close(f);
|
D( "port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp",
|
||||||
return -1;
|
fd );
|
||||||
}
|
f.release();
|
||||||
snprintf( f->name, sizeof(f->name), "%d(lo-client:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
|
return fd;
|
||||||
D( "socket_loopback_client: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
|
|
||||||
return _fh_to_int(f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LISTEN_BACKLOG 4
|
#define LISTEN_BACKLOG 4
|
||||||
|
|
||||||
int socket_loopback_server(int port, int type)
|
// interface_address is INADDR_LOOPBACK or INADDR_ANY.
|
||||||
{
|
static int _network_server(int port, int type, u_long interface_address,
|
||||||
FH f = _fh_alloc( &_fh_socket_class );
|
std::string* error) {
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
SOCKET s;
|
SOCKET s;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
|
unique_fh f(_fh_alloc(&_fh_socket_class));
|
||||||
if (!f) {
|
if (!f) {
|
||||||
|
*error = strerror(errno);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -641,149 +729,151 @@ int socket_loopback_server(int port, int type)
|
||||||
memset(&addr, 0, sizeof(addr));
|
memset(&addr, 0, sizeof(addr));
|
||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
addr.sin_port = htons(port);
|
addr.sin_port = htons(port);
|
||||||
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
addr.sin_addr.s_addr = htonl(interface_address);
|
||||||
|
|
||||||
|
// TODO: Consider using dual-stack socket that can simultaneously listen on
|
||||||
|
// IPv4 and IPv6.
|
||||||
s = socket(AF_INET, type, 0);
|
s = socket(AF_INET, type, 0);
|
||||||
if(s == INVALID_SOCKET) return -1;
|
if (s == INVALID_SOCKET) {
|
||||||
|
*error = SystemErrorCodeToString(WSAGetLastError());
|
||||||
|
D("could not create socket: %s\n", error->c_str());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
f->fh_socket = s;
|
f->fh_socket = s;
|
||||||
|
|
||||||
n = 1;
|
n = 1;
|
||||||
setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char*)&n, sizeof(n));
|
if (setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char*)&n,
|
||||||
|
sizeof(n)) == SOCKET_ERROR) {
|
||||||
|
*error = SystemErrorCodeToString(WSAGetLastError());
|
||||||
|
D("setsockopt level %d optname %d failed: %s\n",
|
||||||
|
SOL_SOCKET, SO_EXCLUSIVEADDRUSE, error->c_str());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) == SOCKET_ERROR) {
|
||||||
_fh_close(f);
|
*error = SystemErrorCodeToString(WSAGetLastError());
|
||||||
|
D("could not bind to %s:%d: %s\n",
|
||||||
|
type != SOCK_STREAM ? "udp" : "tcp", port, error->c_str());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (type == SOCK_STREAM) {
|
if (type == SOCK_STREAM) {
|
||||||
int ret;
|
if (listen(s, LISTEN_BACKLOG) == SOCKET_ERROR) {
|
||||||
|
*error = SystemErrorCodeToString(WSAGetLastError());
|
||||||
ret = listen(s, LISTEN_BACKLOG);
|
D("could not listen on %s:%d: %s\n",
|
||||||
if (ret < 0) {
|
type != SOCK_STREAM ? "udp" : "tcp", port, error->c_str());
|
||||||
_fh_close(f);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
snprintf( f->name, sizeof(f->name), "%d(lo-server:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
|
const int fd = _fh_to_int(f.get());
|
||||||
D( "socket_loopback_server: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
|
snprintf( f->name, sizeof(f->name), "%d(%s-server:%s%d)", fd,
|
||||||
return _fh_to_int(f);
|
interface_address == INADDR_LOOPBACK ? "lo" : "any",
|
||||||
|
type != SOCK_STREAM ? "udp:" : "", port );
|
||||||
|
D( "port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp",
|
||||||
|
fd );
|
||||||
|
f.release();
|
||||||
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int network_loopback_server(int port, int type, std::string* error) {
|
||||||
|
return _network_server(port, type, INADDR_LOOPBACK, error);
|
||||||
|
}
|
||||||
|
|
||||||
int socket_network_client_timeout(const char *host, int port, int type, int timeout,
|
int network_inaddr_any_server(int port, int type, std::string* error) {
|
||||||
int* getaddrinfo_error) {
|
return _network_server(port, type, INADDR_ANY, error);
|
||||||
FH f = _fh_alloc( &_fh_socket_class );
|
}
|
||||||
if (!f) return -1;
|
|
||||||
|
int network_connect(const std::string& host, int port, int type, int timeout, std::string* error) {
|
||||||
|
unique_fh f(_fh_alloc(&_fh_socket_class));
|
||||||
|
if (!f) {
|
||||||
|
*error = strerror(errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (!_winsock_init) _init_winsock();
|
if (!_winsock_init) _init_winsock();
|
||||||
|
|
||||||
hostent* hp = gethostbyname(host);
|
struct addrinfo hints;
|
||||||
if(hp == 0) {
|
memset(&hints, 0, sizeof(hints));
|
||||||
_fh_close(f);
|
hints.ai_family = AF_UNSPEC;
|
||||||
|
hints.ai_socktype = type;
|
||||||
|
|
||||||
|
char port_str[16];
|
||||||
|
snprintf(port_str, sizeof(port_str), "%d", port);
|
||||||
|
|
||||||
|
struct addrinfo* addrinfo_ptr = nullptr;
|
||||||
|
if (getaddrinfo(host.c_str(), port_str, &hints, &addrinfo_ptr) != 0) {
|
||||||
|
*error = SystemErrorCodeToString(WSAGetLastError());
|
||||||
|
D("could not resolve host '%s' and port %s: %s\n", host.c_str(),
|
||||||
|
port_str, error->c_str());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
std::unique_ptr<struct addrinfo, decltype(freeaddrinfo)*>
|
||||||
|
addrinfo(addrinfo_ptr, freeaddrinfo);
|
||||||
|
addrinfo_ptr = nullptr;
|
||||||
|
|
||||||
sockaddr_in addr;
|
// TODO: Try all the addresses if there's more than one? This just uses
|
||||||
memset(&addr, 0, sizeof(addr));
|
// the first. Or, could call WSAConnectByName() (Windows Vista and newer)
|
||||||
addr.sin_family = hp->h_addrtype;
|
// which tries all addresses, takes a timeout and more.
|
||||||
addr.sin_port = htons(port);
|
SOCKET s = socket(addrinfo->ai_family, addrinfo->ai_socktype,
|
||||||
memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
|
addrinfo->ai_protocol);
|
||||||
|
|
||||||
SOCKET s = socket(hp->h_addrtype, type, 0);
|
|
||||||
if(s == INVALID_SOCKET) {
|
if(s == INVALID_SOCKET) {
|
||||||
_fh_close(f);
|
*error = SystemErrorCodeToString(WSAGetLastError());
|
||||||
|
D("could not create socket: %s\n", error->c_str());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
f->fh_socket = s;
|
f->fh_socket = s;
|
||||||
|
|
||||||
// TODO: implement timeouts for Windows.
|
// TODO: Implement timeouts for Windows. Seems like the default in theory
|
||||||
|
// (according to http://serverfault.com/a/671453) and in practice is 21 sec.
|
||||||
if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
if(connect(s, addrinfo->ai_addr, addrinfo->ai_addrlen) == SOCKET_ERROR) {
|
||||||
_fh_close(f);
|
*error = SystemErrorCodeToString(WSAGetLastError());
|
||||||
|
D("could not connect to %s:%s:%s: %s\n",
|
||||||
|
type != SOCK_STREAM ? "udp" : "tcp", host.c_str(), port_str,
|
||||||
|
error->c_str());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf( f->name, sizeof(f->name), "%d(net-client:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
|
const int fd = _fh_to_int(f.get());
|
||||||
D( "socket_network_client_timeout: host '%s' port %d type %s => fd %d\n", host, port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
|
snprintf( f->name, sizeof(f->name), "%d(net-client:%s%d)", fd,
|
||||||
return _fh_to_int(f);
|
type != SOCK_STREAM ? "udp:" : "", port );
|
||||||
}
|
D( "host '%s' port %d type %s => fd %d\n", host.c_str(), port,
|
||||||
|
type != SOCK_STREAM ? "udp" : "tcp", fd );
|
||||||
|
f.release();
|
||||||
int socket_inaddr_any_server(int port, int type)
|
return fd;
|
||||||
{
|
|
||||||
FH f = _fh_alloc( &_fh_socket_class );
|
|
||||||
struct sockaddr_in addr;
|
|
||||||
SOCKET s;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
if (!f)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (!_winsock_init)
|
|
||||||
_init_winsock();
|
|
||||||
|
|
||||||
memset(&addr, 0, sizeof(addr));
|
|
||||||
addr.sin_family = AF_INET;
|
|
||||||
addr.sin_port = htons(port);
|
|
||||||
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
||||||
|
|
||||||
s = socket(AF_INET, type, 0);
|
|
||||||
if(s == INVALID_SOCKET) {
|
|
||||||
_fh_close(f);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
f->fh_socket = s;
|
|
||||||
n = 1;
|
|
||||||
setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char*)&n, sizeof(n));
|
|
||||||
|
|
||||||
if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
|
||||||
_fh_close(f);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == SOCK_STREAM) {
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = listen(s, LISTEN_BACKLOG);
|
|
||||||
if (ret < 0) {
|
|
||||||
_fh_close(f);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
snprintf( f->name, sizeof(f->name), "%d(any-server:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
|
|
||||||
D( "socket_inaddr_server: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
|
|
||||||
return _fh_to_int(f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef accept
|
#undef accept
|
||||||
int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrlen)
|
int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrlen)
|
||||||
{
|
{
|
||||||
FH serverfh = _fh_from_int(serverfd, __func__);
|
FH serverfh = _fh_from_int(serverfd, __func__);
|
||||||
FH fh;
|
|
||||||
|
|
||||||
if ( !serverfh || serverfh->clazz != &_fh_socket_class ) {
|
if ( !serverfh || serverfh->clazz != &_fh_socket_class ) {
|
||||||
D( "adb_socket_accept: invalid fd %d\n", serverfd );
|
D("adb_socket_accept: invalid fd %d\n", serverfd);
|
||||||
|
errno = EBADF;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fh = _fh_alloc( &_fh_socket_class );
|
unique_fh fh(_fh_alloc( &_fh_socket_class ));
|
||||||
if (!fh) {
|
if (!fh) {
|
||||||
D( "adb_socket_accept: not enough memory to allocate accepted socket descriptor\n" );
|
PLOG(ERROR) << "adb_socket_accept: failed to allocate accepted socket "
|
||||||
|
"descriptor";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fh->fh_socket = accept( serverfh->fh_socket, addr, addrlen );
|
fh->fh_socket = accept( serverfh->fh_socket, addr, addrlen );
|
||||||
if (fh->fh_socket == INVALID_SOCKET) {
|
if (fh->fh_socket == INVALID_SOCKET) {
|
||||||
const DWORD err = WSAGetLastError();
|
const DWORD err = WSAGetLastError();
|
||||||
_fh_close( fh );
|
LOG(ERROR) << "adb_socket_accept: accept on fd " << serverfd <<
|
||||||
D( "adb_socket_accept: accept on fd %d return error %ld\n", serverfd, err );
|
" failed: " + SystemErrorCodeToString(err);
|
||||||
|
_socket_set_errno( err );
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf( fh->name, sizeof(fh->name), "%d(accept:%s)", _fh_to_int(fh), serverfh->name );
|
const int fd = _fh_to_int(fh.get());
|
||||||
D( "adb_socket_accept on fd %d returns fd %d\n", serverfd, _fh_to_int(fh) );
|
snprintf( fh->name, sizeof(fh->name), "%d(accept:%s)", fd, serverfh->name );
|
||||||
return _fh_to_int(fh);
|
D( "adb_socket_accept on fd %d returns fd %d\n", serverfd, fd );
|
||||||
|
fh.release();
|
||||||
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -793,10 +883,42 @@ int adb_setsockopt( int fd, int level, int optname, const void* optval, soc
|
||||||
|
|
||||||
if ( !fh || fh->clazz != &_fh_socket_class ) {
|
if ( !fh || fh->clazz != &_fh_socket_class ) {
|
||||||
D("adb_setsockopt: invalid fd %d\n", fd);
|
D("adb_setsockopt: invalid fd %d\n", fd);
|
||||||
|
errno = EBADF;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int result = setsockopt( fh->fh_socket, level, optname,
|
||||||
|
reinterpret_cast<const char*>(optval), optlen );
|
||||||
|
if ( result == SOCKET_ERROR ) {
|
||||||
|
const DWORD err = WSAGetLastError();
|
||||||
|
D( "adb_setsockopt: setsockopt on fd %d level %d optname %d "
|
||||||
|
"failed: %s\n", fd, level, optname,
|
||||||
|
SystemErrorCodeToString(err).c_str() );
|
||||||
|
_socket_set_errno( err );
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int adb_shutdown(int fd)
|
||||||
|
{
|
||||||
|
FH f = _fh_from_int(fd, __func__);
|
||||||
|
|
||||||
|
if (!f || f->clazz != &_fh_socket_class) {
|
||||||
|
D("adb_shutdown: invalid fd %d\n", fd);
|
||||||
|
errno = EBADF;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return setsockopt( fh->fh_socket, level, optname, reinterpret_cast<const char*>(optval), optlen );
|
D( "adb_shutdown: %s\n", f->name);
|
||||||
|
if (shutdown(f->fh_socket, SD_BOTH) == SOCKET_ERROR) {
|
||||||
|
const DWORD err = WSAGetLastError();
|
||||||
|
D("socket shutdown fd %d failed: %s\n", fd,
|
||||||
|
SystemErrorCodeToString(err).c_str());
|
||||||
|
_socket_set_errno(err);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
|
|
@ -1199,16 +1321,19 @@ static const FHClassRec _fh_socketpair_class =
|
||||||
int adb_socketpair(int sv[2]) {
|
int adb_socketpair(int sv[2]) {
|
||||||
SocketPair pair;
|
SocketPair pair;
|
||||||
|
|
||||||
FH fa = _fh_alloc(&_fh_socketpair_class);
|
unique_fh fa(_fh_alloc(&_fh_socketpair_class));
|
||||||
FH fb = _fh_alloc(&_fh_socketpair_class);
|
if (!fa) {
|
||||||
|
return -1;
|
||||||
if (!fa || !fb)
|
}
|
||||||
goto Fail;
|
unique_fh fb(_fh_alloc(&_fh_socketpair_class));
|
||||||
|
if (!fb) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
pair = reinterpret_cast<SocketPair>(malloc(sizeof(*pair)));
|
pair = reinterpret_cast<SocketPair>(malloc(sizeof(*pair)));
|
||||||
if (pair == NULL) {
|
if (pair == NULL) {
|
||||||
D("adb_socketpair: not enough memory to allocate pipes\n" );
|
D("adb_socketpair: not enough memory to allocate pipes\n" );
|
||||||
goto Fail;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bip_buffer_init( &pair->a2b_bip );
|
bip_buffer_init( &pair->a2b_bip );
|
||||||
|
|
@ -1217,10 +1342,10 @@ int adb_socketpair(int sv[2]) {
|
||||||
fa->fh_pair = pair;
|
fa->fh_pair = pair;
|
||||||
fb->fh_pair = pair;
|
fb->fh_pair = pair;
|
||||||
pair->used = 2;
|
pair->used = 2;
|
||||||
pair->a_fd = fa;
|
pair->a_fd = fa.get();
|
||||||
|
|
||||||
sv[0] = _fh_to_int(fa);
|
sv[0] = _fh_to_int(fa.get());
|
||||||
sv[1] = _fh_to_int(fb);
|
sv[1] = _fh_to_int(fb.get());
|
||||||
|
|
||||||
pair->a2b_bip.fdin = sv[0];
|
pair->a2b_bip.fdin = sv[0];
|
||||||
pair->a2b_bip.fdout = sv[1];
|
pair->a2b_bip.fdout = sv[1];
|
||||||
|
|
@ -1230,12 +1355,9 @@ int adb_socketpair(int sv[2]) {
|
||||||
snprintf( fa->name, sizeof(fa->name), "%d(pair:%d)", sv[0], sv[1] );
|
snprintf( fa->name, sizeof(fa->name), "%d(pair:%d)", sv[0], sv[1] );
|
||||||
snprintf( fb->name, sizeof(fb->name), "%d(pair:%d)", sv[1], sv[0] );
|
snprintf( fb->name, sizeof(fb->name), "%d(pair:%d)", sv[1], sv[0] );
|
||||||
D( "adb_socketpair: returns (%d, %d)\n", sv[0], sv[1] );
|
D( "adb_socketpair: returns (%d, %d)\n", sv[0], sv[1] );
|
||||||
|
fa.release();
|
||||||
|
fb.release();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
Fail:
|
|
||||||
_fh_close(fb);
|
|
||||||
_fh_close(fa);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
|
|
@ -2083,6 +2205,7 @@ static void _fh_socket_hook( FH f, int events, EventHook hook )
|
||||||
hook->check = _event_socket_check;
|
hook->check = _event_socket_check;
|
||||||
hook->peek = _event_socket_peek;
|
hook->peek = _event_socket_peek;
|
||||||
|
|
||||||
|
// TODO: check return value?
|
||||||
_event_socket_start( hook );
|
_event_socket_start( hook );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ int local_connect_arbitrary_ports(int console_port, int adb_port, std::string* e
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
fd = socket_loopback_client(adb_port, SOCK_STREAM);
|
fd = network_loopback_client(adb_port, SOCK_STREAM, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
|
|
@ -144,9 +144,10 @@ static void *server_socket_thread(void * arg)
|
||||||
serverfd = -1;
|
serverfd = -1;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if(serverfd == -1) {
|
if(serverfd == -1) {
|
||||||
serverfd = socket_inaddr_any_server(port, SOCK_STREAM);
|
std::string error;
|
||||||
|
serverfd = network_inaddr_any_server(port, SOCK_STREAM, &error);
|
||||||
if(serverfd < 0) {
|
if(serverfd < 0) {
|
||||||
D("server: cannot bind socket yet: %s\n", strerror(errno));
|
D("server: cannot bind socket yet: %s\n", error.c_str());
|
||||||
adb_sleep_ms(1000);
|
adb_sleep_ms(1000);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue