Remove the separate JdwpTransport objects.
Structs containing nothing but function pointers? What are we? C programmers?
Change-Id: I4fbc9dc0d8fc10557afa020b27cda85c939965c3
diff --git a/src/jdwp/jdwp_socket.cc b/src/jdwp/jdwp_socket.cc
index 755ded5..08b4859 100644
--- a/src/jdwp/jdwp_socket.cc
+++ b/src/jdwp/jdwp_socket.cc
@@ -42,45 +42,41 @@
*
* We only talk to one debugger at a time.
*/
-struct JdwpNetState : public JdwpNetStateBase {
+struct JdwpSocketState : public JdwpNetStateBase {
uint16_t listenPort;
int listenSock; /* listen for connection from debugger */
- int wakePipe[2]; /* break out of select */
- in_addr remoteAddr;
- uint16_t remotePort;
-
- JdwpNetState() {
+ JdwpSocketState(JdwpState* state) : JdwpNetStateBase(state) {
listenPort = 0;
listenSock = -1;
- wakePipe[0] = -1;
- wakePipe[1] = -1;
}
+
+ virtual bool Accept();
+ virtual bool Establish(const JdwpOptions*);
+ virtual void Shutdown();
+ virtual bool ProcessIncoming();
+
+ private:
+ in_addr remote_addr_;
+ uint16_t remote_port_;
};
-static void socketStateShutdown(JdwpNetState* state);
-static void socketStateFree(JdwpNetState* state);
-
-static JdwpNetState* GetNetState(JdwpState* state) {
- return reinterpret_cast<JdwpNetState*>(state->netState);
-}
-
-static JdwpNetState* netStartup(uint16_t port, bool probe);
+static JdwpSocketState* SocketStartup(JdwpState* state, uint16_t port, bool probe);
/*
* Set up some stuff for transport=dt_socket.
*/
-static bool prepareSocket(JdwpState* state, const JdwpOptions* options) {
+bool InitSocketTransport(JdwpState* state, const JdwpOptions* options) {
uint16_t port = options->port;
if (options->server) {
if (options->port != 0) {
/* try only the specified port */
- state->netState = netStartup(port, false);
+ state->netState = SocketStartup(state, port, false);
} else {
/* scan through a range of ports, binding to the first available */
for (port = kBasePort; port <= kMaxPort; port++) {
- state->netState = netStartup(port, true);
+ state->netState = SocketStartup(state, port, true);
if (state->netState != NULL) {
break;
}
@@ -91,7 +87,7 @@
return false;
}
} else {
- state->netState = netStartup(0, false);
+ state->netState = SocketStartup(state, 0, false);
}
if (options->suspend) {
@@ -115,8 +111,8 @@
*
* Returns 0 on success.
*/
-static JdwpNetState* netStartup(uint16_t port, bool probe) {
- JdwpNetState* netState = new JdwpNetState;
+static JdwpSocketState* SocketStartup(JdwpState* state, uint16_t port, bool probe) {
+ JdwpSocketState* netState = new JdwpSocketState(state);
if (port == 0) {
return netState;
}
@@ -159,80 +155,38 @@
return netState;
fail:
- socketStateShutdown(netState);
- socketStateFree(netState);
+ netState->Shutdown();
+ delete netState;
return NULL;
}
/*
* Shut down JDWP listener. Don't free state.
*
- * Note that "netState" may be partially initialized if "startup" failed.
- *
* This may be called from a non-JDWP thread as part of shutting the
* JDWP thread down.
*
* (This is currently called several times during startup as we probe
* for an open port.)
*/
-static void socketStateShutdown(JdwpNetState* netState) {
- if (netState == NULL) {
- return;
- }
-
- int listenSock = netState->listenSock;
- int clientSock = netState->clientSock;
+void JdwpSocketState::Shutdown() {
+ int listenSock = this->listenSock;
+ int clientSock = this->clientSock;
/* clear these out so it doesn't wake up and try to reuse them */
- netState->listenSock = netState->clientSock = -1;
+ this->listenSock = this->clientSock = -1;
/* "shutdown" dislodges blocking read() and accept() calls */
- if (listenSock >= 0) {
+ if (listenSock != -1) {
shutdown(listenSock, SHUT_RDWR);
close(listenSock);
}
- if (clientSock >= 0) {
+ if (clientSock != -1) {
shutdown(clientSock, SHUT_RDWR);
close(clientSock);
}
- /* if we might be sitting in select, kick us loose */
- if (netState->wakePipe[1] >= 0) {
- VLOG(jdwp) << "+++ writing to wakePipe";
- TEMP_FAILURE_RETRY(write(netState->wakePipe[1], "", 1));
- }
-}
-
-static void netShutdown(JdwpState* state) {
- socketStateShutdown(GetNetState(state));
-}
-
-/*
- * Free JDWP state.
- *
- * Call this after shutting the network down with socketStateShutdown().
- */
-static void socketStateFree(JdwpNetState* netState) {
- if (netState == NULL) {
- return;
- }
- CHECK_EQ(netState->listenSock, -1);
- CHECK_EQ(netState->clientSock, -1);
-
- if (netState->wakePipe[0] >= 0) {
- close(netState->wakePipe[0]);
- netState->wakePipe[0] = -1;
- }
- if (netState->wakePipe[1] >= 0) {
- close(netState->wakePipe[1]);
- netState->wakePipe[1] = -1;
- }
-
- delete netState;
-}
-
-static void netFree(JdwpState* state) {
- socketStateFree(GetNetState(state));
+ WakePipe();
}
/*
@@ -240,7 +194,7 @@
* packets until the previous transmissions have been acked. JDWP does a
* lot of back-and-forth with small packets, so this may help.
*/
-static int setNoDelay(int fd) {
+static int SetNoDelay(int fd) {
int on = 1;
int cc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
CHECK_EQ(cc, 0);
@@ -252,8 +206,7 @@
* If that's not desirable, use checkConnection() to make sure something
* is pending.
*/
-static bool acceptConnection(JdwpState* state) {
- JdwpNetState* netState = GetNetState(state);
+bool JdwpSocketState::Accept() {
union {
sockaddr_in addrInet;
sockaddr addrPlain;
@@ -261,15 +214,15 @@
socklen_t addrlen;
int sock;
- if (netState->listenSock < 0) {
+ if (listenSock < 0) {
return false; /* you're not listening! */
}
- CHECK_LT(netState->clientSock, 0); /* must not already be talking */
+ CHECK(clientSock == -1); /* must not already be talking */
addrlen = sizeof(addr);
do {
- sock = accept(netState->listenSock, &addr.addrPlain, &addrlen);
+ sock = accept(listenSock, &addr.addrPlain, &addrlen);
if (sock < 0 && errno != EINTR) {
// When we call shutdown() on the socket, accept() returns with
// EINVAL. Don't gripe about it.
@@ -284,19 +237,18 @@
}
} while (sock < 0);
- netState->remoteAddr = addr.addrInet.sin_addr;
- netState->remotePort = ntohs(addr.addrInet.sin_port);
- VLOG(jdwp) << "+++ accepted connection from " << inet_ntoa(netState->remoteAddr) << ":" << netState->remotePort;
+ remote_addr_ = addr.addrInet.sin_addr;
+ remote_port_ = ntohs(addr.addrInet.sin_port);
+ VLOG(jdwp) << "+++ accepted connection from " << inet_ntoa(remote_addr_) << ":" << remote_port_;
- netState->clientSock = sock;
- netState->SetAwaitingHandshake(true);
- netState->inputCount = 0;
+ clientSock = sock;
+ SetAwaitingHandshake(true);
+ input_count_ = 0;
VLOG(jdwp) << "Setting TCP_NODELAY on accepted socket";
- setNoDelay(netState->clientSock);
+ SetNoDelay(clientSock);
- if (pipe(netState->wakePipe) < 0) {
- PLOG(ERROR) << "pipe failed";
+ if (!MakePipe()) {
return false;
}
@@ -306,14 +258,13 @@
/*
* Create a connection to a waiting debugger.
*/
-static bool establishConnection(JdwpState* state, const JdwpOptions* options) {
+bool JdwpSocketState::Establish(const JdwpOptions* options) {
union {
sockaddr_in addrInet;
sockaddr addrPlain;
} addr;
hostent* pEntry;
- CHECK(state != NULL && state->netState != NULL);
CHECK(!options->server);
CHECK(!options->host.empty());
CHECK_NE(options->port, 0);
@@ -321,8 +272,6 @@
/*
* Start by resolving the host name.
*/
-//#undef HAVE_GETHOSTBYNAME_R
-//#warning "forcing non-R"
#ifdef HAVE_GETHOSTBYNAME_R
hostent he;
char auxBuf[128];
@@ -352,9 +301,8 @@
/*
* Create a socket.
*/
- JdwpNetState* netState = GetNetState(state);
- netState->clientSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (netState->clientSock < 0) {
+ clientSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (clientSock < 0) {
PLOG(ERROR) << "Unable to create socket";
return false;
}
@@ -362,21 +310,20 @@
/*
* Try to connect.
*/
- if (connect(netState->clientSock, &addr.addrPlain, sizeof(addr)) != 0) {
+ if (connect(clientSock, &addr.addrPlain, sizeof(addr)) != 0) {
PLOG(ERROR) << "Unable to connect to " << inet_ntoa(addr.addrInet.sin_addr) << ":" << ntohs(addr.addrInet.sin_port);
- close(netState->clientSock);
- netState->clientSock = -1;
+ close(clientSock);
+ clientSock = -1;
return false;
}
LOG(INFO) << "Connection established to " << options->host << " (" << inet_ntoa(addr.addrInet.sin_addr) << ":" << ntohs(addr.addrInet.sin_port) << ")";
- netState->SetAwaitingHandshake(true);
- netState->inputCount = 0;
+ SetAwaitingHandshake(true);
+ input_count_ = 0;
- setNoDelay(netState->clientSock);
+ SetNoDelay(clientSock);
- if (pipe(netState->wakePipe) < 0) {
- PLOG(ERROR) << "pipe failed";
+ if (!MakePipe()) {
return false;
}
@@ -398,27 +345,45 @@
* Returns "false" on error (indicating that the connection has been severed),
* "true" if things are still okay.
*/
-static bool processIncoming(JdwpState* state) {
- JdwpNetState* netState = GetNetState(state);
+bool JdwpSocketState::ProcessIncoming() {
int readCount;
- CHECK_GE(netState->clientSock, 0);
+ CHECK(clientSock != -1);
- if (!netState->HaveFullPacket()) {
+ if (!HaveFullPacket()) {
/* read some more, looping until we have data */
errno = 0;
while (1) {
int selCount;
fd_set readfds;
- int maxfd;
+ int maxfd = -1;
int fd;
- maxfd = netState->listenSock;
- if (netState->clientSock > maxfd) {
- maxfd = netState->clientSock;
+ FD_ZERO(&readfds);
+
+ /* configure fds; note these may get zapped by another thread */
+ fd = listenSock;
+ if (fd >= 0) {
+ FD_SET(fd, &readfds);
+ if (maxfd < fd) {
+ maxfd = fd;
+ }
}
- if (netState->wakePipe[0] > maxfd) {
- maxfd = netState->wakePipe[0];
+ fd = clientSock;
+ if (fd >= 0) {
+ FD_SET(fd, &readfds);
+ if (maxfd < fd) {
+ maxfd = fd;
+ }
+ }
+ fd = wake_pipe_[0];
+ if (fd >= 0) {
+ FD_SET(fd, &readfds);
+ if (maxfd < fd) {
+ maxfd = fd;
+ }
+ } else {
+ LOG(INFO) << "NOTE: entering select w/o wakepipe";
}
if (maxfd < 0) {
@@ -426,24 +391,6 @@
return false;
}
- FD_ZERO(&readfds);
-
- /* configure fds; note these may get zapped by another thread */
- fd = netState->listenSock;
- if (fd >= 0) {
- FD_SET(fd, &readfds);
- }
- fd = netState->clientSock;
- if (fd >= 0) {
- FD_SET(fd, &readfds);
- }
- fd = netState->wakePipe[0];
- if (fd >= 0) {
- FD_SET(fd, &readfds);
- } else {
- LOG(INFO) << "NOTE: entering select w/o wakepipe";
- }
-
/*
* Select blocks until it sees activity on the file descriptors.
* Closing the local file descriptor does not count as activity,
@@ -451,7 +398,7 @@
* and accept(), but not select()).
*
* We can do one of three things: (1) send a signal and catch
- * EINTR, (2) open an additional fd ("wakePipe") and write to
+ * EINTR, (2) open an additional fd ("wake pipe") and write to
* it when it's time to exit, or (3) time out periodically and
* re-issue the select. We're currently using #2, as it's more
* reliable than #1 and generally better than #3. Wastes two fds.
@@ -465,15 +412,15 @@
goto fail;
}
- if (netState->wakePipe[0] >= 0 && FD_ISSET(netState->wakePipe[0], &readfds)) {
- if (netState->listenSock >= 0) {
+ if (wake_pipe_[0] >= 0 && FD_ISSET(wake_pipe_[0], &readfds)) {
+ if (listenSock >= 0) {
LOG(ERROR) << "Exit wake set, but not exiting?";
} else {
LOG(DEBUG) << "Got wake-up signal, bailing out of select";
}
goto fail;
}
- if (netState->listenSock >= 0 && FD_ISSET(netState->listenSock, &readfds)) {
+ if (listenSock >= 0 && FD_ISSET(listenSock, &readfds)) {
LOG(INFO) << "Ignoring second debugger -- accepting and dropping";
union {
sockaddr_in addrInet;
@@ -481,15 +428,15 @@
} addr;
socklen_t addrlen;
int tmpSock;
- tmpSock = accept(netState->listenSock, &addr.addrPlain, &addrlen);
+ tmpSock = accept(listenSock, &addr.addrPlain, &addrlen);
if (tmpSock < 0) {
LOG(INFO) << "Weird -- accept failed";
} else {
close(tmpSock);
}
}
- if (netState->clientSock >= 0 && FD_ISSET(netState->clientSock, &readfds)) {
- readCount = read(netState->clientSock, netState->inputBuffer + netState->inputCount, sizeof(netState->inputBuffer) - netState->inputCount);
+ if (clientSock >= 0 && FD_ISSET(clientSock, &readfds)) {
+ readCount = read(clientSock, input_buffer_ + input_count_, sizeof(input_buffer_) - input_count_);
if (readCount < 0) {
/* read failed */
if (errno != EINTR) {
@@ -507,8 +454,8 @@
}
}
- netState->inputCount += readCount;
- if (!netState->HaveFullPacket()) {
+ input_count_ += readCount;
+ if (!HaveFullPacket()) {
return true; /* still not there yet */
}
}
@@ -521,23 +468,21 @@
*
* Other than this one case, the protocol [claims to be] stateless.
*/
- if (netState->IsAwaitingHandshake()) {
- int cc;
-
- if (memcmp(netState->inputBuffer, kMagicHandshake, kMagicHandshakeLen) != 0) {
- LOG(ERROR) << StringPrintf("ERROR: bad handshake '%.14s'", netState->inputBuffer);
+ if (IsAwaitingHandshake()) {
+ if (memcmp(input_buffer_, kMagicHandshake, kMagicHandshakeLen) != 0) {
+ LOG(ERROR) << StringPrintf("ERROR: bad handshake '%.14s'", input_buffer_);
goto fail;
}
errno = 0;
- cc = TEMP_FAILURE_RETRY(write(netState->clientSock, netState->inputBuffer, kMagicHandshakeLen));
+ int cc = TEMP_FAILURE_RETRY(write(clientSock, input_buffer_, kMagicHandshakeLen));
if (cc != kMagicHandshakeLen) {
PLOG(ERROR) << "Failed writing handshake bytes (" << cc << " of " << kMagicHandshakeLen << ")";
goto fail;
}
- netState->ConsumeBytes(kMagicHandshakeLen);
- netState->SetAwaitingHandshake(false);
+ ConsumeBytes(kMagicHandshakeLen);
+ SetAwaitingHandshake(false);
VLOG(jdwp) << "+++ handshake complete";
return true;
}
@@ -545,36 +490,13 @@
/*
* Handle this packet.
*/
- return state->HandlePacket();
+ return state_->HandlePacket();
fail:
- netState->Close();
+ Close();
return false;
}
-/*
- * Our functions.
- *
- * We can't generally share the implementations with other transports,
- * even if they're also socket-based, because our JdwpNetState will be
- * different from theirs.
- */
-static const JdwpTransport socketTransport = {
- prepareSocket,
- acceptConnection,
- establishConnection,
- netShutdown,
- netFree,
- processIncoming,
-};
-
-/*
- * Return our set.
- */
-const JdwpTransport* SocketTransport() {
- return &socketTransport;
-}
-
} // namespace JDWP
} // namespace art