📄 bthandler.c
字号:
#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/wait.h>#include "btdefines.h"#include "bthandler.h"#include "btutils.h"//PLEASECHECK (Victor): should be included from btutils.h#include "gotype.h"#ifdef ENABLE_DEBUG_LOG#define STATE2STR(state) state2str(state)#define ERROR2STR(error) error2str(error)#define UPDATE_STATE(state, newstate) {DEBUG_LOG2("state %s -> %s", STATE2STR(state), STATE2STR(newstate)); state = newstate;}/* Debug buffer */#define BT_DBGBUF_LEN 4096static char dbgbuf[BT_DBGBUF_LEN];#else //ENABLE_DEBUG_LOG#define STATE2STR(state) "DEBUG DISABLED"#define ERROR2STR(error) "DEBUG DISABLED"#define UPDATE_STATE(state, newstate) {state = newstate;}#endif //ENABLE_DEBUG_LOG#define INIT_LISTEN_TIMER(c, t) {BTSetTimer(&c->listentotaltr, t);BTSetTimer(&c->listenretrytr, 0);}#define INIT_CONNECT_TIMER(c, t) {BTSetTimer(&c->connecttotaltr, t);BTSetTimer(&c->connectretrytr, 0);}int BTHandlerCompare(cBTConnection con, const char *bdaddr, int chan, int profile, int *res){ int res1, res2; if (!con || !bdaddr || !res) return BT_ERR_ARGUMENT; res1 = BTSocketCompare(con->sock, bdaddr, chan, &res2); if (res1 != BT_ERR_NONE) return res1; res1 = (con->profile == profile) ? BT_TRUE : BT_FALSE; if (res1 == BT_TRUE && res2 == BT_TRUE) *res = BT_TRUE; else *res = BT_FALSE; DEBUG_LOG4("%s, %d, %d: res=%d", bdaddr, chan, profile, *res); return BT_ERR_NONE;}int BTHandlerCreate(BTConnection *con, const char *bdaddr, int chan, int profile, int flags, const char *pin){ DEBUG_LOG5("addr=[%s], chan=%d, prof=%d, flags=%d pin=[%s]", bdaddr, chan, profile, flags, pin); BTConnection c; if (!con || chan < 0 || chan > 30 || !bdaddr || !pin) return BT_ERR_ARGUMENT; if (strlen(bdaddr) > (BT_BDADDR_LEN - 1) || strlen(pin) > (BT_PIN_LEN - 1)) return BT_ERR_ARGUMENT; c = (BTConnection)malloc(sizeof(struct sBTConnection)); if (!c) return BT_ERR_NOMEMORY; if (BTSocketCreate(&c->sock, bdaddr, chan) != BT_ERR_NONE) { DEBUG_LOG("creating socket failed"); free(c); return BT_ERR_FAILED; } c->state = BT_STATE_UNINITIALIZED; c->ppp.state = BT_PPP_STATE_UNINITIALIZED; c->profile = profile; c->flags = flags; strcpy(c->pin, pin); c->sendbuf = NULL; c->sendbuflen = 0; c->error = BT_ERR_NONE; if (flags & BT_FLAG_LISTEN) { INIT_LISTEN_TIMER(c, BT_TO_LISTEN_TOTAL); UPDATE_STATE(c->state, BT_STATE_START_LISTENING); } else if (flags & BT_FLAG_OPEN) { INIT_CONNECT_TIMER(c, BT_TO_CONNECT_TOTAL); UPDATE_STATE(c->state, BT_STATE_START_CONNECTING); } else UPDATE_STATE(c->state, BT_STATE_INITIALIZED); UPDATE_STATE(c->ppp.state, BT_PPP_STATE_UNINITIALIZED); c->ppp.refcount = 0; c->ppp.pid = -1; c->reconnecting = 0; *con = c; return BT_ERR_NONE;}int BTHandlerDestroy(BTConnection con){ DEBUG_LOG1("state: %s", STATE2STR(con->state)); int res; if (!con) return BT_ERR_ARGUMENT; res = BTHandlerClose(con); free(con); return res;}int BTHandlerStartApp(BTConnection con, const char *param){ DEBUG_LOG5("profile=%d, param=[%s], state=%s, refcount=%d, flags=0x%x", con->profile, param, STATE2STR(con->state), con->ppp.refcount, con->flags); if (con->profile != BT_PROFILE_DUN) return BT_ERR_NONE; if (!con || !param) return BT_ERR_ARGUMENT; if (strlen(param) > (BT_PPP_PARAM_LEN - 1)) return BT_ERR_ARGUMENT; if (con->state != BT_STATE_INITIALIZED && con->state != BT_STATE_APP_START && con->state != BT_STATE_APP_READY) return BT_ERR_STATE; con->ppp.refcount++; if(con->ppp.refcount > 1 && con->state != BT_STATE_INITIALIZED) return BT_ERR_NONE; else if (con->ppp.refcount == 1) strcpy(con->ppp.param, param); UPDATE_STATE(con->state, BT_STATE_APP_START); UPDATE_STATE(con->ppp.state, BT_PPP_STATE_INIT); return BT_ERR_NONE;}int BTHandlerStopApp(BTConnection con){ int pid; DEBUG_LOG3("profile=%d, state=%s, refcount=%d", con->profile, STATE2STR(con->state), con->ppp.refcount); if (!con) return BT_ERR_ARGUMENT; if (con->profile != BT_PROFILE_DUN) return BT_ERR_NONE; if (con->state != BT_STATE_APP_START && con->state != BT_STATE_APP_READY && con->state != BT_STATE_INITIALIZED) return BT_ERR_STATE; if (con->ppp.refcount) con->ppp.refcount--; if (con->ppp.refcount || con->state == BT_STATE_INITIALIZED) return BT_ERR_NONE; if (con->state == BT_STATE_APP_START && (con->ppp.state == BT_PPP_STATE_CHECKTTY || con->ppp.state == BT_PPP_STATE_START || con->ppp.state == BT_PPP_STATE_CHECKREADY) ) BTSocketReleaseTTY(con->sock); pid = BTGetFileInt(BT_PPP_PIDFILE); if (pid > 0) { DEBUG_LOG1("terminating %d", pid); kill(pid, SIGTERM); } BTSetTimer(&con->ppp.removetr, BT_TO_APPREMOVE); UPDATE_STATE(con->state, BT_STATE_APP_CLOSING); return BT_ERR_NONE;}int BTHandlerSend(BTConnection con, const char *buf, int len, int *sent){#ifdef ENABLE_DEBUG_LOG if (len <= BT_DBGBUF_LEN) { if (buf && len) strncpy(dbgbuf, buf, len); dbgbuf[len - 1] = '\0'; DEBUG_LOG3("buf=[%s], len=%d, state=%s", dbgbuf, len, STATE2STR(con->state)); } else { DEBUG_LOG("debug buffer is too small!"); }#endif //ENABLE_DEBUG_LOG char *tmpbuf; if (!con || !buf || !sent) return BT_ERR_ARGUMENT; if (con->state == BT_STATE_APP_START || con->state == BT_STATE_APP_READY || con->state == BT_STATE_APP_CLOSING) return BT_ERR_STATE; if (con->state != BT_STATE_CONNECTED || con->sendbuf) { if (!con->sendbuf) { con->sendbuf = (char*)malloc(len); if (!con->sendbuf) return BT_ERR_NOMEMORY; } else { tmpbuf = (char*)realloc(con->sendbuf, con->sendbuflen + len); if (!tmpbuf) return BT_ERR_NOMEMORY; con->sendbuf = tmpbuf; } memcpy(con->sendbuf + con->sendbuflen, buf, len); DEBUG_LOG2("send buffer grown %d -> %d", con->sendbuflen, con->sendbuflen + len); con->sendbuflen += len; if (con->state == BT_STATE_START_CONNECTING || con->state == BT_STATE_CONNECTING || con->state == BT_STATE_CONNECTED) return BT_ERR_NONE; if (con->state == BT_STATE_START_LISTENING || con->state == BT_STATE_LISTENING) BTSocketStopListen(con->sock); con->reconnecting = 0; INIT_CONNECT_TIMER(con, BT_TO_CONNECT_TOTAL); UPDATE_STATE(con->state, BT_STATE_START_CONNECTING); } else { if (BTSocketSend(con->sock, buf, len , sent, BT_TO_NONE) != BT_ERR_NONE) { BTSocketClose(con->sock); DEBUG_LOG1("direct send failed, reconnecting %s", strerror(errno)); INIT_CONNECT_TIMER(con, BT_TO_RECONNECT_TOTAL); UPDATE_STATE(con->state, BT_STATE_START_CONNECTING); return BT_ERR_CONNECTION; } } return BT_ERR_NONE;}int BTHandlerReceive(BTConnection con, char *buf, int len, int *received){ int res; if (!con || !buf || !received) return BT_ERR_ARGUMENT; if (con->state != BT_STATE_CONNECTED) return BT_ERR_STATE; res = BTSocketReceive(con->sock, buf, len, received, BT_TO_NONE); switch (res) { case BT_ERR_TIMEOUT: *received = 0; res = BT_ERR_NONE; break; case BT_ERR_NONE:#ifdef ENABLE_DEBUG_LOG if (*received <= BT_DBGBUF_LEN) { if (*received) strncpy(dbgbuf, buf, *received); buf[*received] = '\0'; DEBUG_LOG3("buf=[%s], len=%d, received=%d", buf, len, *received); } else { DEBUG_LOG("debug buffer is too small!"); }#endif //ENABLE_DEBUG_LOG res = BT_ERR_NONE; break; case BT_ERR_FAILED: DEBUG_LOG1("receive failed, reconnecting: %s", strerror(errno)); BTSocketClose(con->sock); con->reconnecting = 1; INIT_CONNECT_TIMER(con, BT_TO_RECONNECT_TOTAL); UPDATE_STATE(con->state, BT_STATE_START_CONNECTING); *received = 0; res = BT_ERR_CONNECTION; break; default: DEBUG_LOG("UNHANDLED ERROR!!!"); res = BT_ERR_FAILED; *received = 0; break; } return res;}int BTHandlerRelease(BTConnection con){ DEBUG_LOG1("state=%s", STATE2STR(con->state)); if (!con) return BT_ERR_ARGUMENT; if (con->state != BT_STATE_START_CONNECTING && con->state != BT_STATE_CONNECTING && con->state != BT_STATE_CONNECTED && con->state != BT_STATE_REMOVE_CONNECTION) return BT_ERR_STATE; BTSocketClose(con->sock); if (con->sendbuf) free(con->sendbuf); con->sendbuf = NULL; con->sendbuflen = 0; if (con->flags & BT_FLAG_LISTEN) { DEBUG_LOG("release to listening"); INIT_LISTEN_TIMER(con, BT_TO_LISTEN_TOTAL); UPDATE_STATE(con->state, BT_STATE_START_LISTENING); } else { DEBUG_LOG("release to initialized"); UPDATE_STATE(con->state, BT_STATE_INITIALIZED); } return BT_ERR_NONE;}int BTHandlerClose(BTConnection con){ int pid; DEBUG_LOG1("state=%s", STATE2STR(con->state)); if (!con) return BT_ERR_ARGUMENT; if (con->state == BT_STATE_APP_START || con->state == BT_STATE_APP_READY || con->state == BT_STATE_APP_CLOSING) { if (con->state != BT_STATE_APP_CLOSING) { pid = BTGetFileInt(BT_PPP_PIDFILE); if (pid > 0) { DEBUG_LOG1("terminating %d", pid); kill(pid, SIGTERM); } } BTSetTimer(&con->ppp.removetr, BT_TO_APPREMOVE); UPDATE_STATE(con->state, BT_STATE_CLOSING); UPDATE_STATE(con->ppp.state, BT_PPP_STATE_CLOSING); } else if (con->state != BT_STATE_CLOSING) { BTSocketClose(con->sock); if (con->sendbuf) free(con->sendbuf); con->sendbuf = NULL; con->sendbuflen = 0; UPDATE_STATE(con->state, BT_STATE_CLOSING); UPDATE_STATE(con->ppp.state, BT_PPP_STATE_UNINITIALIZED); } return BT_ERR_NONE;}int BTHandlerGetState(cBTConnection con, int *state){ if (!con || !state) return BT_ERR_ARGUMENT;// DEBUG_LOG1("state=%s", STATE2STR(con->state)); *state = con->state; return BT_ERR_NONE;}int BTHandlerGetError(cBTConnection con, int *error){ if (!con || !error) return BT_ERR_ARGUMENT; DEBUG_LOG1("error=%s", ERROR2STR(con->error)); *error = con->error; return BT_ERR_NONE;}int BTHandlerSetFlags(BTConnection con, int flags){ DEBUG_LOG3("flags=0x%X -> 0x%X, state=%s", con->flags, flags, STATE2STR(con->state)); if (!con) return BT_ERR_ARGUMENT; if (!(con->flags & BT_FLAG_LISTEN) && (flags & BT_FLAG_LISTEN) && con->state == BT_STATE_INITIALIZED) { INIT_LISTEN_TIMER(con, BT_TO_LISTEN_TOTAL); UPDATE_STATE(con->state, BT_STATE_START_LISTENING); } else if (!(con->flags & BT_FLAG_OPEN) && (flags & BT_FLAG_OPEN) && (con->state == BT_STATE_START_LISTENING || con->state == BT_STATE_LISTENING || con->state == BT_STATE_INITIALIZED) && !(con->flags & BT_FLAG_DONOTRECONNECT)) { if (con->state == BT_STATE_START_LISTENING || con->state == BT_STATE_LISTENING) BTSocketStopListen(con->sock); con->reconnecting = 0; INIT_CONNECT_TIMER(con, BT_TO_CONNECT_TOTAL); UPDATE_STATE(con->state, BT_STATE_START_CONNECTING); } con->flags = flags; return BT_ERR_NONE;}int BTHandlerGetFlags(cBTConnection con, int *flags){ if (!con || !flags) return BT_ERR_ARGUMENT; *flags = con->flags; DEBUG_LOG2("flags=0x%X, state=%s", *flags, STATE2STR(con->state)); return BT_ERR_NONE;}int BTHandlerIsProfileActive(cBTConnection con, int profile, int *res){ if (!con || !profile) return BT_ERR_ARGUMENT; if (con->profile == profile && (con->state == BT_STATE_CONNECTED || con->state == BT_STATE_APP_READY)) *res = BT_TRUE; else *res = BT_FALSE; return BT_ERR_NONE;}int BTHandlerNeedPair(cBTConnection con, int *res){ if (con->state == BT_STATE_START_LISTENING || con->state == BT_STATE_LISTENING || con ->state == BT_STATE_START_CONNECTING || con->state == BT_STATE_CONNECTING || con->state == BT_STATE_APP_START) *res = BT_TRUE; else *res = BT_FALSE; return BT_ERR_NONE;}int BTHandlerRun(BTConnection con){ int i, res, sent, pid;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -