书接上一回,上一回我们讲到分区的mount过程,这一回我们将剩下的加密内容也一同分析下。
接上一篇 fs_mgr_mount_all 开始
上一篇只讲到mount_with_alternatives函数就没有继续讲下去了,这里我们从这里开始讲。同样的,这里我们还是用userdata这一个分区作为例子。userdata在fstab.sailfish的内容也先贴出来。
1 |
/dev/block/platform/soc/624000.ufshc/by-name/userdata /data ext4 errors=panic,noatime,nosuid,nodev,barrier=1,noauto_da_alloc latemount,wait,check,formattable,fileencryption=ice,quota |
下面开始看代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
.................. // 上一篇讲到,userdata是mount成功的,最后这里返回0,所以mret=0 mret = mount_with_alternatives(fstab, i, &last_idx_inspected, &attempted_idx); i = last_idx_inspected; mount_errno = errno; /* Deal with encryptability. */ if (!mret) { // mret=0走这里,handle_encryptable下面分析 // 下面分析的内容可以知道,这里status=FS_MGR_MNTALL_DEV_FILE_ENCRYPTED int status = handle_encryptable(&fstab->recs[attempted_idx]); if (status == FS_MGR_MNTALL_FAIL) { /* Fatal error - no point continuing */ return status; } // if条件为true if (status != FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) { // if条件为false if (encryptable != FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) { // Log and continue LERROR << "Only one encryptable/encrypted partition supported"; } // 最终encrytable=status=FS_MGR_MNTALL_DEV_FILE_ENCRYPTED encryptable = status; } // OK,跳过剩余的代码。 continue; } bool wiped = partition_wiped(fstab->recs[top_idx].blk_device); bool crypt_footer = false; if (mret && mount_errno != EBUSY && mount_errno != EACCES && fs_mgr_is_formattable(&fstab->recs[top_idx]) && wiped) { LERROR << __FUNCTION__ << "(): " << fstab->recs[top_idx].blk_device << " is wiped and " << fstab->recs[top_idx].mount_point << " " << fstab->recs[top_idx].fs_type << " is formattable. Format it."; .................... if (error_count) { return FS_MGR_MNTALL_FAIL; } else { // 返回encrytable=FS_MGR_MNTALL_DEV_FILE_ENCRYPTED return encryptable; } |
fs_mgr_mount_all –> handle_encryptable
这里查看userdata在fstabl.sailfish中的标志位带有”fileencryption=”,对比上一篇中的fs_mgr_flags[]数组可以知道,”fileencryption=”对应于MF_FILEENCRYPTION。这接下来的代码就是比较对应分区信息中是都带有对应的标志的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
// Check to see if a mountable volume has encryption requirements static int handle_encryptable(const struct fstab_rec* rec) { // 从下面的分析可知,函数调用返回false if (needs_block_encryption(rec)) { if (umount(rec->mount_point) == 0) { return FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION; } else { PWARNING << "Could not umount " << rec->mount_point << " - allow continue unencrypted"; return FS_MGR_MNTALL_DEV_NOT_ENCRYPTED; } // 下面分析,函数调用返回false } else if (should_use_metadata_encryption(rec)) { if (umount(rec->mount_point) == 0) { return FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION; } else { PERROR << "Could not umount " << rec->mount_point << " - fail since can't encrypt"; return FS_MGR_MNTALL_FAIL; } // flags匹配MF_FILEENCRYPTION,所以函数返回FS_MGR_MNTALL_DEV_FILE_ENCRYPTED } else if (rec->fs_mgr_flags & (MF_FILEENCRYPTION | MF_FORCEFDEORFBE)) { LINFO << rec->mount_point << " is file encrypted"; return FS_MGR_MNTALL_DEV_FILE_ENCRYPTED; } else if (fs_mgr_is_encryptable(rec)) { return FS_MGR_MNTALL_DEV_NOT_ENCRYPTED; } else { return FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE; } } |
handle_encryptable –> needs_block_encryption
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
static bool needs_block_encryption(const struct fstab_rec* rec) { /* device_is_force_encrypted是通过读取ro.vold.forceencryption熟悉来判断的 明显系统中没有定义该属性值。返回false fs_mgr_is_encryptable是通过对比分区表的flags是否符合条件来判断的。返回false */ if (device_is_force_encrypted() && fs_mgr_is_encryptable(rec)) return true; // 下面if条件为false if (rec->fs_mgr_flags & MF_FORCECRYPT) return true; // if条件为false if (rec->fs_mgr_flags & MF_CRYPT) { /* Check for existence of convert_fde breadcrumb file */ char convert_fde_name[PATH_MAX]; snprintf(convert_fde_name, sizeof(convert_fde_name), "%s/misc/vold/convert_fde", rec->mount_point); if (access(convert_fde_name, F_OK) == 0) return true; } // if条件为false if (rec->fs_mgr_flags & MF_FORCEFDEORFBE) { /* Check for absence of convert_fbe breadcrumb file */ char convert_fbe_name[PATH_MAX]; snprintf(convert_fbe_name, sizeof(convert_fbe_name), "%s/convert_fbe", rec->mount_point); if (access(convert_fbe_name, F_OK) != 0) return true; } return false; } |
handle_encryptable –> should_use_metadata_encryption
1 2 3 4 5 6 |
static bool should_use_metadata_encryption(const struct fstab_rec* rec) { if (!(rec->fs_mgr_flags & (MF_FILEENCRYPTION | MF_FORCEFDEORFBE))) return false; // 下面的if条件判断为true,所以返回false if (!(rec->fs_mgr_flags & MF_KEYDIRECTORY)) return false; return true; } |
到这里,加密部分对应的参数就分析OK了,接下来就是从fs_mgr_mount_all函数向上弹出调用栈,首先是回到mount_fstab函数中。
mount_fstab
上一篇说到mount_fstab会创建一个线程执行mount操作,而父进程则等待子线程返回,并获取返回值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
static int mount_fstab(const char* fstabfile, int mount_mode) { int ret = -1; pid_t pid = fork(); if (pid > 0) { /* Parent. Wait for the child to return */ int status; int wp_ret = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0)); if (wp_ret == -1) { // Unexpected error code. We will continue anyway. PLOG(WARNING) << "waitpid failed"; } if (WIFEXITED(status)) { // 执行ret=FS_MGR_MNTALL_DEV_FILE_ENCRYPTED ret = WEXITSTATUS(status); } else { ret = -1; } } else if (pid == 0) { android::base::ScopedLogSeverity info(android::base::INFO); struct fstab* fstab = fs_mgr_read_fstab(fstabfile); // 在这里返回child_ret = FS_MGR_MNTALL_DEV_FILE_ENCRYPTED int child_ret = fs_mgr_mount_all(fstab, mount_mode); fs_mgr_free_fstab(fstab); if (child_ret == -1) { PLOG(ERROR) << "fs_mgr_mount_all returned an error"; } // 将执行结果返回给父进程 _exit(child_ret); } else { /* fork failed, return an error */ return -1; } // 最终mount_fstab也是返回FS_MGR_MNTALL_DEV_FILE_ENCRYPTED return ret; } |
这一步OK,再往上出栈就到do_mount_all了。
do_mount_all
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
static int do_mount_all(const std::vector<std::string>& args) { std::size_t na = 0; bool import_rc = true; bool queue_event = true; int mount_mode = MOUNT_MODE_DEFAULT; const char* fstabfile = args[1].c_str(); std::size_t path_arg_end = args.size(); const char* prop_post_fix = "default"; for (na = args.size() - 1; na > 1; --na) { if (args[na] == "--early") { path_arg_end = na; queue_event = false; mount_mode = MOUNT_MODE_EARLY; prop_post_fix = "early"; } else if (args[na] == "--late") { path_arg_end = na; import_rc = false; mount_mode = MOUNT_MODE_LATE; prop_post_fix = "late"; } } std::string prop_name = "ro.boottime.init.mount_all."s + prop_post_fix; android::base::Timer t; // mount_fstab返回FS_MGR_MNTALL_DEV_FILE_ENCRYPTED int ret = mount_fstab(fstabfile, mount_mode); property_set(prop_name, std::to_string(t.duration().count())); // userdata在--late阶段,这里不用管 if (import_rc) { /* Paths of .rc files are specified at the 2nd argument and beyond */ import_late(args, 2, path_arg_end); } // 下面看queue_fs_evenet if (queue_event) { /* queue_fs_event will queue event based on mount_fstab return code * and return processed return code*/ ret = queue_fs_event(ret); } return ret; } |
do_mount_all –> queue_fs_event
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
static int queue_fs_event(int code) { int ret = code; .............. /* If reboot worked, there is no return. */ } else if (code == FS_MGR_MNTALL_DEV_FILE_ENCRYPTED) { if (e4crypt_install_keyring()) { return -1; } // 设置两个属性 property_set("ro.crypto.state", "encrypted"); property_set("ro.crypto.type", "file"); // 什么,最后出发的是"nonencrypted"这个event,那不就是说什么都不做? ActionManager::GetInstance().QueueEventTrigger("nonencrypted"); } else if (code == FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED) { if (e4crypt_install_keyring()) { return -1; } ................ return ret; } |
只看相关的内容,其余部分省略掉。首先看key的安装。
queue_fs_event –> e4crypt_install_keyring
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
int e4crypt_install_keyring() { // 这个我最后跟到syscalls.h文件中找到定义就跟不下去了,看函数前缀应该是会变函数,具体不清楚 // 不过看名字应该是添加key内容的 key_serial_t device_keyring = add_key("keyring", "e4crypt", 0, 0, KEY_SPEC_SESSION_KEYRING); if (device_keyring == -1) { PLOG(ERROR) << "Failed to create keyring"; return -1; } LOG(INFO) << "Keyring created with id " << device_keyring << " in process " << getpid(); return 0; } |
这里,在do_mount_all的最后触发了”nonencrypted” event。看这个event的内容只是简单启动late_start和main类的应用。看来这个加密过程还要在稍后的地方进行啊。
on_post_fs阶段
1 2 3 4 5 6 7 8 9 10 11 |
on post-fs-data # We chown/chmod /data again so because mount is run as root + defaults chown system system /data chmod 0771 /data # We restorecon /data in case the userdata partition has been reset. restorecon /data # Make sure we have the device encryption key. start vold installkey /data ................ |
这里,我们从installkey开始,对照function map,installkey这个action对应的函数是do_intallkey
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
static int do_installkey(const std::vector<std::string>& args) { // 如果不是基于文件级加密,返回0 if (!is_file_crypto()) { return 0; } // unencrypted_dir="/data/unencrypted" auto unencrypted_dir = args[1] + e4crypt_unencrypted_folder; if (do_installkeys_ensure_dir_exists(unencrypted_dir.c_str())) { PLOG(ERROR) << "Failed to create " << unencrypted_dir; return -1; } // 设置启动vdc进程的参数 std::vector<std::string> exec_args = {"exec", "/system/bin/vdc", "--wait", "cryptfs", "enablefilecrypto"}; // 创建一个新的进程vdc return do_exec(exec_args); } |
do_installkey –> vdc::main()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
// /system/bin/vdc --wait cryptfs enablefilecrypto // 所以argc=4 int main(int argc, char **argv) { int sock; int wait_for_socket; char *progname; // progname="/system/bin/vdc" progname = argv[0]; // log输出位置选择 if (getppid() == 1) { // If init is calling us then it's during boot and we should log to kmsg android::base::InitLogging(argv, &android::base::KernelLogger); } else { android::base::InitLogging(argv, &android::base::StderrLogger); } // 根据传入参数,wait_for_socket=1 wait_for_socket = argc > 1 && strcmp(argv[1], "--wait") == 0; if (wait_for_socket) { argv++; argc--; } if (argc < 2) { usage(progname); exit(5); } // socket连接对端的名字"vold" const char* sockname = "vold"; if (!strcmp(argv[1], "cryptfs")) { // 最后还是讲sockname设置为"cryptd" sockname = "cryptd"; } // 连接到cryptd while ((sock = socket_local_client(sockname, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM)) < 0) { if (!wait_for_socket) { PLOG(ERROR) << "Error connecting to " << sockname; exit(4); } else { usleep(10000); } } // 执行do_cmd if (!strcmp(argv[1], "monitor")) { exit(do_monitor(sock, 0)); } else { // argc=3,argv="--wait cryptfs enablefilecrypto" exit(do_cmd(sock, argc, argv)); } } |
vdc::main() –> do_cmd
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
static int do_cmd(int sock, int argc, char **argv) { // 获取当前进程PID int seq = getpid(); // 设置字符串CMD="PID cryptfs enablefilecrypto" std::string cmd(android::base::StringPrintf("%d ", seq)); for (int i = 1; i < argc; i++) { if (!strchr(argv[i], ' ')) { cmd.append(argv[i]); } else { cmd.push_back('\"'); cmd.append(argv[i]); cmd.push_back('\"'); } if (i < argc - 1) { cmd.push_back(' '); } } // 讲数据传输到对端,即cryptd if (TEMP_FAILURE_RETRY(write(sock, cmd.c_str(), cmd.length() + 1)) < 0) { PLOG(ERROR) << "Failed to write command"; return errno; } // 执行do_monitor等待回来的数据 return do_monitor(sock, seq); } |
vdc通过socket通信的方式,和cryptd建立连接,并通过write见cmd数据写到cryptd中。最后通过do_monitor等待处理的结果并对结果进行分析。在分析cryptd是如何处理数据前,需要先弄清楚cryptd这个socket server端是什么时候启动起来的。
Vold启动分析
看回前面init.rc中的op-post-fs阶段,在installkey前,有先执行start vold
,所以呢,在执行installkey前,vold是会先启动的。vold的代码在system/vold/main.cpp中
main.cpp::main()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
int main(int argc, char** argv) { setenv("ANDROID_LOG_TAGS", "*:v", 1); android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM)); // 输出log信息 LOG(INFO) << "Vold 3.0 (the awakening) firing up"; LOG(VERBOSE) << "Detected support for:" << (android::vold::IsFilesystemSupported("ext4") ? " ext4" : "") << (android::vold::IsFilesystemSupported("f2fs") ? " f2fs" : "") << (android::vold::IsFilesystemSupported("vfat") ? " vfat" : ""); // 创建一些Manager和Listener VolumeManager *vm; CommandListener *cl; CryptCommandListener *ccl; NetlinkManager *nm; parse_args(argc, argv); // Selinux设置 sehandle = selinux_android_file_context_handle(); if (sehandle) { selinux_android_set_sehandle(sehandle); } // Quickly throw a CLOEXEC on the socket we just inherited from init // 获取对应socket的控制权,可以看到这里就有名为"cryptd"的socket fcntl(android_get_control_socket("vold"), F_SETFD, FD_CLOEXEC); fcntl(android_get_control_socket("cryptd"), F_SETFD, FD_CLOEXEC); mkdir("/dev/block/vold", 0755); /* For when cryptfs checks and mounts an encrypted filesystem */ klog_set_level(6); /* Create our singleton managers */ if (!(vm = VolumeManager::Instance())) { LOG(ERROR) << "Unable to create VolumeManager"; exit(1); } if (!(nm = NetlinkManager::Instance())) { LOG(ERROR) << "Unable to create NetlinkManager"; exit(1); } if (property_get_bool("vold.debug", false)) { vm->setDebug(true); } // 这两个listener下面再讲解 cl = new CommandListener(); ccl = new CryptCommandListener(); vm->setBroadcaster((SocketListener *) cl); nm->setBroadcaster((SocketListener *) cl); if (vm->start()) { PLOG(ERROR) << "Unable to start VolumeManager"; exit(1); } bool has_adoptable; bool has_quota; if (process_config(vm, &has_adoptable, &has_quota)) { PLOG(ERROR) << "Error reading configuration... continuing anyways"; } if (nm->start()) { PLOG(ERROR) << "Unable to start NetlinkManager"; exit(1); } // 启动Listener if (cl->startListener()) { PLOG(ERROR) << "Unable to start CommandListener"; exit(1); } if (ccl->startListener()) { PLOG(ERROR) << "Unable to start CryptCommandListener"; exit(1); } // 设置属性 property_set("vold.has_adoptable", has_adoptable ? "1" : "0"); property_set("vold.has_quota", has_quota ? "1" : "0"); // Do coldboot here so it won't block booting, // also the cold boot is needed in case we have flash drive // connected before Vold launched coldboot("/sys/block"); // Eventually we'll become the monitoring thread while(1) { pause(); } LOG(ERROR) << "Vold exiting"; exit(0); } |
既然前面doInstallkey是通过socket来传输指令的,那当然要分析下socket的服务端是怎么启动的。
new CryptCommandListener()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
// CryptCommandListener是从FrameworkListener继承而来 CryptCommandListener::CryptCommandListener() : // "cryptd"是socket的名字 FrameworkListener("cryptd", true) { // 注册不同的命令对象 registerCmd(new CryptfsCmd()); } // socketName="cryptd", withSeq=true FrameworkListener::FrameworkListener(const char *socketName, bool withSeq) : SocketListener(socketName, true, withSeq) { init(socketName, withSeq); } // FrameworkListener --> init void FrameworkListener::init(const char *socketName UNUSED, bool withSeq) { mCommands = new FrameworkCommandCollection(); errorRate = 0; mCommandCount = 0; mWithSeq = withSeq; mSkipToNextNullByte = false; } // FrameworkListener --> SocketListener // socketName="cryptd",listen=true,withSeq=true SocketListener::SocketListener(const char *socketName, bool listen, bool useCmdNum) { init(socketName, -1, listen, useCmdNum); } // SocketListener --> init void SocketListener::init(const char *socketName, int socketFd, bool listen, bool useCmdNum) { // 标记是否是服务端 mListen = listen; // Socket名字 mSocketName = socketName; // socket文件描述符 mSock = socketFd; mUseCmdNum = useCmdNum; pthread_mutex_init(&mClientsLock, NULL); // 集合对象 mClients = new SocketClientCollection(); } |
ccl->startListener()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
int SocketListener::startListener() { return startListener(4); } int SocketListener::startListener(int backlog) { // 从前面的初始化可以知道mSocketName不为NULL if (!mSocketName && mSock == -1) { SLOGE("Failed to start unbound listener"); errno = EINVAL; return -1; } else if (mSocketName) { // 获取Socket的控制权 if ((mSock = android_get_control_socket(mSocketName)) < 0) { SLOGE("Obtaining file descriptor socket '%s' failed: %s", mSocketName, strerror(errno)); return -1; } SLOGV("got mSock = %d for %s", mSock, mSocketName); fcntl(mSock, F_SETFD, FD_CLOEXEC); } // 如果是服务端就开始监听请求 if (mListen && listen(mSock, backlog) < 0) { SLOGE("Unable to listen on socket (%s)", strerror(errno)); return -1; } else if (!mListen) mClients->push_back(new SocketClient(mSock, false, mUseCmdNum)); if (pipe(mCtrlPipe)) { SLOGE("pipe failed (%s)", strerror(errno)); return -1; } // 创建线程threadStart处理客户端的连接 if (pthread_create(&mThread, NULL, SocketListener::threadStart, this)) { SLOGE("pthread_create (%s)", strerror(errno)); return -1; } return 0; } // 创建的工作线程 void *SocketListener::threadStart(void *obj) { SocketListener *me = reinterpret_cast<SocketListener *>(obj); me->runListener(); pthread_exit(NULL); return NULL; } // 实际的工作函数 void SocketListener::runListener() { SocketClientCollection pendingList; // 循环处理 while(1) { SocketClientCollection::iterator it; // 通过select监控需要处理的socket句柄 fd_set read_fds; int rc = 0; int max = -1; FD_ZERO(&read_fds); // 如果是服务端,将服务端句柄也加入到select中监控 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); // 将连接的client句柄加入监控 for (it = mClients->begin(); it != mClients->end(); ++it) { // NB: calling out to an other object with mClientsLock held (safe) int fd = (*it)->getSocket(); FD_SET(fd, &read_fds); if (fd > max) { max = fd; } } pthread_mutex_unlock(&mClientsLock); SLOGV("mListen=%d, max=%d, mSocketName=%s", mListen, max, mSocketName); if ((rc = select(max + 1, &read_fds, NULL, NULL, NULL)) < 0) { if (errno == EINTR) continue; SLOGE("select failed (%s) mListen=%d, max=%d", strerror(errno), mListen, max); sleep(1); continue; } else if (!rc) continue; // 如果有数据或者请求到来 if (FD_ISSET(mCtrlPipe[0], &read_fds)) { char c = CtrlPipe_Shutdown; TEMP_FAILURE_RETRY(read(mCtrlPipe[0], &c, 1)); if (c == CtrlPipe_Shutdown) { break; } continue; } // 如果是服务端,而且有请求链接到来 if (mListen && FD_ISSET(mSock, &read_fds)) { int c = TEMP_FAILURE_RETRY(accept4(mSock, nullptr, nullptr, SOCK_CLOEXEC)); if (c < 0) { SLOGE("accept failed (%s)", strerror(errno)); sleep(1); continue; } pthread_mutex_lock(&mClientsLock); // 将服务端信息加入到mClient中 mClients->push_back(new SocketClient(c, true, mUseCmdNum)); pthread_mutex_unlock(&mClientsLock); } /* Add all active clients to the pending list first */ pendingList.clear(); pthread_mutex_lock(&mClientsLock); // 迭代记录那些处于活跃状态的client,即那些有数据到达的client for (it = mClients->begin(); it != mClients->end(); ++it) { SocketClient* c = *it; // NB: calling out to an other object with mClientsLock held (safe) int fd = c->getSocket(); if (FD_ISSET(fd, &read_fds)) { // 将活跃的client添加到pendingList中 pendingList.push_back(c); c->incRef(); } } pthread_mutex_unlock(&mClientsLock); // pendingList不为空,开始处理数据 while (!pendingList.empty()) { /* Pop the first item from the list */ it = pendingList.begin(); SocketClient* c = *it; pendingList.erase(it); /* Process it, if false is returned, remove from list */ if (!onDataAvailable(c)) { release(c, false); } c->decRef(); } } } |
cryptd的启动流程知道了,下面继续看看是怎么处理client到达的数据的吧。首先根据纯虚函数和继承可以知道,最后调用的onDataAvailable是FrameworkListener::onDataAvailable,然后FrameworkListener::onDataAvailable会调用到FrameworkListener::dispatchCommand
FrameworkListener::onDataAvailable
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
bool FrameworkListener::onDataAvailable(SocketClient *c) { char buffer[CMD_BUF_SIZE]; int len; len = TEMP_FAILURE_RETRY(read(c->getSocket(), buffer, sizeof(buffer))); if (len < 0) { SLOGE("read() failed (%s)", strerror(errno)); return false; } else if (!len) { return false; } else if (buffer[len-1] != '\0') { SLOGW("String is not zero-terminated"); android_errorWriteLog(0x534e4554, "29831647"); c->sendMsg(500, "Command too large for buffer", false); mSkipToNextNullByte = true; return true; } int offset = 0; int i; for (i = 0; i < len; i++) { if (buffer[i] == '\0') { /* IMPORTANT: dispatchCommand() expects a zero-terminated string */ if (mSkipToNextNullByte) { mSkipToNextNullByte = false; } else { dispatchCommand(c, buffer + offset); } offset = i + 1; } } mSkipToNextNullByte = false; return true; } |
FrameworkListener::dispatchCommand() –> FrameworkListener::dispatchCommand
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { // 下面的代码主要是对传进来的data进行解析,具体代码就不贴出来了 FrameworkCommandCollection::iterator i; int argc = 0; char *argv[FrameworkListener::CMD_ARGS_MAX]; char tmp[CMD_BUF_SIZE]; ................... if (errorRate && (++mCommandCount % errorRate == 0)) { /* ignore this command - let the timeout handler handle it */ SLOGE("Faking a timeout"); goto out; } for (i = mCommands->begin(); i != mCommands->end(); ++i) { FrameworkCommand *c = *i; if (!strcmp(argv[0], c->getCommand())) { // 最后在调用runCommand来执行具体的操作 if (c->runCommand(cli, argc, argv)) { SLOGW("Handler '%s' error (%s)", c->getCommand(), strerror(errno)); } goto out; } } cli->sendMsg(500, "Command not recognized", false); out: int j; for (j = 0; j < argc; j++) free(argv[j]); return; overflow: cli->sendMsg(500, "Command too long", false); goto out; } |
好了好了,这一篇感觉长了,就想到这里,剩下的会在另一篇里在做分析。