diff options
83 files changed, 3018 insertions, 957 deletions
diff --git a/adb/services.c b/adb/services.c index b99cca1..0a5edcf 100644 --- a/adb/services.c +++ b/adb/services.c @@ -33,10 +33,6 @@ # endif #endif -#ifndef HAVE_WIN32_PROC -#include <sys/poll.h> -#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); } diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h index a4351ac..1a14842 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, }, @@ -155,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/include/private/pixelflinger/ggl_context.h b/include/private/pixelflinger/ggl_context.h index 3a030c5..8a36fa9 100644 --- a/include/private/pixelflinger/ggl_context.h +++ b/include/private/pixelflinger/ggl_context.h @@ -21,8 +21,8 @@ #include <stddef.h> #include <string.h> #include <sys/types.h> +#include <endian.h> -#include <utils/Endian.h> #include <pixelflinger/pixelflinger.h> #include <private/pixelflinger/ggl_fixed.h> diff --git a/include/sysutils/FrameworkCommand.h b/include/sysutils/FrameworkCommand.h index 5b50247..6c1fca6 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 8a83c33..4e3d396 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/libacc/Android.mk b/libacc/Android.mk index 77c71c6..f77e2b3 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 @@ -12,8 +11,29 @@ ifeq ($(TARGET_ARCH),arm) LOCAL_SRC_FILES += disassem.cpp endif -LOCAL_SHARED_LIBRARIES := libdl +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 + +LOCAL_CFLAGS := -O0 -g + +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 de36ce5..7d14e3f 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -10,12 +10,17 @@ #include <ctype.h> #include <dlfcn.h> -#include <setjmp.h> +#include <errno.h> #include <stdarg.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <cutils/hashmap.h> + +#if defined(__i386__) +#include <sys/mman.h> +#endif #if defined(__arm__) #include <unistd.h> @@ -43,6 +48,8 @@ // #define LOG_API(...) fprintf (stderr, __VA_ARGS__) // #define ENABLE_ARM_DISASSEMBLY +// #define PROVIDE_TRACE_CODEGEN + namespace acc { class ErrorSink { @@ -63,6 +70,7 @@ class Compiler : public ErrorSink { char* pProgramBase; ErrorSink* mErrorSink; int mSize; + bool mOverflowed; void release() { if (pProgramBase != 0) { @@ -71,13 +79,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: @@ -86,6 +97,7 @@ class Compiler : public ErrorSink { ind = 0; mErrorSink = 0; mSize = 0; + mOverflowed = false; } ~CodeBuf() { @@ -104,7 +116,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; @@ -115,7 +129,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; } @@ -166,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); @@ -988,7 +1004,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: @@ -1024,18 +1047,184 @@ 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]; } void gmov(int l, int t) { o(l + 0x83); - oad((t < LOCAL) << 7 | 5, t); + oad((t > -LOCAL && t < LOCAL) << 7 | 5, t); } }; #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() { @@ -1086,27 +1275,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; - void* pSymbolBase; - char* pGlobalBase; - char* pVarsBase; // Value of variables - - InputStream* file; - - CodeBuf codeBuf; - CodeGenerator* pGen; - class String { public: String() { @@ -1115,18 +1283,57 @@ class Compiler : public ErrorSink { mSize = 0; } + String(const char* item, int len, bool adopt) { + if (len < 0) { + len = strlen(item); + } + if (adopt) { + mpBase = (char*) item; + mUsed = len; + mSize = len + 1; + } else { + mpBase = 0; + mUsed = 0; + mSize = 0; + appendBytes(item, len); + } + } + + String(const String& other) { + mpBase = 0; + mUsed = 0; + mSize = 0; + appendBytes(other.getUnwrapped(), other.len()); + } + ~String() { if (mpBase) { free(mpBase); } } - char* getUnwrapped() { + String& operator=(const String& other) { + clear(); + appendBytes(other.getUnwrapped(), other.len()); + return *this; + } + + inline char* getUnwrapped() const { return mpBase; } + void clear() { + mUsed = 0; + if (mSize > 0) { + mpBase[0] = 0; + } + } + 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 +1341,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 +1363,7 @@ class Compiler : public ErrorSink { free(temp); } - size_t len() { + inline size_t len() const { return mUsed; } @@ -1174,33 +1389,433 @@ class Compiler : public ErrorSink { size_t mSize; }; - String mErrorBuf; + /** + * Wrap an externally allocated string for use as a hash key. + */ + class FakeString : public String { + public: + FakeString(const char* string, size_t length) : + String((char*) string, length, true) {} + + ~FakeString() { + orphan(); + } + }; + + template<class V> class StringTable { + public: + StringTable() { + init(10); + } + + StringTable(size_t initialCapacity) { + init(initialCapacity); + } + + ~StringTable() { + clear(); + hashmapFree(mpMap); + } + + 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; + } - jmp_buf mErrorRecoveryJumpBuf; + 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; + } + + 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) { + mpMap = hashmapCreate(initialCapacity, hashFn, equalsFn); + } + + 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<String> { + public: + MacroTable() : StringTable<String>(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); + // 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); + + 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() { + hashmapFree(mpMap); + } + + int get(String* key) { + return (int) hashmapGet(mpMap, key->getUnwrapped()); + } + + 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 E> class Array { + public: + Array() { + mpBase = 0; + mUsed = 0; + mSize = 0; + } + + ~Array() { + if (mpBase) { + free(mpBase); + } + } + + E get(int i) { + if (i < 0 || i > (int) 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; + } else { + // error("internal error: Popped empty stack."); + } + } + + 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; + }; + + struct InputState { + InputStream* pStream; + int oldCh; + }; + + struct VariableInfo { + VariableInfo() { + pAddress = 0; + pForward = 0; + } + void* pAddress; + void* pForward; // For a forward direction, linked list of data to fix up + }; + + typedef StringTable<VariableInfo> 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); + } + + 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); +#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<Entry> mStack; + }; + + 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 + 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* pGlobalBase; + KeywordTable mKeywords; + SymbolStack mSymbolTable; + InputStream* file; + + CodeBuf codeBuf; + CodeGenerator* pGen; + + MacroTable mMacros; + Array<InputState> mInputStateStack; + + String mErrorBuf; String mPragmas; int mPragmaStringCount; 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; - 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; + 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; + static const int TOK_UNSUPPORTED_KEYWORD = TOK_KEYWORD + 0xff; + + 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 LOCAL = 0x200; static const int SYM_FORWARD = 0; @@ -1208,7 +1823,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; @@ -1242,16 +1856,13 @@ class Compiler : public ErrorSink { static const char operatorLevel[]; void pdef(int t) { - if (dstk - sym_stk >= ALLOC_SIZE) { - error("Symbol table exhausted"); - } - *dstk++ = t; + mTokenString.append(t); } void inp() { if (dptr) { ch = *dptr++; - if (ch == TAG_MACRO) { + if (ch == 0) { dptr = 0; ch = dch; } @@ -1266,13 +1877,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() { @@ -1283,22 +1973,13 @@ 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 { - error("Unsupported preprocessor directive \"%s\"", last_id); + error("Unsupported preprocessor directive \"%s\"", + mTokenString.getUnwrapped()); } - } inp(); } @@ -1306,37 +1987,35 @@ 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"); - } - * 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(); + // Is this a macro? + String* pValue = mMacros.get(&mTokenString); + if (pValue) { + // Yes, it is a macro + dptr = pValue->getUnwrapped(); + dch = ch; + inp(); + next(); + } else { + // Is this a keyword? + int kwtok = mKeywords.get(&mTokenString); + if (kwtok) { + tok = kwtok; + // fprintf(stderr, "tok= keyword %s %x\n", last_id, tok); + } else { + tok = (intptr_t) mSymbolTable.get(&mTokenString); + if (!tok) { + tok = TOK_UNDEFINED_SYMBOL; + } + // fprintf(stderr, "tok= symbol %s %x\n", last_id, tok); } } } @@ -1344,24 +2023,29 @@ 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) { - 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(); @@ -1394,15 +2078,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"); @@ -1415,6 +2103,31 @@ 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"); + return; + } + 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; @@ -1463,7 +2176,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) { @@ -1477,15 +2189,16 @@ 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 */ + 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 */ @@ -1496,6 +2209,7 @@ class Compiler : public ErrorSink { c = tokl; a = tokc; t = tok; + tString = mTokenString; next(); if (t == TOK_NUM) { pGen->li(a); @@ -1538,11 +2252,23 @@ class Compiler : public ErrorSink { } else if (t == '&') { pGen->leaR0(*(int *) tok); next(); + } else if (t == EOF ) { + error("Unexpected EOF."); + } else if (!checkSymbol(t, &tString)) { + // Don't have to do anything special here, the error + // message was printed by checkSymbol() above. } else { - n = *(int *) t; + if (t == TOK_UNDEFINED_SYMBOL) { + t = (intptr_t) mSymbolTable.addGlobal( + new String(tString)); + } + + n = (intptr_t) ((VariableInfo*) t)->pAddress; /* forward reference: try dlsym */ if (!n) { - n = (intptr_t) dlsym(RTLD_DEFAULT, last_id); + n = (intptr_t) dlsym(RTLD_DEFAULT, + tString.getUnwrapped()); + ((VariableInfo*) t)->pAddress = (void*) n; } if ((tok == '=') & l) { /* assignment */ @@ -1551,6 +2277,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(); @@ -1568,7 +2297,7 @@ class Compiler : public ErrorSink { a = pGen->beginFunctionCallArguments(); next(); l = 0; - while (tok != ')') { + while (tok != ')' && tok != EOF) { expr(); pGen->storeR0ToArg(l); if (tok == ',') @@ -1576,7 +2305,7 @@ class Compiler : public ErrorSink { l = l + 4; } pGen->endFunctionCallArguments(a, l); - next(); + skip(')'); if (!n) { /* forward reference */ t = t + 4; @@ -1639,20 +2368,23 @@ 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) { + if (tok == TOK_INT || tok == TOK_CHAR) { + /* declarations */ + localDeclarations(); + } else if (tok == TOK_IF) { next(); 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 */ @@ -1682,16 +2414,20 @@ 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 == '{') { + if (! outermostFunctionBlock) { + mSymbolTable.pushLevel(); + } next(); - /* declarations */ - localDeclarations(); - while (tok != '}') - block(l); - next(); + while (tok != '}' && tok != EOF) + block(l, false); + skip('}'); + if (! outermostFunctionBlock) { + mSymbolTable.popLevel(); + } } else { if (tok == TOK_RETURN) { next(); @@ -1765,24 +2501,47 @@ class Compiler : public ErrorSink { } } - void checkSymbol() { - if (tok <= TOK_DEFINE) { - error("Expected a symbol"); + void addGlobalSymbol() { + tok = (intptr_t) mSymbolTable.addGlobal( + new String(mTokenString)); + reportIfDuplicate(); + } + + void reportIfDuplicate() { + if (!tok) { + error("Duplicate definition of %s", mTokenString.getUnwrapped()); } } + void addLocalSymbol() { + tok = (intptr_t) mSymbolTable.addLocal( + new String(mTokenString)); + reportIfDuplicate(); + } + void localDeclarations() { intptr_t a; Type base; while (acceptType(base)) { - while (tok != ';') { + while (tok != ';' && tok != EOF) { Type t = acceptPointerDeclaration(t); - checkSymbol(); - loc = loc + 4; - *(int *) tok = -loc; - + int variableAddress = 0; + if (checkSymbol()) { + addLocalSymbol(); + if (tok) { + loc = loc + 4; + variableAddress = -loc; + ((VariableInfo*) tok)->pAddress = (void*) variableAddress; + } + } next(); + if (tok == '=') { + /* assignment */ + next(); + expr(); + pGen->storeR0(variableAddress); + } if (tok == ',') next(); } @@ -1790,56 +2549,112 @@ class Compiler : public ErrorSink { } } + bool checkSymbol() { + return checkSymbol(tok, &mTokenString); + } + + bool checkSymbol(int token, String* pText) { + bool result = token < EOF || token >= TOK_UNDEFINED_SYMBOL; + if (!result) { + String temp; + if (token == EOF ) { + temp.printf("EOF"); + } else if (token == TOK_NUM) { + temp.printf("numeric constant"); + } 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\"", + pText->getUnwrapped()); + } + error("Expected symbol. Got %s", temp.getUnwrapped()); + } + return result; + } + void globalDeclarations() { while (tok != EOF) { Type base; expectType(base); Type t = acceptPointerDeclaration(t); - checkSymbol(); - int name = tok; + if (tok >= 0 && tok < TOK_UNDEFINED_SYMBOL) { + error("Unexpected token %d", tok); + break; + } + 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 == ';') { + if (tok == ',' || tok == ';' || tok == '=') { // it's a variable declaration for(;;) { - *(int* *) name = (int*) allocGlobalSpace(4); + 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; } - next(); + skip(','); t = acceptPointerDeclaration(t); - checkSymbol(); - name = tok; + addGlobalSymbol(); + name = (VariableInfo*) tok; next(); } skip(';'); } else { - /* patch forward references (XXX: does not work for function - pointers) */ - pGen->gsym(*(int *) (name + 4)); - /* put function address */ - *(int *) name = 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; int argCount = 0; - while (tok != ')') { + while (tok != ')' && tok != EOF) { Type aType; expectType(aType); aType = acceptPointerDeclaration(aType); - checkSymbol(); - /* 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 == ',') next(); argCount++; } - skip(')'); /* skip ')' */ + skip(')'); rsym = loc = 0; a = pGen->functionEntry(argCount); - block(0); + block(0, true); pGen->gsym(rsym); pGen->functionExit(argCount, a, loc); + mSymbolTable.popLevel(); } } } @@ -1847,6 +2662,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; @@ -1854,18 +2670,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; @@ -1881,18 +2689,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; } @@ -1926,8 +2729,9 @@ class Compiler : public ErrorSink { } if (pGen == NULL) { error("No code generator defined."); + } else { + pGen->setErrorSink(this); } - pGen->setErrorSink(this); } public: @@ -1948,42 +2752,54 @@ 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; - } - 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(); - pGen->finishCompile(); + + cleanup(); + clear(); + codeBuf.init(ALLOC_SIZE); + setArchitecture(NULL); + 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); + glo = pGlobalBase; + inp(); + next(); + globalDeclarations(); + checkForUndefinedForwardReferences(); + result = pGen->finishCompile(); + if (result == 0) { + if (mErrorBuf.len()) { + result = -2; + } } 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; + 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 aMain(argc, argv); + return true; } int dump(FILE* out) { @@ -1999,30 +2815,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 * 8 + TOK_IDENT; - if (tok <= TOK_DEFINE) { - return 0; - } else { - tok = (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 2cff9d3..f8907b4 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,23 @@ 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_CFLAGS := -O0 -g + LOCAL_MODULE_TAGS := tests include $(BUILD_EXECUTABLE) - diff --git a/libacc/tests/data/constants.c b/libacc/tests/data/constants.c new file mode 100644 index 0000000..230109a --- /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'); +} diff --git a/libacc/tests/data/expr-ansi.c b/libacc/tests/data/expr-ansi.c new file mode 100644 index 0000000..d463659 --- /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 0000000..04b6a38 --- /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 0000000..f1ef363 --- /dev/null +++ b/libacc/tests/data/locals.c @@ -0,0 +1,71 @@ +int a; + +int f() { + int a; + // 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); +} + +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); +} + +// Already defined global +// int h() {} +int globCheck() { + fprintf(stdout, "globCheck()\n"); +} + +int fwdCheck() { + b(); + // Undefined forward reference + // c(); +} + +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(); + 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); + nested(); + printf("main 5: a = %d\n", a); + return 0; +} diff --git a/libacc/tests/data/otcc-ansi.c b/libacc/tests/data/otcc-ansi.c index 069514b..72580e9 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,11 +432,20 @@ 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; 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); @@ -445,5 +454,13 @@ int main(int g, int e) { o(); ad(); ab(0); - return (*(int(*)()) *(int*) (P + 592))(g, e); + if (mprotect(ac & (~ 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 577fcf3..433ae2e 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 42802c5..6b53fd5 100644 --- a/libacc/tests/data/returnval-ansi.c +++ b/libacc/tests/data/returnval-ansi.c @@ -1,7 +1,8 @@ + int main(int argc, char** argv) { return f(); } int f() { - return 10; + return 42; } diff --git a/libacc/tests/data/returnval.c b/libacc/tests/data/returnval.c index 1b9dd81..1cf5bae 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/main.cpp b/libacc/tests/main.cpp index acee09d..4f8a65d 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; @@ -105,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) { - 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: diff --git a/libacc/tests/testarm b/libacc/tests/testarm index 24fbc42..1d4b866 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 ccabf7d..1a0b4c5 100755 --- a/libacc/tests/testlocal +++ b/libacc/tests/testlocal @@ -1,17 +1,23 @@ -#!/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 +ACC=`which acc` + +echo "Compiling returnval-ansi.c" +$ACC -S $DATA/returnval-ansi.c + +echo "Compiling whole compiler." +$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 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 + +echo "Done with tests." diff --git a/libsysutils/src/FrameworkCommand.cpp b/libsysutils/src/FrameworkCommand.cpp index 94e7426..c52eac7 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 e8ae847..e9ca897 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 (!index(data, '"')) { + char *next = data; + char *field; + int i; - if (!(cm = strsep(&next, ":"))) { - cli->sendMsg(500, "Malformatted message", false); + 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 f0e846f..857ed4d 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 1f80121..1a937c2 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; diff --git a/logcat/event-log-tags b/logcat/event-log-tags index f9355ec..13f7488 100644 --- a/logcat/event-log-tags +++ b/logcat/event-log-tags @@ -350,3 +350,9 @@ # 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) + +# 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. diff --git a/nexus/Android.mk b/nexus/Android.mk index bd4e3d4..6172e62 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 e8de7f5..8eb378b 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<char *> *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 b57c25f..30c6dc0 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 9d4ff3c..17fb519 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 9137f9a..af03d2e 100644 --- a/nexus/Controller.h +++ b/nexus/Controller.h @@ -23,12 +23,12 @@ #include <utils/List.h> 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 0000000..92d015f --- /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 7e1bd5a..b7fd17b 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 a86202a..5cfb1fe 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 bb8314f..53d16f1 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 f4ae88f..2f13a40 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 e75382d..edc80c9 100644 --- a/nexus/NetworkManager.h +++ b/nexus/NetworkManager.h @@ -20,12 +20,12 @@ #include <sysutils/SocketListener.h> #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 4c144a4..f1ea510 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 323c44c..529aab5 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 3366bab..6faf9b8 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 e69f2c0..9bb6bf2 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(); - } + free(reply); + errno = EIO; + return -1; + } - 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()); + 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)); + } } + } - LOGD("Loaded %d networks\n", mNetworks->size()); - pthread_mutex_unlock(&mNetworksLock); + 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 42f2f79..3efbe4c 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 <pthread.h> -#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 0000000..e40411e --- /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 <stdlib.h> + +#define LOG_TAG "SupplicantAssociatedEvent" +#include <cutils/log.h> + +#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 0000000..aa33c59 --- /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 0000000..00a85b6 --- /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 <stdlib.h> + +#define LOG_TAG "SupplicantAssociatingEvent" +#include <cutils/log.h> + +#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 0000000..d3a4d5c --- /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 0000000..e58bab2 --- /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 <cutils/log.h> + +#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 0000000..03e9842 --- /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 0000000..8b8a7d7 --- /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 <cutils/log.h> + +#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 0000000..0d2606d --- /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 0000000..11e499d --- /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 <cutils/log.h> + +#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 0000000..c09ec62 --- /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 2e6d665..faf7b45 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"); - - /* - * <N>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++; - - /* - * <N>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 2dc6722..9d7cbd9 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 0000000..8695aca --- /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 <stdlib.h> + +#define LOG_TAG "SupplicantEventFactory" +#include <cutils/log.h> + +#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"); + + /* + * <N>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 0000000..22e5707 --- /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 b94648b..b91fc02 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); + + if (!evt) { + LOGW("Dropping unknown supplicant event '%s'", buf); + return true; + } - // 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); + // 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) - rc = mHandlers->onDisconnectedEvent(evt); + mHandlers->onDisconnectedEvent((SupplicantDisconnectedEvent *) evt); + else + LOGW("Whoops - no handler available for event '%s'\n", buf); +#if 0 else if (evt->getType() == SupplicantEvent::EVENT_TERMINATING) - rc = mHandlers->onTerminatingEvent(evt); + mHandlers->onTerminatingEvent(evt); else if (evt->getType() == SupplicantEvent::EVENT_PASSWORD_CHANGED) - rc = mHandlers->onPasswordChangedEvent(evt); + mHandlers->onPasswordChangedEvent(evt); else if (evt->getType() == SupplicantEvent::EVENT_EAP_NOTIFICATION) - rc = mHandlers->onEapNotificationEvent(evt); + mHandlers->onEapNotificationEvent(evt); else if (evt->getType() == SupplicantEvent::EVENT_EAP_STARTED) - rc = mHandlers->onEapStartedEvent(evt); + mHandlers->onEapStartedEvent(evt); else if (evt->getType() == SupplicantEvent::EVENT_EAP_SUCCESS) - rc = mHandlers->onEapSuccessEvent(evt); + 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); + mHandlers->onEapFailureEvent(evt); else if (evt->getType() == SupplicantEvent::EVENT_LINK_SPEED) - rc = mHandlers->onLinkSpeedEvent(evt); + mHandlers->onLinkSpeedEvent(evt); else if (evt->getType() == SupplicantEvent::EVENT_DRIVER_STATE) - rc = mHandlers->onDriverStateEvent(evt); - else { - LOGW("Ignoring unknown event"); - } + 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 3d186ad..a1da773 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 0000000..c53adad --- /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 <cutils/log.h> + +#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 0000000..5f82041 --- /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 0000000..cf0b9da --- /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 <stdlib.h> + +#define LOG_TAG "SupplicantStateChangeEvent" +#include <cutils/log.h> + +#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 0000000..77bff65 --- /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 0000000..87f6c98 --- /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 <stdlib.h> +#include <string.h> + +#define LOG_TAG "SupplicantState" +#include <cutils/log.h> + +#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 0000000..ef01841 --- /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 307c48c..6945e3e 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 d3ebe88..852a288 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 1246703..add4dc3 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 b36856f..1af4d9f 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 3d06806..5c5db1a 100644 --- a/nexus/WifiController.cpp +++ b/nexus/WifiController.cpp @@ -27,34 +27,50 @@ #include "NetworkManager.h" #include "ErrorCode.h" #include "WifiNetwork.h" - -WifiController::WifiController(PropertyManager *propmngr, char *modpath, char *modname, char *modargs) : - Controller("WIFI", propmngr) { +#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 *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 b2f4530..c61d97a 100644 --- a/nexus/WifiController.h +++ b/nexus/WifiController.h @@ -20,15 +20,21 @@ #include <sys/types.h> #include "Controller.h" +#include "ScanResult.h" +#include "WifiNetwork.h" +#include "ISupplicantEventHandler.h" class NetInterface; class Supplicant; class WifiScanner; - -#include "ScanResult.h" -#include "WifiNetwork.h" - -class WifiController : public Controller { +class SupplicantAssociatingEvent; +class SupplicantAssociatedEvent; +class SupplicantConnectedEvent; +class SupplicantScanResultsEvent; +class SupplicantStateChangeEvent; +class SupplicantDisconnectedEvent; + +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 818b91d..7059bd0 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 360ccc2..c2f5d23 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 e460d42..936d33f 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()) { diff --git a/nexus/nexctl.c b/nexus/nexctl.c index cfebbf0..8e1d90c 100644 --- a/nexus/nexctl.c +++ b/nexus/nexctl.c @@ -29,25 +29,59 @@ #include <sys/un.h> #include <cutils/sockets.h> - #include <private/android_filesystem_config.h> +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); + } + + if (!strcmp(argv[1], "monitor")) + exit(do_monitor(sock, 0)); + exit(do_cmd(sock, argc, argv)); +} + +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; } - printf("Connected to nexus\n"); + return do_monitor(sock, 1); +} - char line[255]; +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); - } - - printf("%s", buffer); - printf("-> "); - for (i = 0; i < cursor; i++) { - fprintf(stdout, "%c", line[i]); + 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; } - fflush(stdout); - } else if (FD_ISSET(0, &read_fds)) { - char c; - - 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); - } - - 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); + + int offset = 0; + int i = 0; + + for (i = 0; i < rc; i++) { + if (buffer[i] == '\0') { + int code; + char tmp[4]; + + strncpy(tmp, buffer + offset, 3); + tmp[3] = '\0'; + code = atoi(tmp); + + 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++; } } } + free(buffer); + return 0; +} - exit(0); +static void usage(char *progname) { + fprintf(stderr, "Usage: %s <monitor>|<cmd> [arg1] [arg2...]\n", progname); + exit(1); } + diff --git a/rootdir/Android.mk b/rootdir/Android.mk index b2fe8cf..44e343c 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 672fa1e..58d21e5 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 cb2d577..8c8f12c 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 0000000..4183841 --- /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 0000000..eb50a2d --- /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; + } +} + diff --git a/rootdir/init.rc b/rootdir/init.rc index 9853cc6..cf7d885 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 @@ -50,11 +51,11 @@ 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 - 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 @@ -73,7 +74,10 @@ 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 mkdir /data/local 0771 shell shell mkdir /data/local/tmp 0771 shell shell mkdir /data/data 0771 system system @@ -105,14 +109,12 @@ 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 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 +125,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 @@ -252,16 +255,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 @@ -282,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 + diff --git a/vold/format.c b/vold/format.c index 3383949..a1faf7a 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 2900f2e..46f6ed3 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 602e24c..bf28aae 100644 --- a/vold/logwrapper.h +++ b/vold/logwrapper.h @@ -19,5 +19,5 @@ #define _LOGWRAPPER_H #include <stdlib.h> -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 680be21..fe3b2bb 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 2b0e1fa..7833222 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]); } |