一、先分析Native层:
1、C++基类SocketListener:
-
class SocketListener {
-
int mSock;
-
const char *mSocketName;
-
SocketClientCollection *mClients;
-
pthread_mutex_t mClientsLock;
-
bool mListen;
-
int mCtrlPipe[2];
-
pthread_t mThread;
-
-
public:
-
SocketListener(const char *socketNames, bool listen);
-
SocketListener(int socketFd, bool listen);
-
-
virtual ~SocketListener();
-
int startListener();
-
int stopListener();
-
-
void sendBroadcast(int code, const char *msg, bool addErrno);
-
void sendBroadcast(const char *msg);
-
-
protected:
-
virtual bool onDataAvailable(SocketClient *c) = 0;
-
-
private:
-
static void *threadStart(void *obj);
-
void runListener();
-
};
-
#endif
看关键接口runListener:
-
void SocketListener::runListener() {
-
-
while(1) {
-
SocketClientCollection::iterator it;
-
fd_set read_fds;
-
int rc = 0;
-
int max = 0;
-
-
FD_ZERO(&read_fds);
-
-
if (mListen) {
-
max = mSock;
-
FD_SET(mSock, &read_fds);
-
}
-
-
FD_SET(mCtrlPipe[0], &read_fds);
-
if (mCtrlPipe[0] > max)
-
max = mCtrlPipe[0];
-
-
pthread_mutex_lock(&mClientsLock);
-
for (it = mClients->begin(); it != mClients->end(); ++it) {
-
FD_SET((*it)->getSocket(), &read_fds);
-
if ((*it)->getSocket() > max)
-
max = (*it)->getSocket();
-
}
-
pthread_mutex_unlock(&mClientsLock);
-
-
if ((rc = select(max + 1, &read_fds, NULL, NULL, NULL)) < 0) {
-
SLOGE("select failed (%s)", strerror(errno));
-
sleep(1);
-
continue;
-
} else if (!rc)
-
continue;
-
-
if (FD_ISSET(mCtrlPipe[0], &read_fds))
-
break;
-
if (mListen && FD_ISSET(mSock, &read_fds)) {
-
struct sockaddr addr;
-
socklen_t alen = sizeof(addr);
-
int c;
-
-
if ((c = accept(mSock, &addr, &alen)) < 0) {
-
SLOGE("accept failed (%s)", strerror(errno));
-
sleep(1);
-
continue;
-
}
-
pthread_mutex_lock(&mClientsLock);
-
mClients->push_back(new SocketClient(c));
-
pthread_mutex_unlock(&mClientsLock);
-
}
-
-
do {
-
pthread_mutex_lock(&mClientsLock);
-
for (it = mClients->begin(); it != mClients->end(); ++it) {
-
int fd = (*it)->getSocket();
-
if (FD_ISSET(fd, &read_fds)) {
-
pthread_mutex_unlock(&mClientsLock);
-
if (!onDataAvailable(*it)) {//由子类实现的接口。
-
close(fd);
-
pthread_mutex_lock(&mClientsLock);
-
delete *it;
-
it = mClients->erase(it);
-
pthread_mutex_unlock(&mClientsLock);
-
}
-
FD_CLR(fd, &read_fds);
-
continue;
-
}
-
}
-
pthread_mutex_unlock(&mClientsLock);
-
} while (0);
-
}
-
}
2、他的第一继承者:
-
#include "SocketListener.h"
-
#include "FrameworkCommand.h"
-
-
class SocketClient;
-
-
class FrameworkListener : public SocketListener {
-
public:
-
static const int CMD_ARGS_MAX = 16;
-
private:
-
FrameworkCommandCollection *mCommands;
-
-
public:
-
FrameworkListener(const char *socketName);
-
virtual ~FrameworkListener() {}
-
-
protected:
-
void registerCmd(FrameworkCommand *cmd);
-
virtual bool onDataAvailable(SocketClient *c);
-
-
private:
-
void dispatchCommand(SocketClient *c, char *data);
-
};
他的onDataAvailable接口实现:
-
bool FrameworkListener::onDataAvailable(SocketClient *c) {
-
char buffer[255];
-
int len;
-
-
if ((len = read(c->getSocket(), buffer, sizeof(buffer) -1)) < 0) {
-
SLOGE("read() failed (%s)", strerror(errno));
-
return errno;
-
} else if (!len)
-
return false;
-
-
int offset = 0;
-
int i;
-
-
for (i = 0; i < len; i++) {
-
if (buffer[i] == '\0') {
-
dispatchCommand(c, buffer + offset);
-
offset = i + 1;
-
}
-
}
-
return true;
-
}
3、实例:netd的CommandListener类:
-
class CommandListener : public FrameworkListener {
-
static TetherController *sTetherCtrl;
-
static NatController *sNatCtrl;
-
static PppController *sPppCtrl;
-
static PanController *sPanCtrl;
-
static SoftapController *sSoftapCtrl;
-
static UsbController *sUsbCtrl;
-
-
public:
-
CommandListener();
-
virtual ~CommandListener() {}
-
-
private:
-
-
static int readInterfaceCounters(const char *iface, unsigned long *rx, unsigned long *tx);
-
-
class UsbCmd : public NetdCommand {
-
public:
-
UsbCmd();
-
virtual ~UsbCmd() {}
-
int runCommand(SocketClient *c, int argc, char ** argv);
-
};
-
-
class SoftapCmd : public NetdCommand {
-
public:
-
SoftapCmd();
-
virtual ~SoftapCmd() {}
-
int runCommand(SocketClient *c, int argc, char ** argv);
-
};
-
-
class InterfaceCmd : public NetdCommand {
-
public:
-
InterfaceCmd();
-
virtual ~InterfaceCmd() {}
-
int runCommand(SocketClient *c, int argc, char ** argv);
-
};
-
-
class IpFwdCmd : public NetdCommand {
-
public:
-
IpFwdCmd();
-
virtual ~IpFwdCmd() {}
-
int runCommand(SocketClient *c, int argc, char ** argv);
-
};
-
-
class TetherCmd : public NetdCommand {
-
public:
-
TetherCmd();
-
virtual ~TetherCmd() {}
-
int runCommand(SocketClient *c, int argc, char ** argv);
-
};
-
-
class NatCmd : public NetdCommand {
-
public:
-
NatCmd();
-
virtual ~NatCmd() {}
-
int runCommand(SocketClient *c, int argc, char ** argv);
-
};
-
-
class ListTtysCmd : public NetdCommand {
-
public:
-
ListTtysCmd();
-
virtual ~ListTtysCmd() {}
-
int runCommand(SocketClient *c, int argc, char ** argv);
-
};
-
-
class PppdCmd : public NetdCommand {
-
public:
-
PppdCmd();
-
virtual ~PppdCmd() {}
-
int runCommand(SocketClient *c, int argc, char ** argv);
-
};
-
-
class PanCmd : public NetdCommand {
-
public:
-
PanCmd();
-
virtual ~PanCmd() {}
-
int runCommand(SocketClient *c, int argc, char ** argv);
-
};
-
};
不能忘记NetdCommand类:
-
#include <sysutils/FrameworkCommand.h>
-
-
class NetdCommand : public FrameworkCommand {
-
public:
-
NetdCommand(const char *cmd);
-
virtual ~NetdCommand() {}
-
};
-
4、分析一个子类ListTtysCmd:
-
CommandListener::ListTtysCmd::ListTtysCmd() :
-
NetdCommand("list_ttys") {
-
}
-
-
int CommandListener::ListTtysCmd::runCommand(SocketClient *cli,
-
int argc, char **argv) {
-
TtyCollection *tlist = sPppCtrl->getTtyList();
-
TtyCollection::iterator it;
-
-
for (it = tlist->begin(); it != tlist->end(); ++it) {
-
cli->sendMsg(ResponseCode::TtyListResult, *it, false);
-
}
-
-
cli->sendMsg(ResponseCode::CommandOkay, "Ttys listed.", false);
-
return 0;
-
}
Java层:
-
private void listenToSocket() throws IOException {
-
LocalSocket socket = null;
-
-
try {
-
socket = new LocalSocket();
-
LocalSocketAddress address = new LocalSocketAddress(mSocket,
-
LocalSocketAddress.Namespace.RESERVED);
-
-
socket.connect(address);
-
-
InputStream inputStream = socket.getInputStream();
-
mOutputStream = socket.getOutputStream();
-
-
mCallbacks.onDaemonConnected();
-
-
byte[] buffer = new byte[BUFFER_SIZE];
-
int start = 0;
-
-
while (true) {
-
int count = inputStream.read(buffer, start, BUFFER_SIZE - start);
-
if (count < 0) break;
-
-
// Add our starting point to the count and reset the start.
-
count += start;
-
start = 0;
-
-
for (int i = 0; i < count; i++) {
-
if (buffer[i] == 0) {
-
String event = new String(buffer, start, i - start);
-
if (LOCAL_LOGD) Slog.d(TAG, String.format("RCV <- {%s}", event));
-
-
String[] tokens = event.split(" ", 2);
-
try {
-
int code = Integer.parseInt(tokens[0]);
-
-
if (code >= ResponseCode.UnsolicitedInformational) {
-
mCallbackHandler.sendMessage(
-
mCallbackHandler.obtainMessage(code, event));
-
} else {
-
try {
-
mResponseQueue.put(event);
-
} catch (InterruptedException ex) {
-
Slog.e(TAG, "Failed to put response onto queue", ex);
-
}
-
}
-
} catch (NumberFormatException nfe) {
-
Slog.w(TAG, String.format("Bad msg (%s)", event));
-
}
-
start = i + 1;
-
}
-
}
-
-
// We should end at the amount we read. If not, compact then
-
// buffer and read again.
-
if (start != count) {
-
final int remaining = BUFFER_SIZE - start;
-
System.arraycopy(buffer, start, buffer, 0, remaining);
-
start = remaining;
-
} else {
-
start = 0;
-
}
-
}
-
} catch (IOException ex) {
-
Slog.e(TAG, "Communications error", ex);
-
throw ex;
-
} finally {
-
synchronized (mDaemonLock) {
-
if (mOutputStream != null) {
-
try {
-
mOutputStream.close();
-
} catch (IOException e) {
-
Slog.w(TAG, "Failed closing output stream", e);
-
}
-
mOutputStream = null;
-
}
-
}
-
-
try {
-
if (socket != null) {
-
socket.close();
-
}
-
} catch (IOException ex) {
-
Slog.w(TAG, "Failed closing socket", ex);
-
}
-
}
-
}
sendCommandLocked接口
-
/**
-
* Sends a command to the daemon with a single argument
-
*
-
* @param command The command to send to the daemon
-
* @param argument The argument to send with the command (or null)
-
*/
-
private void sendCommandLocked(String command, String argument)
-
throws NativeDaemonConnectorException {
-
if (command != null && command.indexOf('\0') >= 0) {
-
throw new IllegalArgumentException("unexpected command: " + command);
-
}
-
if (argument != null && argument.indexOf('\0') >= 0) {
-
throw new IllegalArgumentException("unexpected argument: " + argument);
-
}
-
-
if (LOCAL_LOGD) Slog.d(TAG, String.format("SND -> {%s} {%s}", command, argument));
-
if (mOutputStream == null) {
-
Slog.e(TAG, "No connection to daemon", new IllegalStateException());
-
throw new NativeDaemonConnectorException("No output stream!");
-
} else {
-
StringBuilder builder = new StringBuilder(command);
-
if (argument != null) {
-
builder.append(argument);
-
}
-
builder.append('\0');
-
-
try {
-
mOutputStream.write(builder.toString().getBytes());
-
} catch (IOException ex) {
-
Slog.e(TAG, "IOException in sendCommand", ex);
-
}
-
}
-
}