summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--adb/services.c58
-rw-r--r--include/private/android_filesystem_config.h6
-rw-r--r--include/private/pixelflinger/ggl_context.h2
-rw-r--r--include/sysutils/FrameworkCommand.h2
-rw-r--r--include/sysutils/FrameworkListener.h4
-rw-r--r--libacc/Android.mk30
-rw-r--r--libacc/acc.cpp1246
-rw-r--r--libacc/tests/Android.mk20
-rw-r--r--libacc/tests/data/constants.c30
-rw-r--r--libacc/tests/data/expr-ansi.c60
-rw-r--r--libacc/tests/data/expr2.c6
-rw-r--r--libacc/tests/data/locals.c71
-rw-r--r--libacc/tests/data/otcc-ansi.c25
-rw-r--r--libacc/tests/data/otcc.c2
-rw-r--r--libacc/tests/data/returnval-ansi.c3
-rw-r--r--libacc/tests/data/returnval.c3
-rw-r--r--libacc/tests/main.cpp26
-rwxr-xr-xlibacc/tests/testarm2
-rwxr-xr-xlibacc/tests/testlocal36
-rw-r--r--libsysutils/src/FrameworkCommand.cpp2
-rw-r--r--libsysutils/src/FrameworkListener.cpp30
-rw-r--r--libsysutils/src/SocketClient.cpp15
-rw-r--r--libsysutils/src/SocketListener.cpp1
-rw-r--r--logcat/event-log-tags6
-rw-r--r--nexus/Android.mk49
-rw-r--r--nexus/CommandListener.cpp60
-rw-r--r--nexus/CommandListener.h16
-rw-r--r--nexus/Controller.cpp4
-rw-r--r--nexus/Controller.h6
-rw-r--r--nexus/IControllerHandler.h30
-rw-r--r--nexus/ISupplicantEventHandler.h39
-rw-r--r--nexus/LoopController.cpp5
-rw-r--r--nexus/LoopController.h3
-rw-r--r--nexus/NetworkManager.cpp17
-rw-r--r--nexus/NetworkManager.h17
-rw-r--r--nexus/OpenVpnController.cpp9
-rw-r--r--nexus/OpenVpnController.h3
-rw-r--r--nexus/PropertyManager.cpp3
-rw-r--r--nexus/Supplicant.cpp280
-rw-r--r--nexus/Supplicant.h43
-rw-r--r--nexus/SupplicantAssociatedEvent.cpp40
-rw-r--r--nexus/SupplicantAssociatedEvent.h34
-rw-r--r--nexus/SupplicantAssociatingEvent.cpp99
-rw-r--r--nexus/SupplicantAssociatingEvent.h37
-rw-r--r--nexus/SupplicantConnectedEvent.cpp61
-rw-r--r--nexus/SupplicantConnectedEvent.h36
-rw-r--r--nexus/SupplicantConnectionTimeoutEvent.cpp36
-rw-r--r--nexus/SupplicantConnectionTimeoutEvent.h34
-rw-r--r--nexus/SupplicantDisconnectedEvent.cpp33
-rw-r--r--nexus/SupplicantDisconnectedEvent.h30
-rw-r--r--nexus/SupplicantEvent.cpp73
-rw-r--r--nexus/SupplicantEvent.h39
-rw-r--r--nexus/SupplicantEventFactory.cpp119
-rw-r--r--nexus/SupplicantEventFactory.h31
-rw-r--r--nexus/SupplicantListener.cpp67
-rw-r--r--nexus/SupplicantListener.h5
-rw-r--r--nexus/SupplicantScanResultsEvent.cpp34
-rw-r--r--nexus/SupplicantScanResultsEvent.h30
-rw-r--r--nexus/SupplicantStateChangeEvent.cpp45
-rw-r--r--nexus/SupplicantStateChangeEvent.h34
-rw-r--r--nexus/SupplicantStatus.cpp72
-rw-r--r--nexus/SupplicantStatus.h42
-rw-r--r--nexus/TiwlanWifiController.cpp8
-rw-r--r--nexus/TiwlanWifiController.h4
-rw-r--r--nexus/VpnController.cpp16
-rw-r--r--nexus/VpnController.h4
-rw-r--r--nexus/WifiController.cpp212
-rw-r--r--nexus/WifiController.h45
-rw-r--r--nexus/WifiNetwork.cpp54
-rw-r--r--nexus/WifiNetwork.h6
-rw-r--r--nexus/main.cpp8
-rw-r--r--nexus/nexctl.c132
-rw-r--r--rootdir/Android.mk8
-rwxr-xr-xrootdir/etc/ppp/ip-down13
-rwxr-xr-xrootdir/etc/ppp/ip-up47
-rwxr-xr-xrootdir/etc/ppp/peers/common10
-rw-r--r--rootdir/etc/racoon/racoon.conf35
-rw-r--r--rootdir/init.rc39
-rwxr-xr-xvold/format.c4
-rw-r--r--vold/logwrapper.c21
-rw-r--r--vold/logwrapper.h2
-rw-r--r--vold/volmgr_ext3.c2
-rw-r--r--vold/volmgr_vfat.c4
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]);
}