From 17df71e0b277372de1d915c168c07c8877e82395 Mon Sep 17 00:00:00 2001 From: Christopher Tate Date: Fri, 5 Jun 2009 18:20:08 -0700 Subject: [PATCH 01/30] Add an OOM adjustment category for apps undergoing backup In this initial commit, apps undergoing backup are treated equivalently to apps hosting services: more important than anything other than the foreground app. --- rootdir/init.rc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rootdir/init.rc b/rootdir/init.rc index 9853cc654..e16a3f0fa 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -113,6 +113,7 @@ on boot setprop ro.FOREGROUND_APP_ADJ 0 setprop ro.VISIBLE_APP_ADJ 1 setprop ro.SECONDARY_SERVER_ADJ 2 + setprop ro.BACKUP_APP_ADJ 2 setprop ro.HOME_APP_ADJ 4 setprop ro.HIDDEN_APP_MIN_ADJ 7 setprop ro.CONTENT_PROVIDER_ADJ 14 @@ -123,6 +124,7 @@ on boot setprop ro.FOREGROUND_APP_MEM 1536 setprop ro.VISIBLE_APP_MEM 2048 setprop ro.SECONDARY_SERVER_MEM 4096 + setprop ro.BACKUP_APP_MEM 4096 setprop ro.HOME_APP_MEM 4096 setprop ro.HIDDEN_APP_MEM 5120 setprop ro.CONTENT_PROVIDER_MEM 5632 From ce51b3b55f3facfce5dccebc73bd1903e163103e Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Sun, 7 Jun 2009 02:13:02 -0700 Subject: [PATCH 02/30] break dependency on utils/Endian.h --- include/private/pixelflinger/ggl_context.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/private/pixelflinger/ggl_context.h b/include/private/pixelflinger/ggl_context.h index 3a030c526..8a36fa9ee 100644 --- a/include/private/pixelflinger/ggl_context.h +++ b/include/private/pixelflinger/ggl_context.h @@ -21,8 +21,8 @@ #include #include #include +#include -#include #include #include From 2d11dfba277b2f9d98f00a32510d612e779ba757 Mon Sep 17 00:00:00 2001 From: Jack Palevich Date: Mon, 8 Jun 2009 14:34:26 -0700 Subject: [PATCH 03/30] Move macros into their own table. Catch attempts to define macros with parens (not supported.) --- libacc/Android.mk | 2 +- libacc/acc.cpp | 253 +++++++++++++++++++++++++++++++++++++++------- 2 files changed, 220 insertions(+), 35 deletions(-) diff --git a/libacc/Android.mk b/libacc/Android.mk index 77c71c6a2..923de60f5 100644 --- a/libacc/Android.mk +++ b/libacc/Android.mk @@ -12,7 +12,7 @@ ifeq ($(TARGET_ARCH),arm) LOCAL_SRC_FILES += disassem.cpp endif -LOCAL_SHARED_LIBRARIES := libdl +LOCAL_SHARED_LIBRARIES := libdl libcutils include $(BUILD_SHARED_LIBRARY) diff --git a/libacc/acc.cpp b/libacc/acc.cpp index de36ce552..a3a70d187 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #if defined(__arm__) #include @@ -1098,7 +1099,6 @@ class Compiler : public ErrorSink { char* dptr; // Macro state: Points to macro text during macro playback. int dch; // Macro state: Saves old value of ch during a macro playback. char* last_id; - void* pSymbolBase; char* pGlobalBase; char* pVarsBase; // Value of variables @@ -1115,18 +1115,34 @@ class Compiler : public ErrorSink { mSize = 0; } + String(char* item, int len, bool adopt) { + if (adopt) { + mpBase = item; + mUsed = len; + mSize = len + 1; + } else { + mpBase = 0; + mUsed = 0; + mSize = 0; + appendBytes(item, len); + } + } + ~String() { if (mpBase) { free(mpBase); } } - char* getUnwrapped() { + inline char* getUnwrapped() { return mpBase; } void appendCStr(const char* s) { - int n = strlen(s); + appendBytes(s, strlen(s)); + } + + void appendBytes(const char* s, int n) { memcpy(ensure(n), s, n + 1); } @@ -1134,6 +1150,14 @@ class Compiler : public ErrorSink { * ensure(1) = c; } + char* orphan() { + char* result = mpBase; + mpBase = 0; + mUsed = 0; + mSize = 0; + return result; + } + void printf(const char* fmt,...) { va_list ap; va_start(ap, fmt); @@ -1148,7 +1172,7 @@ class Compiler : public ErrorSink { free(temp); } - size_t len() { + inline size_t len() { return mUsed; } @@ -1174,6 +1198,148 @@ class Compiler : public ErrorSink { size_t mSize; }; + /** + * Wrap an externally allocated string for use as a hash key. + */ + class FakeString : public String { + public: + FakeString(char* string, size_t length) : + String(string, length, true) {} + + ~FakeString() { + orphan(); + } + }; + + template class StringTable { + public: + StringTable(size_t initialCapacity) { + mpMap = hashmapCreate(initialCapacity, hashFn, equalsFn); + } + + ~StringTable() { + clear(); + } + + void clear() { + hashmapForEach(mpMap, freeKeyValue, this); + } + + bool contains(String* pKey) { + bool result = hashmapContainsKey(mpMap, pKey); + return result; + } + + V* get(String* pKey) { + V* result = (V*) hashmapGet(mpMap, pKey); + return result; + } + + V* remove(String* pKey) { + V* result = (V*) hashmapRemove(mpMap, pKey); + return result; + } + + V* put(String* pKey, V* value) { + V* result = (V*) hashmapPut(mpMap, pKey, value); + if (result) { + // The key was not adopted by the map, so delete it here. + delete pKey; + } + return result; + } + + protected: + static int hashFn(void* pKey) { + String* pString = (String*) pKey; + return hashmapHash(pString->getUnwrapped(), pString->len()); + } + + static bool equalsFn(void* keyA, void* keyB) { + String* pStringA = (String*) keyA; + String* pStringB = (String*) keyB; + return pStringA->len() == pStringB->len() + && strcmp(pStringA->getUnwrapped(), pStringB->getUnwrapped()) + == 0; + } + + static bool freeKeyValue(void* key, void* value, void* context) { + delete (String*) key; + delete (V*) value; + return true; + } + + Hashmap* mpMap; + }; + + class MacroTable : public StringTable { + public: + MacroTable() : StringTable(10) {} + }; + + template class Array { + public: + Array() { + mpBase = 0; + mUsed = 0; + mSize = 0; + } + + ~Array() { + if (mpBase) { + free(mpBase); + } + } + + E get(int i) { + if (i < 0 || i > mUsed) { + error("internal error: Index out of range"); + return E(); + } + return mpBase[i]; + } + + void set(int i, E val) { + mpBase[i] = val; + } + + void pop() { + if (mUsed > 0) { + mUsed -= 1; + } + } + + void push(E item) { + * ensure(1) = item; + } + + size_t len() { + return mUsed; + } + + private: + E* ensure(int n) { + size_t newUsed = mUsed + n; + if (newUsed > mSize) { + size_t newSize = mSize * 2 + 10; + if (newSize < newUsed) { + newSize = newUsed; + } + mpBase = (E*) realloc(mpBase, sizeof(E) * newSize); + mSize = newSize; + } + E* result = mpBase + mUsed; + mUsed = newUsed; + return result; + } + + E* mpBase; + size_t mUsed; + size_t mSize; + }; + + MacroTable mMacros; + String mErrorBuf; jmp_buf mErrorRecoveryJumpBuf; @@ -1208,7 +1374,6 @@ class Compiler : public ErrorSink { /* tokens in string heap */ static const int TAG_TOK = ' '; - static const int TAG_MACRO = 2; static const int OP_INCREMENT = 0; static const int OP_DECREMENT = 1; @@ -1251,7 +1416,7 @@ class Compiler : public ErrorSink { void inp() { if (dptr) { ch = *dptr++; - if (ch == TAG_MACRO) { + if (ch == 0) { dptr = 0; ch = dch; } @@ -1283,16 +1448,7 @@ class Compiler : public ErrorSink { inp(); next(); if (tok == TOK_DEFINE) { - next(); - pdef(TAG_TOK); /* fill last ident tag */ - *(int *) tok = SYM_DEFINE; - *(char* *) (tok + 4) = dstk; /* define stack */ - while (ch != '\n') { - pdef(ch); - inp(); - } - pdef(ch); - pdef(TAG_MACRO); + doDefine(); } else if (tok == TOK_PRAGMA) { doPragma(); } else { @@ -1319,24 +1475,29 @@ class Compiler : public ErrorSink { if (dstk - sym_stk + 1 > ALLOC_SIZE) { error("symbol stack overflow"); } - * dstk = TAG_TOK; /* no need to mark end of string (we - suppose data is initialized to zero by calloc) */ - tok = (intptr_t) (strstr(sym_stk, (last_id - 1)) - - sym_stk); - * dstk = 0; /* mark real end of ident for dlsym() */ - tok = tok * 8 + TOK_IDENT; - if (tok > TOK_DEFINE) { - if (tok + 8 > ALLOC_SIZE) { - error("Variable Table overflow."); - } - tok = (intptr_t) (pVarsBase + tok); - /* printf("tok=%s %x\n", last_id, tok); */ - /* define handling */ - if (*(int *) tok == SYM_DEFINE) { - dptr = *(char* *) (tok + 4); - dch = ch; - inp(); - next(); + FakeString token(last_id, dstk-last_id); + // Is this a macro? + String* pValue = mMacros.get(&token); + if (pValue) { + // Yes, it is a macro + dstk = last_id-1; + dptr = pValue->getUnwrapped(); + dch = ch; + inp(); + next(); + } else { + * dstk = TAG_TOK; /* no need to mark end of string (we + suppose data is initialized to zero by calloc) */ + tok = (intptr_t) (strstr(sym_stk, (last_id - 1)) + - sym_stk); + * dstk = 0; /* mark real end of ident for dlsym() */ + tok = tok * 8 + TOK_IDENT; + if (tok > TOK_DEFINE) { + if (tok + 8 > ALLOC_SIZE) { + error("Variable Table overflow."); + } + tok = (intptr_t) (pVarsBase + tok); + /* printf("tok=%s %x\n", last_id, tok); */ } } } @@ -1415,6 +1576,30 @@ class Compiler : public ErrorSink { #endif } + void doDefine() { + String* pName = new String(); + while (isspace(ch)) { + inp(); + } + while (isid()) { + pName->append(ch); + inp(); + } + if (ch == '(') { + delete pName; + error("Defines with arguments not supported"); + } + while (isspace(ch)) { + inp(); + } + String* pValue = new String(); + while (ch != '\n' && ch != EOF) { + pValue->append(ch); + inp(); + } + delete mMacros.put(pName, pValue); + } + void doPragma() { // # pragma name(val) int state = 0; From 36d9414f72b629dacc2c972e93d16cec08ef44b6 Mon Sep 17 00:00:00 2001 From: Jack Palevich Date: Mon, 8 Jun 2009 15:55:32 -0700 Subject: [PATCH 04/30] Make a host version of acc for testing. Don't run the code we've compiled unless the -R option is present. --- libacc/Android.mk | 26 +++++++++++++--- libacc/acc.cpp | 49 ++++++++++++++++++------------ libacc/tests/Android.mk | 21 +++++++++++-- libacc/tests/data/returnval-ansi.c | 5 ++- libacc/tests/main.cpp | 6 +++- libacc/tests/testarm | 2 +- libacc/tests/testlocal | 31 ++++++++++--------- 7 files changed, 96 insertions(+), 44 deletions(-) diff --git a/libacc/Android.mk b/libacc/Android.mk index 923de60f5..f3c2d3564 100644 --- a/libacc/Android.mk +++ b/libacc/Android.mk @@ -1,9 +1,8 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) -# -# Shared library -# +# Shared library for target +# ======================================================== LOCAL_MODULE:= libacc LOCAL_SRC_FILES := acc.cpp @@ -16,4 +15,23 @@ LOCAL_SHARED_LIBRARIES := libdl libcutils include $(BUILD_SHARED_LIBRARY) -include $(call all-makefiles-under,$(LOCAL_PATH)) \ No newline at end of file +# Shared library for host +# ======================================================== + +include $(CLEAR_VARS) +LOCAL_MODULE:= libacc +LOCAL_SRC_FILES := acc.cpp + +ifeq ($(TARGET_ARCH),arm) +LOCAL_SRC_FILES += disassem.cpp +endif + +LOCAL_STATIC_LIBRARIES := libcutils +LOCAL_LDLIBS := -ldl + +include $(BUILD_HOST_SHARED_LIBRARY) + +# Build children +# ======================================================== + +include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/libacc/acc.cpp b/libacc/acc.cpp index a3a70d187..db37ee27c 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -1087,26 +1087,6 @@ class Compiler : public ErrorSink { size_t mPosition; }; - int ch; // Current input character, or EOF - intptr_t tok; // token - intptr_t tokc; // token extra info - int tokl; // token operator level - intptr_t rsym; // return symbol - intptr_t loc; // local variable index - char* glo; // global variable index - char* sym_stk; - char* dstk; // Define stack - char* dptr; // Macro state: Points to macro text during macro playback. - int dch; // Macro state: Saves old value of ch during a macro playback. - char* last_id; - char* pGlobalBase; - char* pVarsBase; // Value of variables - - InputStream* file; - - CodeBuf codeBuf; - CodeGenerator* pGen; - class String { public: String() { @@ -1306,6 +1286,8 @@ class Compiler : public ErrorSink { void pop() { if (mUsed > 0) { mUsed -= 1; + } else { + error("internal error: Popped empty stack."); } } @@ -1338,7 +1320,34 @@ class Compiler : public ErrorSink { size_t mSize; }; + struct InputState { + InputStream* pStream; + int oldCh; + }; + + + int ch; // Current input character, or EOF + intptr_t tok; // token + intptr_t tokc; // token extra info + int tokl; // token operator level + intptr_t rsym; // return symbol + intptr_t loc; // local variable index + char* glo; // global variable index + char* sym_stk; + char* dstk; // Define stack + char* dptr; // Macro state: Points to macro text during macro playback. + int dch; // Macro state: Saves old value of ch during a macro playback. + char* last_id; + char* pGlobalBase; + char* pVarsBase; // Value of variables + + InputStream* file; + + CodeBuf codeBuf; + CodeGenerator* pGen; + MacroTable mMacros; + Array mInputStateStack; String mErrorBuf; diff --git a/libacc/tests/Android.mk b/libacc/tests/Android.mk index 2cff9d315..1e4d328e8 100644 --- a/libacc/tests/Android.mk +++ b/libacc/tests/Android.mk @@ -1,5 +1,9 @@ LOCAL_PATH:= $(call my-dir) + +# Executable for host +# ======================================================== include $(CLEAR_VARS) +LOCAL_MODULE:= acc LOCAL_SRC_FILES:= \ main.cpp @@ -7,9 +11,22 @@ LOCAL_SRC_FILES:= \ LOCAL_SHARED_LIBRARIES := \ libacc +LOCAL_MODULE_TAGS := tests + +include $(BUILD_HOST_EXECUTABLE) + +# Executable for target +# ======================================================== +include $(CLEAR_VARS) LOCAL_MODULE:= acc +LOCAL_SRC_FILES:= \ + main.cpp + +LOCAL_SHARED_LIBRARIES := \ + libacc + + LOCAL_MODULE_TAGS := tests -include $(BUILD_EXECUTABLE) - +include $(BUILD_EXECUTABLE) \ No newline at end of file diff --git a/libacc/tests/data/returnval-ansi.c b/libacc/tests/data/returnval-ansi.c index 42802c5cc..e386009a6 100644 --- a/libacc/tests/data/returnval-ansi.c +++ b/libacc/tests/data/returnval-ansi.c @@ -1,7 +1,10 @@ +#define VALUE (2*FOO) +#define FOO 12 + int main(int argc, char** argv) { return f(); } int f() { - return 10; + return VALUE; } diff --git a/libacc/tests/main.cpp b/libacc/tests/main.cpp index acee09d3c..d624cbbde 100644 --- a/libacc/tests/main.cpp +++ b/libacc/tests/main.cpp @@ -32,6 +32,7 @@ int run(MainPtr mainFunc, int argc, char** argv) { int main(int argc, char** argv) { const char* inFile = NULL; bool printListing; + bool runResults = false; FILE* in = stdin; int i; for (i = 1; i < argc; i++) { @@ -41,6 +42,9 @@ int main(int argc, char** argv) { case 'S': printListing = true; break; + case 'R': + runResults = true; + break; default: fprintf(stderr, "Unrecognized flag %s\n", arg); return 3; @@ -108,7 +112,7 @@ int main(int argc, char** argv) { accGetScriptLabel(script, "main", (ACCvoid**) & mainPointer); result = accGetError(script); - if (result == ACC_NO_ERROR) { + if (result == ACC_NO_ERROR && runResults) { fprintf(stderr, "Executing compiled code:\n"); int codeArgc = argc - i + 1; char** codeArgv = argv + i - 1; diff --git a/libacc/tests/testarm b/libacc/tests/testarm index 24fbc422b..1d4b866c4 100755 --- a/libacc/tests/testarm +++ b/libacc/tests/testarm @@ -6,4 +6,4 @@ cd .. mm -j8 cd tests adb sync -adb shell /system/bin/acc -S /system/bin/returnval-ansi.c +adb shell /system/bin/acc -R -S /system/bin/returnval-ansi.c diff --git a/libacc/tests/testlocal b/libacc/tests/testlocal index ccabf7d50..2989e11f4 100755 --- a/libacc/tests/testlocal +++ b/libacc/tests/testlocal @@ -1,17 +1,18 @@ -#!/bin/sh -rm -f test-acc -cd .. -g++ -I../include acc.cpp disassem.cpp tests/main.cpp -g -ldl -o tests/test-acc -cd tests -if [ -x "test-acc" ]; then - ./test-acc -S data/returnval-ansi.c +#!/bin/bash - if [ "$(uname)" = "Linux" ]; then - if [ "$(uname -m)" = "i686" ]; then - echo "Linux i686. Testing otcc-ansi.c" - ./test-acc data/otcc-ansi.c data/returnval.c - echo "Linux i686. Testing otcc-ansi.c data/otcc.c" - ./test-acc data/otcc-ansi.c data/otcc.c data/returnval.c - fi - fi +SCRIPT_DIR=`dirname $BASH_SOURCE` +DATA=$SCRIPT_DIR/data + +echo "Compiling returnval-ansi.c" +acc -S $DATA/returnval-ansi.c + +echo "Compiling whole compiler." +acc -S "$DATA/otcc-ansi.c" + +if (( "$(uname)" = "Linux" )) && (( "$(uname -m)" = "i686" )); then + echo "Linux i686. Testing otcc-ansi.c" + acc -R "$DATA/otcc-ansi.c" "$DATA/returnval.c" + acc -R $DATA/otcc-ansi.c $DATA/otcc.c $DATA/returnval.c fi + +echo "Done with tests." From cae5f6aa21f86b3253d44f5d95ea4067726753b3 Mon Sep 17 00:00:00 2001 From: Jim Miller Date: Mon, 8 Jun 2009 19:00:27 -0700 Subject: [PATCH 05/30] Add tag for AggregationService. --- logcat/event-log-tags | 3 +++ 1 file changed, 3 insertions(+) diff --git a/logcat/event-log-tags b/logcat/event-log-tags index f9355ec18..e13a71158 100644 --- a/logcat/event-log-tags +++ b/logcat/event-log-tags @@ -350,3 +350,6 @@ # browser stats for diary study 70101 browser_zoom_level_change (start level|1|5),(end level|1|5),(time|2|3) 70102 browser_double_tap_duration (duration|1|3),(time|2|3) + +# aggregation service +70200 aggregation (aggregation time|2|3) From 1f75d709c10f49d2e2390b888e766bcfd17da860 Mon Sep 17 00:00:00 2001 From: Chung-yih Wang Date: Mon, 1 Jun 2009 19:04:05 +0800 Subject: [PATCH 06/30] Add VPN and Keystore services and data directories. -- changed the default mode to 0770 for keystore with the new user 'keystore'. -- add the keystore service providing the basic key lookup/install/remove, but only keystore user can access the key content. --- include/private/android_filesystem_config.h | 4 +++- rootdir/init.rc | 21 ++++++++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h index a4351aca7..459062682 100644 --- a/include/private/android_filesystem_config.h +++ b/include/private/android_filesystem_config.h @@ -50,6 +50,7 @@ #define AID_DHCP 1014 /* dhcp client */ #define AID_SDCARD_RW 1015 /* external storage write access */ #define AID_VPN 1016 /* vpn system */ +#define AID_KEYSTORE 1017 /* keystore subsystem */ #define AID_SHELL 2000 /* adb and debug shell user */ #define AID_CACHE 2001 /* cache access */ @@ -97,7 +98,8 @@ static struct android_id_info android_ids[] = { { "net_bt", AID_NET_BT, }, { "sdcard_rw", AID_SDCARD_RW, }, { "vpn", AID_VPN, }, - { "inet", AID_INET, }, + { "keystore", AID_KEYSTORE, }, + { "inet", AID_INET, }, { "net_raw", AID_NET_RAW, }, { "misc", AID_MISC, }, { "nobody", AID_NOBODY, }, diff --git a/rootdir/init.rc b/rootdir/init.rc index e16a3f0fa..9d764d22e 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -54,7 +54,7 @@ loglevel 3 # mount mtd partitions # Mount /system rw first to give the filesystem a chance to save a checkpoint - mount yaffs2 mtd@system /system + mount yaffs2 mtd@system /system mount yaffs2 mtd@system /system ro remount # We chown/chmod /data again so because mount is run as root + defaults @@ -74,6 +74,9 @@ loglevel 3 # create basic filesystem structure mkdir /data/misc 01771 system misc mkdir /data/misc/hcid 0770 bluetooth bluetooth + mkdir /data/misc/keystore 0770 keystore keystore + mkdir /data/misc/vpn 0770 system system + mkdir /data/misc/vpn/profiles 0770 system system mkdir /data/local 0771 shell shell mkdir /data/local/tmp 0771 shell shell mkdir /data/data 0771 system system @@ -284,3 +287,19 @@ service installd /system/bin/installd service flash_recovery /system/bin/flash_image recovery /system/recovery.img oneshot + +service racoon /system/bin/racoon -F -f /etc/racoon/racoon.conf + socket racoon stream 600 system system + disabled + oneshot + +service mtpd /system/bin/mtpd + socket mtpd stream 600 system system + disabled + oneshot + +service keystore /system/bin/keystore + user keystore + group keystore + socket keystore stream 666 + From 720f08f3ffb27084f2a9c98d661dae53d7191ebf Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Tue, 9 Jun 2009 14:38:56 -0700 Subject: [PATCH 07/30] Add /config mounting point Signed-off-by: Dmitry Shmidt --- rootdir/init.rc | 1 + 1 file changed, 1 insertion(+) diff --git a/rootdir/init.rc b/rootdir/init.rc index 9d764d22e..25463a8d5 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -23,6 +23,7 @@ loglevel 3 mkdir /system mkdir /data 0771 system system mkdir /cache 0770 system cache + mkdir /config 0500 root root mkdir /sqlite_stmt_journals 01777 root root mount tmpfs tmpfs /sqlite_stmt_journals size=4m From 8dc662efe9e0c820eb001d66315bc32b2358fc57 Mon Sep 17 00:00:00 2001 From: Jack Palevich Date: Tue, 9 Jun 2009 22:53:47 +0000 Subject: [PATCH 08/30] Make otcc code work in x64 based system with 32-bit chroot. Set execute permission on code before running it. Handle negative relative offsets for global variables. Add printfs to report the progress of nested compiles. Change way we detect whether we can run the host compiler or not. We used to check if we were running on a 32-bit Linux. Now we check if the executable is a 32-bit Linux executable. --- libacc/acc.cpp | 18 +++++++++++++++--- libacc/tests/data/otcc-ansi.c | 21 +++++++++++++++++---- libacc/tests/data/otcc.c | 2 ++ libacc/tests/data/returnval-ansi.c | 4 +--- libacc/tests/data/returnval.c | 3 --- libacc/tests/testlocal | 15 +++++++++------ 6 files changed, 44 insertions(+), 19 deletions(-) diff --git a/libacc/acc.cpp b/libacc/acc.cpp index db37ee27c..e0043efb4 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -18,6 +19,10 @@ #include #include +#if defined(__i386__) +#include +#endif + #if defined(__arm__) #include #endif @@ -989,7 +994,14 @@ class Compiler : public ErrorSink { } virtual int finishCompile() { - return 0; + size_t pagesize = 4096; + size_t base = (size_t) getBase() & ~ (pagesize - 1); + size_t top = ((size_t) getPC() + pagesize - 1) & ~ (pagesize - 1); + int err = mprotect((void*) base, top - base, PROT_READ | PROT_WRITE | PROT_EXEC); + if (err) { + error("mprotect() failed: %d", errno); + } + return err; } private: @@ -1031,7 +1043,7 @@ class Compiler : public ErrorSink { void gmov(int l, int t) { o(l + 0x83); - oad((t < LOCAL) << 7 | 5, t); + oad((t > -LOCAL && t < LOCAL) << 7 | 5, t); } }; @@ -2165,7 +2177,7 @@ public: inp(); next(); globalDeclarations(); - pGen->finishCompile(); + result = pGen->finishCompile(); } return result; } diff --git a/libacc/tests/data/otcc-ansi.c b/libacc/tests/data/otcc-ansi.c index 069514bf0..5b758794f 100644 --- a/libacc/tests/data/otcc-ansi.c +++ b/libacc/tests/data/otcc-ansi.c @@ -50,7 +50,7 @@ void ad() { o(); } C = 0; - d = h; + d = h; if (X()) { E(32); M = D; @@ -162,7 +162,7 @@ void Z(int e) { void N(int j, int e) { ae(j + 131); - s((e < 512) << 7 | 5, e); + s((e > -512 && e < 512) << 7 | 5, e); } void T (int j) { @@ -404,7 +404,7 @@ void ab (int j) { v=v +4; } ad(); - if( d == 44)ad(); + if( d == 44)ad() ; } ad(); } @@ -432,7 +432,12 @@ void ab (int j) { } } +int run(int g, int e) { + return (*(int(*)()) *(int*) (P + 592))(g, e); +} + int main(int g, int e) { + int result; Q = stdin; if (g-- > 1) { e = e + 4; @@ -445,5 +450,13 @@ int main(int g, int e) { o(); ad(); ab(0); - return (*(int(*)()) *(int*) (P + 592))(g, e); + if (mprotect((ac + 592) & (~ 4095), (99999 + 4095) & (~ 4095), 7)) { + printf("Mprotect failed. %d\n", errno); + return -1; + } + fprintf(stderr, "otcc-ansi.c: About to execute compiled code:\n"); + result = run(g, e); + fprintf(stderr, "atcc-ansi.c: result: %d\n", result); + return result; } + diff --git a/libacc/tests/data/otcc.c b/libacc/tests/data/otcc.c index 577fcf37c..433ae2ea6 100644 --- a/libacc/tests/data/otcc.c +++ b/libacc/tests/data/otcc.c @@ -441,6 +441,8 @@ P V; o f; c; ab(0); +mprotect(ac & (~ 4095), (99999 + 4095) & (~ 4095), 7); +fprintf(stderr, "otcc.c: about to execute compiled code.\n"); J(*(int(*)f)k(P+592))(g,n; } diff --git a/libacc/tests/data/returnval-ansi.c b/libacc/tests/data/returnval-ansi.c index e386009a6..6b53fd54b 100644 --- a/libacc/tests/data/returnval-ansi.c +++ b/libacc/tests/data/returnval-ansi.c @@ -1,10 +1,8 @@ -#define VALUE (2*FOO) -#define FOO 12 int main(int argc, char** argv) { return f(); } int f() { - return VALUE; + return 42; } diff --git a/libacc/tests/data/returnval.c b/libacc/tests/data/returnval.c index 1b9dd8177..1cf5bae93 100644 --- a/libacc/tests/data/returnval.c +++ b/libacc/tests/data/returnval.c @@ -1,6 +1,3 @@ -#pragma foo3(bar) //sdfsfd -#pragma a(b) - main() { return 42; } diff --git a/libacc/tests/testlocal b/libacc/tests/testlocal index 2989e11f4..1650bf9fb 100755 --- a/libacc/tests/testlocal +++ b/libacc/tests/testlocal @@ -2,17 +2,20 @@ SCRIPT_DIR=`dirname $BASH_SOURCE` DATA=$SCRIPT_DIR/data +ACC=`which acc` echo "Compiling returnval-ansi.c" -acc -S $DATA/returnval-ansi.c +$ACC -S $DATA/returnval-ansi.c echo "Compiling whole compiler." -acc -S "$DATA/otcc-ansi.c" +$ACC -S "$DATA/otcc-ansi.c" -if (( "$(uname)" = "Linux" )) && (( "$(uname -m)" = "i686" )); then - echo "Linux i686. Testing otcc-ansi.c" - acc -R "$DATA/otcc-ansi.c" "$DATA/returnval.c" - acc -R $DATA/otcc-ansi.c $DATA/otcc.c $DATA/returnval.c +if file $ACC | grep -q "ELF 32-bit LSB executable, Intel 80386"; then + echo "Linux 32bit Intel." + $ACC -R $DATA/returnval-ansi.c + echo Testing otcc-ansi.c + $ACC -R "$DATA/otcc-ansi.c" "$DATA/returnval.c" + $ACC -R $DATA/otcc-ansi.c $DATA/otcc.c $DATA/returnval.c fi echo "Done with tests." From 1d36696821cd81ed7b668bb9d2b0b8a43540ccd2 Mon Sep 17 00:00:00 2001 From: Jaikumar Ganesh Date: Tue, 5 May 2009 22:28:54 -0700 Subject: [PATCH 09/30] Bluez4 changes Rename hcid to bluetoothd and change permissions. --- include/private/android_filesystem_config.h | 2 +- rootdir/init.rc | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h index 459062682..1a1484277 100644 --- a/include/private/android_filesystem_config.h +++ b/include/private/android_filesystem_config.h @@ -157,7 +157,7 @@ static struct fs_path_config android_files[] = { { 00550, AID_ROOT, AID_SHELL, "system/etc/init.gprs-pppd" }, { 00550, AID_DHCP, AID_SHELL, "system/etc/dhcpcd/dhcpcd-run-hooks" }, { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/dbus.conf" }, - { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluez/hcid.conf" }, + { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluez/main.conf" }, { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluez/input.conf" }, { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluez/audio.conf" }, { 00440, AID_RADIO, AID_AUDIO, "/system/etc/AudioPara4.csv" }, diff --git a/rootdir/init.rc b/rootdir/init.rc index 25463a8d5..357e332f2 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -74,7 +74,7 @@ loglevel 3 # create basic filesystem structure mkdir /data/misc 01771 system misc - mkdir /data/misc/hcid 0770 bluetooth bluetooth + mkdir /data/misc/bluetoothd 0770 bluetooth bluetooth mkdir /data/misc/keystore 0770 keystore keystore mkdir /data/misc/vpn 0770 system system mkdir /data/misc/vpn/profiles 0770 system system @@ -258,16 +258,18 @@ service bootanim /system/bin/bootanimation disabled oneshot -service dbus /system/bin/dbus-daemon --system --nofork +#STOPSHIP: Remove logwrapper before production +service dbus /system/bin/logwrapper /system/bin/dbus-daemon --system --nofork socket dbus stream 660 bluetooth bluetooth user bluetooth group bluetooth net_bt_admin -service hcid /system/bin/hcid -s -n -f /etc/bluez/hcid.conf +#STOPSHIP: Remove logwrapper and -d option before production +service bluetoothd /system/bin/logwrapper /system/bin/bluetoothd -d -n socket bluetooth stream 660 bluetooth bluetooth socket dbus_bluetooth stream 660 bluetooth bluetooth # init.rc does not yet support applying capabilities, so run as root and - # let hcid drop uid to bluetooth with the right linux capabilities + # let bluetoothd drop uid to bluetooth with the right linux capabilities group bluetooth net_bt_admin misc disabled From 3d6f16e5edc9834b13a0bcc8a33c98e25518d919 Mon Sep 17 00:00:00 2001 From: San Mehat Date: Wed, 10 Jun 2009 10:49:57 -0700 Subject: [PATCH 10/30] init.rc: Set default cpu shares for background scheduler group to < 1% Signed-off-by: San Mehat --- rootdir/init.rc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rootdir/init.rc b/rootdir/init.rc index 9d764d22e..27e833b90 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -50,7 +50,7 @@ loglevel 3 mkdir /dev/cpuctl/bg_non_interactive chown system system /dev/cpuctl/bg_non_interactive/tasks chmod 0777 /dev/cpuctl/bg_non_interactive/tasks - write /dev/cpuctl/bg_non_interactive/cpu.shares 1024 + write /dev/cpuctl/bg_non_interactive/cpu.shares 1 # mount mtd partitions # Mount /system rw first to give the filesystem a chance to save a checkpoint From 0a280a0dde38444398da102c17f260270a0a4c4e Mon Sep 17 00:00:00 2001 From: Jack Palevich Date: Thu, 11 Jun 2009 10:53:51 -0700 Subject: [PATCH 11/30] Remove use of setjmp/longjmp from libacc compiler. It makes it harder to deal with memory allocation. Also fix bug in the otcc-ansi.c test, where the wrong part of the code buffer was being mprotected, so that if the code buffer happened to be allocated across a page boundary, some code would no receive execute permission. --- libacc/acc.cpp | 79 ++++++++++++++++++++--------------- libacc/tests/data/otcc-ansi.c | 2 +- 2 files changed, 47 insertions(+), 34 deletions(-) diff --git a/libacc/acc.cpp b/libacc/acc.cpp index e0043efb4..e7f95b036 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -69,6 +68,7 @@ class Compiler : public ErrorSink { char* pProgramBase; ErrorSink* mErrorSink; int mSize; + bool mOverflowed; void release() { if (pProgramBase != 0) { @@ -77,13 +77,16 @@ class Compiler : public ErrorSink { } } - void check(int n) { + bool check(int n) { int newSize = ind - pProgramBase + n; - if (newSize > mSize) { + bool overflow = newSize > mSize; + if (overflow && !mOverflowed) { + mOverflowed = true; if (mErrorSink) { mErrorSink->error("Code too large: %d bytes", newSize); } } + return overflow; } public: @@ -92,6 +95,7 @@ class Compiler : public ErrorSink { ind = 0; mErrorSink = 0; mSize = 0; + mOverflowed = false; } ~CodeBuf() { @@ -110,7 +114,9 @@ class Compiler : public ErrorSink { } int o4(int n) { - check(4); + if(check(4)) { + return 0; + } intptr_t result = (intptr_t) ind; * (int*) ind = n; ind += 4; @@ -121,7 +127,9 @@ class Compiler : public ErrorSink { * Output a byte. Handles all values, 0..ff. */ void ob(int n) { - check(1); + if(check(1)) { + return; + } *ind++ = n; } @@ -1037,6 +1045,7 @@ class Compiler : public ErrorSink { int decodeOp(int op) { if (op < 0 || op > OP_COUNT) { error("Out-of-range operator: %d\n", op); + op = 0; } return operatorHelper[op]; } @@ -1363,8 +1372,6 @@ class Compiler : public ErrorSink { String mErrorBuf; - jmp_buf mErrorRecoveryJumpBuf; - String mPragmas; int mPragmaStringCount; @@ -1430,6 +1437,7 @@ class Compiler : public ErrorSink { void pdef(int t) { if (dstk - sym_stk >= ALLOC_SIZE) { error("Symbol table exhausted"); + return; } *dstk++ = t; } @@ -1475,7 +1483,6 @@ class Compiler : public ErrorSink { } else { error("Unsupported preprocessor directive \"%s\"", last_id); } - } inp(); } @@ -1609,6 +1616,7 @@ class Compiler : public ErrorSink { if (ch == '(') { delete pName; error("Defines with arguments not supported"); + return; } while (isspace(ch)) { inp(); @@ -1669,7 +1677,6 @@ class Compiler : public ErrorSink { mErrorBuf.printf("%ld: ", file->getLine()); mErrorBuf.vprintf(fmt, ap); mErrorBuf.printf("\n"); - longjmp(mErrorRecoveryJumpBuf, 1); } void skip(intptr_t c) { @@ -2053,6 +2060,7 @@ class Compiler : public ErrorSink { char* allocGlobalSpace(int bytes) { if (glo - pGlobalBase + bytes > ALLOC_SIZE) { error("Global space exhausted"); + return NULL; } char* result = glo; glo += bytes; @@ -2132,8 +2140,9 @@ class Compiler : public ErrorSink { } if (pGen == NULL) { error("No code generator defined."); + } else { + pGen->setErrorSink(this); } - pGen->setErrorSink(this); } public: @@ -2154,30 +2163,34 @@ public: int compile(const char* text, size_t textLength) { int result; - if (! (result = setjmp(mErrorRecoveryJumpBuf))) { - cleanup(); - clear(); - codeBuf.init(ALLOC_SIZE); - setArchitecture(NULL); - if (!pGen) { - return -1; + + cleanup(); + clear(); + codeBuf.init(ALLOC_SIZE); + setArchitecture(NULL); + if (!pGen) { + return -1; + } + pGen->init(&codeBuf); + file = new TextInputStream(text, textLength); + sym_stk = (char*) calloc(1, ALLOC_SIZE); + static const char* predefinedSymbols = + " int char void" + " if else while break return for" + " pragma define main "; + dstk = strcpy(sym_stk, predefinedSymbols) + + strlen(predefinedSymbols); + pGlobalBase = (char*) calloc(1, ALLOC_SIZE); + glo = pGlobalBase; + pVarsBase = (char*) calloc(1, ALLOC_SIZE); + inp(); + next(); + globalDeclarations(); + result = pGen->finishCompile(); + if (result == 0) { + if (mErrorBuf.len()) { + result = -2; } - pGen->init(&codeBuf); - file = new TextInputStream(text, textLength); - sym_stk = (char*) calloc(1, ALLOC_SIZE); - static const char* predefinedSymbols = - " int char void" - " if else while break return for" - " pragma define main "; - dstk = strcpy(sym_stk, predefinedSymbols) - + strlen(predefinedSymbols); - pGlobalBase = (char*) calloc(1, ALLOC_SIZE); - glo = pGlobalBase; - pVarsBase = (char*) calloc(1, ALLOC_SIZE); - inp(); - next(); - globalDeclarations(); - result = pGen->finishCompile(); } return result; } diff --git a/libacc/tests/data/otcc-ansi.c b/libacc/tests/data/otcc-ansi.c index 5b758794f..3ffad36ac 100644 --- a/libacc/tests/data/otcc-ansi.c +++ b/libacc/tests/data/otcc-ansi.c @@ -450,7 +450,7 @@ int main(int g, int e) { o(); ad(); ab(0); - if (mprotect((ac + 592) & (~ 4095), (99999 + 4095) & (~ 4095), 7)) { + if (mprotect(ac & (~ 4095), (99999 + 4095) & (~ 4095), 7)) { printf("Mprotect failed. %d\n", errno); return -1; } From 2db168f12feb0e25209b4aee385af074ef87157a Mon Sep 17 00:00:00 2001 From: Jack Palevich Date: Thu, 11 Jun 2009 14:29:47 -0700 Subject: [PATCH 12/30] Use a separate table for keywords. --- libacc/acc.cpp | 181 ++++++++++++++++++++++++++++-------------- libacc/tests/main.cpp | 22 ++--- 2 files changed, 134 insertions(+), 69 deletions(-) diff --git a/libacc/acc.cpp b/libacc/acc.cpp index e7f95b036..fb4f4f689 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -1204,8 +1204,8 @@ class Compiler : public ErrorSink { */ class FakeString : public String { public: - FakeString(char* string, size_t length) : - String(string, length, true) {} + FakeString(const char* string, size_t length) : + String((char*) string, length, true) {} ~FakeString() { orphan(); @@ -1220,6 +1220,7 @@ class Compiler : public ErrorSink { ~StringTable() { clear(); + hashmapFree(mpMap); } void clear() { @@ -1278,6 +1279,71 @@ class Compiler : public ErrorSink { MacroTable() : StringTable(10) {} }; + class KeywordTable { + public: + + KeywordTable(){ + mpMap = hashmapCreate(40, hashFn, equalsFn); + put("int", TOK_INT); + put("char", TOK_CHAR); + put("void", TOK_VOID); + put("if", TOK_IF); + put("else", TOK_ELSE); + put("while", TOK_WHILE); + put("break", TOK_BREAK); + put("return", TOK_RETURN); + put("for", TOK_FOR); + put("pragma", TOK_PRAGMA); + } + + ~KeywordTable() { + hashmapFree(mpMap); + } + + int get(char* key) { + return (int) hashmapGet(mpMap, key); + } + + const char* lookupKeyFor(int value) { + FindValContext context; + context.key = 0; + hashmapForEach(mpMap, findKeyFn, &context); + return context.key; + } + + private: + void put(const char* kw, int val) { + hashmapPut(mpMap, (void*) kw, (void*) val); + } + + static int hashFn(void* pKey) { + char* pString = (char*) pKey; + return hashmapHash(pString, strlen(pString)); + } + + static bool equalsFn(void* keyA, void* keyB) { + const char* pStringA = (const char*) keyA; + const char* pStringB = (const char*) keyB; + return strcmp(pStringA, pStringB) == 0; + } + + struct FindValContext { + char* key; + int value; + }; + + static bool findKeyFn(void* key, void* value, void* context) { + FindValContext* pContext = (FindValContext*) context; + if ((int) value == pContext->value) { + pContext->key = (char*) key; + return false; + } + return true; + } + + Hashmap* mpMap; + }; + template class Array { public: Array() { @@ -1346,6 +1412,11 @@ class Compiler : public ErrorSink { int oldCh; }; + struct VariableInfo { + void* pA; + void* pB; + }; + int ch; // Current input character, or EOF intptr_t tok; // token @@ -1360,7 +1431,8 @@ class Compiler : public ErrorSink { int dch; // Macro state: Saves old value of ch during a macro playback. char* last_id; char* pGlobalBase; - char* pVarsBase; // Value of variables + VariableInfo* pVarsBase; // Value of variables + KeywordTable mKeywords; InputStream* file; @@ -1377,20 +1449,22 @@ class Compiler : public ErrorSink { static const int ALLOC_SIZE = 99999; - // Indentifiers start at 0x100 and increase by # (chars + 1) * 8 - static const int TOK_IDENT = 0x100; - static const int TOK_INT = 0x100; - static const int TOK_CHAR = TOK_INT + 4*8; - static const int TOK_VOID = TOK_CHAR + 5*8; - static const int TOK_IF = TOK_VOID + 5*8; - static const int TOK_ELSE = TOK_IF + 3*8; - static const int TOK_WHILE = TOK_ELSE + 5*8; - static const int TOK_BREAK = TOK_WHILE + 6*8; - static const int TOK_RETURN = TOK_BREAK + 6*8; - static const int TOK_FOR = TOK_RETURN + 7*8; - static const int TOK_PRAGMA = TOK_FOR + 4*8; - static const int TOK_DEFINE = TOK_PRAGMA + 7*8; - static const int TOK_MAIN = TOK_DEFINE + 7*8; + // Keywords start at 0x100 and increase by 1 + static const int TOK_KEYWORD = 0x100; + static const int TOK_INT = TOK_KEYWORD + 0; + static const int TOK_CHAR = TOK_KEYWORD + 1; + static const int TOK_VOID = TOK_KEYWORD + 2; + static const int TOK_IF = TOK_KEYWORD + 3; + static const int TOK_ELSE = TOK_KEYWORD + 4; + static const int TOK_WHILE = TOK_KEYWORD + 5; + static const int TOK_BREAK = TOK_KEYWORD + 6; + static const int TOK_RETURN = TOK_KEYWORD + 7; + static const int TOK_FOR = TOK_KEYWORD + 8; + static const int TOK_PRAGMA = TOK_KEYWORD + 9; + static const int TOK_DEFINE = TOK_KEYWORD + 10; + + // Symbols start at 0x200 + static const int TOK_SYMBOL = 0x200; static const int TOK_DUMMY = 1; static const int TOK_NUM = 2; @@ -1514,18 +1588,20 @@ class Compiler : public ErrorSink { inp(); next(); } else { - * dstk = TAG_TOK; /* no need to mark end of string (we - suppose data is initialized to zero by calloc) */ - tok = (intptr_t) (strstr(sym_stk, (last_id - 1)) - - sym_stk); - * dstk = 0; /* mark real end of ident for dlsym() */ - tok = tok * 8 + TOK_IDENT; - if (tok > TOK_DEFINE) { - if (tok + 8 > ALLOC_SIZE) { - error("Variable Table overflow."); - } - tok = (intptr_t) (pVarsBase + tok); - /* printf("tok=%s %x\n", last_id, tok); */ + // Is this a keyword? + * dstk = 0; + int kwtok = mKeywords.get(last_id); + if (kwtok) { + tok = kwtok; + // fprintf(stderr, "tok= keyword %s %x\n", last_id, tok); + } else { + * dstk = TAG_TOK; /* no need to mark end of string (we + suppose data is initialized to zero by calloc) */ + tok = (intptr_t) (strstr(sym_stk, (last_id - 1)) + - sym_stk); + * dstk = 0; /* mark real end of ident for dlsym() */ + tok = (intptr_t) & (pVarsBase[tok]); + // fprintf(stderr, "tok= symbol %s %x\n", last_id, tok); } } } @@ -1583,15 +1659,19 @@ class Compiler : public ErrorSink { } #if 0 { - char* p; + const char* p; printf("tok=0x%x ", tok); - if (tok >= TOK_IDENT) { + if (tok >= TOK_KEYWORD) { printf("'"); - if (tok> TOK_DEFINE) - p = sym_stk + 1 + ((char*) tok - pVarsBase - TOK_IDENT) / 8; - else - p = sym_stk + 1 + (tok - TOK_IDENT) / 8; + if (tok>= TOK_SYMBOL) + p = sym_stk + 1 + ((char*) tok - (char*) pVarsBase) / 8; + else { + p = mKeywords.lookupKeyFor(tok); + if (!p) { + p = "unknown keyword"; + } + } while (*p != TAG_TOK && *p) printf("%c", *p++); printf("'\n"); @@ -1979,7 +2059,7 @@ class Compiler : public ErrorSink { } void checkSymbol() { - if (tok <= TOK_DEFINE) { + if (tok < TOK_SYMBOL) { error("Expected a symbol"); } } @@ -2174,15 +2254,10 @@ public: pGen->init(&codeBuf); file = new TextInputStream(text, textLength); sym_stk = (char*) calloc(1, ALLOC_SIZE); - static const char* predefinedSymbols = - " int char void" - " if else while break return for" - " pragma define main "; - dstk = strcpy(sym_stk, predefinedSymbols) - + strlen(predefinedSymbols); + dstk = sym_stk; pGlobalBase = (char*) calloc(1, ALLOC_SIZE); glo = pGlobalBase; - pVarsBase = (char*) calloc(1, ALLOC_SIZE); + pVarsBase = (VariableInfo*) calloc(1, ALLOC_SIZE); inp(); next(); globalDeclarations(); @@ -2195,16 +2270,6 @@ public: return result; } - int run(int argc, char** argv) { - typedef int (*mainPtr)(int argc, char** argv); - mainPtr aMain = (mainPtr) *(int*) (pVarsBase + TOK_MAIN); - if (!aMain) { - fprintf(stderr, "Could not find function \"main\".\n"); - return -1; - } - return aMain(argc, argv); - } - int dump(FILE* out) { fwrite(codeBuf.getBase(), 1, codeBuf.getSize(), out); return 0; @@ -2233,13 +2298,9 @@ public: if (memcmp(pSym, name, nameLen) == 0 && pSym[nameLen] == TAG_TOK) { int tok = pSym - 1 - sym_stk; - tok = tok * 8 + TOK_IDENT; - if (tok <= TOK_DEFINE) { - return 0; - } else { - tok = (intptr_t) (pVarsBase + tok); - return * (void**) tok; - } + tok = tok * sizeof(VariableInfo); + tok = (intptr_t) ((intptr_t) pVarsBase + tok); + return * (void**) tok; } } } diff --git a/libacc/tests/main.cpp b/libacc/tests/main.cpp index d624cbbde..4f8a65de8 100644 --- a/libacc/tests/main.cpp +++ b/libacc/tests/main.cpp @@ -109,16 +109,20 @@ int main(int argc, char** argv) { } } - accGetScriptLabel(script, "main", (ACCvoid**) & mainPointer); + if (runResults) { + accGetScriptLabel(script, "main", (ACCvoid**) & mainPointer); - result = accGetError(script); - if (result == ACC_NO_ERROR && runResults) { - fprintf(stderr, "Executing compiled code:\n"); - int codeArgc = argc - i + 1; - char** codeArgv = argv + i - 1; - codeArgv[0] = (char*) (inFile ? inFile : "stdin"); - result = run(mainPointer, codeArgc, codeArgv); - fprintf(stderr, "result: %d\n", result); + result = accGetError(script); + if (result != ACC_NO_ERROR) { + fprintf(stderr, "Could not find main: %d\n", result); + } else { + fprintf(stderr, "Executing compiled code:\n"); + int codeArgc = argc - i + 1; + char** codeArgv = argv + i - 1; + codeArgv[0] = (char*) (inFile ? inFile : "stdin"); + result = run(mainPointer, codeArgc, codeArgv); + fprintf(stderr, "result: %d\n", result); + } } exit: From 02d40b51c6d9f9dfc91f7d3b17a1f4f6db1ea972 Mon Sep 17 00:00:00 2001 From: Mike Lockwood Date: Thu, 11 Jun 2009 17:34:19 -0400 Subject: [PATCH 13/30] Revert "adb: Workaround for adb disconnect problem." This reverts commit e38a31e305b0944c0cd1ae782e47e3145d731f0f. This change had the unfortunate side effect of breaking ctrl-C when executing "adb shell " Signed-off-by: Mike Lockwood --- adb/services.c | 58 +++----------------------------------------------- 1 file changed, 3 insertions(+), 55 deletions(-) diff --git a/adb/services.c b/adb/services.c index b99cca1cb..0a5edcf4b 100644 --- a/adb/services.c +++ b/adb/services.c @@ -33,10 +33,6 @@ # endif #endif -#ifndef HAVE_WIN32_PROC -#include -#endif - typedef struct stinfo stinfo; struct stinfo { @@ -203,8 +199,8 @@ static int create_service_thread(void (*func)(int, void *), void *cookie) static int create_subprocess(const char *cmd, const char *arg0, const char *arg1) { #ifdef HAVE_WIN32_PROC - fprintf(stderr, "error: create_subprocess not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1); - return -1; + fprintf(stderr, "error: create_subprocess not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1); + return -1; #else /* !HAVE_WIN32_PROC */ char *devname; int ptm; @@ -271,54 +267,6 @@ static int create_subprocess(const char *cmd, const char *arg0, const char *arg1 #define SHELL_COMMAND "/system/bin/sh" #endif -static void shell_service(int s, void *command) -{ - char buffer[MAX_PAYLOAD]; - int fd, ret = 0; - unsigned count = 0; - - fd = create_subprocess(SHELL_COMMAND, "-c", (char *)command); - - while (1) { - while (count < sizeof(buffer)) { -#ifndef HAVE_WIN32_PROC - /* add a 200ms timeout so we don't block indefinitely with our - buffer partially filled. - */ - if (count > 0) { - struct pollfd pollfd; - - pollfd.fd = fd; - pollfd.events = POLLIN; - ret = poll(&pollfd, 1, 200); - if (ret <= 0) { - D("poll returned %d\n", ret); - // file has closed or we timed out - // set ret to 1 so we don't exit the outer loop - ret = 1; - break; - } - } -#endif - ret = adb_read(fd, buffer + count, sizeof(buffer) - count); - D("ret: %d, count: %d\n", ret, count); - if (ret > 0) - count += ret; - else - break; - } - - D("writing: %d\n", count); - adb_write(s, buffer, count); - count = 0; - if (ret <= 0) - break; - } - - adb_close(fd); - adb_close(s); -} - int service_to_fd(const char *name) { int ret = -1; @@ -372,7 +320,7 @@ int service_to_fd(const char *name) #endif } else if(!HOST && !strncmp(name, "shell:", 6)) { if(name[6]) { - ret = create_service_thread(shell_service, (void *)(name + 6)); + ret = create_subprocess(SHELL_COMMAND, "-c", name + 6); } else { ret = create_subprocess(SHELL_COMMAND, "-", 0); } From 2cf6cff71f36b76e816a7a90c66f4b04c71e8278 Mon Sep 17 00:00:00 2001 From: Dan Egnor Date: Thu, 11 Jun 2009 15:28:59 -0700 Subject: [PATCH 14/30] Add a note to event-log-tags listing the log tag range reserved for partner use, etc.. --- logcat/event-log-tags | 3 +++ 1 file changed, 3 insertions(+) diff --git a/logcat/event-log-tags b/logcat/event-log-tags index f9355ec18..6df379230 100644 --- a/logcat/event-log-tags +++ b/logcat/event-log-tags @@ -350,3 +350,6 @@ # browser stats for diary study 70101 browser_zoom_level_change (start level|1|5),(end level|1|5),(time|2|3) 70102 browser_double_tap_duration (duration|1|3),(time|2|3) + +# NOTE - the range 1000000-2000000 is reserved for partners and others who +# want to define their own log tags without conflicting with the core platform. From 303d8ffca9c508a6b25408fc3b2e80ead252e1ed Mon Sep 17 00:00:00 2001 From: Jack Palevich Date: Thu, 11 Jun 2009 19:06:24 -0700 Subject: [PATCH 15/30] Improve local variable scoping. Until now we faked local variables -- they only worked correctly if there was no overlap between local variables and global variables. Use a symbol table stack instead of a string list. Fix bug with looking up undefined symbols. --- libacc/Android.mk | 2 + libacc/acc.cpp | 293 +++++++++++++++++++++++----------- libacc/tests/Android.mk | 3 +- libacc/tests/data/expr-ansi.c | 60 +++++++ libacc/tests/data/expr2.c | 6 + libacc/tests/data/locals.c | 49 ++++++ libacc/tests/data/otcc-ansi.c | 4 + libacc/tests/testlocal | 4 +- 8 files changed, 324 insertions(+), 97 deletions(-) create mode 100644 libacc/tests/data/expr-ansi.c create mode 100644 libacc/tests/data/expr2.c create mode 100644 libacc/tests/data/locals.c diff --git a/libacc/Android.mk b/libacc/Android.mk index f3c2d3564..f77e2b34d 100644 --- a/libacc/Android.mk +++ b/libacc/Android.mk @@ -22,6 +22,8 @@ include $(CLEAR_VARS) LOCAL_MODULE:= libacc LOCAL_SRC_FILES := acc.cpp +LOCAL_CFLAGS := -O0 -g + ifeq ($(TARGET_ARCH),arm) LOCAL_SRC_FILES += disassem.cpp endif diff --git a/libacc/acc.cpp b/libacc/acc.cpp index fb4f4f689..b07a1d809 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -1116,9 +1116,12 @@ class Compiler : public ErrorSink { mSize = 0; } - String(char* item, int len, bool adopt) { + String(const char* item, int len, bool adopt) { + if (len < 0) { + len = strlen(item); + } if (adopt) { - mpBase = item; + mpBase = (char*) item; mUsed = len; mSize = len + 1; } else { @@ -1129,16 +1132,30 @@ class Compiler : public ErrorSink { } } + String(const String& other) { + mpBase = 0; + mUsed = 0; + mSize = 0; + appendBytes(other.getUnwrapped(), other.len()); + } + ~String() { if (mpBase) { free(mpBase); } } - inline char* getUnwrapped() { + inline char* getUnwrapped() const { return mpBase; } + void clear() { + mUsed = 0; + if (mSize > 0) { + mpBase[0] = 0; + } + } + void appendCStr(const char* s) { appendBytes(s, strlen(s)); } @@ -1173,7 +1190,7 @@ class Compiler : public ErrorSink { free(temp); } - inline size_t len() { + inline size_t len() const { return mUsed; } @@ -1214,8 +1231,12 @@ class Compiler : public ErrorSink { template class StringTable { public: + StringTable() { + init(10); + } + StringTable(size_t initialCapacity) { - mpMap = hashmapCreate(initialCapacity, hashFn, equalsFn); + init(initialCapacity); } ~StringTable() { @@ -1252,6 +1273,11 @@ class Compiler : public ErrorSink { } protected: + + void init(size_t initialCapacity) { + mpMap = hashmapCreate(initialCapacity, hashFn, equalsFn); + } + static int hashFn(void* pKey) { String* pString = (String*) pKey; return hashmapHash(pString->getUnwrapped(), pString->len()); @@ -1300,8 +1326,8 @@ class Compiler : public ErrorSink { hashmapFree(mpMap); } - int get(char* key) { - return (int) hashmapGet(mpMap, key); + int get(String* key) { + return (int) hashmapGet(mpMap, key->getUnwrapped()); } const char* lookupKeyFor(int value) { @@ -1359,8 +1385,8 @@ class Compiler : public ErrorSink { } E get(int i) { - if (i < 0 || i > mUsed) { - error("internal error: Index out of range"); + if (i < 0 || i > (int) mUsed) { + // error("internal error: Index out of range"); return E(); } return mpBase[i]; @@ -1374,7 +1400,7 @@ class Compiler : public ErrorSink { if (mUsed > 0) { mUsed -= 1; } else { - error("internal error: Popped empty stack."); + // error("internal error: Popped empty stack."); } } @@ -1413,10 +1439,101 @@ class Compiler : public ErrorSink { }; struct VariableInfo { - void* pA; - void* pB; + VariableInfo() { + pAddress = 0; + pForward = 0; + } + void* pAddress; + void* pForward; // For a forward direction, linked list of data to fix up }; + typedef StringTable SymbolTable; + + class SymbolStack { + public: + SymbolStack() { + mLevel = 0; + addEntry(); + } + + void pushLevel() { + mLevel++; + } + + void popLevel() { + mLevel--; + Entry e = mStack.get(mStack.len()-1); + if (mLevel < e.level) { + mStack.pop(); + delete e.pTable; + } + } + + VariableInfo* get(String* pName) { + int len = mStack.len(); + VariableInfo* v = NULL; + int level = -1; + for (int i = len - 1; i >= 0; i--) { + Entry e = mStack.get(i); + v = e.pTable->get(pName); + if (v) { + level = e.level; + break; + } + } +#if 0 + fprintf(stderr, "Lookup %s %08x level %d\n", pName->getUnwrapped(), v, level); + if (v) { + fprintf(stderr, " %08x %08x\n", v->pAddress, v->pForward); + } +#endif + return v; + } + + VariableInfo* addLocal(String* pName) { + int len = mStack.len(); + if (mStack.get(len-1).level != mLevel) { + addEntry(); + len++; + } + return addImp(len-1, pName); + } + + VariableInfo* addGlobal(String* pName) { + return addImp(0, pName); + } + + private: + VariableInfo* addImp(int entryIndex, String* pName) { + Entry e = mStack.get(entryIndex); + SymbolTable* pTable = e.pTable; + VariableInfo* v = new VariableInfo(); + delete pTable->put(pName, v); +#if 0 + fprintf(stderr, "Add \"%s\" %08x level %d\n", pName->getUnwrapped(), v, e.level); +#endif + return v; + } + + void addEntry() { + Entry e; + e.level = mLevel; + e.pTable = new SymbolTable(); + mStack.push(e); + } + + struct Entry { + Entry() { + level = 0; + pTable = NULL; + } + int level; + SymbolTable* pTable; + }; + + int mLevel; + Array mStack; + }; int ch; // Current input character, or EOF intptr_t tok; // token @@ -1425,15 +1542,12 @@ class Compiler : public ErrorSink { intptr_t rsym; // return symbol intptr_t loc; // local variable index char* glo; // global variable index - char* sym_stk; - char* dstk; // Define stack + String mTokenString; char* dptr; // Macro state: Points to macro text during macro playback. int dch; // Macro state: Saves old value of ch during a macro playback. - char* last_id; char* pGlobalBase; - VariableInfo* pVarsBase; // Value of variables KeywordTable mKeywords; - + SymbolStack mSymbolTable; InputStream* file; CodeBuf codeBuf; @@ -1449,6 +1563,11 @@ class Compiler : public ErrorSink { static const int ALLOC_SIZE = 99999; + static const int TOK_DUMMY = 1; + static const int TOK_NUM = 2; + + // 3..255 are character and/or operators + // Keywords start at 0x100 and increase by 1 static const int TOK_KEYWORD = 0x100; static const int TOK_INT = TOK_KEYWORD + 0; @@ -1463,11 +1582,11 @@ class Compiler : public ErrorSink { static const int TOK_PRAGMA = TOK_KEYWORD + 9; static const int TOK_DEFINE = TOK_KEYWORD + 10; - // Symbols start at 0x200 - static const int TOK_SYMBOL = 0x200; + static const int TOK_UNDEFINED_SYMBOL = 0x200; + + // Symbols start at 0x300, but are really pointers to VariableInfo structs. + static const int TOK_SYMBOL = 0x300; - static const int TOK_DUMMY = 1; - static const int TOK_NUM = 2; static const int LOCAL = 0x200; @@ -1509,11 +1628,7 @@ class Compiler : public ErrorSink { static const char operatorLevel[]; void pdef(int t) { - if (dstk - sym_stk >= ALLOC_SIZE) { - error("Symbol table exhausted"); - return; - } - *dstk++ = t; + mTokenString.append(t); } void inp() { @@ -1555,7 +1670,8 @@ class Compiler : public ErrorSink { } else if (tok == TOK_PRAGMA) { doPragma(); } else { - error("Unsupported preprocessor directive \"%s\"", last_id); + error("Unsupported preprocessor directive \"%s\"", + mTokenString.getUnwrapped()); } } inp(); @@ -1564,43 +1680,34 @@ class Compiler : public ErrorSink { tok = ch; /* encode identifiers & numbers */ if (isid()) { - pdef(TAG_TOK); - last_id = dstk; + mTokenString.clear(); while (isid()) { pdef(ch); inp(); } if (isdigit(tok)) { - tokc = strtol(last_id, 0, 0); + tokc = strtol(mTokenString.getUnwrapped(), 0, 0); tok = TOK_NUM; } else { - if (dstk - sym_stk + 1 > ALLOC_SIZE) { - error("symbol stack overflow"); - } - FakeString token(last_id, dstk-last_id); // Is this a macro? - String* pValue = mMacros.get(&token); + String* pValue = mMacros.get(&mTokenString); if (pValue) { // Yes, it is a macro - dstk = last_id-1; dptr = pValue->getUnwrapped(); dch = ch; inp(); next(); } else { // Is this a keyword? - * dstk = 0; - int kwtok = mKeywords.get(last_id); + int kwtok = mKeywords.get(&mTokenString); if (kwtok) { tok = kwtok; // fprintf(stderr, "tok= keyword %s %x\n", last_id, tok); } else { - * dstk = TAG_TOK; /* no need to mark end of string (we - suppose data is initialized to zero by calloc) */ - tok = (intptr_t) (strstr(sym_stk, (last_id - 1)) - - sym_stk); - * dstk = 0; /* mark real end of ident for dlsym() */ - tok = (intptr_t) & (pVarsBase[tok]); + tok = (intptr_t) mSymbolTable.get(&mTokenString); + if (!tok) { + tok = TOK_UNDEFINED_SYMBOL; + } // fprintf(stderr, "tok= symbol %s %x\n", last_id, tok); } } @@ -1831,11 +1938,21 @@ class Compiler : public ErrorSink { } else if (t == '&') { pGen->leaR0(*(int *) tok); next(); + } else if (t == EOF ) { + error("Unexpected EOF."); + } else if (t < TOK_UNDEFINED_SYMBOL) { + error("Unexpected symbol or keyword"); } else { + if (t == TOK_UNDEFINED_SYMBOL) { + t = (intptr_t) mSymbolTable.addGlobal( + new String(mTokenString)); + } + n = *(int *) t; /* forward reference: try dlsym */ if (!n) { - n = (intptr_t) dlsym(RTLD_DEFAULT, last_id); + n = (intptr_t) dlsym(RTLD_DEFAULT, + mTokenString.getUnwrapped()); } if ((tok == '=') & l) { /* assignment */ @@ -1979,12 +2096,14 @@ class Compiler : public ErrorSink { pGen->gjmp(n - codeBuf.getPC() - pGen->jumpOffset()); /* jmp */ pGen->gsym(a); } else if (tok == '{') { + mSymbolTable.pushLevel(); next(); /* declarations */ localDeclarations(); - while (tok != '}') + while (tok != '}' && tok != EOF) block(l); - next(); + skip('}'); + mSymbolTable.popLevel(); } else { if (tok == TOK_RETURN) { next(); @@ -2064,6 +2183,20 @@ class Compiler : public ErrorSink { } } + void defineGlobalSymbol() { + if (tok == TOK_UNDEFINED_SYMBOL) { + // TODO: don't allow multiple definitions at same level. + tok = (intptr_t) mSymbolTable.addGlobal( + new String(mTokenString)); + } + } + + void defineLocalSymbol() { + // TODO: don't allow multiple definitions at same level. + tok = (intptr_t) mSymbolTable.addLocal( + new String(mTokenString)); + } + void localDeclarations() { intptr_t a; Type base; @@ -2071,7 +2204,7 @@ class Compiler : public ErrorSink { while (acceptType(base)) { while (tok != ';') { Type t = acceptPointerDeclaration(t); - checkSymbol(); + defineLocalSymbol(); loc = loc + 4; *(int *) tok = -loc; @@ -2088,37 +2221,38 @@ class Compiler : public ErrorSink { Type base; expectType(base); Type t = acceptPointerDeclaration(t); - checkSymbol(); - int name = tok; + defineGlobalSymbol(); + VariableInfo* name = (VariableInfo*) tok; next(); if (tok == ',' || tok == ';') { // it's a variable declaration for(;;) { - *(int* *) name = (int*) allocGlobalSpace(4); + name->pAddress = (int*) allocGlobalSpace(4); if (tok != ',') { break; } - next(); + skip(','); t = acceptPointerDeclaration(t); - checkSymbol(); - name = tok; + defineGlobalSymbol(); + name = (VariableInfo*) tok; next(); } skip(';'); } else { /* patch forward references (XXX: does not work for function pointers) */ - pGen->gsym(*(int *) (name + 4)); + pGen->gsym((int) name->pForward); /* put function address */ - *(int *) name = codeBuf.getPC(); + name->pAddress = (void*) codeBuf.getPC(); skip('('); + mSymbolTable.pushLevel(); intptr_t a = 8; int argCount = 0; - while (tok != ')') { + while (tok != ')' && tok != EOF) { Type aType; expectType(aType); aType = acceptPointerDeclaration(aType); - checkSymbol(); + defineLocalSymbol(); /* read param name and compute offset */ *(int *) tok = a; a = a + 4; @@ -2127,12 +2261,13 @@ class Compiler : public ErrorSink { next(); argCount++; } - skip(')'); /* skip ')' */ + skip(')'); rsym = loc = 0; a = pGen->functionEntry(argCount); block(0); pGen->gsym(rsym); pGen->functionExit(argCount, a, loc); + mSymbolTable.popLevel(); } } } @@ -2148,18 +2283,10 @@ class Compiler : public ErrorSink { } void cleanup() { - if (sym_stk != 0) { - free(sym_stk); - sym_stk = 0; - } if (pGlobalBase != 0) { free(pGlobalBase); pGlobalBase = 0; } - if (pVarsBase != 0) { - free(pVarsBase); - pVarsBase = 0; - } if (pGen) { delete pGen; pGen = 0; @@ -2175,18 +2302,13 @@ class Compiler : public ErrorSink { tokc = 0; tokl = 0; ch = 0; - pVarsBase = 0; rsym = 0; loc = 0; glo = 0; - sym_stk = 0; - dstk = 0; dptr = 0; dch = 0; - last_id = 0; file = 0; pGlobalBase = 0; - pVarsBase = 0; pGen = 0; mPragmaStringCount = 0; } @@ -2253,11 +2375,8 @@ public: } pGen->init(&codeBuf); file = new TextInputStream(text, textLength); - sym_stk = (char*) calloc(1, ALLOC_SIZE); - dstk = sym_stk; pGlobalBase = (char*) calloc(1, ALLOC_SIZE); glo = pGlobalBase; - pVarsBase = (VariableInfo*) calloc(1, ALLOC_SIZE); inp(); next(); globalDeclarations(); @@ -2283,26 +2402,10 @@ public: * If found, return its value. */ void* lookup(const char* name) { - if (!sym_stk) { - return NULL; - } - size_t nameLen = strlen(name); - char* pSym = sym_stk; - char c; - for(;;) { - c = *pSym++; - if (c == 0) { - break; - } - if (c == TAG_TOK) { - if (memcmp(pSym, name, nameLen) == 0 - && pSym[nameLen] == TAG_TOK) { - int tok = pSym - 1 - sym_stk; - tok = tok * sizeof(VariableInfo); - tok = (intptr_t) ((intptr_t) pVarsBase + tok); - return * (void**) tok; - } - } + String string(name, -1, false); + VariableInfo* pVariableInfo = mSymbolTable.get(&string); + if (pVariableInfo) { + return pVariableInfo->pAddress; } return NULL; } diff --git a/libacc/tests/Android.mk b/libacc/tests/Android.mk index 1e4d328e8..f8907b45b 100644 --- a/libacc/tests/Android.mk +++ b/libacc/tests/Android.mk @@ -26,7 +26,8 @@ LOCAL_SRC_FILES:= \ LOCAL_SHARED_LIBRARIES := \ libacc +LOCAL_CFLAGS := -O0 -g LOCAL_MODULE_TAGS := tests -include $(BUILD_EXECUTABLE) \ No newline at end of file +include $(BUILD_EXECUTABLE) diff --git a/libacc/tests/data/expr-ansi.c b/libacc/tests/data/expr-ansi.c new file mode 100644 index 000000000..d463659bd --- /dev/null +++ b/libacc/tests/data/expr-ansi.c @@ -0,0 +1,60 @@ +/* Test operators */ + +void testInc() { int a, b; a = 3; b = a++; printf("3++ = %d %d\n", b, a); } +void testDec() { int a, b; a = 3; b = a--; printf("3-- = %d %d\n", b, a); } +void testTimes(){ printf("%d * %d = %d\n", 10, 4, 10 * 4); } +void testDiv(){ printf("%d / %d = %d\n", 11, 4, 11 / 4); } +void testMod(){ printf("%d %% %d = %d\n", 11, 4, 11 % 4); } +void testPlus(){ printf("%d + %d = %d\n", 10, 4, 10 + 4); } +void testMinus(){ printf("%d - %d = %d\n", 10, 4, 10 - 4); } +void testShiftLeft(){ printf("%d << %d = %d\n", 10, 4, 10 << 4); } +void testShiftRight(){ printf("%d >> %d = %d\n", 100, 4, 100 >> 4); } +void testLess(){ printf("%d < %d = %d\n", 10, 4, 10 < 4); } +void testLesEqual(){ printf("%d <= %d = %d\n", 10, 4, 10 <= 4); } +void testGreater(){ printf("%d > %d = %d\n", 10, 4, 10 > 4); } +void testGreaterEqual(){ printf("%d >= %d = %d\n", 10, 4, 10 >= 4); } +void testEqualTo(){ printf("%d == %d = %d\n", 10, 4, 10 == 4); } +void testNotEqualTo(){ printf("%d != %d = %d\n", 10, 4, 10 != 4); } +void testBitAnd(){ printf("%d & %d = %d\n", 10, 7, 10 & 7); } +void testBitXor(){ printf("%d ^ %d = %d\n", 10, 7, 10 ^ 7); } +void testBitOr(){ printf("%d | %d = %d\n", 10, 4, 10 | 4); } +void testAssignment(){ int a, b; a = 3; b = a; printf("b == %d\n", b); } +void testLogicalAnd(){ printf("%d && %d = %d\n", 10, 4, 10 && 4); } +void testLogicalOr(){ printf("%d || %d = %d\n", 10, 4, 10 || 4); } +void testAddressOf(){ int a; printf("&a is %d\n", &a); } +void testPointerIndirection(){ int a, b; a = &b; b = 17; printf("*%d = %d =?= %d\n", a, * (int*) a, b); } +void testNegation(){ printf("-%d = %d\n", 10, -10); } +void testUnaryPlus(){ printf("+%d = %d\n", 10, +10); } +void testUnaryNot(){ printf("!%d = %d\n", 10, !10); } +void testBitNot(){ printf("~%d = %d\n", 10, ~10); } + +int main(int a, char** b) { + testInc(); + testDec(); + testTimes(); + testDiv(); + testMod(); + testPlus(); + testMinus(); + testShiftLeft(); + testShiftRight(); + testLess(); + testLesEqual(); + testGreater(); + testGreaterEqual(); + testEqualTo(); + testNotEqualTo(); + testBitAnd(); + testBinXor(); + testBitOr(); + testAssignment(); + testLogicalAnd(); + testLogicalOr(); + testAddressOf(); + testPointerIndirection(); + testNegation(); + testUnaryPlus(); + testUnaryNot(); + testBitNot(); + return 0; +} diff --git a/libacc/tests/data/expr2.c b/libacc/tests/data/expr2.c new file mode 100644 index 000000000..04b6a38d3 --- /dev/null +++ b/libacc/tests/data/expr2.c @@ -0,0 +1,6 @@ +/* Test operators */ + +main() { + int a; + a = a++; +} diff --git a/libacc/tests/data/locals.c b/libacc/tests/data/locals.c new file mode 100644 index 000000000..318162dee --- /dev/null +++ b/libacc/tests/data/locals.c @@ -0,0 +1,49 @@ +int a; + +int f() { + int a; + printf("f 0: a = %d b = %d\n", a, b); + a = 2; + printf("f 1: a = %d\n", a); +} + +int g(int a) { + printf("g 0: a = %d\n", a); + a = 3; + printf("g 1: a = %d\n", a); +} + +int h(int a) { + int a; // gcc 4.3 says error: 'a' redeclared as different kind of symbol + + printf("h 0: a = %d\n", a); + a = 4; + printf("h 1: a = %d\n", a); +} + +int globCheck() { + fprintf(stdout, "globCheck()\n"); +} + +int fwdCheck() { + b(); +} + +int b() { + printf("b()\n"); +} + +int main() { + globCheck(); + fwdCheck(); + printf("main 0: a = %d\n", a); + a = 5; + printf("main 1: a = %d\n", a); + f(); + printf("main 2: a = %d\n", a); + g(77); + printf("main 3: a = %d\n", a); + h(30); + printf("main 4: a = %d\n", a); + return 0; +} diff --git a/libacc/tests/data/otcc-ansi.c b/libacc/tests/data/otcc-ansi.c index 3ffad36ac..72580e95f 100644 --- a/libacc/tests/data/otcc-ansi.c +++ b/libacc/tests/data/otcc-ansi.c @@ -442,6 +442,10 @@ int main(int g, int e) { if (g-- > 1) { e = e + 4; Q = fopen(*(int*) e, "r"); + if (!Q) { + fprintf(stderr, "otcc-ansi.c: could not open file %s\n", *(int*) e); + return -2; + } } D = strcpy(R = calloc(1, 99999), " int if else while break return for define main ") + 48; v = calloc(1, 99999); diff --git a/libacc/tests/testlocal b/libacc/tests/testlocal index 1650bf9fb..1a0b4c5e6 100755 --- a/libacc/tests/testlocal +++ b/libacc/tests/testlocal @@ -12,9 +12,11 @@ $ACC -S "$DATA/otcc-ansi.c" if file $ACC | grep -q "ELF 32-bit LSB executable, Intel 80386"; then echo "Linux 32bit Intel." + echo "TESTING returnval-ansi.c:" $ACC -R $DATA/returnval-ansi.c - echo Testing otcc-ansi.c + echo TESTING otcc-ansi.c returnval-ansi.c $ACC -R "$DATA/otcc-ansi.c" "$DATA/returnval.c" + echo TESTING otcc-ansi.c otcc.c returnval-ansi.c $ACC -R $DATA/otcc-ansi.c $DATA/otcc.c $DATA/returnval.c fi From b67b18f7c2217ae83e9ffc808cb9a58b233ec5bc Mon Sep 17 00:00:00 2001 From: Jack Palevich Date: Thu, 11 Jun 2009 21:12:23 -0700 Subject: [PATCH 16/30] Add code generator tracer. --- libacc/acc.cpp | 173 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 172 insertions(+), 1 deletion(-) diff --git a/libacc/acc.cpp b/libacc/acc.cpp index b07a1d809..60d1ddc16 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -48,6 +48,8 @@ // #define LOG_API(...) fprintf (stderr, __VA_ARGS__) // #define ENABLE_ARM_DISASSEMBLY +// #define PROVIDE_TRACE_CODEGEN + namespace acc { class ErrorSink { @@ -180,7 +182,7 @@ class Compiler : public ErrorSink { pCodeBuf->setErrorSink(mErrorSink); } - void setErrorSink(ErrorSink* pErrorSink) { + virtual void setErrorSink(ErrorSink* pErrorSink) { mErrorSink = pErrorSink; if (pCodeBuf) { pCodeBuf->setErrorSink(mErrorSink); @@ -1058,6 +1060,171 @@ class Compiler : public ErrorSink { #endif // PROVIDE_X86_CODEGEN +#ifdef PROVIDE_TRACE_CODEGEN + class TraceCodeGenerator : public CodeGenerator { + private: + CodeGenerator* mpBase; + + public: + TraceCodeGenerator(CodeGenerator* pBase) { + mpBase = pBase; + } + + virtual ~TraceCodeGenerator() { + delete mpBase; + } + + virtual void init(CodeBuf* pCodeBuf) { + mpBase->init(pCodeBuf); + } + + void setErrorSink(ErrorSink* pErrorSink) { + mpBase->setErrorSink(pErrorSink); + } + + /* returns address to patch with local variable size + */ + virtual int functionEntry(int argCount) { + int result = mpBase->functionEntry(argCount); + fprintf(stderr, "functionEntry(%d) -> %d\n", argCount, result); + return result; + } + + virtual void functionExit(int argCount, int localVariableAddress, int localVariableSize) { + fprintf(stderr, "functionExit(%d, %d, %d)\n", + argCount, localVariableAddress, localVariableSize); + mpBase->functionExit(argCount, localVariableAddress, localVariableSize); + } + + /* load immediate value */ + virtual void li(int t) { + fprintf(stderr, "li(%d)\n", t); + mpBase->li(t); + } + + virtual int gjmp(int t) { + int result = mpBase->gjmp(t); + fprintf(stderr, "gjmp(%d) = %d\n", t, result); + return result; + } + + /* l = 0: je, l == 1: jne */ + virtual int gtst(bool l, int t) { + int result = mpBase->gtst(l, t); + fprintf(stderr, "gtst(%d,%d) = %d\n", l, t, result); + return result; + } + + virtual void gcmp(int op) { + fprintf(stderr, "gcmp(%d)\n", op); + mpBase->gcmp(op); + } + + virtual void genOp(int op) { + fprintf(stderr, "genOp(%d)\n", op); + mpBase->genOp(op); + } + + virtual void clearR1() { + fprintf(stderr, "clearR1()\n"); + mpBase->clearR1(); + } + + virtual void pushR0() { + fprintf(stderr, "pushR0()\n"); + mpBase->pushR0(); + } + + virtual void popR1() { + fprintf(stderr, "popR1()\n"); + mpBase->popR1(); + } + + virtual void storeR0ToR1(bool isInt) { + fprintf(stderr, "storeR0ToR1(%d)\n", isInt); + mpBase->storeR0ToR1(isInt); + } + + virtual void loadR0FromR0(bool isInt) { + fprintf(stderr, "loadR0FromR0(%d)\n", isInt); + mpBase->loadR0FromR0(isInt); + } + + virtual void leaR0(int ea) { + fprintf(stderr, "leaR0(%d)\n", ea); + mpBase->leaR0(ea); + } + + virtual void storeR0(int ea) { + fprintf(stderr, "storeR0(%d)\n", ea); + mpBase->storeR0(ea); + } + + virtual void loadR0(int ea, bool isIncDec, int op) { + fprintf(stderr, "loadR0(%d, %d, %d)\n", ea, isIncDec, op); + mpBase->loadR0(ea, isIncDec, op); + } + + virtual int beginFunctionCallArguments() { + int result = mpBase->beginFunctionCallArguments(); + fprintf(stderr, "beginFunctionCallArguments() = %d\n", result); + return result; + } + + virtual void storeR0ToArg(int l) { + fprintf(stderr, "storeR0ToArg(%d)\n", l); + mpBase->storeR0ToArg(l); + } + + virtual void endFunctionCallArguments(int a, int l) { + fprintf(stderr, "endFunctionCallArguments(%d, %d)\n", a, l); + mpBase->endFunctionCallArguments(a, l); + } + + virtual int callForward(int symbol) { + int result = mpBase->callForward(symbol); + fprintf(stderr, "callForward(%d) = %d\n", symbol, result); + return result; + } + + virtual void callRelative(int t) { + fprintf(stderr, "callRelative(%d)\n", t); + mpBase->callRelative(t); + } + + virtual void callIndirect(int l) { + fprintf(stderr, "callIndirect(%d)\n", l); + mpBase->callIndirect(l); + } + + virtual void adjustStackAfterCall(int l, bool isIndirect) { + fprintf(stderr, "adjustStackAfterCall(%d, %d)\n", l, isIndirect); + mpBase->adjustStackAfterCall(l, isIndirect); + } + + virtual int jumpOffset() { + return mpBase->jumpOffset(); + } + + virtual int disassemble(FILE* out) { + return mpBase->disassemble(out); + } + + /* output a symbol and patch all calls to it */ + virtual void gsym(int t) { + fprintf(stderr, "gsym(%d)\n", t); + mpBase->gsym(t); + } + + virtual int finishCompile() { + int result = mpBase->finishCompile(); + fprintf(stderr, "finishCompile() = %d\n", result); + return result; + } + }; + +#endif // PROVIDE_TRACE_CODEGEN + class InputStream { public: int getChar() { @@ -2373,6 +2540,10 @@ public: if (!pGen) { return -1; } +#ifdef PROVIDE_TRACE_CODEGEN + pGen = new TraceCodeGenerator(pGen); +#endif + pGen->setErrorSink(this); pGen->init(&codeBuf); file = new TextInputStream(text, textLength); pGlobalBase = (char*) calloc(1, ALLOC_SIZE); From 61d22dc763af7c1528ddf8a30054015a9b299e73 Mon Sep 17 00:00:00 2001 From: Jack Palevich Date: Thu, 11 Jun 2009 22:03:24 -0700 Subject: [PATCH 17/30] Improve nested variable test. Test that we can have two levels of local variables. --- libacc/tests/data/locals.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/libacc/tests/data/locals.c b/libacc/tests/data/locals.c index 318162dee..6982980c5 100644 --- a/libacc/tests/data/locals.c +++ b/libacc/tests/data/locals.c @@ -33,6 +33,20 @@ int b() { printf("b()\n"); } +int nested() { + int a; + printf("nested 0: a = %d\n", a); + a = 50; + printf("nested 1: a = %d\n", a); + { + int a; + printf("nested 2: a = %d\n", a); + a = 51; + printf("nested 3: a = %d\n", a); + } + printf("nested 4: a = %d\n", a); +} + int main() { globCheck(); fwdCheck(); @@ -45,5 +59,7 @@ int main() { printf("main 3: a = %d\n", a); h(30); printf("main 4: a = %d\n", a); + nested(); + printf("main 5: a = %d\n", a); return 0; } From 0bd9a9f5bcaefda8d7d37c9383b004b516009b85 Mon Sep 17 00:00:00 2001 From: Chung-yih Wang Date: Fri, 12 Jun 2009 22:35:42 +0800 Subject: [PATCH 18/30] Add the ipcp scripts for pppd and racoon configuration for ipsec-tools. 1. add ip-up/ip-down script 2. add /etc/ppp/peers/common 3. add /etc/racoon/racoon.conf --- rootdir/Android.mk | 8 +++--- rootdir/etc/ppp/ip-down | 13 ---------- rootdir/etc/ppp/ip-up | 47 ++++++++++++++++++++-------------- rootdir/etc/ppp/peers/common | 10 ++++++++ rootdir/etc/racoon/racoon.conf | 35 +++++++++++++++++++++++++ 5 files changed, 78 insertions(+), 35 deletions(-) create mode 100755 rootdir/etc/ppp/peers/common create mode 100644 rootdir/etc/racoon/racoon.conf diff --git a/rootdir/Android.mk b/rootdir/Android.mk index b2fe8cf15..44e343c22 100644 --- a/rootdir/Android.mk +++ b/rootdir/Android.mk @@ -6,13 +6,15 @@ include $(CLEAR_VARS) copy_from := \ etc/dbus.conf \ etc/init.goldfish.sh \ + etc/ppp/ip-up \ + etc/ppp/ip-down \ + etc/ppp/peers/common \ + etc/racoon/racoon.conf \ etc/hosts dont_copy := \ etc/init.gprs-pppd \ - etc/ppp/chap-secrets \ - etc/ppp/ip-down \ - etc/ppp/ip-up + etc/ppp/chap-secrets copy_to := $(addprefix $(TARGET_OUT)/,$(copy_from)) copy_from := $(addprefix $(LOCAL_PATH)/,$(copy_from)) diff --git a/rootdir/etc/ppp/ip-down b/rootdir/etc/ppp/ip-down index 672fa1e74..58d21e5fe 100755 --- a/rootdir/etc/ppp/ip-down +++ b/rootdir/etc/ppp/ip-down @@ -1,14 +1 @@ #!/system/bin/sh -case $1 in - ppp1) - echo 0 > /proc/sys/net/ipv4/ip_forward; - ;; -esac - -# Use interface name if linkname is not available -NAME=${LINKNAME:-"$1"} - -/system/bin/setprop "net.$NAME.dns1" "$DNS1" -/system/bin/setprop "net.$NAME.dns2" "$DNS2" -/system/bin/setprop "net.$NAME.local-ip" "$IPLOCAL" -/system/bin/setprop "net.$NAME.remote-ip" "$IPREMOTE" diff --git a/rootdir/etc/ppp/ip-up b/rootdir/etc/ppp/ip-up index cb2d57785..8c8f12c89 100755 --- a/rootdir/etc/ppp/ip-up +++ b/rootdir/etc/ppp/ip-up @@ -1,24 +1,33 @@ #!/system/bin/sh -case $1 in - ppp1) - /android/bin/iptables --flush; - /android/bin/iptables --table nat --flush; - /android/bin/iptables --delete-chain; - /android/bin/iptables --table nat --append POSTROUTING --out-interface ppp0 -j MASQUERADE; - /android/bin/iptables --append FORWARD --in-interface ppp1 -j ACCEPT; - echo 0 > /proc/sys/net/ipv4/ip_forward; - echo 1 > /proc/sys/net/ipv4/ip_forward; - ;; - ppp0) - /system/bin/setprop "net.interfaces.defaultroute" "gprs" - ;; -esac # Use interface name if linkname is not available -NAME=${LINKNAME:-"$1"} -/system/bin/setprop "net.$NAME.dns1" "$DNS1" -/system/bin/setprop "net.$NAME.dns2" "$DNS2" -/system/bin/setprop "net.$NAME.local-ip" "$IPLOCAL" -/system/bin/setprop "net.$NAME.remote-ip" "$IPREMOTE" +/system/bin/setprop "net.dns1" "$DNS1" +/system/bin/setprop "net.dns2" "$DNS2" + +# Retrieve the default gateway from /proc/net/route +RTAB=`cat /proc/net/route` +flag=-1; i=0; +for l in $RTAB; do + if (exp flag==1) then DGW=$l; flag=0; fi; + if (exp i%11 == 1) then + if (exp $l=="00000000") then flag=1; fi; + fi; + i=`exp i+1`; +done +FH=${DGW%????} +LH=${DGW#????} +A=`exp 0x${LH#??}` +B=`exp 0x${LH%??}` +C=`exp 0x${FH#??}` +D=`exp 0x${FH%??}` +GATEWAY="$A.$B.$C.$D" +VPNSERVER=`getprop "net.vpn.server_ip"` + +# Protect the route to vpn server +/system/bin/route add -net $VPNSERVER netmask 255.255.255.255 gw $GATEWAY + +# Route all traffic to vpn connection +/system/bin/route add -net 0.0.0.0 netmask 128.0.0.0 gw $IPREMOTE +/system/bin/route add -net 128.0.0.0 netmask 128.0.0.0 gw $IPREMOTE diff --git a/rootdir/etc/ppp/peers/common b/rootdir/etc/ppp/peers/common new file mode 100755 index 000000000..4183841cd --- /dev/null +++ b/rootdir/etc/ppp/peers/common @@ -0,0 +1,10 @@ +ipcp-accept-local +ipcp-accept-remote +refuse-eap +noccp +noauth +idle 1800 +mtu 1400 +mru 1400 +nodefaultroute +usepeerdns diff --git a/rootdir/etc/racoon/racoon.conf b/rootdir/etc/racoon/racoon.conf new file mode 100644 index 000000000..eb50a2d3a --- /dev/null +++ b/rootdir/etc/racoon/racoon.conf @@ -0,0 +1,35 @@ +#path certificate ""; +path certificate "/"; + +sainfo anonymous { + encryption_algorithm aes, 3des; + authentication_algorithm hmac_sha1, hmac_md5; + compression_algorithm deflate; + lifetime time 3600 sec; +} + +remote anonymous { + exchange_mode main; + doi ipsec_doi; + situation identity_only; + ike_frag on; + generate_policy on; + my_identifier asn1dn; + nat_traversal on; # always use NAT-T + ca_type x509 "ca.crt"; + certificate_type x509 "user.crt" "user.key"; + verify_identifier off; + verify_cert on; + nonce_size 16; + initial_contact on; + proposal_check obey; + + proposal { + authentication_method rsasig; + hash_algorithm sha1; + encryption_algorithm 3des; + lifetime time 3600 sec; + dh_group 2; + } +} + From 825c27d239e5bcf3c8b2cb99c320f0b1836ef338 Mon Sep 17 00:00:00 2001 From: San Mehat Date: Fri, 12 Jun 2009 07:39:52 -0700 Subject: [PATCH 19/30] vold: Give logwrapper the ability to put jobs into the background sched group. Also set disk check/format execution to background. Signed-off-by: San Mehat --- vold/format.c | 4 ++-- vold/logwrapper.c | 21 ++++++++++++++++++++- vold/logwrapper.h | 2 +- vold/volmgr_ext3.c | 2 +- vold/volmgr_vfat.c | 4 ++-- 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/vold/format.c b/vold/format.c index 3383949f0..a1faf7aa4 100755 --- a/vold/format.c +++ b/vold/format.c @@ -44,7 +44,7 @@ int format_partition(blkdev_t *part, char *type) args[3] = "-O android"; args[4] = devpath; args[5] = NULL; - rc = logwrap(5, args); + rc = logwrap(5, args, 1); } else { char *args[7]; args[0] = MKE2FS_PATH; @@ -54,7 +54,7 @@ int format_partition(blkdev_t *part, char *type) args[4] = "-v"; args[5] = devpath; args[6] = NULL; - rc = logwrap(6, args); + rc = logwrap(6, args, 1); } free(devpath); diff --git a/vold/logwrapper.c b/vold/logwrapper.c index 2900f2e2b..46f6ed32a 100644 --- a/vold/logwrapper.c +++ b/vold/logwrapper.c @@ -100,7 +100,7 @@ void child(int argc, char* argv[]) { } } -int logwrap(int argc, char* argv[], pid_t *childPid) +int logwrap(int argc, char* argv[], pid_t *childPid, int background) { pid_t pid; @@ -138,6 +138,25 @@ int logwrap(int argc, char* argv[], pid_t *childPid) dup2(child_ptty, 2); close(child_ptty); + if (background) { + int fd = open("/dev/cpuctl/bg_non_interactive/tasks", O_WRONLY); + + if (fd >=0 ) { + char text[64]; + + sprintf(text, "%d", getpid()); + if (write(fd, text, strlen(text)) < 0) { + LOG(LOG_WARN, "logwrapper", + "Unable to background process (%s)", strerror(errno)); + close(fd); + } + close(fd); + } else { + LOG(LOG_WARN, "logwrapper", + "Unable to background process (%s)", strerror(errno)); + } + } + child(argc, argv); } else { return parent(argv[0], parent_ptty); diff --git a/vold/logwrapper.h b/vold/logwrapper.h index 602e24cb2..bf28aae34 100644 --- a/vold/logwrapper.h +++ b/vold/logwrapper.h @@ -19,5 +19,5 @@ #define _LOGWRAPPER_H #include -int logwrap(int argc, char* argv[]); +int logwrap(int argc, char* argv[], int background); #endif diff --git a/vold/volmgr_ext3.c b/vold/volmgr_ext3.c index 680be2190..fe3b2bb46 100644 --- a/vold/volmgr_ext3.c +++ b/vold/volmgr_ext3.c @@ -107,7 +107,7 @@ int ext_check(blkdev_t *dev) args[3] = devpath; args[4] = NULL; - int rc = logwrap(4, args); + int rc = logwrap(4, args, 1); if (rc == 0) { LOG_VOL("filesystem '%s' had no errors", devpath); diff --git a/vold/volmgr_vfat.c b/vold/volmgr_vfat.c index 2b0e1fa1e..78332226e 100644 --- a/vold/volmgr_vfat.c +++ b/vold/volmgr_vfat.c @@ -62,13 +62,13 @@ int vfat_check(blkdev_t *dev) args[3] = "-p"; args[4] = blkdev_get_devpath(dev); args[5] = NULL; - rc = logwrap(5, args); + rc = logwrap(5, args, 1); free(args[4]); } else { args[2] = "-n"; args[3] = blkdev_get_devpath(dev); args[4] = NULL; - rc = logwrap(4, args); + rc = logwrap(4, args, 1); free(args[3]); } From a6baa23f0831f98e84ee4afbfb6cdb3ac5c1f5ea Mon Sep 17 00:00:00 2001 From: Jack Palevich Date: Fri, 12 Jun 2009 11:25:59 -0700 Subject: [PATCH 20/30] Improve symbol-related error checking + Duplicate symbols. + Undefined variables; + Forward-referenced functions that were never defined. --- libacc/acc.cpp | 139 ++++++++++++++++++++++++++++--------- libacc/tests/data/locals.c | 10 ++- 2 files changed, 113 insertions(+), 36 deletions(-) diff --git a/libacc/acc.cpp b/libacc/acc.cpp index 60d1ddc16..4af7f25f0 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -1312,6 +1312,12 @@ class Compiler : public ErrorSink { } } + String& operator=(const String& other) { + clear(); + appendBytes(other.getUnwrapped(), other.len()); + return *this; + } + inline char* getUnwrapped() const { return mpBase; } @@ -1439,6 +1445,12 @@ class Compiler : public ErrorSink { return result; } + void forEach(bool (*callback)(String* key, V* value, void* context), + void* context) { + hashmapForEach(mpMap, (bool (*)(void*, void*, void*)) callback, + context); + } + protected: void init(size_t initialCapacity) { @@ -1670,11 +1682,21 @@ class Compiler : public ErrorSink { return addImp(0, pName); } + void forEachGlobal( + bool (*callback)(String* key, VariableInfo* value, void* context), + void* context) { + mStack.get(0).pTable->forEach(callback, context); + } + private: VariableInfo* addImp(int entryIndex, String* pName) { Entry e = mStack.get(entryIndex); SymbolTable* pTable = e.pTable; + if (pTable->contains(pName)) { + return NULL; + } VariableInfo* v = new VariableInfo(); + delete pTable->put(pName, v); #if 0 fprintf(stderr, "Add \"%s\" %08x level %d\n", pName->getUnwrapped(), v, e.level); @@ -2044,6 +2066,7 @@ class Compiler : public ErrorSink { void unary(intptr_t l) { intptr_t n, t, a; int c; + String tString; t = 0; n = 1; /* type of expression 0 = forward, 1 = value, other = lvalue */ @@ -2063,6 +2086,7 @@ class Compiler : public ErrorSink { c = tokl; a = tokc; t = tok; + tString = mTokenString; next(); if (t == TOK_NUM) { pGen->li(a); @@ -2112,14 +2136,15 @@ class Compiler : public ErrorSink { } else { if (t == TOK_UNDEFINED_SYMBOL) { t = (intptr_t) mSymbolTable.addGlobal( - new String(mTokenString)); + new String(tString)); } - n = *(int *) t; + n = (intptr_t) ((VariableInfo*) t)->pAddress; /* forward reference: try dlsym */ if (!n) { n = (intptr_t) dlsym(RTLD_DEFAULT, - mTokenString.getUnwrapped()); + tString.getUnwrapped()); + ((VariableInfo*) t)->pAddress = (void*) n; } if ((tok == '=') & l) { /* assignment */ @@ -2128,6 +2153,9 @@ class Compiler : public ErrorSink { pGen->storeR0(n); } else if (tok != '(') { /* variable */ + if (!n) { + error("Undefined variable %s", tString.getUnwrapped()); + } pGen->loadR0(n, tokl == 11, tokc); if (tokl == 11) { next(); @@ -2216,7 +2244,7 @@ class Compiler : public ErrorSink { return pGen->gtst(0, 0); } - void block(intptr_t l) { + void block(intptr_t l, bool outermostFunctionBlock) { intptr_t a, n, t; if (tok == TOK_IF) { @@ -2224,12 +2252,12 @@ class Compiler : public ErrorSink { skip('('); a = test_expr(); skip(')'); - block(l); + block(l, false); if (tok == TOK_ELSE) { next(); n = pGen->gjmp(0); /* jmp */ pGen->gsym(a); - block(l); + block(l, false); pGen->gsym(n); /* patch else jmp */ } else { pGen->gsym(a); /* patch if test */ @@ -2259,18 +2287,22 @@ class Compiler : public ErrorSink { } } skip(')'); - block((intptr_t) &a); + block((intptr_t) &a, false); pGen->gjmp(n - codeBuf.getPC() - pGen->jumpOffset()); /* jmp */ pGen->gsym(a); } else if (tok == '{') { - mSymbolTable.pushLevel(); + if (! outermostFunctionBlock) { + mSymbolTable.pushLevel(); + } next(); /* declarations */ localDeclarations(); while (tok != '}' && tok != EOF) - block(l); + block(l, false); skip('}'); - mSymbolTable.popLevel(); + if (! outermostFunctionBlock) { + mSymbolTable.popLevel(); + } } else { if (tok == TOK_RETURN) { next(); @@ -2350,18 +2382,22 @@ class Compiler : public ErrorSink { } } - void defineGlobalSymbol() { - if (tok == TOK_UNDEFINED_SYMBOL) { - // TODO: don't allow multiple definitions at same level. - tok = (intptr_t) mSymbolTable.addGlobal( - new String(mTokenString)); + void addGlobalSymbol() { + tok = (intptr_t) mSymbolTable.addGlobal( + new String(mTokenString)); + reportIfDuplicate(); + } + + void reportIfDuplicate() { + if (!tok) { + error("Duplicate definition of %s", mTokenString.getUnwrapped()); } } - void defineLocalSymbol() { - // TODO: don't allow multiple definitions at same level. + void addLocalSymbol() { tok = (intptr_t) mSymbolTable.addLocal( new String(mTokenString)); + reportIfDuplicate(); } void localDeclarations() { @@ -2371,10 +2407,11 @@ class Compiler : public ErrorSink { while (acceptType(base)) { while (tok != ';') { Type t = acceptPointerDeclaration(t); - defineLocalSymbol(); - loc = loc + 4; - *(int *) tok = -loc; - + addLocalSymbol(); + if (tok) { + loc = loc + 4; + *(int *) tok = -loc; + } next(); if (tok == ',') next(); @@ -2388,29 +2425,39 @@ class Compiler : public ErrorSink { Type base; expectType(base); Type t = acceptPointerDeclaration(t); - defineGlobalSymbol(); + if (tok == TOK_UNDEFINED_SYMBOL) { + addGlobalSymbol(); + } VariableInfo* name = (VariableInfo*) tok; + if (name && name->pAddress) { + error("Already defined global %s", + mTokenString.getUnwrapped()); + } next(); if (tok == ',' || tok == ';') { // it's a variable declaration for(;;) { - name->pAddress = (int*) allocGlobalSpace(4); + if (name) { + name->pAddress = (int*) allocGlobalSpace(4); + } if (tok != ',') { break; } skip(','); t = acceptPointerDeclaration(t); - defineGlobalSymbol(); + addGlobalSymbol(); name = (VariableInfo*) tok; next(); } skip(';'); } else { - /* patch forward references (XXX: does not work for function - pointers) */ - pGen->gsym((int) name->pForward); - /* put function address */ - name->pAddress = (void*) codeBuf.getPC(); + if (name) { + /* patch forward references (XXX: does not work for function + pointers) */ + pGen->gsym((int) name->pForward); + /* put function address */ + name->pAddress = (void*) codeBuf.getPC(); + } skip('('); mSymbolTable.pushLevel(); intptr_t a = 8; @@ -2419,10 +2466,12 @@ class Compiler : public ErrorSink { Type aType; expectType(aType); aType = acceptPointerDeclaration(aType); - defineLocalSymbol(); - /* read param name and compute offset */ - *(int *) tok = a; - a = a + 4; + addLocalSymbol(); + if (tok) { + /* read param name and compute offset */ + *(int *) tok = a; + a = a + 4; + } next(); if (tok == ',') next(); @@ -2431,7 +2480,7 @@ class Compiler : public ErrorSink { skip(')'); rsym = loc = 0; a = pGen->functionEntry(argCount); - block(0); + block(0, true); pGen->gsym(rsym); pGen->functionExit(argCount, a, loc); mSymbolTable.popLevel(); @@ -2551,6 +2600,7 @@ public: inp(); next(); globalDeclarations(); + checkForUndefinedForwardReferences(); result = pGen->finishCompile(); if (result == 0) { if (mErrorBuf.len()) { @@ -2560,6 +2610,27 @@ public: return result; } + void checkForUndefinedForwardReferences() { + mSymbolTable.forEachGlobal(static_ufrcFn, this); + } + + static bool static_ufrcFn(String* key, VariableInfo* value, + void* context) { + Compiler* pCompiler = (Compiler*) context; + return pCompiler->undefinedForwardReferenceCheck(key, value); + } + + bool undefinedForwardReferenceCheck(String* key, VariableInfo* value) { +#if 0 + fprintf(stderr, "%s 0x%8x 0x%08x\n", key->getUnwrapped(), + value->pAddress, value->pForward); +#endif + if (!value->pAddress && value->pForward) { + error("Undefined forward reference: %s", key->getUnwrapped()); + } + return true; + } + int dump(FILE* out) { fwrite(codeBuf.getBase(), 1, codeBuf.getSize(), out); return 0; diff --git a/libacc/tests/data/locals.c b/libacc/tests/data/locals.c index 6982980c5..f1ef363c4 100644 --- a/libacc/tests/data/locals.c +++ b/libacc/tests/data/locals.c @@ -2,7 +2,9 @@ int a; int f() { int a; - printf("f 0: a = %d b = %d\n", a, b); + // Undefined variable b + // printf("f 0: a = %d b = %d\n", a, b); + printf("f 0: a = %d\n", a); a = 2; printf("f 1: a = %d\n", a); } @@ -14,19 +16,23 @@ int g(int a) { } int h(int a) { - int a; // gcc 4.3 says error: 'a' redeclared as different kind of symbol + // int a; // gcc 4.3 says error: 'a' redeclared as different kind of symbol printf("h 0: a = %d\n", a); a = 4; printf("h 1: a = %d\n", a); } +// Already defined global +// int h() {} int globCheck() { fprintf(stdout, "globCheck()\n"); } int fwdCheck() { b(); + // Undefined forward reference + // c(); } int b() { From 2ccc40d096ef18ca595f95c6c52532400be34807 Mon Sep 17 00:00:00 2001 From: Jack Palevich Date: Fri, 12 Jun 2009 11:53:07 -0700 Subject: [PATCH 21/30] Make #define work again. (Had accidentally omitted the keyword.) --- libacc/acc.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libacc/acc.cpp b/libacc/acc.cpp index 4af7f25f0..7903c6ee1 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -1498,7 +1498,10 @@ class Compiler : public ErrorSink { put("break", TOK_BREAK); put("return", TOK_RETURN); put("for", TOK_FOR); + // TODO: remove these preprocessor-specific keywords. You should + // be able to have symbols named pragma or define. put("pragma", TOK_PRAGMA); + put("define", TOK_DEFINE); } ~KeywordTable() { From b4758ff1defaf01f381bce1630607ad1763f72ec Mon Sep 17 00:00:00 2001 From: Jack Palevich Date: Fri, 12 Jun 2009 12:49:14 -0700 Subject: [PATCH 22/30] Implement string and character backslash constants. Until now we only supported '\n'. Now we support everything, including octal ('\033') and hex '\x27' constants. --- libacc/acc.cpp | 113 +++++++++++++++++++++++++++++----- libacc/tests/data/constants.c | 30 +++++++++ 2 files changed, 127 insertions(+), 16 deletions(-) create mode 100644 libacc/tests/data/constants.c diff --git a/libacc/acc.cpp b/libacc/acc.cpp index 7903c6ee1..816902e1f 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -1841,13 +1841,92 @@ class Compiler : public ErrorSink { return isalnum(ch) | (ch == '_'); } - /* read a character constant */ - void getq() { + /* read a character constant, advances ch to after end of constant */ + int getq() { + int val = ch; if (ch == '\\') { inp(); - if (ch == 'n') - ch = '\n'; + if (isoctal(ch)) { + // 1 to 3 octal characters. + val = 0; + for(int i = 0; i < 3; i++) { + if (isoctal(ch)) { + val = (val << 3) + ch - '0'; + inp(); + } + } + return val; + } else if (ch == 'x' || ch == 'X') { + // N hex chars + inp(); + if (! isxdigit(ch)) { + error("'x' character escape requires at least one digit."); + } else { + val = 0; + while (isxdigit(ch)) { + int d = ch; + if (isdigit(d)) { + d -= '0'; + } else if (d <= 'F') { + d = d - 'A' + 10; + } else { + d = d - 'a' + 10; + } + val = (val << 4) + d; + inp(); + } + } + } else { + int val = ch; + switch (ch) { + case 'a': + val = '\a'; + break; + case 'b': + val = '\b'; + break; + case 'f': + val = '\f'; + break; + case 'n': + val = '\n'; + break; + case 'r': + val = '\r'; + break; + case 't': + val = '\t'; + break; + case 'v': + val = '\v'; + break; + case '\\': + val = '\\'; + break; + case '\'': + val = '\''; + break; + case '"': + val = '"'; + break; + case '?': + val = '?'; + break; + default: + error("Undefined character escape %c", ch); + break; + } + inp(); + return val; + } + } else { + inp(); } + return val; + } + + static bool isoctal(int ch) { + return ch >= '0' && ch <= '7'; } void next() { @@ -1908,10 +1987,12 @@ class Compiler : public ErrorSink { inp(); if (tok == '\'') { tok = TOK_NUM; - getq(); - tokc = ch; - inp(); - inp(); + tokc = getq(); + if (ch != '\'') { + error("Expected a ' character, got %c", ch); + } else { + inp(); + } } else if ((tok == '/') & (ch == '*')) { inp(); while (ch) { @@ -2071,14 +2152,14 @@ class Compiler : public ErrorSink { int c; String tString; t = 0; - n = 1; /* type of expression 0 = forward, 1 = value, other = - lvalue */ + n = 1; /* type of expression 0 = forward, 1 = value, other = lvalue */ if (tok == '\"') { pGen->li((int) glo); - while (ch != '\"') { - getq(); - *allocGlobalSpace(1) = ch; - inp(); + while (ch != '\"' && ch != EOF) { + *allocGlobalSpace(1) = getq(); + } + if (ch != '\"') { + error("Unterminated string constant."); } *glo = 0; /* align heap */ @@ -2176,7 +2257,7 @@ class Compiler : public ErrorSink { a = pGen->beginFunctionCallArguments(); next(); l = 0; - while (tok != ')') { + while (tok != ')' && tok != EOF) { expr(); pGen->storeR0ToArg(l); if (tok == ',') @@ -2184,7 +2265,7 @@ class Compiler : public ErrorSink { l = l + 4; } pGen->endFunctionCallArguments(a, l); - next(); + skip(')'); if (!n) { /* forward reference */ t = t + 4; diff --git a/libacc/tests/data/constants.c b/libacc/tests/data/constants.c new file mode 100644 index 000000000..230109a4e --- /dev/null +++ b/libacc/tests/data/constants.c @@ -0,0 +1,30 @@ +#define FOO 0x10 + +int main() { + printf("0 = %d\n", 0); + printf("010 = %d\n", 010); + printf("0x10 = %d\n", FOO); + printf("'\\a' = %d\n", '\a'); + printf("'\\b' = %d\n", '\b'); + printf("'\\f' = %d\n", '\f'); + printf("'\\n' = %d\n", '\n'); + printf("'\\r' = %d\n", '\r'); + printf("'\\t' = %d\n", '\t'); + printf("'\\v' = %d\n", '\v'); + // Undefined + // printf("'\\z' = %d\n", '\z'); + printf("'\\\\' = %d\n", '\\'); + printf("'\\'' = %d\n", '\''); + printf("'\\\"' = %d\n", '\"'); + printf("'\\?' = %d\n", '\?'); + printf("'\\0' = %d\n", '\0'); + printf("'\\1' = %d\n", '\1'); + printf("'\\12' = %d\n", '\12'); + printf("'\\123' = %d\n", '\123'); + printf("'\\x0' = %d\n", '\x0'); + printf("'\\x1' = %d\n", '\x1'); + printf("'\\x12' = %d\n", '\x12'); + printf("'\\x123' = %d\n", '\x123'); + printf("'\\x1f' = %d\n", '\x1f'); + printf("'\\x1F' = %d\n", '\x1F'); +} From 22e3e8e1a63ba947cae52e143f650df679fd46ba Mon Sep 17 00:00:00 2001 From: Jack Palevich Date: Fri, 12 Jun 2009 13:12:55 -0700 Subject: [PATCH 23/30] Handle end-of-file inside of comments, local declarations. --- libacc/acc.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/libacc/acc.cpp b/libacc/acc.cpp index 816902e1f..a00a6334a 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -1995,18 +1995,21 @@ class Compiler : public ErrorSink { } } else if ((tok == '/') & (ch == '*')) { inp(); - while (ch) { - while (ch != '*') + while (ch && ch != EOF) { + while (ch != '*' && ch != EOF) inp(); inp(); if (ch == '/') ch = 0; } + if (ch == EOF) { + error("End of file inside comment."); + } inp(); next(); } else if ((tok == '/') & (ch == '/')) { inp(); - while (ch && (ch != '\n')) { + while (ch && (ch != '\n') && (ch != EOF)) { inp(); } inp(); @@ -2489,7 +2492,7 @@ class Compiler : public ErrorSink { Type base; while (acceptType(base)) { - while (tok != ';') { + while (tok != ';' && tok != EOF) { Type t = acceptPointerDeclaration(t); addLocalSymbol(); if (tok) { From f1728bec74f952763a02a4c7d38c33b20d700870 Mon Sep 17 00:00:00 2001 From: Jack Palevich Date: Fri, 12 Jun 2009 13:53:51 -0700 Subject: [PATCH 24/30] Reserve all C99 keywords. And improve checks/error messages around using non-symbols where a symbol is expected. --- libacc/acc.cpp | 90 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 75 insertions(+), 15 deletions(-) diff --git a/libacc/acc.cpp b/libacc/acc.cpp index a00a6334a..8b3765a3d 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -1502,6 +1502,41 @@ class Compiler : public ErrorSink { // be able to have symbols named pragma or define. put("pragma", TOK_PRAGMA); put("define", TOK_DEFINE); + + const char* unsupported[] = { + "auto", + "case", + "const", + "continue", + "default", + "do", + "double", + "enum", + "extern", + "float", + "goto", + "long", + "register", + "short", + "signed", + "sizeof", + "static", + "struct", + "switch", + "typedef", + "union", + "unsigned", + "volatile", + "_Bool", + "_Complex", + "_Imaginary", + "inline", + "restrict", + 0}; + + for(int i = 0; unsupported[i]; i++) { + put(unsupported[i], TOK_UNSUPPORTED_KEYWORD); + } } ~KeywordTable() { @@ -1773,6 +1808,7 @@ class Compiler : public ErrorSink { static const int TOK_FOR = TOK_KEYWORD + 8; static const int TOK_PRAGMA = TOK_KEYWORD + 9; static const int TOK_DEFINE = TOK_KEYWORD + 10; + static const int TOK_UNSUPPORTED_KEYWORD = TOK_KEYWORD + 0xff; static const int TOK_UNDEFINED_SYMBOL = 0x200; @@ -2463,12 +2499,6 @@ class Compiler : public ErrorSink { } } - void checkSymbol() { - if (tok < TOK_SYMBOL) { - error("Expected a symbol"); - } - } - void addGlobalSymbol() { tok = (intptr_t) mSymbolTable.addGlobal( new String(mTokenString)); @@ -2494,10 +2524,12 @@ class Compiler : public ErrorSink { while (acceptType(base)) { while (tok != ';' && tok != EOF) { Type t = acceptPointerDeclaration(t); - addLocalSymbol(); - if (tok) { - loc = loc + 4; - *(int *) tok = -loc; + if (checkSymbol()) { + addLocalSymbol(); + if (tok) { + loc = loc + 4; + *(int *) tok = -loc; + } } next(); if (tok == ',') @@ -2507,11 +2539,37 @@ class Compiler : public ErrorSink { } } + bool checkSymbol() { + bool result = isSymbol(); + if (!result) { + String temp; + if (tok >= 0 && tok < 256) { + temp.printf("char \'%c\'", tok); + } else if (tok >= TOK_KEYWORD && tok < TOK_UNSUPPORTED_KEYWORD) { + temp.printf("keyword \"%s\"", mTokenString.getUnwrapped()); + } else { + temp.printf("reserved keyword \"%s\"", + mTokenString.getUnwrapped()); + } + error("Expected symbol. Got %s", temp.getUnwrapped()); + } + return result; + } + + /* Is a possibly undefined symbol */ + bool isSymbol() { + return tok < EOF || tok >= TOK_UNDEFINED_SYMBOL; + } + void globalDeclarations() { while (tok != EOF) { Type base; expectType(base); Type t = acceptPointerDeclaration(t); + if (tok >= 0 && tok < TOK_UNDEFINED_SYMBOL) { + error("Unexpected token %d", tok); + break; + } if (tok == TOK_UNDEFINED_SYMBOL) { addGlobalSymbol(); } @@ -2553,11 +2611,13 @@ class Compiler : public ErrorSink { Type aType; expectType(aType); aType = acceptPointerDeclaration(aType); - addLocalSymbol(); - if (tok) { - /* read param name and compute offset */ - *(int *) tok = a; - a = a + 4; + if (checkSymbol()) { + addLocalSymbol(); + if (tok) { + /* read param name and compute offset */ + *(int *) tok = a; + a = a + 4; + } } next(); if (tok == ',') From d709b582604e7f9d53b97f9ae13c5e12b2466c56 Mon Sep 17 00:00:00 2001 From: Mike Chan Date: Fri, 12 Jun 2009 13:55:15 -0700 Subject: [PATCH 25/30] remove 3G timeout values from init.rc, this should be device specific Signed-off-by: Mike Chan --- rootdir/init.rc | 3 --- 1 file changed, 3 deletions(-) diff --git a/rootdir/init.rc b/rootdir/init.rc index 27e833b90..2e00c7110 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -108,9 +108,6 @@ on boot # set RLIMIT_NICE to allow priorities from 19 to -20 setrlimit 13 40 40 -# Set timeout value for rmnet stats. - write /sys/devices/virtual/net/rmnet0/timeout_suspend 5000000 - # Define the oom_adj values for the classes of processes that can be # killed by the kernel. These are used in ActivityManagerService. setprop ro.FOREGROUND_APP_ADJ 0 From d7461a7342e706bece657172799ea8db9a104237 Mon Sep 17 00:00:00 2001 From: Jack Palevich Date: Fri, 12 Jun 2009 14:26:58 -0700 Subject: [PATCH 26/30] Support variable initialization. Global variables can only be initialized to integer constants. Local variables can be initialized to arbitrary expressions. --- libacc/acc.cpp | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/libacc/acc.cpp b/libacc/acc.cpp index 8b3765a3d..0cb51ffba 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -2524,14 +2524,22 @@ class Compiler : public ErrorSink { while (acceptType(base)) { while (tok != ';' && tok != EOF) { Type t = acceptPointerDeclaration(t); + int variableAddress = 0; if (checkSymbol()) { addLocalSymbol(); if (tok) { loc = loc + 4; - *(int *) tok = -loc; + variableAddress = -loc; + ((VariableInfo*) tok)->pAddress = (void*) variableAddress; } } next(); + if (tok == '=') { + /* assignment */ + next(); + expr(); + pGen->storeR0(variableAddress); + } if (tok == ',') next(); } @@ -2543,7 +2551,11 @@ class Compiler : public ErrorSink { bool result = isSymbol(); if (!result) { String temp; - if (tok >= 0 && tok < 256) { + if (tok == EOF ) { + temp.printf("EOF"); + } else if (tok == TOK_NUM) { + temp.printf("numeric constant"); + } else if (tok >= 0 && tok < 256) { temp.printf("char \'%c\'", tok); } else if (tok >= TOK_KEYWORD && tok < TOK_UNSUPPORTED_KEYWORD) { temp.printf("keyword \"%s\"", mTokenString.getUnwrapped()); @@ -2579,12 +2591,23 @@ class Compiler : public ErrorSink { mTokenString.getUnwrapped()); } next(); - if (tok == ',' || tok == ';') { + if (tok == ',' || tok == ';' || tok == '=') { // it's a variable declaration for(;;) { if (name) { name->pAddress = (int*) allocGlobalSpace(4); } + if (tok == '=') { + next(); + if (tok == TOK_NUM) { + if (name) { + * (int*) name->pAddress = tokc; + } + next(); + } else { + error("Expected an integer constant"); + } + } if (tok != ',') { break; } From a1804ddebaf8f54f922716dcfe83d9726dd18493 Mon Sep 17 00:00:00 2001 From: Jack Palevich Date: Fri, 12 Jun 2009 14:40:04 -0700 Subject: [PATCH 27/30] Allow local variables to be declared anywhere in a block. --- libacc/acc.cpp | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/libacc/acc.cpp b/libacc/acc.cpp index 0cb51ffba..7d14e3fdf 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -2254,8 +2254,9 @@ class Compiler : public ErrorSink { next(); } else if (t == EOF ) { error("Unexpected EOF."); - } else if (t < TOK_UNDEFINED_SYMBOL) { - error("Unexpected symbol or keyword"); + } else if (!checkSymbol(t, &tString)) { + // Don't have to do anything special here, the error + // message was printed by checkSymbol() above. } else { if (t == TOK_UNDEFINED_SYMBOL) { t = (intptr_t) mSymbolTable.addGlobal( @@ -2370,7 +2371,10 @@ class Compiler : public ErrorSink { void block(intptr_t l, bool outermostFunctionBlock) { intptr_t a, n, t; - if (tok == TOK_IF) { + if (tok == TOK_INT || tok == TOK_CHAR) { + /* declarations */ + localDeclarations(); + } else if (tok == TOK_IF) { next(); skip('('); a = test_expr(); @@ -2418,8 +2422,6 @@ class Compiler : public ErrorSink { mSymbolTable.pushLevel(); } next(); - /* declarations */ - localDeclarations(); while (tok != '}' && tok != EOF) block(l, false); skip('}'); @@ -2548,31 +2550,30 @@ class Compiler : public ErrorSink { } bool checkSymbol() { - bool result = isSymbol(); + return checkSymbol(tok, &mTokenString); + } + + bool checkSymbol(int token, String* pText) { + bool result = token < EOF || token >= TOK_UNDEFINED_SYMBOL; if (!result) { String temp; - if (tok == EOF ) { + if (token == EOF ) { temp.printf("EOF"); - } else if (tok == TOK_NUM) { + } else if (token == TOK_NUM) { temp.printf("numeric constant"); - } else if (tok >= 0 && tok < 256) { - temp.printf("char \'%c\'", tok); - } else if (tok >= TOK_KEYWORD && tok < TOK_UNSUPPORTED_KEYWORD) { - temp.printf("keyword \"%s\"", mTokenString.getUnwrapped()); + } else if (token >= 0 && token < 256) { + temp.printf("char \'%c\'", token); + } else if (token >= TOK_KEYWORD && token < TOK_UNSUPPORTED_KEYWORD) { + temp.printf("keyword \"%s\"", pText->getUnwrapped()); } else { temp.printf("reserved keyword \"%s\"", - mTokenString.getUnwrapped()); + pText->getUnwrapped()); } error("Expected symbol. Got %s", temp.getUnwrapped()); } return result; } - /* Is a possibly undefined symbol */ - bool isSymbol() { - return tok < EOF || tok >= TOK_UNDEFINED_SYMBOL; - } - void globalDeclarations() { while (tok != EOF) { Type base; From c73a3a5771a2d29d1bae666bfde12f751d66fc96 Mon Sep 17 00:00:00 2001 From: San Mehat Date: Mon, 15 Jun 2009 14:06:03 -0700 Subject: [PATCH 28/30] libsysutils: Move to a null terminated string protocol using space as a field separator. Also removes some debugging Signed-off-by: San Mehat --- include/sysutils/FrameworkCommand.h | 2 +- include/sysutils/FrameworkListener.h | 4 +++- libsysutils/src/FrameworkCommand.cpp | 2 +- libsysutils/src/FrameworkListener.cpp | 30 +++++++++++++++------------ libsysutils/src/SocketClient.cpp | 15 +++----------- libsysutils/src/SocketListener.cpp | 1 - 6 files changed, 25 insertions(+), 29 deletions(-) diff --git a/include/sysutils/FrameworkCommand.h b/include/sysutils/FrameworkCommand.h index 5b50247b5..6c1fca620 100644 --- a/include/sysutils/FrameworkCommand.h +++ b/include/sysutils/FrameworkCommand.h @@ -29,7 +29,7 @@ public: FrameworkCommand(const char *cmd); virtual ~FrameworkCommand() { } - virtual int runCommand(SocketClient *c, char *data) = 0; + virtual int runCommand(SocketClient *c, int argc, char **argv) = 0; const char *getCommand() { return mCommand; } }; diff --git a/include/sysutils/FrameworkListener.h b/include/sysutils/FrameworkListener.h index 8a83c3346..4e3d39648 100644 --- a/include/sysutils/FrameworkListener.h +++ b/include/sysutils/FrameworkListener.h @@ -22,6 +22,8 @@ class SocketClient; class FrameworkListener : public SocketListener { +public: + static const int CMD_ARGS_MAX = 8; private: FrameworkCommandCollection *mCommands; @@ -34,6 +36,6 @@ protected: virtual bool onDataAvailable(SocketClient *c); private: - void dispatchCommand(SocketClient *c, char *cmd); + void dispatchCommand(SocketClient *c, char *data); }; #endif diff --git a/libsysutils/src/FrameworkCommand.cpp b/libsysutils/src/FrameworkCommand.cpp index 94e7426ca..c52eac76f 100644 --- a/libsysutils/src/FrameworkCommand.cpp +++ b/libsysutils/src/FrameworkCommand.cpp @@ -25,7 +25,7 @@ FrameworkCommand::FrameworkCommand(const char *cmd) { mCommand = cmd; } -int FrameworkCommand::runCommand(SocketClient *c, char *data) { +int FrameworkCommand::runCommand(SocketClient *c, int argc, char **argv) { LOGW("Command %s has no run handler!", getCommand()); errno = ENOSYS; return -1; diff --git a/libsysutils/src/FrameworkListener.cpp b/libsysutils/src/FrameworkListener.cpp index e8ae8478e..e9ca8977f 100644 --- a/libsysutils/src/FrameworkListener.cpp +++ b/libsysutils/src/FrameworkListener.cpp @@ -36,17 +36,14 @@ bool FrameworkListener::onDataAvailable(SocketClient *c) { if ((len = read(c->getSocket(), buffer, sizeof(buffer) -1)) < 0) { LOGE("read() failed (%s)", strerror(errno)); return errno; - } else if (!len) { - LOGW("Lost connection to client"); + } else if (!len) return false; - } int offset = 0; int i; for (i = 0; i < len; i++) { - if (buffer[i] == '\n') { - buffer[i] = '\0'; + if (buffer[i] == '\0') { dispatchCommand(c, buffer + offset); offset = i + 1; } @@ -58,13 +55,20 @@ void FrameworkListener::registerCmd(FrameworkCommand *cmd) { mCommands->push_back(cmd); } -void FrameworkListener::dispatchCommand(SocketClient *cli, char *cmd) { - char *next = cmd; - char *cm; - char *arg; +void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { + int argc; + char *argv[FrameworkListener::CMD_ARGS_MAX]; - if (!(cm = strsep(&next, ":"))) { - cli->sendMsg(500, "Malformatted message", false); + if (!index(data, '"')) { + char *next = data; + char *field; + int i; + + for (i = 0; (i < FrameworkListener::CMD_ARGS_MAX) && + (argv[i] = strsep(&next, " ")); i++); + argc = i+1; + } else { + LOGD("blehhh not supported"); return; } @@ -73,8 +77,8 @@ void FrameworkListener::dispatchCommand(SocketClient *cli, char *cmd) { for (i = mCommands->begin(); i != mCommands->end(); ++i) { FrameworkCommand *c = *i; - if (!strcmp(cm, c->getCommand())) { - if (c->runCommand(cli, next)) { + if (!strcmp(argv[0], c->getCommand())) { + if (c->runCommand(cli, argc, argv)) { LOGW("Handler '%s' error (%s)", c->getCommand(), strerror(errno)); } return; diff --git a/libsysutils/src/SocketClient.cpp b/libsysutils/src/SocketClient.cpp index f0e846f4f..857ed4d10 100644 --- a/libsysutils/src/SocketClient.cpp +++ b/libsysutils/src/SocketClient.cpp @@ -33,19 +33,10 @@ int SocketClient::sendMsg(const char *msg) { return -1; } - char *tmp; - const char *bp = msg; - - if (msg[strlen(msg)] != '\n') { - tmp = (char *) alloca(strlen(msg) + 1); - strcpy(tmp, msg); - strcat(tmp, "\n"); - bp = tmp; - } - + // Send the message including null character int rc = 0; - const char *p = bp; - int brtw = strlen(bp); + const char *p = msg; + int brtw = strlen(msg) + 1; pthread_mutex_lock(&mWriteMutex); while(brtw) { diff --git a/libsysutils/src/SocketListener.cpp b/libsysutils/src/SocketListener.cpp index 1f80121a5..1a937c296 100644 --- a/libsysutils/src/SocketListener.cpp +++ b/libsysutils/src/SocketListener.cpp @@ -157,7 +157,6 @@ void SocketListener::runListener() { if (FD_ISSET(fd, &read_fds)) { pthread_mutex_unlock(&mClientsLock); if (!onDataAvailable(*it)) { - LOGD("SocketListener closing client socket"); close(fd); pthread_mutex_lock(&mClientsLock); delete *it; From 669a7011e7e23c0594242465caa15b46b92aa340 Mon Sep 17 00:00:00 2001 From: San Mehat Date: Mon, 15 Jun 2009 14:07:28 -0700 Subject: [PATCH 29/30] nexctl: Refactor so Nexus can be tested from scripts easily. Also adds 'monitor' mode for monitoring broadcasts Signed-off-by: San Mehat --- nexus/nexctl.c | 128 +++++++++++++++++++++++++++++-------------------- 1 file changed, 76 insertions(+), 52 deletions(-) diff --git a/nexus/nexctl.c b/nexus/nexctl.c index cfebbf0cd..8e1d90c24 100644 --- a/nexus/nexctl.c +++ b/nexus/nexctl.c @@ -29,25 +29,59 @@ #include #include - #include +static void usage(char *progname); +static int do_monitor(int sock, int stop_after_cmd); +static int do_cmd(int sock, int argc, char **argv); + int main(int argc, char **argv) { int sock; + if (argc < 2) + usage(argv[0]); + if ((sock = socket_local_client("nexus", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM)) < 0) { fprintf(stderr, "Error connecting (%s)\n", strerror(errno)); - exit(1); + exit(4); } - printf("Connected to nexus\n"); + if (!strcmp(argv[1], "monitor")) + exit(do_monitor(sock, 0)); + exit(do_cmd(sock, argc, argv)); +} - char line[255]; +static int do_cmd(int sock, int argc, char **argv) { + char final_cmd[255] = { '\0' }; + int i; + + for (i = 1; i < argc; i++) { + char *cmp; + + if (!index(argv[i], ' ')) + asprintf(&cmp, "%s%s", argv[i], (i == (argc -1)) ? "" : " "); + else + asprintf(&cmp, "\"%s\"%s", argv[i], (i == (argc -1)) ? "" : " "); + + strcat(final_cmd, cmp); + free(cmp); + } + + if (write(sock, final_cmd, strlen(final_cmd) + 1) < 0) { + perror("write"); + return errno; + } + + return do_monitor(sock, 1); +} + +static int do_monitor(int sock, int stop_after_cmd) { char *buffer = malloc(4096); - int cursor = 0; - int col = 0; + + if (!stop_after_cmd) + printf("[Connected to Nexus]\n"); while(1) { fd_set read_fds; @@ -59,66 +93,56 @@ int main(int argc, char **argv) { FD_ZERO(&read_fds); FD_SET(sock, &read_fds); - FD_SET(0, &read_fds); - if (col == 0) { - fprintf(stdout, "-> "); - fflush(stdout); - col = 3; - } - if ((rc = select(sock +1, &read_fds, NULL, NULL, &to)) < 0) { fprintf(stderr, "Error in select (%s)\n", strerror(errno)); - exit(2); + free(buffer); + return errno; } else if (!rc) { continue; + fprintf(stderr, "[TIMEOUT]\n"); + return ETIMEDOUT; } else if (FD_ISSET(sock, &read_fds)) { memset(buffer, 0, 4096); if ((rc = read(sock, buffer, 4096)) <= 0) { - fprintf(stderr, "Error reading response (%s)\n", strerror(errno)); - exit(2); - } - int i; - for (i = 0; i < col; i++) { - fprintf(stdout, "%c", 8); + if (rc == 0) + fprintf(stderr, "Lost connection to Nexus - did it crash?\n"); + else + fprintf(stderr, "Error reading data (%s)\n", strerror(errno)); + free(buffer); + if (rc == 0) + return ECONNRESET; + return errno; } + + int offset = 0; + int i = 0; - printf("%s", buffer); - printf("-> "); - for (i = 0; i < cursor; i++) { - fprintf(stdout, "%c", line[i]); - } - fflush(stdout); - } else if (FD_ISSET(0, &read_fds)) { - char c; + for (i = 0; i < rc; i++) { + if (buffer[i] == '\0') { + int code; + char tmp[4]; - if ((rc = read(0, &c, 1)) < 0) { - fprintf(stderr, "Error reading from terminal (%s)\n", strerror(errno)); - exit(2); - } else if (!rc) { - fprintf(stderr, "0 length read from terminal\n"); - exit(2); - } + strncpy(tmp, buffer + offset, 3); + tmp[3] = '\0'; + code = atoi(tmp); - fprintf(stdout, "%c", c); - fflush(stdout); - - line[cursor] = c; - - if (c == '\n') { - if ((rc = write(sock, line, strlen(line))) < 0) { - fprintf(stderr, "Error writing to nexus (%s)\n", strerror(errno)); - exit(2); + printf("%s\n", buffer + offset); + if (stop_after_cmd) { + if (code >= 200 && code < 600) + return 0; + } + offset = i + 1; } - memset(line, 0, sizeof(line)); - cursor = 0; - col = 0; - } else { - cursor++; - col++; } } } - - exit(0); + free(buffer); + return 0; } + +static void usage(char *progname) { + fprintf(stderr, "Usage: %s | [arg1] [arg2...]\n", progname); + exit(1); +} + From 3aff2d1de59972684bf2ab798351be5544158239 Mon Sep 17 00:00:00 2001 From: San Mehat Date: Mon, 15 Jun 2009 14:10:44 -0700 Subject: [PATCH 30/30] Nexus: Clean up supplicant events, protocol, and continue plumbing - Create SupplicantEvent classes for events - New SupplicantEventFactory for creating events - Extract Controller -> NetworkManager callbacks into IControllerHandler - Move ScanResult handling from Supplicant -> WifiController - Plumb more 'onConnected()' code - Instead of re-creating NetworkList every-time, merge in new entries - Extract SupplicantListener -> Supplicant callbacks into ISupplicantEventHandler - Move SupplicantListener callback handling to WifiController - Add unlocked version of lookupNetwork() - Save supplicant config after setting a WifiNetwork variable - Move property registration from WifiNetwork -> Supplicant - Change wifi enable broadcast messages - Add 3 new events: 'onAssociating', 'onAssociated', 'onConnectionTimeout' - Add support for handling KeyManagement Signed-off-by: San Mehat --- nexus/Android.mk | 49 ++-- nexus/CommandListener.cpp | 60 ++--- nexus/CommandListener.h | 16 +- nexus/Controller.cpp | 4 +- nexus/Controller.h | 6 +- nexus/IControllerHandler.h | 30 +++ nexus/ISupplicantEventHandler.h | 39 ++- nexus/LoopController.cpp | 5 +- nexus/LoopController.h | 3 +- nexus/NetworkManager.cpp | 17 +- nexus/NetworkManager.h | 17 +- nexus/OpenVpnController.cpp | 9 +- nexus/OpenVpnController.h | 3 +- nexus/PropertyManager.cpp | 3 +- nexus/Supplicant.cpp | 286 +++++++-------------- nexus/Supplicant.h | 43 +--- nexus/SupplicantAssociatedEvent.cpp | 40 +++ nexus/SupplicantAssociatedEvent.h | 34 +++ nexus/SupplicantAssociatingEvent.cpp | 99 +++++++ nexus/SupplicantAssociatingEvent.h | 37 +++ nexus/SupplicantConnectedEvent.cpp | 61 +++++ nexus/SupplicantConnectedEvent.h | 36 +++ nexus/SupplicantConnectionTimeoutEvent.cpp | 36 +++ nexus/SupplicantConnectionTimeoutEvent.h | 34 +++ nexus/SupplicantDisconnectedEvent.cpp | 33 +++ nexus/SupplicantDisconnectedEvent.h | 30 +++ nexus/SupplicantEvent.cpp | 73 +----- nexus/SupplicantEvent.h | 39 ++- nexus/SupplicantEventFactory.cpp | 119 +++++++++ nexus/SupplicantEventFactory.h | 31 +++ nexus/SupplicantListener.cpp | 83 +++--- nexus/SupplicantListener.h | 5 +- nexus/SupplicantScanResultsEvent.cpp | 34 +++ nexus/SupplicantScanResultsEvent.h | 30 +++ nexus/SupplicantStateChangeEvent.cpp | 45 ++++ nexus/SupplicantStateChangeEvent.h | 34 +++ nexus/SupplicantStatus.cpp | 72 ++++++ nexus/SupplicantStatus.h | 42 +++ nexus/TiwlanWifiController.cpp | 8 +- nexus/TiwlanWifiController.h | 4 +- nexus/VpnController.cpp | 16 +- nexus/VpnController.h | 4 +- nexus/WifiController.cpp | 210 +++++++++++++-- nexus/WifiController.h | 43 +++- nexus/WifiNetwork.cpp | 54 +++- nexus/WifiNetwork.h | 6 +- nexus/main.cpp | 8 +- 47 files changed, 1480 insertions(+), 510 deletions(-) create mode 100644 nexus/IControllerHandler.h create mode 100644 nexus/SupplicantAssociatedEvent.cpp create mode 100644 nexus/SupplicantAssociatedEvent.h create mode 100644 nexus/SupplicantAssociatingEvent.cpp create mode 100644 nexus/SupplicantAssociatingEvent.h create mode 100644 nexus/SupplicantConnectedEvent.cpp create mode 100644 nexus/SupplicantConnectedEvent.h create mode 100644 nexus/SupplicantConnectionTimeoutEvent.cpp create mode 100644 nexus/SupplicantConnectionTimeoutEvent.h create mode 100644 nexus/SupplicantDisconnectedEvent.cpp create mode 100644 nexus/SupplicantDisconnectedEvent.h create mode 100644 nexus/SupplicantEventFactory.cpp create mode 100644 nexus/SupplicantEventFactory.h create mode 100644 nexus/SupplicantScanResultsEvent.cpp create mode 100644 nexus/SupplicantScanResultsEvent.h create mode 100644 nexus/SupplicantStateChangeEvent.cpp create mode 100644 nexus/SupplicantStateChangeEvent.h create mode 100644 nexus/SupplicantStatus.cpp create mode 100644 nexus/SupplicantStatus.h diff --git a/nexus/Android.mk b/nexus/Android.mk index bd4e3d4ea..6172e62f7 100644 --- a/nexus/Android.mk +++ b/nexus/Android.mk @@ -5,26 +5,35 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) -LOCAL_SRC_FILES:= \ - main.cpp \ - NetworkManager.cpp \ - CommandListener.cpp \ - Controller.cpp \ - WifiController.cpp \ - LoopController.cpp \ - NexusCommand.cpp \ - TiwlanWifiController.cpp \ - Supplicant.cpp \ - SupplicantEvent.cpp \ - SupplicantListener.cpp \ - VpnController.cpp \ - ScanResult.cpp \ - WifiScanner.cpp \ - WifiNetwork.cpp \ - OpenVpnController.cpp \ - InterfaceConfig.cpp \ - PropertyManager.cpp \ - SupplicantState.cpp +LOCAL_SRC_FILES:= \ + main.cpp \ + NetworkManager.cpp \ + CommandListener.cpp \ + Controller.cpp \ + WifiController.cpp \ + LoopController.cpp \ + NexusCommand.cpp \ + TiwlanWifiController.cpp \ + Supplicant.cpp \ + SupplicantEvent.cpp \ + SupplicantListener.cpp \ + VpnController.cpp \ + ScanResult.cpp \ + WifiScanner.cpp \ + WifiNetwork.cpp \ + OpenVpnController.cpp \ + InterfaceConfig.cpp \ + PropertyManager.cpp \ + SupplicantState.cpp \ + SupplicantEventFactory.cpp \ + SupplicantConnectedEvent.cpp \ + SupplicantAssociatingEvent.cpp \ + SupplicantAssociatedEvent.cpp \ + SupplicantStateChangeEvent.cpp \ + SupplicantScanResultsEvent.cpp \ + SupplicantConnectionTimeoutEvent.cpp \ + SupplicantDisconnectedEvent.cpp \ + SupplicantStatus.cpp LOCAL_MODULE:= nexus diff --git a/nexus/CommandListener.cpp b/nexus/CommandListener.cpp index e8de7f585..8eb378bcd 100644 --- a/nexus/CommandListener.cpp +++ b/nexus/CommandListener.cpp @@ -53,7 +53,8 @@ CommandListener::WifiCreateNetworkCmd::WifiCreateNetworkCmd() : NexusCommand("wifi_create_network") { } -int CommandListener::WifiCreateNetworkCmd::runCommand(SocketClient *cli, char *data) { +int CommandListener::WifiCreateNetworkCmd::runCommand(SocketClient *cli, + int argc, char **argv) { NetworkManager *nm = NetworkManager::Instance(); WifiController *wc = (WifiController *) nm->findController("WIFI"); WifiNetwork *wn; @@ -72,11 +73,12 @@ CommandListener::WifiRemoveNetworkCmd::WifiRemoveNetworkCmd() : NexusCommand("wifi_remove_network") { } -int CommandListener::WifiRemoveNetworkCmd::runCommand(SocketClient *cli, char *data) { +int CommandListener::WifiRemoveNetworkCmd::runCommand(SocketClient *cli, + int argc, char **argv) { NetworkManager *nm = NetworkManager::Instance(); WifiController *wc = (WifiController *) nm->findController("WIFI"); - if (wc->removeNetwork(atoi(data))) + if (wc->removeNetwork(atoi(argv[1]))) cli->sendMsg(ErrorCode::OperationFailed, "Failed to remove network", true); else { cli->sendMsg(ErrorCode::CommandOkay, "Network removed.", false); @@ -88,7 +90,8 @@ CommandListener::WifiScanResultsCmd::WifiScanResultsCmd() : NexusCommand("wifi_scan_results") { } -int CommandListener::WifiScanResultsCmd::runCommand(SocketClient *cli, char *data) { +int CommandListener::WifiScanResultsCmd::runCommand(SocketClient *cli, + int argc, char **argv) { NetworkManager *nm = NetworkManager::Instance(); WifiController *wc = (WifiController *) nm->findController("WIFI"); @@ -114,7 +117,8 @@ CommandListener::WifiListNetworksCmd::WifiListNetworksCmd() : NexusCommand("wifi_list_networks") { } -int CommandListener::WifiListNetworksCmd::runCommand(SocketClient *cli, char *data) { +int CommandListener::WifiListNetworksCmd::runCommand(SocketClient *cli, + int argc, char **argv) { NetworkManager *nm = NetworkManager::Instance(); WifiController *wc = (WifiController *) nm->findController("WIFI"); @@ -144,23 +148,19 @@ CommandListener::GetCmd::GetCmd() : NexusCommand("get") { } -int CommandListener::GetCmd::runCommand(SocketClient *cli, char *data) { - char *next = data; - char *propname; +int CommandListener::GetCmd::runCommand(SocketClient *cli, int argc, char **argv) { + char val[Property::ValueMaxSize]; - if (!(propname = strsep(&next, ":"))) - goto out_inval; - - char pb[Property::NameMaxSize + 6]; - snprintf(pb, sizeof(pb), "%s:", propname); - - if (!NetworkManager::Instance()->getPropMngr()->get(propname, - &pb[strlen(pb)], - sizeof(pb) - strlen(pb))) { + if (!NetworkManager::Instance()->getPropMngr()->get(argv[1], + val, + sizeof(val))) { goto out_inval; } - cli->sendMsg(ErrorCode::PropertyRead, pb, false); + char *tmp; + asprintf(&tmp, "%s %s", argv[1], val); + cli->sendMsg(ErrorCode::PropertyRead, tmp, false); + free(tmp); cli->sendMsg(ErrorCode::CommandOkay, "Property read.", false); return 0; @@ -174,23 +174,9 @@ CommandListener::SetCmd::SetCmd() : NexusCommand("set") { } -int CommandListener::SetCmd::runCommand(SocketClient *cli, char *data) { - char *bword; - char *last; - char propname[Property::NameMaxSize]; - char propval[Property::ValueMaxSize]; - - if (!(bword = strtok_r(data, ":", &last))) - goto out_inval; - - strncpy(propname, bword, sizeof(propname)); - - if (!(bword = strtok_r(NULL, ":", &last))) - goto out_inval; - - strncpy(propval, bword, sizeof(propval)); - - if (NetworkManager::Instance()->getPropMngr()->set(propname, propval)) +int CommandListener::SetCmd::runCommand(SocketClient *cli, int argc, + char **argv) { + if (NetworkManager::Instance()->getPropMngr()->set(argv[1], argv[2])) goto out_inval; cli->sendMsg(ErrorCode::CommandOkay, "Property set.", false); @@ -206,7 +192,7 @@ CommandListener::ListCmd::ListCmd() : NexusCommand("list") { } -int CommandListener::ListCmd::runCommand(SocketClient *cli, char *data) { +int CommandListener::ListCmd::runCommand(SocketClient *cli, int argc, char **argv) { android::List *pc; if (!(pc = NetworkManager::Instance()->getPropMngr()->createPropertyList())) { @@ -227,7 +213,7 @@ int CommandListener::ListCmd::runCommand(SocketClient *cli, char *data) { } char *buf; - if (asprintf(&buf, "%s:%s", (*it), p_v) < 0) { + if (asprintf(&buf, "%s %s", (*it), p_v) < 0) { LOGE("Failed to allocate memory"); free((*it)); continue; diff --git a/nexus/CommandListener.h b/nexus/CommandListener.h index b57c25ffb..30c6dc054 100644 --- a/nexus/CommandListener.h +++ b/nexus/CommandListener.h @@ -31,56 +31,56 @@ private: public: WifiScanCmd(); virtual ~WifiScanCmd() {} - int runCommand(SocketClient *c, char *data); + int runCommand(SocketClient *c, int argc, char ** argv); }; class WifiScanResultsCmd : public NexusCommand { public: WifiScanResultsCmd(); virtual ~WifiScanResultsCmd() {} - int runCommand(SocketClient *c, char *data); + int runCommand(SocketClient *c, int argc, char ** argv); }; class WifiCreateNetworkCmd : public NexusCommand { public: WifiCreateNetworkCmd(); virtual ~WifiCreateNetworkCmd() {} - int runCommand(SocketClient *c, char *data); + int runCommand(SocketClient *c, int argc, char ** argv); }; class WifiRemoveNetworkCmd : public NexusCommand { public: WifiRemoveNetworkCmd(); virtual ~WifiRemoveNetworkCmd() {} - int runCommand(SocketClient *c, char *data); + int runCommand(SocketClient *c, int argc, char ** argv); }; class WifiListNetworksCmd : public NexusCommand { public: WifiListNetworksCmd(); virtual ~WifiListNetworksCmd() {} - int runCommand(SocketClient *c, char *data); + int runCommand(SocketClient *c, int argc, char ** argv); }; class SetCmd : public NexusCommand { public: SetCmd(); virtual ~SetCmd() {} - int runCommand(SocketClient *c, char *data); + int runCommand(SocketClient *c, int argc, char ** argv); }; class GetCmd : public NexusCommand { public: GetCmd(); virtual ~GetCmd() {} - int runCommand(SocketClient *c, char *data); + int runCommand(SocketClient *c, int argc, char ** argv); }; class ListCmd : public NexusCommand { public: ListCmd(); virtual ~ListCmd() {} - int runCommand(SocketClient *c, char *data); + int runCommand(SocketClient *c, int argc, char ** argv); }; }; diff --git a/nexus/Controller.cpp b/nexus/Controller.cpp index 9d4ff3c65..17fb51939 100644 --- a/nexus/Controller.cpp +++ b/nexus/Controller.cpp @@ -34,9 +34,11 @@ extern "C" int init_module(void *, unsigned int, const char *); extern "C" int delete_module(const char *, unsigned int); -Controller::Controller(const char *name, PropertyManager *propMngr) { +Controller::Controller(const char *name, PropertyManager *propMngr, + IControllerHandler *handlers) { mPropMngr = propMngr; mName = strdup(name); + mHandlers = handlers; mBoundInterface = NULL; } diff --git a/nexus/Controller.h b/nexus/Controller.h index 9137f9a86..af03d2e59 100644 --- a/nexus/Controller.h +++ b/nexus/Controller.h @@ -23,12 +23,12 @@ #include class PropertyManager; +class IControllerHandler; #include "PropertyManager.h" #include "IPropertyProvider.h" class Controller : public IPropertyProvider { -private: /* * Name of this controller - WIFI/VPN/USBNET/BTNET/BTDUN/LOOP/etc */ @@ -42,9 +42,11 @@ private: protected: PropertyManager *mPropMngr; + IControllerHandler *mHandlers; public: - Controller(const char *name, PropertyManager *propMngr); + Controller(const char *name, PropertyManager *propMngr, + IControllerHandler *handlers); virtual ~Controller(); virtual int start(); diff --git a/nexus/IControllerHandler.h b/nexus/IControllerHandler.h new file mode 100644 index 000000000..92d015f43 --- /dev/null +++ b/nexus/IControllerHandler.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _ICONTROLLER_HANDLER_H +#define _ICONTROLLER_HANDLER_H + +class Controller; +class InterfaceConfig; + +class IControllerHandler { +public: + virtual void onInterfaceStarted(Controller *c, const InterfaceConfig *cfg) = 0; + virtual void onInterfaceStopping(Controller *c, const char *name) = 0; +}; + +#endif + diff --git a/nexus/ISupplicantEventHandler.h b/nexus/ISupplicantEventHandler.h index 7e1bd5ab8..b7fd17b56 100644 --- a/nexus/ISupplicantEventHandler.h +++ b/nexus/ISupplicantEventHandler.h @@ -17,21 +17,34 @@ #ifndef _ISUPPLICANT_EVENT_HANDLER_H #define _ISUPPLICANT_EVENT_HANDLER_H +class SupplicantAssociatingEvent; +class SupplicantAssociatedEvent; +class SupplicantConnectedEvent; +class SupplicantScanResultsEvent; +class SupplicantStateChangeEvent; +class SupplicantConnectionTimeoutEvent; +class SupplicantDisconnectedEvent; + class ISupplicantEventHandler { public: - virtual int onConnectedEvent(SupplicantEvent *evt) = 0; - virtual int onDisconnectedEvent(SupplicantEvent *evt) = 0; - virtual int onTerminatingEvent(SupplicantEvent *evt) = 0; - virtual int onPasswordChangedEvent(SupplicantEvent *evt) = 0; - virtual int onEapNotificationEvent(SupplicantEvent *evt) = 0; - virtual int onEapStartedEvent(SupplicantEvent *evt) = 0; - virtual int onEapMethodEvent(SupplicantEvent *evt) = 0; - virtual int onEapSuccessEvent(SupplicantEvent *evt) = 0; - virtual int onEapFailureEvent(SupplicantEvent *evt) = 0; - virtual int onScanResultsEvent(SupplicantEvent *evt) = 0; - virtual int onStateChangeEvent(SupplicantEvent *evt) = 0; - virtual int onLinkSpeedEvent(SupplicantEvent *evt) = 0; - virtual int onDriverStateEvent(SupplicantEvent *evt) = 0; + virtual void onAssociatingEvent(SupplicantAssociatingEvent *evt) = 0; + virtual void onAssociatedEvent(SupplicantAssociatedEvent *evt) = 0; + virtual void onConnectedEvent(SupplicantConnectedEvent *evt) = 0; + virtual void onScanResultsEvent(SupplicantScanResultsEvent *evt) = 0; + virtual void onStateChangeEvent(SupplicantStateChangeEvent *evt) = 0; + virtual void onConnectionTimeoutEvent(SupplicantConnectionTimeoutEvent *evt) = 0; + virtual void onDisconnectedEvent(SupplicantDisconnectedEvent *evt) = 0; +#if 0 + virtual void onTerminatingEvent(SupplicantEvent *evt) = 0; + virtual void onPasswordChangedEvent(SupplicantEvent *evt) = 0; + virtual void onEapNotificationEvent(SupplicantEvent *evt) = 0; + virtual void onEapStartedEvent(SupplicantEvent *evt) = 0; + virtual void onEapMethodEvent(SupplicantEvent *evt) = 0; + virtual void onEapSuccessEvent(SupplicantEvent *evt) = 0; + virtual void onEapFailureEvent(SupplicantEvent *evt) = 0; + virtual void onLinkSpeedEvent(SupplicantEvent *evt) = 0; + virtual void onDriverStateEvent(SupplicantEvent *evt) = 0; +#endif }; #endif diff --git a/nexus/LoopController.cpp b/nexus/LoopController.cpp index a86202a3f..5cfb1fecb 100644 --- a/nexus/LoopController.cpp +++ b/nexus/LoopController.cpp @@ -19,8 +19,9 @@ #include "LoopController.h" #include "PropertyManager.h" -LoopController::LoopController(PropertyManager *propmngr) : - Controller("LOOP", propmngr) { +LoopController::LoopController(PropertyManager *propmngr, + IControllerHandler *handlers) : + Controller("LOOP", propmngr, handlers) { } int LoopController::set(const char *name, const char *value) { diff --git a/nexus/LoopController.h b/nexus/LoopController.h index bb8314f22..53d16f138 100644 --- a/nexus/LoopController.h +++ b/nexus/LoopController.h @@ -19,10 +19,11 @@ #include "Controller.h" +class ControllerHandler; class LoopController : public Controller { public: - LoopController(PropertyManager *propmngr); + LoopController(PropertyManager *propmngr, IControllerHandler *h); virtual ~LoopController() {} int set(const char *name, const char *value); diff --git a/nexus/NetworkManager.cpp b/nexus/NetworkManager.cpp index f4ae88fd7..2f13a408e 100644 --- a/nexus/NetworkManager.cpp +++ b/nexus/NetworkManager.cpp @@ -89,23 +89,26 @@ Controller *NetworkManager::findController(const char *name) { return NULL; } -int NetworkManager::onInterfaceStart(Controller *c, const InterfaceConfig *cfg) { +void NetworkManager::onInterfaceStarted(Controller *c, const InterfaceConfig *cfg) { LOGD("Interface %s started by controller %s", c->getBoundInterface(), c->getName()); // Look up the interface if (0) { // already started? - errno = EADDRINUSE; - return -1; } - if (cfg->getUseDhcp()) { + if (cfg) { + if (cfg->getUseDhcp()) { + // Launch DHCP thread + } else { + // Static configuration + } } else { + LOGD("No InterfaceConfig for %s:%s - assuming self-managed", + c->getName(), c->getBoundInterface()); } - return 0; } -int NetworkManager::onInterfaceStop(Controller *c, const char *name) { +void NetworkManager::onInterfaceStopping(Controller *c, const char *name) { LOGD("Interface %s stopped by controller %s", name, c->getName()); - return 0; } diff --git a/nexus/NetworkManager.h b/nexus/NetworkManager.h index e75382d59..edc80c9b5 100644 --- a/nexus/NetworkManager.h +++ b/nexus/NetworkManager.h @@ -20,12 +20,12 @@ #include #include "Controller.h" - #include "PropertyManager.h" +#include "IControllerHandler.h" class InterfaceConfig; -class NetworkManager { +class NetworkManager : public IControllerHandler { private: static NetworkManager *sInstance; @@ -55,16 +55,7 @@ private: NetworkManager(PropertyManager *propMngr); -public: - /* - * Called from a controller when an interface is available/ready for use. - * 'cfg' contains information on how this interface should be configured. - */ - int onInterfaceStart(Controller *c, const InterfaceConfig *cfg); - - /* - * Called from a controller when an interface should be shut down - */ - int onInterfaceStop(Controller *c, const char *name); + void onInterfaceStarted(Controller *c, const InterfaceConfig *cfg); + void onInterfaceStopping(Controller *c, const char *name); }; #endif diff --git a/nexus/OpenVpnController.cpp b/nexus/OpenVpnController.cpp index 4c144a46a..f1ea51022 100644 --- a/nexus/OpenVpnController.cpp +++ b/nexus/OpenVpnController.cpp @@ -30,8 +30,9 @@ #define DAEMON_PROP_NAME "vpn.openvpn.status" #define DAEMON_CONFIG_FILE "/data/misc/openvpn/openvpn.conf" -OpenVpnController::OpenVpnController(PropertyManager *propmngr) : - VpnController(propmngr) { +OpenVpnController::OpenVpnController(PropertyManager *propmngr, + IControllerHandler *handlers) : + VpnController(propmngr, handlers) { mServiceManager = new ServiceManager(); } @@ -40,11 +41,11 @@ OpenVpnController::~OpenVpnController() { } int OpenVpnController::start() { - return 0; + return VpnController::start(); } int OpenVpnController::stop() { - return 0; + return VpnController::stop(); } int OpenVpnController::enable() { diff --git a/nexus/OpenVpnController.h b/nexus/OpenVpnController.h index 323c44cbf..529aab53b 100644 --- a/nexus/OpenVpnController.h +++ b/nexus/OpenVpnController.h @@ -21,13 +21,14 @@ #include "VpnController.h" class ServiceManager; +class IControllerHandler; class OpenVpnController : public VpnController { private: ServiceManager *mServiceManager; public: - OpenVpnController(PropertyManager *propmngr); + OpenVpnController(PropertyManager *propmngr, IControllerHandler *handlers); virtual ~OpenVpnController(); int start(); diff --git a/nexus/PropertyManager.cpp b/nexus/PropertyManager.cpp index 3366babe7..6faf9b830 100644 --- a/nexus/PropertyManager.cpp +++ b/nexus/PropertyManager.cpp @@ -37,7 +37,8 @@ int PropertyManager::registerProperty(const char *name, IPropertyProvider *pp) { for (it = mPropertyPairs->begin(); it != mPropertyPairs->end(); ++it) { if (!strcmp(name, (*it)->getName())) { errno = EADDRINUSE; - LOGE("Failed to register property (%s)", strerror(errno)); + LOGE("Failed to register property %s (%s)", + name, strerror(errno)); pthread_mutex_unlock(&mLock); return -1; } diff --git a/nexus/Supplicant.cpp b/nexus/Supplicant.cpp index e69f2c0df..9bb6bf2c1 100644 --- a/nexus/Supplicant.cpp +++ b/nexus/Supplicant.cpp @@ -29,13 +29,10 @@ #include "Supplicant.h" #include "SupplicantListener.h" -#include "SupplicantState.h" -#include "SupplicantEvent.h" -#include "ScanResult.h" -#include "PropertyManager.h" #include "NetworkManager.h" #include "ErrorCode.h" #include "WifiController.h" +#include "SupplicantStatus.h" #include "libwpa_client/wpa_ctrl.h" @@ -45,21 +42,16 @@ #define SUPP_CONFIG_TEMPLATE "/system/etc/wifi/wpa_supplicant.conf" #define SUPP_CONFIG_FILE "/data/misc/wifi/wpa_supplicant.conf" -Supplicant::Supplicant(WifiController *wc, PropertyManager *propmngr) { +Supplicant::Supplicant(WifiController *wc, ISupplicantEventHandler *handlers) { + mHandlers = handlers; mController = wc; - mPropMngr = propmngr; mInterfaceName = NULL; mCtrl = NULL; mMonitor = NULL; mListener = NULL; - mState = SupplicantState::UNKNOWN; - mServiceManager = new ServiceManager(); - mLatestScanResults = new ScanResultCollection(); - pthread_mutex_init(&mLatestScanResultsLock, NULL); - mNetworks = new WifiNetworkCollection(); pthread_mutex_init(&mNetworksLock, NULL); } @@ -92,14 +84,11 @@ int Supplicant::start() { return -1; } - mPropMngr->registerProperty("wifi.supplicant.state", this); return 0; } int Supplicant::stop() { - mPropMngr->unregisterProperty("wifi.supplicant.state"); - if (mListener->stopListener()) { LOGW("Unable to stop supplicant listener (%s)", strerror(errno)); return -1; @@ -125,6 +114,30 @@ bool Supplicant::isStarted() { return mServiceManager->isRunning(SUPPLICANT_SERVICE_NAME); } +SupplicantStatus *Supplicant::getStatus() { + char *reply; + size_t len = 4096; + + if (!(reply = (char *) malloc(len))) { + errno = ENOMEM; + return NULL; + } + + if (sendCommand("STATUS", reply, &len)) { + free(reply); + return NULL; + } + + SupplicantStatus *ss = SupplicantStatus::createStatus(reply, len); + + free (reply); + return ss; +} + +/* + * Retrieves the list of networks from Supplicant + * and merge them into our current list + */ int Supplicant::refreshNetworkList() { char *reply; size_t len = 4096; @@ -144,27 +157,59 @@ int Supplicant::refreshNetworkList() { if (!strtok_r(reply, "\n", &linep_next)) { LOGW("Malformatted network list\n"); - } else { - pthread_mutex_lock(&mNetworksLock); - if (!mNetworks->empty()) { - WifiNetworkCollection::iterator i; - - for (i = mNetworks->begin(); i !=mNetworks->end(); ++i) - delete *i; - mNetworks->clear(); - } - - while((linep = strtok_r(NULL, "\n", &linep_next))) { - WifiNetwork *wn = new WifiNetwork(mController, this, linep); - mNetworks->push_back(wn); - if (wn->refresh()) - LOGW("Unable to refresh network id %d", wn->getNetworkId()); - } - - LOGD("Loaded %d networks\n", mNetworks->size()); - pthread_mutex_unlock(&mNetworksLock); + free(reply); + errno = EIO; + return -1; } + pthread_mutex_lock(&mNetworksLock); + + int num_added = 0; + int num_refreshed = 0; + int num_removed = 0; + while((linep = strtok_r(NULL, "\n", &linep_next))) { + // TODO: Move the decode into a static method so we + // don't create new_wn when we don't have to. + WifiNetwork *new_wn = new WifiNetwork(mController, this, linep); + WifiNetwork *merge_wn; + + if ((merge_wn = this->lookupNetwork_UNLOCKED(new_wn->getNetworkId()))) { + num_refreshed++; + if (merge_wn->refresh()) { + LOGW("Error refreshing network %d (%s)", + merge_wn->getNetworkId(), strerror(errno)); + } + delete new_wn; + } else { + num_added++; + new_wn->registerProperties(); + mNetworks->push_back(new_wn); + if (new_wn->refresh()) { + LOGW("Unable to refresh network id %d (%s)", + new_wn->getNetworkId(), strerror(errno)); + } + } + } + + if (!mNetworks->empty()) { + // TODO: Add support for detecting removed networks + WifiNetworkCollection::iterator i; + + for (i = mNetworks->begin(); i != mNetworks->end(); ++i) { + if (0) { + num_removed++; + (*i)->unregisterProperties(); + delete (*i); + i = mNetworks->erase(i); + } + } + } + + + LOGD("Networks added %d, refreshed %d, removed %d\n", + num_added, num_refreshed, num_removed); + pthread_mutex_unlock(&mNetworksLock); + free(reply); return 0; } @@ -192,7 +237,7 @@ int Supplicant::connectToSupplicant() { return -1; } - mListener = new SupplicantListener(this, mMonitor); + mListener = new SupplicantListener(mHandlers, mMonitor); if (mListener->startListener()) { LOGE("Error - unable to start supplicant listener"); @@ -245,165 +290,6 @@ int Supplicant::triggerScan(bool active) { return 0; } -int Supplicant::set(const char *name, const char *value) { - const char *n = name + strlen("wifi.supplicant."); - - errno = -EROFS; - return -1; -} - -const char *Supplicant::get(const char *name, char *buffer, size_t max) { - const char *n = name + strlen("wifi.supplicant."); - - if (!strcasecmp(n, "state")) - return SupplicantState::toString(mState, buffer, max); - errno = ENOENT; - return NULL; -} - -int Supplicant::onConnectedEvent(SupplicantEvent *evt) { - LOGD("onConnectedEvent(%s)", evt->getEvent()); - return 0; -} - -int Supplicant::onDisconnectedEvent(SupplicantEvent *evt) { - LOGD("onDisconnectedEvent(%s)", evt->getEvent()); - return 0; -} - -int Supplicant::onTerminatingEvent(SupplicantEvent *evt) { - LOGD("onTerminatingEvent(%s)", evt->getEvent()); - return 0; -} - -int Supplicant::onPasswordChangedEvent(SupplicantEvent *evt) { - LOGD("onPasswordChangedEvent(%s)", evt->getEvent()); - return 0; -} - -int Supplicant::onEapNotificationEvent(SupplicantEvent *evt) { - LOGD("onEapNotificationEvent(%s)", evt->getEvent()); - return 0; -} - -int Supplicant::onEapStartedEvent(SupplicantEvent *evt) { - LOGD("onEapStartedEvent(%s)", evt->getEvent()); - return 0; -} - -int Supplicant::onEapMethodEvent(SupplicantEvent *evt) { - LOGD("onEapMethodEvent(%s)", evt->getEvent()); - return 0; -} - -int Supplicant::onEapSuccessEvent(SupplicantEvent *evt) { - LOGD("onEapSuccessEvent(%s)", evt->getEvent()); - return 0; -} - -int Supplicant::onEapFailureEvent(SupplicantEvent *evt) { - LOGD("onEapFailureEvent(%s)", evt->getEvent()); - return 0; -} - -int Supplicant::onScanResultsEvent(SupplicantEvent *evt) { - if (!strcmp(evt->getEvent(), "Ready")) { - char *reply; - - if (!(reply = (char *) malloc(4096))) { - errno = ENOMEM; - return -1; - } - - size_t len = 4096; - - if (sendCommand("SCAN_RESULTS", reply, &len)) { - LOGW("onScanResultsEvent(%s): Error getting scan results (%s)", - evt->getEvent(), strerror(errno)); - free(reply); - return -1; - } - - pthread_mutex_lock(&mLatestScanResultsLock); - if (!mLatestScanResults->empty()) { - ScanResultCollection::iterator i; - - for (i = mLatestScanResults->begin(); - i !=mLatestScanResults->end(); ++i) { - delete *i; - } - mLatestScanResults->clear(); - } - - char *linep; - char *linep_next = NULL; - - if (!strtok_r(reply, "\n", &linep_next)) { - free(reply); - pthread_mutex_unlock(&mLatestScanResultsLock); - return 0; - } - - while((linep = strtok_r(NULL, "\n", &linep_next))) - mLatestScanResults->push_back(new ScanResult(linep)); - - char tmp[128]; - sprintf(tmp, "Scan results ready (%d)", mLatestScanResults->size()); - NetworkManager::Instance()->getBroadcaster()-> - sendBroadcast(ErrorCode::UnsolicitedInformational, tmp, false); - pthread_mutex_unlock(&mLatestScanResultsLock); - free(reply); - } else { - LOGW("Unknown SCAN_RESULTS event (%s)", evt->getEvent()); - } - return 0; -} - -int Supplicant::onStateChangeEvent(SupplicantEvent *evt) { - char *bword, *last; - char *tmp = strdup(evt->getEvent()); - - if (!(bword = strtok_r(tmp, " ", &last))) { - LOGE("Malformatted state update (%s)", evt->getEvent()); - free(tmp); - return 0; - } - - if (!(bword = strtok_r(NULL, " ", &last))) { - LOGE("Malformatted state update (%s)", evt->getEvent()); - free(tmp); - return 0; - } - - mState = atoi(&bword[strlen("state=")]); - LOGD("State changed to %d", mState); - free(tmp); - return 0; -} - -int Supplicant::onLinkSpeedEvent(SupplicantEvent *evt) { - LOGD("onLinkSpeedEvent(%s)", evt->getEvent()); - return 0; -} - -int Supplicant::onDriverStateEvent(SupplicantEvent *evt) { - LOGD("onDriverStateEvent(%s)", evt->getEvent()); - return 0; -} - -// XXX: Use a cursor + smartptr instead -ScanResultCollection *Supplicant::createLatestScanResults() { - ScanResultCollection *d = new ScanResultCollection(); - ScanResultCollection::iterator i; - - pthread_mutex_lock(&mLatestScanResultsLock); - for (i = mLatestScanResults->begin(); i != mLatestScanResults->end(); ++i) - d->push_back((*i)->clone()); - - pthread_mutex_unlock(&mLatestScanResultsLock); - return d; -} - WifiNetwork *Supplicant::createNetwork() { char reply[255]; size_t len = sizeof(reply) -1; @@ -445,14 +331,18 @@ int Supplicant::removeNetwork(WifiNetwork *wn) { WifiNetwork *Supplicant::lookupNetwork(int networkId) { pthread_mutex_lock(&mNetworksLock); + WifiNetwork *wn = lookupNetwork_UNLOCKED(networkId); + pthread_mutex_unlock(&mNetworksLock); + return wn; +} + +WifiNetwork *Supplicant::lookupNetwork_UNLOCKED(int networkId) { WifiNetworkCollection::iterator it; for (it = mNetworks->begin(); it != mNetworks->end(); ++it) { if ((*it)->getNetworkId() == networkId) { - pthread_mutex_unlock(&mNetworksLock); return *it; } } - pthread_mutex_unlock(&mNetworksLock); errno = ENOENT; return NULL; } @@ -528,6 +418,12 @@ int Supplicant::setNetworkVar(int networkId, const char *var, const char *val) { return -1; } free(tmp); + + len = sizeof(reply) -1; + if (sendCommand("SAVE_CONFIG", reply, &len)) { + LOGE("Error saving config after %s = %s", var, val); + return -1; + } return 0; } diff --git a/nexus/Supplicant.h b/nexus/Supplicant.h index 42f2f79a2..3efbe4cd4 100644 --- a/nexus/Supplicant.h +++ b/nexus/Supplicant.h @@ -19,38 +19,31 @@ struct wpa_ctrl; class SupplicantListener; -class SupplicantEvent; class ServiceManager; -class PropertyManager; class Controller; class WifiController; +class SupplicantStatus; #include -#include "ScanResult.h" #include "WifiNetwork.h" -#include "IPropertyProvider.h" #include "ISupplicantEventHandler.h" -class Supplicant : public IPropertyProvider, public ISupplicantEventHandler { +class Supplicant { private: struct wpa_ctrl *mCtrl; struct wpa_ctrl *mMonitor; SupplicantListener *mListener; - int mState; ServiceManager *mServiceManager; - PropertyManager *mPropMngr; WifiController *mController; char *mInterfaceName; - ScanResultCollection *mLatestScanResults; - pthread_mutex_t mLatestScanResultsLock; - - WifiNetworkCollection *mNetworks; - pthread_mutex_t mNetworksLock; + WifiNetworkCollection *mNetworks; + pthread_mutex_t mNetworksLock; + ISupplicantEventHandler *mHandlers; public: - Supplicant(WifiController *wc, PropertyManager *propmngr); + Supplicant(WifiController *wc, ISupplicantEventHandler *handlers); virtual ~Supplicant(); int start(); @@ -58,7 +51,6 @@ public: bool isStarted(); int triggerScan(bool active); - ScanResultCollection *createLatestScanResults(); WifiNetwork *createNetwork(); WifiNetwork *lookupNetwork(int networkId); @@ -71,33 +63,18 @@ public: size_t max); int enableNetwork(int networkId, bool enabled); - int getState() { return mState; } + SupplicantStatus *getStatus(); + Controller *getController() { return (Controller *) mController; } const char *getInterfaceName() { return mInterfaceName; } - int set(const char *name, const char *value); - const char *get(const char *name, char *buffer, size_t max); + int sendCommand(const char *cmd, char *reply, size_t *reply_len); private: int connectToSupplicant(); - int sendCommand(const char *cmd, char *reply, size_t *reply_len); int setupConfig(); int retrieveInterfaceName(); - - // ISupplicantEventHandler methods - virtual int onConnectedEvent(SupplicantEvent *evt); - virtual int onDisconnectedEvent(SupplicantEvent *evt); - virtual int onTerminatingEvent(SupplicantEvent *evt); - virtual int onPasswordChangedEvent(SupplicantEvent *evt); - virtual int onEapNotificationEvent(SupplicantEvent *evt); - virtual int onEapStartedEvent(SupplicantEvent *evt); - virtual int onEapMethodEvent(SupplicantEvent *evt); - virtual int onEapSuccessEvent(SupplicantEvent *evt); - virtual int onEapFailureEvent(SupplicantEvent *evt); - virtual int onScanResultsEvent(SupplicantEvent *evt); - virtual int onStateChangeEvent(SupplicantEvent *evt); - virtual int onLinkSpeedEvent(SupplicantEvent *evt); - virtual int onDriverStateEvent(SupplicantEvent *evt); + WifiNetwork *lookupNetwork_UNLOCKED(int networkId); }; #endif diff --git a/nexus/SupplicantAssociatedEvent.cpp b/nexus/SupplicantAssociatedEvent.cpp new file mode 100644 index 000000000..e40411efe --- /dev/null +++ b/nexus/SupplicantAssociatedEvent.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#define LOG_TAG "SupplicantAssociatedEvent" +#include + +#include "SupplicantAssociatedEvent.h" + +SupplicantAssociatedEvent::SupplicantAssociatedEvent(int level, char *event, + size_t len) : + SupplicantEvent(SupplicantEvent::EVENT_ASSOCIATED, + level) { + char *p = event; + + // "00:13:46:40:40:aa" + mBssid = (char *) malloc(18); + strncpy(mBssid, p, 17); + mBssid[17] = '\0'; +} + +SupplicantAssociatedEvent::~SupplicantAssociatedEvent() { + if (mBssid) + free(mBssid); +} + diff --git a/nexus/SupplicantAssociatedEvent.h b/nexus/SupplicantAssociatedEvent.h new file mode 100644 index 000000000..aa33c59b7 --- /dev/null +++ b/nexus/SupplicantAssociatedEvent.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SupplicantAssociatedEvent_H +#define _SupplicantAssociatedEvent_H + +#include "SupplicantEvent.h" + +class SupplicantAssociatedEvent : public SupplicantEvent { + char *mBssid; + char *mSsid; + int mFreq; + +public: + SupplicantAssociatedEvent(int level, char *event, size_t len); + virtual ~SupplicantAssociatedEvent(); + + const char *getBssid() { return mBssid; } +}; + +#endif diff --git a/nexus/SupplicantAssociatingEvent.cpp b/nexus/SupplicantAssociatingEvent.cpp new file mode 100644 index 000000000..00a85b654 --- /dev/null +++ b/nexus/SupplicantAssociatingEvent.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#define LOG_TAG "SupplicantAssociatingEvent" +#include + +#include "SupplicantAssociatingEvent.h" + +SupplicantAssociatingEvent::SupplicantAssociatingEvent(int level, char *event, + size_t len) : + SupplicantEvent(SupplicantEvent::EVENT_ASSOCIATING, + level) { + char *p = event; + + mBssid = NULL; + mSsid = NULL; + + // SSID 'default' + // OR + // "00:13:46:40:40:aa (SSID='default' freq=2437 MHz)" + + if (strncmp(event, "SSID", 4)) { + mBssid = (char *) malloc(18); + strncpy(mBssid, p, 17); + mBssid[17] = '\0'; + p += 25; + + // "00:13:46:40:40:aa (SSID='default' freq=2437 MHz)" + // ^ + // p + char *q = index(p, '\''); + if (!q) { + LOGE("Unable to decode SSID (p = {%s})\n", p); + return; + } + mSsid = (char *) malloc((q - p) +1); + strncpy(mSsid, p, q-p); + mSsid[q-p] = '\0'; + + p = q + 7; + + // "00:13:46:40:40:aa (SSID='default' freq=2437 MHz)" + // ^ + // p + if (!(q = index(p, ' '))) { + LOGE("Unable to decode frequency\n"); + return; + } + *q = '\0'; + mFreq = atoi(p); + } else { + p+= 6; + + // SSID 'default' + // ^ + // p + + char *q = index(p, '\''); + if (!q) { + LOGE("Unable to decode SSID (p = {%s})\n", p); + return; + } + mSsid = (char *) malloc((q - p) +1); + strncpy(mSsid, p, q-p); + mSsid[q-p] = '\0'; + } +} + +SupplicantAssociatingEvent::SupplicantAssociatingEvent(const char *bssid, + const char *ssid, + int freq) : + SupplicantEvent(SupplicantEvent::EVENT_ASSOCIATING, -1) { + mBssid = strdup(bssid); + mSsid= strdup(ssid); + mFreq = freq; +} + +SupplicantAssociatingEvent::~SupplicantAssociatingEvent() { + if (mBssid) + free(mBssid); + if (mSsid) + free(mSsid); +} + diff --git a/nexus/SupplicantAssociatingEvent.h b/nexus/SupplicantAssociatingEvent.h new file mode 100644 index 000000000..d3a4d5cd9 --- /dev/null +++ b/nexus/SupplicantAssociatingEvent.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SupplicantAssociatingEvent_H +#define _SupplicantAssociatingEvent_H + +#include "SupplicantEvent.h" + +class SupplicantAssociatingEvent : public SupplicantEvent { + char *mBssid; + char *mSsid; + int mFreq; + +public: + SupplicantAssociatingEvent(int level, char *event, size_t len); + SupplicantAssociatingEvent(const char *bssid, const char *ssid, int freq); + virtual ~SupplicantAssociatingEvent(); + + const char *getBssid() { return mBssid; } + const char *getSsid() { return mSsid; } + int getFreq() { return mFreq;} +}; + +#endif diff --git a/nexus/SupplicantConnectedEvent.cpp b/nexus/SupplicantConnectedEvent.cpp new file mode 100644 index 000000000..e58bab22e --- /dev/null +++ b/nexus/SupplicantConnectedEvent.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "SupplicantConnectedEvent" +#include + +#include "SupplicantConnectedEvent.h" + +SupplicantConnectedEvent::SupplicantConnectedEvent(int level, char *event, + size_t len) : + SupplicantEvent(SupplicantEvent::EVENT_CONNECTED, + level) { + char *p; + + // "- Connection to 00:13:46:40:40:aa completed (auth) [id=1 id_str=], 89" + + if ((p = index(event + 2, ' ')) && (++p = index(p, ' '))) { + mBssid = (char *) malloc(18); + strncpy(mBssid, ++p, 17); + mBssid[17] = '\0'; + + // "- Connection to 00:13:46:40:40:aa completed (auth) [id=1 id_str=], 89" + // ^ + // p + + if ((p = index(p, ' ')) && ((++p = index(p, ' ')))) { + if (!strncmp(++p, "(auth)", 6)) + mReassociated = false; + else + mReassociated = true; + } else + LOGE("Unable to decode re-assocation"); + } else + LOGE("Unable to decode event"); +} + +SupplicantConnectedEvent::SupplicantConnectedEvent(const char *bssid, + bool reassocated) : + SupplicantEvent(SupplicantEvent::EVENT_CONNECTED, -1) { + mBssid = strdup(bssid); + mReassociated = reassocated; +} + +SupplicantConnectedEvent::~SupplicantConnectedEvent() { + if (mBssid) + free(mBssid); +} + diff --git a/nexus/SupplicantConnectedEvent.h b/nexus/SupplicantConnectedEvent.h new file mode 100644 index 000000000..03e9842a1 --- /dev/null +++ b/nexus/SupplicantConnectedEvent.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SupplicantConnectedEvent_H +#define _SupplicantConnectedEvent_H + +#include "SupplicantEvent.h" + +class SupplicantConnectedEvent : public SupplicantEvent { +private: + char *mBssid; + bool mReassociated; + +public: + SupplicantConnectedEvent(int level, char *event, size_t len); + SupplicantConnectedEvent(const char *bssid, bool reassicated); + virtual ~SupplicantConnectedEvent(); + + const char *getBssid() { return mBssid; } + bool getReassociated() { return mReassociated; } +}; + +#endif diff --git a/nexus/SupplicantConnectionTimeoutEvent.cpp b/nexus/SupplicantConnectionTimeoutEvent.cpp new file mode 100644 index 000000000..8b8a7d755 --- /dev/null +++ b/nexus/SupplicantConnectionTimeoutEvent.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "SupplicantConnectionTimeoutEvent" +#include + +#include "SupplicantConnectionTimeoutEvent.h" + +SupplicantConnectionTimeoutEvent::SupplicantConnectionTimeoutEvent(int level, char *event, + size_t len) : + SupplicantEvent(SupplicantEvent::EVENT_CONNECTIONTIMEOUT, + level) { + // 00:13:46:40:40:aa timed out.' + mBssid = (char *) malloc(18); + strncpy(mBssid, event, 17); + mBssid[17] = '\0'; +} + +SupplicantConnectionTimeoutEvent::~SupplicantConnectionTimeoutEvent() { + if (mBssid) + free(mBssid); +} + diff --git a/nexus/SupplicantConnectionTimeoutEvent.h b/nexus/SupplicantConnectionTimeoutEvent.h new file mode 100644 index 000000000..0d2606d04 --- /dev/null +++ b/nexus/SupplicantConnectionTimeoutEvent.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SupplicantConnectionTimeoutEvent_H +#define _SupplicantConnectionTimeoutEvent_H + +#include "SupplicantEvent.h" + +class SupplicantConnectionTimeoutEvent : public SupplicantEvent { +private: + char *mBssid; + bool mReassociated; + +public: + SupplicantConnectionTimeoutEvent(int level, char *event, size_t len); + virtual ~SupplicantConnectionTimeoutEvent(); + + const char *getBssid() { return mBssid; } +}; + +#endif diff --git a/nexus/SupplicantDisconnectedEvent.cpp b/nexus/SupplicantDisconnectedEvent.cpp new file mode 100644 index 000000000..11e499db2 --- /dev/null +++ b/nexus/SupplicantDisconnectedEvent.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "SupplicantDisconnectedEvent" +#include + +#include "SupplicantDisconnectedEvent.h" + +SupplicantDisconnectedEvent::SupplicantDisconnectedEvent(int level, char *event, + size_t len) : + SupplicantEvent(SupplicantEvent::EVENT_DISCONNECTED, + level) { +} + +SupplicantDisconnectedEvent::SupplicantDisconnectedEvent() : + SupplicantEvent(SupplicantEvent::EVENT_DISCONNECTED, -1) { +} + +SupplicantDisconnectedEvent::~SupplicantDisconnectedEvent() { +} diff --git a/nexus/SupplicantDisconnectedEvent.h b/nexus/SupplicantDisconnectedEvent.h new file mode 100644 index 000000000..c09ec622f --- /dev/null +++ b/nexus/SupplicantDisconnectedEvent.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SupplicantDisconnectedEvent_H +#define _SupplicantDisconnectedEvent_H + +#include "SupplicantEvent.h" + +class SupplicantDisconnectedEvent : public SupplicantEvent { + +public: + SupplicantDisconnectedEvent(int level, char *event, size_t len); + SupplicantDisconnectedEvent(); + virtual ~SupplicantDisconnectedEvent(); +}; + +#endif diff --git a/nexus/SupplicantEvent.cpp b/nexus/SupplicantEvent.cpp index 2e6d66542..faf7b45f4 100644 --- a/nexus/SupplicantEvent.cpp +++ b/nexus/SupplicantEvent.cpp @@ -23,74 +23,7 @@ #include "libwpa_client/wpa_ctrl.h" -SupplicantEvent::SupplicantEvent(char *event, size_t len) { - - if (event[0] == '<') { - char *match = strchr(event, '>'); - if (match) { - char tmp[16]; - - strncpy(tmp, &event[1], (match - event)); - mLevel = atoi(tmp); - event += (match - event) + 1; - } else - LOGW("Unclosed level brace in event"); - } else - LOGW("No level specified in event"); - - /* - * CTRL-EVENT-XXX - * ^ - * +---- event - */ - - if (!strncmp(event, WPA_EVENT_CONNECTED, strlen(WPA_EVENT_CONNECTED))) - mType = SupplicantEvent::EVENT_CONNECTED; - else if (!strncmp(event, WPA_EVENT_DISCONNECTED, strlen(WPA_EVENT_DISCONNECTED))) - mType = SupplicantEvent::EVENT_DISCONNECTED; - else if (!strncmp(event, WPA_EVENT_TERMINATING, strlen(WPA_EVENT_TERMINATING))) - mType = SupplicantEvent::EVENT_TERMINATING; - else if (!strncmp(event, WPA_EVENT_PASSWORD_CHANGED, strlen(WPA_EVENT_PASSWORD_CHANGED))) - mType = SupplicantEvent::EVENT_PASSWORD_CHANGED; - else if (!strncmp(event, WPA_EVENT_EAP_NOTIFICATION, strlen(WPA_EVENT_EAP_NOTIFICATION))) - mType = SupplicantEvent::EVENT_EAP_NOTIFICATION; - else if (!strncmp(event, WPA_EVENT_EAP_STARTED, strlen(WPA_EVENT_EAP_STARTED))) - mType = SupplicantEvent::EVENT_EAP_STARTED; - else if (!strncmp(event, WPA_EVENT_EAP_METHOD, strlen(WPA_EVENT_EAP_METHOD))) - mType = SupplicantEvent::EVENT_EAP_METHOD; - else if (!strncmp(event, WPA_EVENT_EAP_SUCCESS, strlen(WPA_EVENT_EAP_SUCCESS))) - mType = SupplicantEvent::EVENT_EAP_SUCCESS; - else if (!strncmp(event, WPA_EVENT_EAP_FAILURE, strlen(WPA_EVENT_EAP_FAILURE))) - mType = SupplicantEvent::EVENT_EAP_FAILURE; - else if (!strncmp(event, WPA_EVENT_SCAN_RESULTS, strlen(WPA_EVENT_SCAN_RESULTS))) - mType = SupplicantEvent::EVENT_SCAN_RESULTS; - else if (!strncmp(event, WPA_EVENT_STATE_CHANGE, strlen(WPA_EVENT_STATE_CHANGE))) - mType = SupplicantEvent::EVENT_STATE_CHANGE; - else if (!strncmp(event, WPA_EVENT_LINK_SPEED, strlen(WPA_EVENT_LINK_SPEED))) - mType = SupplicantEvent::EVENT_LINK_SPEED; - else if (!strncmp(event, WPA_EVENT_DRIVER_STATE, strlen(WPA_EVENT_DRIVER_STATE))) - mType = SupplicantEvent::EVENT_DRIVER_STATE; - else { - LOGW("Unknown supplicant event '%s'", event); - mType = SupplicantEvent::EVENT_UNKNOWN; - } - - for (event; *event != ' '; event++); - event++; - - /* - * CTRL-EVENT-XXX YYYY - * ^ - * +---- event - */ - - for (event; *event == ' '; event++); - - mEvent = strdup(event); - mLen = len; -} - -SupplicantEvent::~SupplicantEvent() { - if (mEvent) - free(mEvent); +SupplicantEvent::SupplicantEvent(int type, int level) { + mType = type; + mLevel = level; } diff --git a/nexus/SupplicantEvent.h b/nexus/SupplicantEvent.h index 2dc67225c..9d7cbd9f2 100644 --- a/nexus/SupplicantEvent.h +++ b/nexus/SupplicantEvent.h @@ -22,33 +22,32 @@ class SupplicantEvent { private: int mType; - char *mEvent; - size_t mLen; int mLevel; public: - static const int EVENT_UNKNOWN = 0; - static const int EVENT_CONNECTED = 1; - static const int EVENT_DISCONNECTED = 2; - static const int EVENT_TERMINATING = 3; - static const int EVENT_PASSWORD_CHANGED = 4; - static const int EVENT_EAP_NOTIFICATION = 5; - static const int EVENT_EAP_STARTED = 6; - static const int EVENT_EAP_METHOD = 7; - static const int EVENT_EAP_SUCCESS = 8; - static const int EVENT_EAP_FAILURE = 9; - static const int EVENT_SCAN_RESULTS = 10; - static const int EVENT_STATE_CHANGE = 11; - static const int EVENT_LINK_SPEED = 12; - static const int EVENT_DRIVER_STATE = 13; + static const int EVENT_UNKNOWN = 0; + static const int EVENT_CONNECTED = 1; + static const int EVENT_DISCONNECTED = 2; + static const int EVENT_TERMINATING = 3; + static const int EVENT_PASSWORD_CHANGED = 4; + static const int EVENT_EAP_NOTIFICATION = 5; + static const int EVENT_EAP_STARTED = 6; + static const int EVENT_EAP_METHOD = 7; + static const int EVENT_EAP_SUCCESS = 8; + static const int EVENT_EAP_FAILURE = 9; + static const int EVENT_SCAN_RESULTS = 10; + static const int EVENT_STATE_CHANGE = 11; + static const int EVENT_LINK_SPEED = 12; + static const int EVENT_DRIVER_STATE = 13; + static const int EVENT_ASSOCIATING = 14; + static const int EVENT_ASSOCIATED = 15; + static const int EVENT_CONNECTIONTIMEOUT = 16; public: - SupplicantEvent(char *event, size_t len); - virtual ~SupplicantEvent(); + SupplicantEvent(int type, int level); + virtual ~SupplicantEvent() {} int getType() { return mType; } - const char *getEvent() { return mEvent; } - int getLen() { return mLen; } int getLevel() { return mLevel; } }; diff --git a/nexus/SupplicantEventFactory.cpp b/nexus/SupplicantEventFactory.cpp new file mode 100644 index 000000000..8695aca19 --- /dev/null +++ b/nexus/SupplicantEventFactory.cpp @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#define LOG_TAG "SupplicantEventFactory" +#include + +#include "SupplicantEvent.h" +#include "SupplicantEventFactory.h" +#include "SupplicantAssociatingEvent.h" +#include "SupplicantAssociatedEvent.h" +#include "SupplicantConnectedEvent.h" +#include "SupplicantStateChangeEvent.h" +#include "SupplicantScanResultsEvent.h" +#include "SupplicantConnectionTimeoutEvent.h" +#include "SupplicantDisconnectedEvent.h" +#if 0 +#include "SupplicantTerminatingEvent.h" +#include "SupplicantPasswordChangedEvent.h" +#include "SupplicantEapNotificationEvent.h" +#include "SupplicantEapStartedEvent.h" +#include "SupplicantEapMethodEvent.h" +#include "SupplicantEapSuccessEvent.h" +#include "SupplicantEapFailureEvent.h" +#include "SupplicantLinkSpeedEvent.h" +#include "SupplicantDriverStateEvent.h" +#endif + +#include "libwpa_client/wpa_ctrl.h" + +SupplicantEventFactory::SupplicantEventFactory() { +} + +SupplicantEvent *SupplicantEventFactory::createEvent(char *event, size_t len) { + int level = 0; + + if (event[0] == '<') { + char *match = strchr(event, '>'); + if (match) { + char tmp[16]; + + strncpy(tmp, &event[1], (match - event)); + level = atoi(tmp); + event += (match - event) + 1; + } else + LOGW("Unclosed level brace in event"); + } else + LOGW("No level specified in event"); + + /* + * CTRL-EVENT-XXX + * ^ + * +---- event + */ + + if (!strncmp(event, "Authentication with ", 20)) { + if (!strcmp(event + strlen(event) - strlen(" timed out."), + " timed out.")) { + return new SupplicantConnectionTimeoutEvent(level, + event + 20, + len); + } else + return NULL; + + } else if (!strncmp(event, "Associated with ", 16)) + return new SupplicantAssociatedEvent(level, event + 16, len); + else if (!strncmp(event, "Trying to associate with ", 25)) + return new SupplicantAssociatingEvent(level, event + 25, len); + else if (!strncmp(event, WPA_EVENT_CONNECTED, strlen(WPA_EVENT_CONNECTED))) { + return new SupplicantConnectedEvent(level, + event + strlen(WPA_EVENT_CONNECTED), + len); + } else if (!strncmp(event, WPA_EVENT_SCAN_RESULTS, strlen(WPA_EVENT_SCAN_RESULTS))) { + return new SupplicantScanResultsEvent(level, + event + strlen(WPA_EVENT_SCAN_RESULTS), + len); + } else if (!strncmp(event, WPA_EVENT_STATE_CHANGE, strlen(WPA_EVENT_STATE_CHANGE))) { + return new SupplicantStateChangeEvent(level, + event + strlen(WPA_EVENT_STATE_CHANGE), + len); + } + else if (!strncmp(event, WPA_EVENT_DISCONNECTED, strlen(WPA_EVENT_DISCONNECTED))) + return new SupplicantDisconnectedEvent(level, event, len); +#if 0 + else if (!strncmp(event, WPA_EVENT_TERMINATING, strlen(WPA_EVENT_TERMINATING))) + return new SupplicantTerminatingEvent(event, len); + else if (!strncmp(event, WPA_EVENT_PASSWORD_CHANGED, strlen(WPA_EVENT_PASSWORD_CHANGED))) + return new SupplicantPasswordChangedEvent(event, len); + else if (!strncmp(event, WPA_EVENT_EAP_NOTIFICATION, strlen(WPA_EVENT_EAP_NOTIFICATION))) + return new SupplicantEapNotificationEvent(event, len); + else if (!strncmp(event, WPA_EVENT_EAP_STARTED, strlen(WPA_EVENT_EAP_STARTED))) + return new SupplicantEapStartedEvent(event, len); + else if (!strncmp(event, WPA_EVENT_EAP_METHOD, strlen(WPA_EVENT_EAP_METHOD))) + return new SupplicantEapMethodEvent(event, len); + else if (!strncmp(event, WPA_EVENT_EAP_SUCCESS, strlen(WPA_EVENT_EAP_SUCCESS))) + return new SupplicantEapSuccessEvent(event, len); + else if (!strncmp(event, WPA_EVENT_EAP_FAILURE, strlen(WPA_EVENT_EAP_FAILURE))) + return new SupplicantEapFailureEvent(event, len); + else if (!strncmp(event, WPA_EVENT_LINK_SPEED, strlen(WPA_EVENT_LINK_SPEED))) + return new SupplicantLinkSpeedEvent(event, len); + else if (!strncmp(event, WPA_EVENT_DRIVER_STATE, strlen(WPA_EVENT_DRIVER_STATE))) + return new SupplicantDriverStateEvent(event, len); +#endif + return NULL; +} diff --git a/nexus/SupplicantEventFactory.h b/nexus/SupplicantEventFactory.h new file mode 100644 index 000000000..22e5707e8 --- /dev/null +++ b/nexus/SupplicantEventFactory.h @@ -0,0 +1,31 @@ + +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SupplicantEventFactory_H +#define _SupplicantEventFactory_H + +class SupplicantEvent; + +class SupplicantEventFactory { +public: + SupplicantEventFactory(); + virtual ~SupplicantEventFactory() {} + + SupplicantEvent *createEvent(char *event, size_t len); +}; + +#endif diff --git a/nexus/SupplicantListener.cpp b/nexus/SupplicantListener.cpp index b94648b29..b91fc02db 100644 --- a/nexus/SupplicantListener.cpp +++ b/nexus/SupplicantListener.cpp @@ -24,14 +24,21 @@ #include "libwpa_client/wpa_ctrl.h" #include "SupplicantListener.h" -#include "SupplicantEvent.h" #include "ISupplicantEventHandler.h" +#include "SupplicantEventFactory.h" +#include "SupplicantEvent.h" +#include "SupplicantAssociatingEvent.h" +#include "SupplicantAssociatedEvent.h" +#include "SupplicantConnectedEvent.h" +#include "SupplicantScanResultsEvent.h" +#include "SupplicantStateChangeEvent.h" SupplicantListener::SupplicantListener(ISupplicantEventHandler *handlers, struct wpa_ctrl *monitor) : SocketListener(wpa_ctrl_get_fd(monitor), false) { mHandlers = handlers; mMonitor = monitor; + mFactory = new SupplicantEventFactory(); } bool SupplicantListener::onDataAvailable(SocketClient *cli) { @@ -53,44 +60,50 @@ bool SupplicantListener::onDataAvailable(SocketClient *cli) { return false; } - SupplicantEvent *evt = new SupplicantEvent(buf, nread); + SupplicantEvent *evt = mFactory->createEvent(buf, nread); - // XXX: Make this a factory - // XXX: Instead of calling Supplicant directly - // extract an Interface and use that instead - if (evt->getType() == SupplicantEvent::EVENT_CONNECTED) - rc = mHandlers->onConnectedEvent(evt); - else if (evt->getType() == SupplicantEvent::EVENT_DISCONNECTED) - rc = mHandlers->onDisconnectedEvent(evt); - else if (evt->getType() == SupplicantEvent::EVENT_TERMINATING) - rc = mHandlers->onTerminatingEvent(evt); - else if (evt->getType() == SupplicantEvent::EVENT_PASSWORD_CHANGED) - rc = mHandlers->onPasswordChangedEvent(evt); - else if (evt->getType() == SupplicantEvent::EVENT_EAP_NOTIFICATION) - rc = mHandlers->onEapNotificationEvent(evt); - else if (evt->getType() == SupplicantEvent::EVENT_EAP_STARTED) - rc = mHandlers->onEapStartedEvent(evt); - else if (evt->getType() == SupplicantEvent::EVENT_EAP_SUCCESS) - rc = mHandlers->onEapSuccessEvent(evt); - else if (evt->getType() == SupplicantEvent::EVENT_EAP_FAILURE) - rc = mHandlers->onEapFailureEvent(evt); - else if (evt->getType() == SupplicantEvent::EVENT_SCAN_RESULTS) - rc = mHandlers->onScanResultsEvent(evt); - else if (evt->getType() == SupplicantEvent::EVENT_STATE_CHANGE) - rc = mHandlers->onStateChangeEvent(evt); - else if (evt->getType() == SupplicantEvent::EVENT_LINK_SPEED) - rc = mHandlers->onLinkSpeedEvent(evt); - else if (evt->getType() == SupplicantEvent::EVENT_DRIVER_STATE) - rc = mHandlers->onDriverStateEvent(evt); - else { - LOGW("Ignoring unknown event"); + if (!evt) { + LOGW("Dropping unknown supplicant event '%s'", buf); + return true; } + // Call the appropriate handler + if (evt->getType() == SupplicantEvent::EVENT_ASSOCIATING) + mHandlers->onAssociatingEvent((SupplicantAssociatingEvent *) evt); + else if (evt->getType() == SupplicantEvent::EVENT_ASSOCIATED) + mHandlers->onAssociatedEvent((SupplicantAssociatedEvent *) evt); + else if (evt->getType() == SupplicantEvent::EVENT_CONNECTED) + mHandlers->onConnectedEvent((SupplicantConnectedEvent *) evt); + else if (evt->getType() == SupplicantEvent::EVENT_SCAN_RESULTS) + mHandlers->onScanResultsEvent((SupplicantScanResultsEvent *) evt); + else if (evt->getType() == SupplicantEvent::EVENT_STATE_CHANGE) + mHandlers->onStateChangeEvent((SupplicantStateChangeEvent *) evt); + else if (evt->getType() == SupplicantEvent::EVENT_CONNECTIONTIMEOUT) + mHandlers->onConnectionTimeoutEvent((SupplicantConnectionTimeoutEvent *) evt); + else if (evt->getType() == SupplicantEvent::EVENT_DISCONNECTED) + mHandlers->onDisconnectedEvent((SupplicantDisconnectedEvent *) evt); + else + LOGW("Whoops - no handler available for event '%s'\n", buf); +#if 0 + else if (evt->getType() == SupplicantEvent::EVENT_TERMINATING) + mHandlers->onTerminatingEvent(evt); + else if (evt->getType() == SupplicantEvent::EVENT_PASSWORD_CHANGED) + mHandlers->onPasswordChangedEvent(evt); + else if (evt->getType() == SupplicantEvent::EVENT_EAP_NOTIFICATION) + mHandlers->onEapNotificationEvent(evt); + else if (evt->getType() == SupplicantEvent::EVENT_EAP_STARTED) + mHandlers->onEapStartedEvent(evt); + else if (evt->getType() == SupplicantEvent::EVENT_EAP_SUCCESS) + mHandlers->onEapSuccessEvent(evt); + else if (evt->getType() == SupplicantEvent::EVENT_EAP_FAILURE) + mHandlers->onEapFailureEvent(evt); + else if (evt->getType() == SupplicantEvent::EVENT_LINK_SPEED) + mHandlers->onLinkSpeedEvent(evt); + else if (evt->getType() == SupplicantEvent::EVENT_DRIVER_STATE) + mHandlers->onDriverStateEvent(evt); +#endif + delete evt; - if (rc) { - LOGW("Handler %d (%s) error: %s", evt->getType(), evt->getEvent(), strerror(errno)); - return false; - } return true; } diff --git a/nexus/SupplicantListener.h b/nexus/SupplicantListener.h index 3d186adfa..a1da7734e 100644 --- a/nexus/SupplicantListener.h +++ b/nexus/SupplicantListener.h @@ -23,12 +23,13 @@ struct wpa_ctrl; class Supplicant; class SocketClient; class ISupplicantEventHandler; +class SupplicantEventFactory; class SupplicantListener: public SocketListener { -private: struct wpa_ctrl *mMonitor; ISupplicantEventHandler *mHandlers; - + SupplicantEventFactory *mFactory; + public: SupplicantListener(ISupplicantEventHandler *handlers, struct wpa_ctrl *monitor); diff --git a/nexus/SupplicantScanResultsEvent.cpp b/nexus/SupplicantScanResultsEvent.cpp new file mode 100644 index 000000000..c53adad2d --- /dev/null +++ b/nexus/SupplicantScanResultsEvent.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "SupplicantScanResultsEvent" +#include + +#include "SupplicantScanResultsEvent.h" + +SupplicantScanResultsEvent::SupplicantScanResultsEvent(int level, char *event, + size_t len) : + SupplicantEvent(SupplicantEvent::EVENT_SCAN_RESULTS, + level) { +} + +SupplicantScanResultsEvent::SupplicantScanResultsEvent() : + SupplicantEvent(SupplicantEvent::EVENT_SCAN_RESULTS, -1) { +} + +SupplicantScanResultsEvent::~SupplicantScanResultsEvent() { +} + diff --git a/nexus/SupplicantScanResultsEvent.h b/nexus/SupplicantScanResultsEvent.h new file mode 100644 index 000000000..5f82041f8 --- /dev/null +++ b/nexus/SupplicantScanResultsEvent.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SupplicantScanResultsEvent_H +#define _SupplicantScanResultsEvent_H + +#include "SupplicantEvent.h" + +class SupplicantScanResultsEvent : public SupplicantEvent { + +public: + SupplicantScanResultsEvent(int level, char *event, size_t len); + SupplicantScanResultsEvent(); + virtual ~SupplicantScanResultsEvent(); +}; + +#endif diff --git a/nexus/SupplicantStateChangeEvent.cpp b/nexus/SupplicantStateChangeEvent.cpp new file mode 100644 index 000000000..cf0b9daa6 --- /dev/null +++ b/nexus/SupplicantStateChangeEvent.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#define LOG_TAG "SupplicantStateChangeEvent" +#include + +#include "SupplicantStateChangeEvent.h" + +SupplicantStateChangeEvent::SupplicantStateChangeEvent(int level, char *event, + size_t len) : + SupplicantEvent(SupplicantEvent::EVENT_STATE_CHANGE, + level) { + // XXX: move this stuff into a static creation method + char *p = index(event, ' '); + if (!p) { + LOGW("Bad event '%s'\n", event); + return; + } + + mState = atoi(p + strlen("state=") + 1); +} + +SupplicantStateChangeEvent::SupplicantStateChangeEvent(int state) : + SupplicantEvent(SupplicantEvent::EVENT_STATE_CHANGE, -1) { + mState = state; +} + +SupplicantStateChangeEvent::~SupplicantStateChangeEvent() { +} + diff --git a/nexus/SupplicantStateChangeEvent.h b/nexus/SupplicantStateChangeEvent.h new file mode 100644 index 000000000..77bff654a --- /dev/null +++ b/nexus/SupplicantStateChangeEvent.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SupplicantStateChangeEvent_H +#define _SupplicantStateChangeEvent_H + +#include "SupplicantEvent.h" + +class SupplicantStateChangeEvent : public SupplicantEvent { +private: + int mState; + +public: + SupplicantStateChangeEvent(int level, char *event, size_t len); + SupplicantStateChangeEvent(int state); + virtual ~SupplicantStateChangeEvent(); + + int getState() { return mState; } +}; + +#endif diff --git a/nexus/SupplicantStatus.cpp b/nexus/SupplicantStatus.cpp new file mode 100644 index 000000000..87f6c98dc --- /dev/null +++ b/nexus/SupplicantStatus.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#define LOG_TAG "SupplicantState" +#include + +#include "SupplicantStatus.h" +#include "SupplicantState.h" + +SupplicantStatus::SupplicantStatus() { + mWpaState = SupplicantState::UNKNOWN; + mId = -1; + mBssid = NULL; + mSsid = NULL; +} + +SupplicantStatus::SupplicantStatus(int state, int id, char *bssid, char *ssid) : + mWpaState(state), mId(id), mBssid(bssid), mSsid(ssid) { + +LOGD("state %d, id %d, bssid %p, ssid %p\n", mWpaState, mId, mBssid, mSsid); +} + +SupplicantStatus::~SupplicantStatus() { + if (mBssid) + free(mBssid); + if (mSsid) + free(mSsid); +} + +SupplicantStatus *SupplicantStatus::createStatus(char *data, int len) { + char *bssid = NULL; + char *ssid = NULL; + int id = -1; + int state = SupplicantState::UNKNOWN; + + char *next = data; + char *line; + while((line = strsep(&next, "\n"))) { + char *token = strsep(&next, "="); + char *value = strsep(&next, "="); + + if (!strcmp(token, "bssid")) + bssid = strdup(value); + else if (!strcmp(token, "ssid")) + ssid = strdup(value); + else if (!strcmp(token, "id")) + id = atoi(value); + else if (!strcmp(token, "wpa_state")) + state = atoi(value); + else + LOGD("Ignoring unsupported status token '%s'", token); + } + + return new SupplicantStatus(state, id, bssid, ssid); + +} diff --git a/nexus/SupplicantStatus.h b/nexus/SupplicantStatus.h new file mode 100644 index 000000000..ef018410e --- /dev/null +++ b/nexus/SupplicantStatus.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SupplicantStatus_H +#define _SupplicantStatus_H + +class SupplicantStatus { +private: + int mWpaState; + int mId; + char *mBssid; + char *mSsid; + +private: + SupplicantStatus(); + SupplicantStatus(int state, int id, char *bssid, char *ssid); + +public: + virtual ~SupplicantStatus(); + static SupplicantStatus *createStatus(char *data, int len); + + int getWpaState() { return mWpaState; } + int getId() { return mId; } + const char *getBssid() { return mBssid; } + const char *getSsid() { return mSsid; } + +}; + +#endif diff --git a/nexus/TiwlanWifiController.cpp b/nexus/TiwlanWifiController.cpp index 307c48c0d..6945e3ea2 100644 --- a/nexus/TiwlanWifiController.cpp +++ b/nexus/TiwlanWifiController.cpp @@ -30,8 +30,12 @@ extern "C" int sched_yield(void); -TiwlanWifiController::TiwlanWifiController(PropertyManager *propmngr, char *modpath, char *modname, char *modargs) : - WifiController(propmngr, modpath, modname, modargs) { +TiwlanWifiController::TiwlanWifiController(PropertyManager *propmngr, + IControllerHandler *handlers, + char *modpath, char *modname, + char *modargs) : + WifiController(propmngr, handlers, modpath, modname, + modargs) { } int TiwlanWifiController::powerUp() { diff --git a/nexus/TiwlanWifiController.h b/nexus/TiwlanWifiController.h index d3ebe88fb..852a288b2 100644 --- a/nexus/TiwlanWifiController.h +++ b/nexus/TiwlanWifiController.h @@ -20,9 +20,11 @@ #include "PropertyManager.h" #include "WifiController.h" +class IControllerHandler; + class TiwlanWifiController : public WifiController { public: - TiwlanWifiController(PropertyManager *propmngr, char *modpath, char *modname, char *modargs); + TiwlanWifiController(PropertyManager *propmngr, IControllerHandler *handlers, char *modpath, char *modname, char *modargs); virtual ~TiwlanWifiController() {} virtual int powerUp(); diff --git a/nexus/VpnController.cpp b/nexus/VpnController.cpp index 1246703ab..add4dc39a 100644 --- a/nexus/VpnController.cpp +++ b/nexus/VpnController.cpp @@ -25,18 +25,19 @@ #include "PropertyManager.h" #include "VpnController.h" -VpnController::VpnController(PropertyManager *propmngr) : - Controller("VPN", propmngr) { +VpnController::VpnController(PropertyManager *propmngr, + IControllerHandler *handlers) : + Controller("VPN", propmngr, handlers) { mEnabled = false; - propmngr->registerProperty("vpn.enabled", this); - propmngr->registerProperty("vpn.gateway", this); } int VpnController::start() { + mPropMngr->registerProperty("vpn.enabled", this); return 0; } int VpnController::stop() { + mPropMngr->unregisterProperty("vpn.enabled"); return 0; } @@ -49,8 +50,13 @@ int VpnController::set(const char *name, const char *value) { return 0; rc = (en ? enable() : disable()); - if (!rc) + if (!rc) { mEnabled = en; + if (en) + mPropMngr->unregisterProperty("vpn.gateway"); + else + mPropMngr->unregisterProperty("vpn.gateway"); + } return rc; } if (!strcmp(name, "vpn.gateway")) { if (!inet_aton(value, &mVpnGateway)) { diff --git a/nexus/VpnController.h b/nexus/VpnController.h index b36856fa1..1af4d9fbc 100644 --- a/nexus/VpnController.h +++ b/nexus/VpnController.h @@ -21,6 +21,8 @@ #include "Controller.h" +class IControllerHandler; + class VpnController : public Controller { bool mEnabled; /* @@ -29,7 +31,7 @@ class VpnController : public Controller { struct in_addr mVpnGateway; public: - VpnController(PropertyManager *propmngr); + VpnController(PropertyManager *propmngr, IControllerHandler *handlers); virtual ~VpnController() {} virtual int start(); diff --git a/nexus/WifiController.cpp b/nexus/WifiController.cpp index 3d068061b..5c5db1a1d 100644 --- a/nexus/WifiController.cpp +++ b/nexus/WifiController.cpp @@ -27,34 +27,50 @@ #include "NetworkManager.h" #include "ErrorCode.h" #include "WifiNetwork.h" +#include "ISupplicantEventHandler.h" +#include "SupplicantState.h" +#include "SupplicantStatus.h" +#include "SupplicantAssociatingEvent.h" +#include "SupplicantAssociatedEvent.h" +#include "SupplicantConnectedEvent.h" +#include "SupplicantScanResultsEvent.h" +#include "SupplicantStateChangeEvent.h" +#include "SupplicantConnectionTimeoutEvent.h" +#include "SupplicantDisconnectedEvent.h" -WifiController::WifiController(PropertyManager *propmngr, char *modpath, char *modname, char *modargs) : - Controller("WIFI", propmngr) { +WifiController::WifiController(PropertyManager *mPropMngr, + IControllerHandler *handlers, + char *modpath, char *modname, char *modargs) : + Controller("WIFI", mPropMngr, handlers) { strncpy(mModulePath, modpath, sizeof(mModulePath)); strncpy(mModuleName, modname, sizeof(mModuleName)); strncpy(mModuleArgs, modargs, sizeof(mModuleArgs)); - mSupplicant = new Supplicant(this, propmngr); + mLatestScanResults = new ScanResultCollection(); + pthread_mutex_init(&mLatestScanResultsLock, NULL); + + mSupplicant = new Supplicant(this, this); mScanner = new WifiScanner(mSupplicant, 10); mCurrentScanMode = 0; mEnabled = false; - propmngr->registerProperty("wifi.enabled", this); + mSupplicantState = SupplicantState::UNKNOWN; } int WifiController::start() { + mPropMngr->registerProperty("wifi.enabled", this); return 0; } int WifiController::stop() { - errno = ENOSYS; - return -1; + mPropMngr->unregisterProperty("wifi.enabled"); + return 0; } int WifiController::enable() { if (!isPoweredUp()) { - sendStatusBroadcast("POWERING_UP"); + sendStatusBroadcast("Powering up WiFi hardware"); if (powerUp()) { LOGE("Powerup failed (%s)", strerror(errno)); return -1; @@ -62,7 +78,7 @@ int WifiController::enable() { } if (mModuleName[0] != '\0' && !isKernelModuleLoaded(mModuleName)) { - sendStatusBroadcast("LOADING_DRIVER"); + sendStatusBroadcast("Loading WiFi driver"); if (loadKernelModule(mModulePath, mModuleArgs)) { LOGE("Kernel module load failed (%s)", strerror(errno)); goto out_powerdown; @@ -70,7 +86,7 @@ int WifiController::enable() { } if (!isFirmwareLoaded()) { - sendStatusBroadcast("LOADING_FIRMWARE"); + sendStatusBroadcast("Loading WiFI firmware"); if (loadFirmware()) { LOGE("Firmware load failed (%s)", strerror(errno)); goto out_powerdown; @@ -78,7 +94,7 @@ int WifiController::enable() { } if (!mSupplicant->isStarted()) { - sendStatusBroadcast("STARTING_SUPPLICANT"); + sendStatusBroadcast("Starting WPA Supplicant"); if (mSupplicant->start()) { LOGE("Supplicant start failed (%s)", strerror(errno)); goto out_unloadmodule; @@ -93,6 +109,7 @@ int WifiController::enable() { if (mSupplicant->refreshNetworkList()) LOGW("Error getting list of networks (%s)", strerror(errno)); + mPropMngr->registerProperty("wifi.supplicant.state", this); mPropMngr->registerProperty("wifi.scanmode", this); mPropMngr->registerProperty("wifi.interface", this); @@ -121,8 +138,11 @@ void WifiController::sendStatusBroadcast(const char *msg) { int WifiController::disable() { mPropMngr->unregisterProperty("wifi.scanmode"); + mPropMngr->unregisterProperty("wifi.supplicant.state"); + mPropMngr->unregisterProperty("wifi.scanmode"); + if (mSupplicant->isStarted()) { - sendStatusBroadcast("STOPPING_SUPPLICANT"); + sendStatusBroadcast("Stopping WPA Supplicant"); if (mSupplicant->stop()) { LOGE("Supplicant stop failed (%s)", strerror(errno)); return -1; @@ -131,7 +151,7 @@ int WifiController::disable() { LOGW("disable(): Supplicant not running?"); if (mModuleName[0] != '\0' && isKernelModuleLoaded(mModuleName)) { - sendStatusBroadcast("UNLOADING_DRIVER"); + sendStatusBroadcast("Unloading WiFi driver"); if (unloadKernelModule(mModuleName)) { LOGE("Unable to unload module (%s)", strerror(errno)); return -1; @@ -139,7 +159,7 @@ int WifiController::disable() { } if (isPoweredUp()) { - sendStatusBroadcast("POWERING_DOWN"); + sendStatusBroadcast("Powering down WiFi hardware"); if (powerDown()) { LOGE("Powerdown failed (%s)", strerror(errno)); return -1; @@ -184,7 +204,15 @@ int WifiController::removeNetwork(int networkId) { } ScanResultCollection *WifiController::createScanResults() { - return mSupplicant->createLatestScanResults(); + ScanResultCollection *d = new ScanResultCollection(); + ScanResultCollection::iterator i; + + pthread_mutex_lock(&mLatestScanResultsLock); + for (i = mLatestScanResults->begin(); i != mLatestScanResults->end(); ++i) + d->push_back((*i)->clone()); + + pthread_mutex_unlock(&mLatestScanResultsLock); + return d; } WifiNetworkCollection *WifiController::createNetworkList() { @@ -207,7 +235,10 @@ int WifiController::set(const char *name, const char *value) { return -1; } else if (!strcmp(name, "wifi.scanmode")) return setScanMode((uint32_t) strtoul(value, NULL, 0)); - else + else if (!strcmp(name, "wifi.supplicant.state")) { + errno = EROFS; + return -1; + } else return Controller::set(name, value); return rc; } @@ -221,9 +252,158 @@ const char *WifiController::get(const char *name, char *buffer, size_t maxsize) (getBoundInterface() ? getBoundInterface() : "none")); } else if (!strcmp(name, "wifi.scanmode")) snprintf(buffer, maxsize, "0x%.8x", mCurrentScanMode); + else if (!strcmp(name, "wifi.supplicant.state")) + return SupplicantState::toString(mSupplicantState, buffer, maxsize); else return Controller::get(name, buffer, maxsize); return buffer; } +void WifiController::onAssociatingEvent(SupplicantAssociatingEvent *evt) { + LOGD("onAssociatingEvent(%s, %s, %d)", + (evt->getBssid() ? evt->getBssid() : "n/a"), + (evt->getSsid() ? evt->getSsid() : "n/a"), + evt->getFreq()); +} + +void WifiController::onAssociatedEvent(SupplicantAssociatedEvent *evt) { + LOGD("onAssociatedEvent(%s)", evt->getBssid()); +} + +void WifiController::onConnectedEvent(SupplicantConnectedEvent *evt) { + LOGD("onConnectedEvent(%s, %d)", evt->getBssid(), evt->getReassociated()); + if (!evt->getReassociated()) { + SupplicantStatus *ss = mSupplicant->getStatus(); + WifiNetwork *wn; + + if (ss->getWpaState() != SupplicantState::COMPLETED) { + char tmp[32]; + + LOGW("onConnected() with SupplicantState = %s!", + SupplicantState::toString(ss->getWpaState(), tmp, + sizeof(tmp))); + return; + } + + if (ss->getId() == -1) { + LOGW("onConnected() with id = -1!"); + return; + } + + if (!(wn = mSupplicant->lookupNetwork(ss->getId()))) { + LOGW("Error looking up connected network id %d (%s)", + ss->getId(), strerror(errno)); + return; + } + + delete ss; + mHandlers->onInterfaceStarted(this, wn->getIfaceCfg()); + } +} + +void WifiController::onScanResultsEvent(SupplicantScanResultsEvent *evt) { + char *reply; + + if (!(reply = (char *) malloc(4096))) { + LOGE("Out of memory"); + return; + } + + size_t len = 4096; + + if (mSupplicant->sendCommand("SCAN_RESULTS", reply, &len)) { + LOGW("onScanResultsEvent: Error getting scan results (%s)", + strerror(errno)); + free(reply); + return; + } + + pthread_mutex_lock(&mLatestScanResultsLock); + if (!mLatestScanResults->empty()) { + ScanResultCollection::iterator i; + + for (i = mLatestScanResults->begin(); + i !=mLatestScanResults->end(); ++i) { + delete *i; + } + mLatestScanResults->clear(); + } + + char *linep; + char *linep_next = NULL; + + if (!strtok_r(reply, "\n", &linep_next)) { + free(reply); + pthread_mutex_unlock(&mLatestScanResultsLock); + return; + } + + while((linep = strtok_r(NULL, "\n", &linep_next))) + mLatestScanResults->push_back(new ScanResult(linep)); + + char *tmp; + asprintf(&tmp, "Scan results ready (%d)", mLatestScanResults->size()); + NetworkManager::Instance()->getBroadcaster()-> + sendBroadcast(ErrorCode::UnsolicitedInformational, tmp, false); + free(tmp); + pthread_mutex_unlock(&mLatestScanResultsLock); + free(reply); +} + +void WifiController::onStateChangeEvent(SupplicantStateChangeEvent *evt) { + char tmp[32]; + char tmp2[32]; + + LOGD("onStateChangeEvent(%s -> %s)", + SupplicantState::toString(mSupplicantState, tmp, sizeof(tmp)), + SupplicantState::toString(evt->getState(), tmp2, sizeof(tmp2))); + + mSupplicantState = evt->getState(); +} + +void WifiController::onConnectionTimeoutEvent(SupplicantConnectionTimeoutEvent *evt) { + LOGD("onConnectionTimeoutEvent(%s)", evt->getBssid()); +} + +void WifiController::onDisconnectedEvent(SupplicantDisconnectedEvent *evt) { + LOGD("onDisconnectedEvent()"); +} + +#if 0 +void WifiController::onTerminatingEvent(SupplicantEvent *evt) { + LOGD("onTerminatingEvent(%s)", evt->getEvent()); +} + +void WifiController::onPasswordChangedEvent(SupplicantEvent *evt) { + LOGD("onPasswordChangedEvent(%s)", evt->getEvent()); +} + +void WifiController::onEapNotificationEvent(SupplicantEvent *evt) { + LOGD("onEapNotificationEvent(%s)", evt->getEvent()); +} + +void WifiController::onEapStartedEvent(SupplicantEvent *evt) { + LOGD("onEapStartedEvent(%s)", evt->getEvent()); +} + +void WifiController::onEapMethodEvent(SupplicantEvent *evt) { + LOGD("onEapMethodEvent(%s)", evt->getEvent()); +} + +void WifiController::onEapSuccessEvent(SupplicantEvent *evt) { + LOGD("onEapSuccessEvent(%s)", evt->getEvent()); +} + +void WifiController::onEapFailureEvent(SupplicantEvent *evt) { + LOGD("onEapFailureEvent(%s)", evt->getEvent()); +} + +void WifiController::onLinkSpeedEvent(SupplicantEvent *evt) { + LOGD("onLinkSpeedEvent(%s)", evt->getEvent()); +} + +void WifiController::onDriverStateEvent(SupplicantEvent *evt) { + LOGD("onDriverStateEvent(%s)", evt->getEvent()); +} +#endif diff --git a/nexus/WifiController.h b/nexus/WifiController.h index b2f453070..c61d97a5a 100644 --- a/nexus/WifiController.h +++ b/nexus/WifiController.h @@ -20,15 +20,21 @@ #include #include "Controller.h" +#include "ScanResult.h" +#include "WifiNetwork.h" +#include "ISupplicantEventHandler.h" class NetInterface; class Supplicant; class WifiScanner; +class SupplicantAssociatingEvent; +class SupplicantAssociatedEvent; +class SupplicantConnectedEvent; +class SupplicantScanResultsEvent; +class SupplicantStateChangeEvent; +class SupplicantDisconnectedEvent; -#include "ScanResult.h" -#include "WifiNetwork.h" - -class WifiController : public Controller { +class WifiController : public Controller, public ISupplicantEventHandler { public: static const uint32_t SCAN_ENABLE_MASK = 0x01; static const uint32_t SCAN_ACTIVE_MASK = 0x02; @@ -45,12 +51,18 @@ private: char mModulePath[255]; char mModuleName[64]; char mModuleArgs[255]; + uint32_t mCurrentScanMode; WifiScanner *mScanner; + int mSupplicantState; + + ScanResultCollection *mLatestScanResults; + pthread_mutex_t mLatestScanResultsLock; + bool mEnabled; public: - WifiController(PropertyManager *propmngr, char *modpath, char *modname, char *modargs); + WifiController(PropertyManager *propmngr, IControllerHandler *handlers, char *modpath, char *modname, char *modargs); virtual ~WifiController() {} int start(); @@ -85,6 +97,27 @@ private: int setScanMode(uint32_t mode); int enable(); int disable(); + + // ISupplicantEventHandler methods + virtual void onAssociatingEvent(SupplicantAssociatingEvent *evt); + virtual void onAssociatedEvent(SupplicantAssociatedEvent *evt); + virtual void onConnectedEvent(SupplicantConnectedEvent *evt); + virtual void onScanResultsEvent(SupplicantScanResultsEvent *evt); + virtual void onStateChangeEvent(SupplicantStateChangeEvent *evt); + virtual void onConnectionTimeoutEvent(SupplicantConnectionTimeoutEvent *evt); + virtual void onDisconnectedEvent(SupplicantDisconnectedEvent *evt); +#if 0 + virtual void onTerminatingEvent(SupplicantEvent *evt); + virtual void onPasswordChangedEvent(SupplicantEvent *evt); + virtual void onEapNotificationEvent(SupplicantEvent *evt); + virtual void onEapStartedEvent(SupplicantEvent *evt); + virtual void onEapMethodEvent(SupplicantEvent *evt); + virtual void onEapSuccessEvent(SupplicantEvent *evt); + virtual void onEapFailureEvent(SupplicantEvent *evt); + virtual void onLinkSpeedEvent(SupplicantEvent *evt); + virtual void onDriverStateEvent(SupplicantEvent *evt); +#endif + }; #endif diff --git a/nexus/WifiNetwork.cpp b/nexus/WifiNetwork.cpp index 818b91d95..7059bd04b 100644 --- a/nexus/WifiNetwork.cpp +++ b/nexus/WifiNetwork.cpp @@ -76,7 +76,7 @@ WifiNetwork::WifiNetwork(WifiController *c, Supplicant *suppl, const char *data) mDefaultKeyIndex = -1; mPriority = -1; mHiddenSsid = NULL; - mAllowedKeyManagement = 0; + mAllowedKeyManagement = KeyManagementMask::UNKNOWN; mAllowedProtocols = 0; mAllowedAuthAlgorithms = 0; mAllowedPairwiseCiphers = 0; @@ -94,8 +94,6 @@ WifiNetwork::WifiNetwork(WifiController *c, Supplicant *suppl, const char *data) asprintf(&tmp2, "wifi.net.%d", mNetid); mIfaceCfg = new InterfaceConfig(tmp2); free(tmp2); - - registerProperties(); free(tmp); } @@ -121,8 +119,6 @@ WifiNetwork::WifiNetwork(WifiController *c, Supplicant *suppl, int networkId) { asprintf(&tmp2, "wifi.net.%d", mNetid); mIfaceCfg = new InterfaceConfig(tmp2); free(tmp2); - - registerProperties(); } WifiNetwork *WifiNetwork::clone() { @@ -153,7 +149,6 @@ WifiNetwork *WifiNetwork::clone() { } WifiNetwork::~WifiNetwork() { - unregisterProperties(); if (mSsid) free(mSsid); if (mBssid) @@ -203,7 +198,26 @@ int WifiNetwork::refresh() { len = sizeof(buffer); if (mSuppl->getNetworkVar(mNetid, "key_mgmt", buffer, len)) { - // TODO + if (!strcmp(buffer, "NONE")) + setAllowedKeyManagement(KeyManagementMask::NONE); + else if (index(buffer, ' ')) { + char *next = buffer; + char *token; + uint32_t mask = 0; + + while((token = strsep(&next, " "))) { + if (!strcmp(token, "WPA-PSK")) + mask |= KeyManagementMask::WPA_PSK; + else if (!strcmp(token, "WPA-EAP")) + mask |= KeyManagementMask::WPA_EAP; + else if (!strcmp(token, "IEE8021X")) + mask |= KeyManagementMask::IEEE8021X; + else + LOGW("Unsupported key management scheme '%s'" , token); + } + setAllowedKeyManagement(mask); + } else + LOGE("Unsupported key management '%s'", buffer); } len = sizeof(buffer); @@ -273,7 +287,7 @@ int WifiNetwork::set(const char *name, const char *value) { while((v_token = strsep(&v_next, " "))) { if (!strcasecmp(v_token, "NONE")) { - mask = 0; + mask = KeyManagementMask::NONE; none = true; } else if (!none) { if (!strcasecmp(v_token, "WPA_PSK")) @@ -363,7 +377,29 @@ const char *WifiNetwork::get(const char *name, char *buffer, size_t maxsize) { snprintf(buffer, maxsize, "%d", getDefaultKeyIndex()); else if (!strcasecmp(fc, "pri")) snprintf(buffer, maxsize, "%d", getPriority()); - else if (!strcasecmp(fc, "hiddenssid")) { + else if (!strcasecmp(fc, "AllowedKeyManagement")) { + if (getAllowedKeyManagement() == KeyManagementMask::NONE) + strncpy(buffer, "NONE", maxsize); + else { + char tmp[80] = { '\0' }; + + if (getAllowedKeyManagement() & KeyManagementMask::WPA_PSK) + strcat(tmp, "WPA_PSK "); + if (getAllowedKeyManagement() & KeyManagementMask::WPA_EAP) + strcat(tmp, "WPA_EAP "); + if (getAllowedKeyManagement() & KeyManagementMask::IEEE8021X) + strcat(tmp, "IEEE8021X"); + if (tmp[0] == '\0') { + strncpy(buffer, "(internal error)", maxsize); + errno = ENOENT; + return NULL; + } + if (tmp[strlen(tmp)] == ' ') + tmp[strlen(tmp)] = '\0'; + + strncpy(buffer, tmp, maxsize); + } + } else if (!strcasecmp(fc, "hiddenssid")) { strncpy(buffer, getHiddenSsid() ? getHiddenSsid() : "none", maxsize); diff --git a/nexus/WifiNetwork.h b/nexus/WifiNetwork.h index 360ccc28c..c2f5d235a 100644 --- a/nexus/WifiNetwork.h +++ b/nexus/WifiNetwork.h @@ -157,8 +157,6 @@ private: private: WifiNetwork(); - int registerProperties(); - int unregisterProperties(); public: WifiNetwork(WifiController *c, Supplicant *suppl, int networkId); @@ -167,6 +165,8 @@ public: virtual ~WifiNetwork(); WifiNetwork *clone(); + int registerProperties(); + int unregisterProperties(); int getNetworkId() { return mNetid; } const char *getSsid() { return mSsid; } @@ -187,7 +187,7 @@ public: int set(const char *name, const char *value); const char *get(const char *name, char *buffer, size_t maxsize); -// InterfaceConfig *getIfaceCfg() { return mIfaceCfg; } + InterfaceConfig *getIfaceCfg() { return mIfaceCfg; } int setEnabled(bool enabled); int setSsid(const char *ssid); diff --git a/nexus/main.cpp b/nexus/main.cpp index e460d4209..936d33f65 100644 --- a/nexus/main.cpp +++ b/nexus/main.cpp @@ -40,10 +40,10 @@ int main() { nm->setBroadcaster((SocketListener *) cl); - nm->attachController(new LoopController(nm->getPropMngr())); - nm->attachController(new TiwlanWifiController(nm->getPropMngr(), "/system/lib/modules/wlan.ko", "wlan", "")); -// nm->attachController(new AndroidL2TPVpnController()); - nm->attachController(new OpenVpnController(nm->getPropMngr())); + nm->attachController(new LoopController(nm->getPropMngr(), nm)); + nm->attachController(new TiwlanWifiController(nm->getPropMngr(), nm, "/system/lib/modules/wlan.ko", "wlan", "")); +// nm->attachController(new AndroidL2TPVpnController(nm->getPropMngr(), nm)); + nm->attachController(new OpenVpnController(nm->getPropMngr(), nm)); if (NetworkManager::Instance()->run()) {