1168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat/* 2168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * Copyright (C) 2008 The Android Open Source Project 3168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * 4168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * Licensed under the Apache License, Version 2.0 (the "License"); 5168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * you may not use this file except in compliance with the License. 6168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * You may obtain a copy of the License at 7168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * 8168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * http://www.apache.org/licenses/LICENSE-2.0 9168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * 10168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * Unless required by applicable law or agreed to in writing, software 11168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * distributed under the License is distributed on an "AS IS" BASIS, 12168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * See the License for the specific language governing permissions and 14168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * limitations under the License. 15168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat */ 16168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 17168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#define LOG_TAG "FrameworkListener" 18168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 1966ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn#include <errno.h> 2066ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn#include <stdlib.h> 2166ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn#include <string.h> 22cfd5b080af8de527d768f0ff7902c26af8d49307Mark Salyzyn#include <unistd.h> 23168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 24cfd5b080af8de527d768f0ff7902c26af8d49307Mark Salyzyn#include <log/log.h> 25168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <sysutils/FrameworkCommand.h> 2666ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn#include <sysutils/FrameworkListener.h> 27fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat#include <sysutils/SocketClient.h> 28168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 296d358ae44ccfbcd5b89511d142f334b2cc1b67b1Josef Kindbergstatic const int CMD_BUF_SIZE = 1024; 306d358ae44ccfbcd5b89511d142f334b2cc1b67b1Josef Kindberg 31e16baef4d2f59c0b5f78e66c838d6c5e7d9b7363Mark Salyzyn#define UNUSED __attribute__((unused)) 32e16baef4d2f59c0b5f78e66c838d6c5e7d9b7363Mark Salyzyn 338702bb17f40022e970e8acd40b348d074e39afc7Robert GreenwaltFrameworkListener::FrameworkListener(const char *socketName, bool withSeq) : 348702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt SocketListener(socketName, true, withSeq) { 358702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt init(socketName, withSeq); 368702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt} 378702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt 38168415b822cae1f8b54ef09c41c11a9b97b87f40San MehatFrameworkListener::FrameworkListener(const char *socketName) : 398702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt SocketListener(socketName, true, false) { 408702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt init(socketName, false); 418702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt} 428702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt 43dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark SalyzynFrameworkListener::FrameworkListener(int sock) : 44dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn SocketListener(sock, true) { 45dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn init(NULL, false); 46dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn} 47dfc47e86858ea67c72f1df2fdb97094b8e8248f2Mark Salyzyn 48e16baef4d2f59c0b5f78e66c838d6c5e7d9b7363Mark Salyzynvoid FrameworkListener::init(const char *socketName UNUSED, bool withSeq) { 49168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat mCommands = new FrameworkCommandCollection(); 508702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt errorRate = 0; 518702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt mCommandCount = 0; 528702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt mWithSeq = withSeq; 53470484d2a25ad432190a01d1c763b4b36db33c7eConnor O'Brien mSkipToNextNullByte = false; 54168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat} 55168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 56fa644ffe944c01a9b00f8d7676d58394fabee285San Mehatbool FrameworkListener::onDataAvailable(SocketClient *c) { 576d358ae44ccfbcd5b89511d142f334b2cc1b67b1Josef Kindberg char buffer[CMD_BUF_SIZE]; 58168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat int len; 59168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 60c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner len = TEMP_FAILURE_RETRY(read(c->getSocket(), buffer, sizeof(buffer))); 61c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner if (len < 0) { 627e8529a8b528fd30586aa037f15a31b29582c537San Mehat SLOGE("read() failed (%s)", strerror(errno)); 63f31d2ed1fd3a39a92bccc12eb66728594290ef3bKenny Root return false; 64470484d2a25ad432190a01d1c763b4b36db33c7eConnor O'Brien } else if (!len) { 65168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat return false; 66470484d2a25ad432190a01d1c763b4b36db33c7eConnor O'Brien } else if (buffer[len-1] != '\0') { 676d358ae44ccfbcd5b89511d142f334b2cc1b67b1Josef Kindberg SLOGW("String is not zero-terminated"); 68470484d2a25ad432190a01d1c763b4b36db33c7eConnor O'Brien android_errorWriteLog(0x534e4554, "29831647"); 69470484d2a25ad432190a01d1c763b4b36db33c7eConnor O'Brien c->sendMsg(500, "Command too large for buffer", false); 70470484d2a25ad432190a01d1c763b4b36db33c7eConnor O'Brien mSkipToNextNullByte = true; 71d3c86412adfb3b782ee8b4a70b8c25be5d35138aNIEJuhu return true; 72470484d2a25ad432190a01d1c763b4b36db33c7eConnor O'Brien } 73168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 74d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat int offset = 0; 75168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat int i; 76168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 77168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat for (i = 0; i < len; i++) { 78c73a3a5771a2d29d1bae666bfde12f751d66fc96San Mehat if (buffer[i] == '\0') { 79c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner /* IMPORTANT: dispatchCommand() expects a zero-terminated string */ 80470484d2a25ad432190a01d1c763b4b36db33c7eConnor O'Brien if (mSkipToNextNullByte) { 81470484d2a25ad432190a01d1c763b4b36db33c7eConnor O'Brien mSkipToNextNullByte = false; 82470484d2a25ad432190a01d1c763b4b36db33c7eConnor O'Brien } else { 83470484d2a25ad432190a01d1c763b4b36db33c7eConnor O'Brien dispatchCommand(c, buffer + offset); 84470484d2a25ad432190a01d1c763b4b36db33c7eConnor O'Brien } 85d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat offset = i + 1; 86168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 87168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 886d358ae44ccfbcd5b89511d142f334b2cc1b67b1Josef Kindberg 89470484d2a25ad432190a01d1c763b4b36db33c7eConnor O'Brien mSkipToNextNullByte = false; 90168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat return true; 91168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat} 92168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 93168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehatvoid FrameworkListener::registerCmd(FrameworkCommand *cmd) { 94168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat mCommands->push_back(cmd); 95168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat} 96168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 97c73a3a5771a2d29d1bae666bfde12f751d66fc96San Mehatvoid FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { 98c4a895b7094461c98101924cf096680bfb7856f1San Mehat FrameworkCommandCollection::iterator i; 99c4a895b7094461c98101924cf096680bfb7856f1San Mehat int argc = 0; 100c73a3a5771a2d29d1bae666bfde12f751d66fc96San Mehat char *argv[FrameworkListener::CMD_ARGS_MAX]; 1016d358ae44ccfbcd5b89511d142f334b2cc1b67b1Josef Kindberg char tmp[CMD_BUF_SIZE]; 102c4a895b7094461c98101924cf096680bfb7856f1San Mehat char *p = data; 103c4a895b7094461c98101924cf096680bfb7856f1San Mehat char *q = tmp; 104c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner char *qlimit = tmp + sizeof(tmp) - 1; 105c4a895b7094461c98101924cf096680bfb7856f1San Mehat bool esc = false; 106c4a895b7094461c98101924cf096680bfb7856f1San Mehat bool quote = false; 1078702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt bool haveCmdNum = !mWithSeq; 108c4a895b7094461c98101924cf096680bfb7856f1San Mehat 109c4a895b7094461c98101924cf096680bfb7856f1San Mehat memset(argv, 0, sizeof(argv)); 110c4a895b7094461c98101924cf096680bfb7856f1San Mehat memset(tmp, 0, sizeof(tmp)); 111c4a895b7094461c98101924cf096680bfb7856f1San Mehat while(*p) { 112c4a895b7094461c98101924cf096680bfb7856f1San Mehat if (*p == '\\') { 113c4a895b7094461c98101924cf096680bfb7856f1San Mehat if (esc) { 114c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner if (q >= qlimit) 115c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner goto overflow; 116c4a895b7094461c98101924cf096680bfb7856f1San Mehat *q++ = '\\'; 117c4a895b7094461c98101924cf096680bfb7856f1San Mehat esc = false; 118c4a895b7094461c98101924cf096680bfb7856f1San Mehat } else 119c4a895b7094461c98101924cf096680bfb7856f1San Mehat esc = true; 120c4a895b7094461c98101924cf096680bfb7856f1San Mehat p++; 121c4a895b7094461c98101924cf096680bfb7856f1San Mehat continue; 122c4a895b7094461c98101924cf096680bfb7856f1San Mehat } else if (esc) { 123c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner if (*p == '"') { 124c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner if (q >= qlimit) 125c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner goto overflow; 126c4a895b7094461c98101924cf096680bfb7856f1San Mehat *q++ = '"'; 127c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner } else if (*p == '\\') { 128c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner if (q >= qlimit) 129c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner goto overflow; 130c4a895b7094461c98101924cf096680bfb7856f1San Mehat *q++ = '\\'; 131c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner } else { 132c4a895b7094461c98101924cf096680bfb7856f1San Mehat cli->sendMsg(500, "Unsupported escape sequence", false); 133c4a895b7094461c98101924cf096680bfb7856f1San Mehat goto out; 134c4a895b7094461c98101924cf096680bfb7856f1San Mehat } 135c4a895b7094461c98101924cf096680bfb7856f1San Mehat p++; 136c4a895b7094461c98101924cf096680bfb7856f1San Mehat esc = false; 137c4a895b7094461c98101924cf096680bfb7856f1San Mehat continue; 138c4a895b7094461c98101924cf096680bfb7856f1San Mehat } 139c4a895b7094461c98101924cf096680bfb7856f1San Mehat 140c4a895b7094461c98101924cf096680bfb7856f1San Mehat if (*p == '"') { 141c4a895b7094461c98101924cf096680bfb7856f1San Mehat if (quote) 142c4a895b7094461c98101924cf096680bfb7856f1San Mehat quote = false; 143c4a895b7094461c98101924cf096680bfb7856f1San Mehat else 144c4a895b7094461c98101924cf096680bfb7856f1San Mehat quote = true; 145c4a895b7094461c98101924cf096680bfb7856f1San Mehat p++; 146c4a895b7094461c98101924cf096680bfb7856f1San Mehat continue; 147c4a895b7094461c98101924cf096680bfb7856f1San Mehat } 148c73a3a5771a2d29d1bae666bfde12f751d66fc96San Mehat 149c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner if (q >= qlimit) 150c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner goto overflow; 151c4a895b7094461c98101924cf096680bfb7856f1San Mehat *q = *p++; 152c4a895b7094461c98101924cf096680bfb7856f1San Mehat if (!quote && *q == ' ') { 153c4a895b7094461c98101924cf096680bfb7856f1San Mehat *q = '\0'; 1548702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt if (!haveCmdNum) { 1558702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt char *endptr; 1568702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt int cmdNum = (int)strtol(tmp, &endptr, 0); 1578702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt if (endptr == NULL || *endptr != '\0') { 1588702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt cli->sendMsg(500, "Invalid sequence number", false); 1598702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt goto out; 1608702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt } 1618702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt cli->setCmdNum(cmdNum); 1628702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt haveCmdNum = true; 1638702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt } else { 1648702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt if (argc >= CMD_ARGS_MAX) 1658702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt goto overflow; 1668702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt argv[argc++] = strdup(tmp); 1678702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt } 168c4a895b7094461c98101924cf096680bfb7856f1San Mehat memset(tmp, 0, sizeof(tmp)); 169c4a895b7094461c98101924cf096680bfb7856f1San Mehat q = tmp; 170c4a895b7094461c98101924cf096680bfb7856f1San Mehat continue; 171c4a895b7094461c98101924cf096680bfb7856f1San Mehat } 172c4a895b7094461c98101924cf096680bfb7856f1San Mehat q++; 173fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 174fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 175c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner *q = '\0'; 176c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner if (argc >= CMD_ARGS_MAX) 177c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner goto overflow; 178c4a895b7094461c98101924cf096680bfb7856f1San Mehat argv[argc++] = strdup(tmp); 179c4a895b7094461c98101924cf096680bfb7856f1San Mehat#if 0 1809418fd1821d5f31e6004a6f70cb14f59735dc589Mark Salyzyn for (int k = 0; k < argc; k++) { 1817e8529a8b528fd30586aa037f15a31b29582c537San Mehat SLOGD("arg[%d] = '%s'", k, argv[k]); 182c4a895b7094461c98101924cf096680bfb7856f1San Mehat } 183c4a895b7094461c98101924cf096680bfb7856f1San Mehat#endif 184168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 185c4a895b7094461c98101924cf096680bfb7856f1San Mehat if (quote) { 186c4a895b7094461c98101924cf096680bfb7856f1San Mehat cli->sendMsg(500, "Unclosed quotes error", false); 187c4a895b7094461c98101924cf096680bfb7856f1San Mehat goto out; 188c4a895b7094461c98101924cf096680bfb7856f1San Mehat } 189c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner 1908702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt if (errorRate && (++mCommandCount % errorRate == 0)) { 1918702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt /* ignore this command - let the timeout handler handle it */ 1928702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt SLOGE("Faking a timeout"); 1938702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt goto out; 1948702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt } 1958702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt 196168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat for (i = mCommands->begin(); i != mCommands->end(); ++i) { 197168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat FrameworkCommand *c = *i; 198168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 199c73a3a5771a2d29d1bae666bfde12f751d66fc96San Mehat if (!strcmp(argv[0], c->getCommand())) { 200c73a3a5771a2d29d1bae666bfde12f751d66fc96San Mehat if (c->runCommand(cli, argc, argv)) { 2017e8529a8b528fd30586aa037f15a31b29582c537San Mehat SLOGW("Handler '%s' error (%s)", c->getCommand(), strerror(errno)); 202168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 203c4a895b7094461c98101924cf096680bfb7856f1San Mehat goto out; 204168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 205168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 206d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat cli->sendMsg(500, "Command not recognized", false); 207c4a895b7094461c98101924cf096680bfb7856f1San Mehatout: 208c4a895b7094461c98101924cf096680bfb7856f1San Mehat int j; 209c4a895b7094461c98101924cf096680bfb7856f1San Mehat for (j = 0; j < argc; j++) 210c4a895b7094461c98101924cf096680bfb7856f1San Mehat free(argv[j]); 211fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat return; 212c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner 213c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turneroverflow: 214c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner cli->sendMsg(500, "Command too long", false); 215c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner goto out; 216168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat} 217