diff --git a/CMakeLists.txt b/CMakeLists.txt index a6009db..1350a16 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,12 +14,14 @@ set(SRCS ${PROJECT_SOURCE_DIR}/src/xdbd.c ${PROJECT_SOURCE_DIR}/src/adb/adb.c ${PROJECT_SOURCE_DIR}/src/adb/xdbd_adb.c + ${PROJECT_SOURCE_DIR}/src/adb/xdbd_adb_request.c ${PROJECT_SOURCE_DIR}/src/adb/command.c ${PROJECT_SOURCE_DIR}/src/adb/packet.c ${PROJECT_SOURCE_DIR}/src/connection/connection.c ${PROJECT_SOURCE_DIR}/src/event/xdbd_event.c ${PROJECT_SOURCE_DIR}/src/event/select/xdbd_select.c ${PROJECT_SOURCE_DIR}/src/core/xdbd_pool.c + ${PROJECT_SOURCE_DIR}/src/core/xdbd_buf.c ) set( diff --git a/include/xdbd.h b/include/xdbd.h index 298487c..baae989 100644 --- a/include/xdbd.h +++ b/include/xdbd.h @@ -23,12 +23,10 @@ #define xdbd_msec_t unsigned -typedef struct adb_command_s adb_command_t; -typedef struct adb_packet_s adb_packet_t; typedef struct xdbd_connection_s xdbd_connection_t; typedef struct xdbd_listening_s xdbd_listening_t; typedef struct xdbd_event_s xdbd_event_t; -typedef struct adb_pcmd_s adb_pcmd_t; +typedef struct xdbd_buf_s xdbd_buf_t; typedef struct xdbd_s xdbd_t; @@ -49,6 +47,7 @@ struct xdbd_s { #define xdbd_memcpy(dst, src, n) (void) memcpy(dst, src, n) #define xdbd_cpymem(dst, src, n) (((u_char *) memcpy(dst, src, n)) + (n)) +#define xdbd_cpymem(dst, src, n) (((u_char *) memcpy(dst, src, n)) + (n)) /*socket*/ #define xdbd_socket socket diff --git a/src/adb/adb.h b/src/adb/adb.h index 414bfa1..cfe0249 100644 --- a/src/adb/adb.h +++ b/src/adb/adb.h @@ -4,8 +4,25 @@ #include #include +typedef struct adb_command_s adb_command_t; +typedef struct adb_pcmd_s adb_pcmd_t; +typedef struct xdbd_adb_header_s xdbd_adb_header_t; +typedef struct xdbd_adb_packet_s xdbd_adb_packet_t; +typedef struct xdbd_adb_request_s xdbd_adb_request_t; // https://android.googlesource.com/platform/packages/modules/adb/+/master/protocol.txt +/* AUTH packets first argument */ +/* Request */ +#define ADB_AUTH_TOKEN 1 +/* Response */ +#define ADB_AUTH_SIGNATURE 2 +#define ADB_AUTH_RSAPUBLICKEY 3 + +#define ADB_VERSION_MIN 0x01000000 +#define ADB_VERSION_SKIP_CHECKSUM 0x01000001 +#define ADB_VERSION 0x01000001 + + enum TransportType { kTransportUsb, kTransportLocal, diff --git a/src/adb/command.c b/src/adb/command.c index 3226c11..f8d642f 100644 --- a/src/adb/command.c +++ b/src/adb/command.c @@ -1,10 +1,67 @@ +#include +#include +#include #include #include -#include +#include +#include +#include +#include -adb_command_t adb_cmds[] = { +int xdbd_process_shell_cmd(xdbd_adb_request_t *r, xdbd_adb_packet_t *p, const adb_command_t *cmd); + +static adb_command_t adb_cmds[] = { { - .cmd = "shell", - .handler = NULL, + .cmd = xdbd_string("shell"), + .handler = xdbd_process_shell_cmd, }, }; + +int xdbd_process_shell_cmd(xdbd_adb_request_t *r, xdbd_adb_packet_t *p, const adb_command_t *cmd) { + xdbd_adb_packet_t *out; + + out = xdbd_palloc(r->pool, sizeof(xdbd_adb_packet_t)); + if (out == NULL) { + return XDBD_ERR; + } + + out->payload = xdbd_create_buf(r->pool, ADB_MAX_PACKET_SIZE); + if (out->payload == NULL) { + return XDBD_ERR; + } + + bfdev_log_info("shell_cmd: send okay packet\n"); + xdbd_okey_packet(r, out); + + xdbd_buf_append_mem(r->out, r->pool, &out->header, sizeof(xdbd_adb_header_t)); + xdbd_buf_append_buf(r->out, r->pool, out->payload); + + return XDBD_OK; +} + +int xddb_process_cmd(xdbd_adb_request_t *r, xdbd_adb_packet_t *p) { + size_t i; + const xdbd_adb_header_t *h; + const adb_command_t *cmd; + const xdbd_buf_t *paylod; + + h = &p->header; + paylod = p->payload; + for (i = 0; i < BFDEV_ARRAY_SIZE(adb_cmds); i++) { + cmd = &adb_cmds[i]; + + /*FIME: parse the payload to cmd and argv*/ + /* + if (cmd->cmd.size != h->dlen) { + continue; + } + + if (strncmp((const char *)cmd->cmd.data, (const char *)paylod->pos, h->dlen) != 0) { + continue; + } + */ + return cmd->handler(r, p, cmd); + } + + return XDBD_ERR; +} diff --git a/src/adb/command.h b/src/adb/command.h index 5cbff86..dde2e88 100644 --- a/src/adb/command.h +++ b/src/adb/command.h @@ -1,15 +1,17 @@ #ifndef __COMMAND__H__ #define __COMMAND__H__ +#include #include -typedef int (*adb_cmd_pt)(const char *cmd); +typedef int (*adb_cmd_pt)(xdbd_adb_request_t *r, xdbd_adb_packet_t *p, const adb_command_t *cmd); struct adb_command_s { - const char *cmd; + xdbd_str_t cmd; adb_cmd_pt handler; }; +int xddb_process_cmd(xdbd_adb_request_t *r, xdbd_adb_packet_t *p); #endif /*__COMMAND__H__*/ diff --git a/src/adb/packet.c b/src/adb/packet.c index e550a75..15b94bf 100644 --- a/src/adb/packet.c +++ b/src/adb/packet.c @@ -1,55 +1,394 @@ +#include +#include +#include +#include "xdbd_adb.h" +#include "xdbd_buf.h" +#include "xdbd_pool.h" #include #include #include #include +#include +#include +#include + +int xdbd_process_cnxn_packet(xdbd_adb_request_t *r, xdbd_adb_packet_t *p); +int xdbd_process_auth_packet(xdbd_adb_request_t *r, xdbd_adb_packet_t *p); +int xdbd_process_open_packet(xdbd_adb_request_t *r, xdbd_adb_packet_t *p); +int xdbd_process_close_packet(xdbd_adb_request_t *r, xdbd_adb_packet_t *p); +int xdbd_process_write_packet(xdbd_adb_request_t *r, xdbd_adb_packet_t *p); +int xdbd_process_okay_packet(xdbd_adb_request_t *r, xdbd_adb_packet_t *p); +int xdbd_process_bug_on_packet(xdbd_adb_request_t *r, xdbd_adb_packet_t *p); static adb_pcmd_t pcmds[] = { { .pcmd = PCMD_SYNC, - .handler = NULL + .handler = xdbd_process_bug_on_packet }, { .pcmd = PCMD_CNXN, - .handler = NULL + .handler = xdbd_process_cnxn_packet }, { .pcmd = PCMD_OPEN, - .handler = NULL + .handler = xdbd_process_open_packet }, { - .pcmd = PCMD_OKPCMDY, - .handler = NULL + .pcmd = PCMD_OKAY, + .handler = xdbd_process_okay_packet }, { .pcmd = PCMD_CLSE, - .handler = NULL + .handler = xdbd_process_close_packet }, { .pcmd = PCMD_WRTE, - .handler = NULL + .handler = xdbd_process_write_packet }, { - .pcmd = PCMD_PCMDUTH, - .handler = NULL + .pcmd = PCMD_AUTH, + .handler = xdbd_process_auth_packet }, { .pcmd = PCMD_STLS, - .handler = NULL + .handler = xdbd_process_bug_on_packet } }; -int xdbd_process_packet(adb_packet_t *p) { +int xdbd_fill_packet(xdbd_adb_request_t *r, xdbd_adb_packet_t *out) { + out->header.magic = ~out->header.pcmd; + + //TODO. compilicatable + out->header.dchecksum = 0; + + + out->header.dlen = xdbd_buf_size(out->payload); + + return XDBD_OK; +} + +int xdbd_okey_packet(xdbd_adb_request_t *r, xdbd_adb_packet_t *out) { + unsigned host_id, device_id; + out->header.pcmd = PCMD_OKAY; + + host_id = r->p->header.arg0; + device_id = 1; + + //the arg0 is yourself's id gen by yourself + //the arg1 is remote's id gen by remote + out->header.arg0 = device_id; + out->header.arg1 = host_id; + + if (xdbd_fill_packet(r, out) != XDBD_OK) { + return XDBD_ERR; + } + + bfdev_log_info("prepare to send okay packet\n"); + xdbd_dump_adb_packet(r->pool, out); + return XDBD_OK; +} + +int xdbd_write_packet(xdbd_adb_request_t *r, xdbd_adb_packet_t *out, xdbd_str_t *in) { + unsigned host_id; + out->header.pcmd = PCMD_WRTE; + + host_id = r->p->header.arg0; + + out->header.arg0 = 1; + out->header.arg1 = host_id; + + if (xdbd_buf_append_string(out->payload, r->pool, in) == NULL) { + return XDBD_ERR; + } + + if (xdbd_fill_packet(r, out) != XDBD_OK) { + return XDBD_ERR; + } + + bfdev_log_info("prepare to send write packet\n"); + + xdbd_dump_adb_packet(r->pool, out); + return XDBD_OK; +} + +int xdbd_close_packet(xdbd_adb_request_t *r, xdbd_adb_packet_t *out) { + unsigned host_id, device_id; + out->header.pcmd = PCMD_CLSE; + + host_id = r->p->header.arg0; + device_id = 1; + + + out->header.arg0 = device_id; + out->header.arg1 = host_id; + + if (xdbd_fill_packet(r, out) != XDBD_OK) { + return XDBD_ERR; + } + + bfdev_log_info("prepare to send okay packet\n"); + xdbd_dump_adb_packet(r->pool, out); + return XDBD_OK; +} + + +int xdbd_process_cnxn_packet(xdbd_adb_request_t *r, xdbd_adb_packet_t *p) { + xdbd_adb_packet_t *out; + + out = xdbd_palloc(r->pool, sizeof(xdbd_adb_packet_t)); + if (out == NULL) { + return XDBD_ERR; + } + + out->payload = xdbd_create_buf(r->pool, ADB_MAX_PACKET_SIZE); + if (out->payload == NULL) { + return XDBD_ERR; + } + + out->header.pcmd = PCMD_AUTH; + + out->header.arg0 = ADB_AUTH_TOKEN; + out->header.arg1 = 0; + + //FIXME: this must be 20 size??? + xdbd_buf_append_cstring(out->payload, r->pool, "randomstring12345678"); + + if (xdbd_fill_packet(r, out) != XDBD_OK) { + return XDBD_ERR; + } + + xdbd_dump_adb_packet(r->pool, out); + + xdbd_buf_append_mem(r->out, r->pool, &out->header, sizeof(xdbd_adb_header_t)); + xdbd_buf_append_buf(r->out, r->pool, out->payload); + + return XDBD_OK; +} + + +int xdbd_process_bug_on_packet(xdbd_adb_request_t *r, xdbd_adb_packet_t *p) { + bfdev_log_err("bug on: xdbd dont support this packet"); + return XDBD_ERR; +} + +int xdbd_process_auth_packet(xdbd_adb_request_t *r, xdbd_adb_packet_t *p) { + bfdev_log_info("auth packet\n"); + xdbd_adb_packet_t *out; + int i; + //FIXME: read it from env or other place + const char *freatures = "shell_v2,cmd,stat_v2,ls_v2,fixed_push_mkdir,\ + apex,abb,fixed_push_symlink_timestamp,abb_exec,remount_shell,track_app,\ + sendrecv_v2,sendrecv_v2_brotli,sendrecv_v2_lz4,\ + sendrecv_v2_zstd,sendrecv_v2_dry_run_send,openscreen_mdns;"; + + out = xdbd_palloc(r->pool, sizeof(xdbd_adb_packet_t)); + if (out == NULL) { + return XDBD_ERR; + } + + out->payload = xdbd_create_buf(r->pool, ADB_MAX_PACKET_SIZE); + if (out->payload == NULL) { + return XDBD_ERR; + } + + out->header.pcmd = PCMD_CNXN; + out->header.arg0 = ADB_VERSION; + out->header.arg1 = ADB_MAX_PACKET_SIZE; + + static const char* cnxn_props[] = { + "ro.product.name=ffashion;", + "ro.product.model=ffashion;", + "ro.product.device=ffashion;", + }; + + xdbd_buf_append_cstring(out->payload, r->pool, "device::"); + + for (i = 0; i < BFDEV_ARRAY_SIZE(cnxn_props); i++) { + xdbd_buf_append_cstring(out->payload, r->pool, cnxn_props[i]); + } + + xdbd_buf_append_cstring(out->payload, r->pool, "features="); + xdbd_buf_append_cstring(out->payload, r->pool, freatures); + if (xdbd_fill_packet(r, out) != XDBD_OK) { + return XDBD_ERR; + } + + //FIXME: maybe remove it?? + xdbd_buf_append_mem(r->out, r->pool, &out->header, sizeof(xdbd_adb_header_t)); + xdbd_buf_append_buf(r->out, r->pool, out->payload); + + return XDBD_OK; +} + +int xdbd_process_open_packet(xdbd_adb_request_t *r, xdbd_adb_packet_t *p) { + bfdev_log_info("open packet\n"); + + if (p->header.arg0 == 0) { + return XDBD_ERR; + } + + return xddb_process_cmd(r, p); +} + +int xdbd_process_close_packet(xdbd_adb_request_t *r, xdbd_adb_packet_t *p) { + bfdev_log_info("close packet\n"); + xdbd_adb_close_request(r); + //FIXME: process it + return XDBD_ERR; +} + +int xdbd_process_write_packet(xdbd_adb_request_t *r, xdbd_adb_packet_t *p) { + xdbd_adb_packet_t *out; + xdbd_connection_t *c = r->coonection; + + xdbd_str_t t_data = xdbd_string("helloworld\r\n"); + + out = xdbd_palloc(r->pool, sizeof(xdbd_adb_packet_t)); + if (out == NULL) { + return XDBD_ERR; + } + + out->payload = xdbd_create_buf(r->pool, ADB_MAX_PACKET_SIZE); + if (out->payload == NULL) { + return XDBD_ERR; + } + + xdbd_okey_packet(r, out); + xdbd_buf_append_mem(r->out, r->pool, &out->header, sizeof(xdbd_adb_header_t)); + xdbd_buf_append_buf(r->out, r->pool, out->payload); + + c->send(c, r->out->pos, xdbd_buf_size(r->out)); + + xdbd_reset_buf(out->payload); + xdbd_reset_buf(r->out); + xdbd_write_packet(r, out, &t_data); + + xdbd_buf_append_mem(r->out, r->pool, &out->header, sizeof(xdbd_adb_header_t)); + xdbd_buf_append_buf(r->out, r->pool, out->payload); + + c->send(c, r->out->pos, xdbd_buf_size(r->out)); + xdbd_reset_buf(r->out); + + return XDBD_OK; +} + +int xdbd_process_okay_packet(xdbd_adb_request_t *r, xdbd_adb_packet_t *p) { + xdbd_adb_packet_t *out; + + out = xdbd_palloc(r->pool, sizeof(xdbd_adb_packet_t)); + if (out == NULL) { + return XDBD_ERR; + } + + out->payload = xdbd_create_buf(r->pool, ADB_MAX_PACKET_SIZE); + if (out->payload == NULL) { + return XDBD_ERR; + } + + xdbd_okey_packet(r, out); + xdbd_buf_append_mem(r->out, r->pool, &out->header, sizeof(xdbd_adb_header_t)); + xdbd_buf_append_buf(r->out, r->pool, out->payload); + + return XDBD_OK; +} + +int xdbd_process_packet(xdbd_adb_request_t *r, xdbd_adb_packet_t *p) { + xdbd_adb_header_t *h; adb_pcmd_t *pcmd; + h = &p->header; + size_t i; + + if (h->magic != ~h->pcmd) { + bfdev_log_err("process_packet: magic error\n"); + return XDBD_ERR; + } - for (size_t i = 0; i < BFDEV_ARRAY_SIZE(pcmds); i++) { + if (r->out == NULL) { + r->out = xdbd_create_buf(r->pool, 1024); + if (r->out == NULL) { + return XDBD_ERR; + } + } + + for (i = 0; i < BFDEV_ARRAY_SIZE(pcmds); i++) { pcmd = &pcmds[i]; - if (pcmd->pcmd != p->pcmd) { + if (pcmd->pcmd != h->pcmd) { continue; } - return pcmd->handler(p); + return pcmd->handler(r, p); } return XDBD_ERR; } + +xdbd_buf_t *xdbd_dump_hex(xdbd_pool_t *pool, xdbd_str_t str) { + xdbd_buf_t *b; + size_t i; + char c[3]; + b = xdbd_create_buf(pool, 1024); + if (b == NULL) { + return NULL; + } + + for (i = 0; i < str.size; i++) { + snprintf(c, sizeof(c), "%02x", str.data[i]); + if (xdbd_buf_append_cstring(b, pool, c) == NULL) { + return NULL; + } + } + + return b; +} + +xdbd_buf_t *xdbd_dump_adb_header(xdbd_pool_t *pool, const xdbd_adb_header_t *h) { + unsigned command = h->pcmd; + int len = h->dlen; + char cmd[9]; + char arg0[12], arg1[12]; + int n; + + for (n = 0; n < 4; n++) { + int b = (command >> (n * 8)) & 255; + if (b < 32 || b >= 127) break; + cmd[n] = (char)b; + } + if (n == 4) { + cmd[4] = 0; + } else { + // There is some non-ASCII name in the command, so dump the hexadecimal value instead + snprintf(cmd, sizeof cmd, "%08x", command); + } + + if (h->arg0 < 256U) + snprintf(arg0, sizeof arg0, "%d", h->arg0); + else + snprintf(arg0, sizeof arg0, "0x%x", h->arg0); + + if (h->arg1 < 256U) + snprintf(arg1, sizeof arg1, "%d", h->arg1); + else + snprintf(arg1, sizeof arg1, "0x%x", h->arg1); + + + bfdev_log_debug("[%s] arg0=%s arg1=%s (len=%d), (magic=%u)\n", cmd, arg0, arg1, len, h->magic); + + return NULL; +} + +void xdbd_dump_adb_packet(xdbd_pool_t *pool, const xdbd_adb_packet_t *p) { + //FIXME: + xdbd_str_t hex_payload; + xdbd_buf_t *payload; + + xdbd_dump_adb_header(pool, &p->header); + + hex_payload.data = p->payload->pos; + hex_payload.size = xdbd_buf_size(p->payload); + + payload = xdbd_dump_hex(pool, hex_payload); + + bfdev_log_debug("%.*s\n", (int)xdbd_buf_size(payload), payload->pos); + return; +} diff --git a/src/adb/packet.h b/src/adb/packet.h index 3f1a02b..6120d58 100644 --- a/src/adb/packet.h +++ b/src/adb/packet.h @@ -1,35 +1,64 @@ #ifndef __PACKET__H__ #define __PACKET__H__ +#include "xdbd_string.h" #include +#include +#include +/* #define PCMD_SYNC 0x434e5953 #define PCMD_CNXN 0x4e584e43 #define PCMD_OPEN 0x4e45504f -#define PCMD_OKPCMDY 0x59414b4f +#define PCMD_OKAY 0x59414b4f #define PCMD_CLSE 0x45534c43 #define PCMD_WRTE 0x45545257 -#define PCMD_PCMDUTH 0x48545541 +#define PCMD_AUTH 0x48545541 #define PCMD_STLS 0x534C5453 +*/ -struct adb_packet_s { +#define PCMD_ASCII(pcmd) ( \ + (((pcmd[3]) & 0xff) << 24) | \ + (((pcmd[2]) & 0xff) << 16) | \ + (((pcmd[1]) & 0xff) << 8) | \ + (((pcmd[0]) & 0xff) << 0) \ +) + +#define PCMD_SYNC PCMD_ASCII("SYNC") +#define PCMD_CNXN PCMD_ASCII("CNXN") +#define PCMD_OPEN PCMD_ASCII("OPEN") +#define PCMD_OKAY PCMD_ASCII("OKAY") +#define PCMD_CLSE PCMD_ASCII("CLSE") +#define PCMD_WRTE PCMD_ASCII("WRTE") +#define PCMD_AUTH PCMD_ASCII("AUTH") +#define PCMD_STLS PCMD_ASCII("STLS") + + +struct xdbd_adb_header_s { unsigned pcmd; - unsigned arg1, arg2; + unsigned arg0, arg1; //data length unsigned dlen; - unsigned dcrc32; + unsigned dchecksum; unsigned magic; - char data[]; +} __bfdev_packed; + +struct xdbd_adb_packet_s { + xdbd_adb_header_t header; + xdbd_buf_t *payload; }; -typedef int (*adb_pcmd_pt)(adb_packet_t *p); +typedef int (*xdbd_adb_pcmd_pt)(xdbd_adb_request_t *r, xdbd_adb_packet_t *p); /* protocol command */ struct adb_pcmd_s { unsigned pcmd; - adb_pcmd_pt handler; + xdbd_adb_pcmd_pt handler; }; -int xdbd_process_packet(adb_packet_t *p); +int xdbd_process_packet(xdbd_adb_request_t *r, xdbd_adb_packet_t *p); +void xdbd_dump_adb_packet(xdbd_pool_t *pool, const xdbd_adb_packet_t *p); +int xdbd_okey_packet(xdbd_adb_request_t *r, xdbd_adb_packet_t *p); +int xdbd_write_packet(xdbd_adb_request_t *r, xdbd_adb_packet_t *p, xdbd_str_t *in); #endif /*__PACKET__H__*/ diff --git a/src/adb/xdbd_adb.c b/src/adb/xdbd_adb.c index 6bf76e6..8f62ca0 100644 --- a/src/adb/xdbd_adb.c +++ b/src/adb/xdbd_adb.c @@ -1,56 +1,359 @@ -#include "bfdev/log.h" -#include "connection.h" -#include "xdbd.h" -#include "xdbd_pool.h" +#define MODULE_NAME "xdbd_adb" +#define bfdev_log_fmt(fmt) MODULE_NAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include #include #include +#include +#include + +size_t xdbd_adb_read_adb_header(xdbd_adb_request_t *r) { + ssize_t n; + xdbd_connection_t *c; + int rc; + xdbd_event_t *rev; + + c = r->coonection; + rev = c->read; + + n = xdbd_buf_size(r->buffer); + + if (n >= sizeof(xdbd_adb_header_t)) { + return n; + } + + if (rev->ready) { + n = c->recv(c, r->buffer->last, r->buffer->end - r->buffer->last); + }else { + n = XDBD_AGAIN; + } + + if (n == XDBD_AGAIN) { + if (xdbd_handle_read_event(rev, 0) != XDBD_OK) { + xdbd_adb_close_request(r); + return XDBD_ERR; + } + return XDBD_AGAIN; + } + + if (n == 0) { + bfdev_log_debug("close connection by client\n"); + } + if (n == 0 || n == XDBD_ERR) { + xdbd_adb_close_request(r); + return XDBD_ERR; + } + + r->buffer->last += n; + return n; +} + +int xdbd_adb_parse_adb_header(xdbd_adb_request_t *r, xdbd_buf_t *b) { + ssize_t n; + + n = xdbd_buf_size(b); + + if (n < sizeof(xdbd_adb_header_t)) { + return XDBD_AGAIN; + } + + xdbd_memcpy(&r->h, b->start, sizeof(xdbd_adb_header_t)); + + r->p = xdbd_palloc(r->temp_pool, sizeof(xdbd_adb_packet_t)); + if (r->p == NULL) { + return XDBD_ERR; + } + + r->p->payload = xdbd_create_buf(r->temp_pool, r->h.dlen); + if (r->p->payload == NULL) { + return XDBD_ERR; + } + + + r->buffer->pos += sizeof(xdbd_adb_header_t); + return XDBD_OK; +} + +size_t xdbd_adb_read_adb_payload(xdbd_adb_request_t *r) { + ssize_t n; + xdbd_connection_t *c; + int rc; + xdbd_event_t *rev; + + c = r->coonection; + rev = c->read; + + n = xdbd_buf_size(r->buffer); + + if (n >= r->h.dlen) { + return n; + } + + if (rev->ready) { + n = c->recv(c, r->buffer->last, r->buffer->end - r->buffer->last); + }else { + n = XDBD_AGAIN; + } + + if (n == XDBD_AGAIN) { + if (xdbd_handle_read_event(rev, 0) != XDBD_OK) { + xdbd_adb_close_request(r); + return XDBD_ERR; + } + } + + if (n == 0) { + bfdev_log_debug("close connection by client\n"); + } + + if (n == 0 || n == XDBD_ERR) { + xdbd_adb_close_request(r); + return XDBD_ERR; + } + + r->buffer->last += n; + return n; +} + +int xdbd_adb_parse_adb_payload(xdbd_adb_request_t *r, xdbd_buf_t *b) { + r->p->header = r->h; + + xdbd_buf_append_buf(r->p->payload, r->pool, b); + + xdbd_dump_adb_packet(r->pool, r->p); + + //XDBD_OK + r->buffer->pos += r->p->header.dlen; + return XDBD_OK; + +} + +void xdbd_adb_process_adb_payload(xdbd_event_t *rev) { + xdbd_connection_t *c; + xdbd_adb_request_t *r; + int rc; + size_t n; + c = rev->data; + + r = c->data; + rc = XDBD_AGAIN; + + if (rev->timeout) { + c->timeout = 1; + xdbd_adb_close_request(r); + return; + } + + for (;;) { + if (rc == XDBD_AGAIN) { + n = xdbd_adb_read_adb_payload(r); + + if (n == XDBD_AGAIN || n == XDBD_ERR) { + break; + } + } + + rc = xdbd_adb_parse_adb_payload(r, r->buffer); + + if (rc == XDBD_OK) { + rev->handler = xdbd_adb_block_reading; + //do something for send packet + + rc = xdbd_process_packet(r, r->p); + + if (rc == XDBD_AGAIN) { + return; + } + + if (rc == XDBD_ERR) { + return; + } + + if (xdbd_buf_size(r->out) == 0) { + rev->handler = xdbd_adb_wait_apacket_handler; + break; + } + + //TODO: more check. + n = c->send(c, r->out->pos, xdbd_buf_size(r->out)); + bfdev_log_info("send %ld\n", n); + if (n == 0) { + bfdev_log_err("fuck close\n"); + } + + rev->handler = xdbd_adb_wait_apacket_handler; + break; + } + + if (rc == XDBD_AGAIN) { + if (r->buffer->pos == r->buffer->last) { + //never reach payload size too much + return; + } + + break; + } + + if (rc == XDBD_ERR) { + xdbd_adb_close_request(r); + return ; + } + } +} + +void xdbd_adb_process_adb_header(xdbd_event_t *rev) { + xdbd_connection_t *c; + xdbd_adb_request_t *r; + int rc; + size_t n; + c = rev->data; + + r = c->data; + rc = XDBD_AGAIN; + + if (rev->timeout) { + c->timeout = 1; + xdbd_adb_close_request(r); + return; + } + + for (;;) { + if (rc == XDBD_AGAIN) { + n = xdbd_adb_read_adb_header(r); + + if (n == XDBD_AGAIN || n == XDBD_ERR) { + break; + } + } + + rc = xdbd_adb_parse_adb_header(r, r->buffer); + + if (rc == XDBD_OK) { + rev->handler = xdbd_adb_process_adb_payload; + xdbd_adb_process_adb_payload(rev); + break; + } + + if (rc == XDBD_AGAIN) { + break; + } + + if (rc == XDBD_ERR) { + xdbd_adb_close_request(r); + return ; + } + } +} void xdbd_adb_wait_apacket_handler(xdbd_event_t *ev) { - bfdev_log_debug("xdbd_adb_handler\n"); + bfdev_log_debug("xdbd_adb_wait_apacket_handler\n"); xdbd_connection_t *c; size_t n; + xdbd_buf_t *b; + size_t size; c = ev->data; - unsigned char buf[1024]; - xdbd_memzero(buf, sizeof(buf)); + size = ADB_MAX_PACKET_SIZE; + b = c->buffer; + if (b == NULL) { + b = xdbd_create_buf(c->pool, size); + if (b == NULL) { + xdbd_adb_close_connection(c); + return; + } + + c->buffer = b; + } + + xdbd_reset_buf(b); - n = c->recv(c, buf, sizeof(buf)); + size = b->end - b->start; + n = c->recv(c, b->start, size); if (n == XDBD_ERR) { bfdev_log_err("c->recv error\n"); - + xdbd_adb_close_connection(c); return; } if (n == XDBD_AGAIN) { bfdev_log_info("c->recv need again\n"); + + if (xdbd_handle_read_event(ev, 0) != XDBD_OK) { + xdbd_adb_close_connection(c); + return; + } + + return; } if (n == 0) { bfdev_log_debug("close connection by client\n"); xdbd_adb_close_connection(c); + return; } - bfdev_log_info("%s receive size %ld\n", (char *)buf, n); + b->last += n; + + bfdev_log_info("%s receive size %ld\n", (char *)b->start, n); + + c->data = xdbd_adb_create_request(c); + if (c->data == NULL) { + xdbd_adb_close_connection(c); + return; + } + ev->handler = xdbd_adb_process_adb_header; + xdbd_adb_process_adb_header(ev); } void xdbd_adb_empty_handler(xdbd_event_t *ev) { return; } -void -xdbd_adb_close_connection(xdbd_connection_t *c) { - xdbd_pool_t *pool; +void xdbd_adb_block_reading(xdbd_event_t *ev) { + xdbd_connection_t *c; + c = ev->data; + + if (xdbd_event_flags & XDBD_USE_LEVEL_EVENT + && c->read->active) { + + if (xdbd_del_event(c->read, XDBD_READ_EVENT, 0) != XDBD_OK) { + //FIXME: + // ngx_http_close_request(r, 0); + } + } + return; +} + +void xdbd_adb_close_connection(xdbd_connection_t *c) { + xdbd_pool_t *pool, *temp_pool; pool = c->pool; c->destroyed = 1; pool = c->pool; + temp_pool = c->temp_pool; xdbd_close_connection(c->listening->xdbd, c); xdbd_destroy_pool(pool); + + xdbd_destroy_pool(temp_pool); +} + +void xdbd_adb_close_request(xdbd_adb_request_t *r) { + xdbd_connection_t *c; + + c = r->coonection; + + xdbd_adb_close_connection(c); } diff --git a/src/adb/xdbd_adb.h b/src/adb/xdbd_adb.h index 0021b52..3b0a879 100644 --- a/src/adb/xdbd_adb.h +++ b/src/adb/xdbd_adb.h @@ -4,9 +4,12 @@ #include #include #include - +#include +#define ADB_MAX_PACKET_SIZE 1024 * 1024 void xdbd_adb_wait_apacket_handler(xdbd_event_t *ev); void xdbd_adb_empty_handler(xdbd_event_t *ev); +void xdbd_adb_block_reading(xdbd_event_t *ev); void xdbd_adb_close_connection(xdbd_connection_t *c); +void xdbd_adb_close_request(xdbd_adb_request_t *r); #endif /*__XDBD_ADB__H__*/ diff --git a/src/adb/xdbd_adb_request.c b/src/adb/xdbd_adb_request.c new file mode 100644 index 0000000..b69af4d --- /dev/null +++ b/src/adb/xdbd_adb_request.c @@ -0,0 +1,21 @@ +#include "xdbd_pool.h" +#include +#include + +xdbd_adb_request_t *xdbd_adb_create_request(xdbd_connection_t *c) { + xdbd_adb_request_t *r; + + r = xdbd_palloc(c->pool, sizeof(xdbd_adb_request_t)); + if (r == NULL) { + return NULL; + } + + r->pool = c->pool; + r->temp_pool = c->temp_pool; + + r->buffer = c->buffer; + + r->coonection = c; + + return r; +} diff --git a/src/adb/xdbd_adb_request.h b/src/adb/xdbd_adb_request.h new file mode 100644 index 0000000..a2a09b6 --- /dev/null +++ b/src/adb/xdbd_adb_request.h @@ -0,0 +1,28 @@ +#ifndef __XDBD_ADB_REQUEST__H__ +#define __XDBD_ADB_REQUEST__H__ + +#include "adb.h" +#include "xdbd.h" +#include +#include +#include + +struct xdbd_adb_connection_s { + xdbd_connection_t *coonection; + xdbd_pool_t *pool; +}; + +struct xdbd_adb_request_s { + xdbd_buf_t *buffer; + xdbd_buf_t *body; + xdbd_pool_t *pool; + xdbd_pool_t *temp_pool; + xdbd_adb_header_t h; + xdbd_adb_packet_t *p; + xdbd_connection_t *coonection; + xdbd_buf_t *out; +}; + +xdbd_adb_request_t *xdbd_adb_create_request(xdbd_connection_t *c); + +#endif /*__XDBD_ADB_REQUEST__H__*/ diff --git a/src/connection/connection.h b/src/connection/connection.h index 754a77e..3039fd7 100644 --- a/src/connection/connection.h +++ b/src/connection/connection.h @@ -25,6 +25,7 @@ struct xdbd_listening_s { struct xdbd_connection_s { xdbd_pool_t *pool; + xdbd_pool_t *temp_pool; xdbd_socket_t fd; xdbd_event_t *read; xdbd_event_t *write; @@ -44,7 +45,9 @@ struct xdbd_connection_s { off_t sent; + xdbd_buf_t *buffer; unsigned destroyed:1; + unsigned timeout:1; }; #define ADB_CONNECTION_DEFAULT_PORT 5555 diff --git a/src/core/xdbd_buf.c b/src/core/xdbd_buf.c new file mode 100644 index 0000000..8cee9b4 --- /dev/null +++ b/src/core/xdbd_buf.c @@ -0,0 +1,66 @@ +#include +#include +#include +#include +#include +xdbd_buf_t *xdbd_create_buf(xdbd_pool_t *pool, size_t size) { + xdbd_buf_t *buf; + + buf = xdbd_palloc(pool, sizeof(xdbd_buf_t)); + if (buf == NULL) { + return NULL; + } + + buf->start = xdbd_palloc(pool, size); + if (buf->start == NULL) { + return NULL; + } + + buf->end = buf->start + size; + buf->pos = buf->start; + buf->last = buf->start; + return buf; +} + +xdbd_buf_t *xdbd_buf_append_mem(xdbd_buf_t *b, xdbd_pool_t *pool, const void *mem, size_t len) { + unsigned capacity, size; + u_char *p; + if (len > (size_t)(b->end - b->last)) { + + size = xdbd_buf_size(b); + + capacity = xdbd_buf_capacity(b); + capacity <<= 1; + + if (capacity < (size + len)) { + capacity = size + len; + } + + p = xdbd_palloc(pool, capacity); + if (p == NULL) { + return NULL; + } + + + b->last = xdbd_cpymem(p, b->pos, size);; + + b->start = b->pos = p; + b->end = p + capacity; + } + + b->last = xdbd_cpymem(b->last, mem, len); + + return b; +} + +xdbd_buf_t *xdbd_buf_append_cstring(xdbd_buf_t *b, xdbd_pool_t *pool, const char *str) { + return xdbd_buf_append_mem(b, pool, str, strlen(str)); +} + +xdbd_buf_t *xdbd_buf_append_string(xdbd_buf_t *b, xdbd_pool_t *pool, xdbd_str_t *str) { + return xdbd_buf_append_mem(b, pool, str->data, str->size); +} + +xdbd_buf_t *xdbd_buf_append_buf(xdbd_buf_t *b, xdbd_pool_t *pool, xdbd_buf_t *buf) { + return xdbd_buf_append_mem(b, pool, buf->pos, xdbd_buf_size(buf)); +} diff --git a/src/core/xdbd_buf.h b/src/core/xdbd_buf.h new file mode 100644 index 0000000..3a1310f --- /dev/null +++ b/src/core/xdbd_buf.h @@ -0,0 +1,23 @@ +#ifndef __XDBD_BUF__H__ +#define __XDBD_BUF__H__ +#include +#include +struct xdbd_buf_s { + u_char *start; + u_char *end; + u_char *pos; + u_char *last; +}; + +xdbd_buf_t *xdbd_create_buf(xdbd_pool_t *pool, size_t size); +xdbd_buf_t* xdbd_buf_append_mem(xdbd_buf_t *b, xdbd_pool_t *pool, const void *mem, size_t len); +xdbd_buf_t *xdbd_buf_append_string(xdbd_buf_t *b, xdbd_pool_t *pool, xdbd_str_t *str); +xdbd_buf_t *xdbd_buf_append_buf(xdbd_buf_t *b, xdbd_pool_t *pool, xdbd_buf_t *buf); +xdbd_buf_t *xdbd_buf_append_cstring(xdbd_buf_t *b, xdbd_pool_t *pool, const char *str); + +#define xdbd_buf_size(b) (off_t) ((b)->last - (b)->pos) +#define xdbd_buf_capacity(b) (b)->end - (b)->start +#define xdbd_reset_buf(b) (b)->pos = (b)->last = (b)->start + + +#endif /*__XDBD_BUF__H__*/ diff --git a/src/core/xdbd_string.c b/src/core/xdbd_string.c new file mode 100644 index 0000000..d74c8e8 --- /dev/null +++ b/src/core/xdbd_string.c @@ -0,0 +1 @@ +#include diff --git a/src/core/xdbd_string.h b/src/core/xdbd_string.h new file mode 100644 index 0000000..2b3c1e1 --- /dev/null +++ b/src/core/xdbd_string.h @@ -0,0 +1,13 @@ +#ifndef __XDBD_STRING__H__ +#define __XDBD_STRING__H__ +#include + +typedef struct { + ssize_t size; + u_char *data; +} xdbd_str_t; + +#define xdbd_string(str) { sizeof(str) - 1, (u_char *) str } +#define xdbd_null_string { 0, NULL } + +#endif /*__XDBD_STRING__H__*/ diff --git a/src/event/xdbd_event.c b/src/event/xdbd_event.c index 540d323..3e73567 100644 --- a/src/event/xdbd_event.c +++ b/src/event/xdbd_event.c @@ -24,8 +24,7 @@ bfdev_list_head_t xdbd_posted_events; static unsigned xdbd_timer_resolution; #define DEFAULT_CONNECTIONS 512 -int -xdbd_handle_read_event(xdbd_event_t *rev, unsigned flags) { +int xdbd_handle_read_event(xdbd_event_t *rev, unsigned flags) { /* select, poll, /dev/poll */ if (xdbd_event_flags & XDBD_USE_LEVEL_EVENT) { if (!rev->active && !rev->ready) { @@ -52,8 +51,7 @@ xdbd_handle_read_event(xdbd_event_t *rev, unsigned flags) { return XDBD_OK; } -int -xdbd_handle_write_event(xdbd_event_t *wev, unsigned flags) { +int xdbd_handle_write_event(xdbd_event_t *wev, unsigned flags) { if (xdbd_event_flags & XDBD_USE_LEVEL_EVENT) { /* select, poll, /dev/poll */ @@ -100,6 +98,9 @@ xdbd_close_accepted_connection(xdbd_connection_t *c) { xdbd_destroy_pool(c->pool); } + if (c->temp_pool) { + xdbd_destroy_pool(c->temp_pool); + } } static void xdbd_event_accept(xdbd_event_t *ev) { @@ -136,6 +137,11 @@ static void xdbd_event_accept(xdbd_event_t *ev) { return; } + c->temp_pool = xdbd_create_pool(); + if (c->temp_pool == NULL) { + return; + } + c->sockaddr = xdbd_palloc(c->pool, socklen); if (c->sockaddr == NULL) { xdbd_close_accepted_connection(c); @@ -289,15 +295,13 @@ static int xdbd_event_init_connections(xdbd_t *xdbd) { i = xdbd->connection_n; next = NULL; - do { - i--; - + while (i--) { c[i].data = next; c[i].read = &xdbd->read_events[i]; c[i].write = &xdbd->write_events[i]; c[i].fd = (xdbd_socket_t) -1; next = &c[i]; - } while (i); + } xdbd->free_connections = next; xdbd->free_connection_n = xdbd->connection_n; diff --git a/src/event/xdbd_event.h b/src/event/xdbd_event.h index 6b226b2..11872a0 100644 --- a/src/event/xdbd_event.h +++ b/src/event/xdbd_event.h @@ -194,6 +194,8 @@ typedef struct xdbd_event_module_s { int xdbd_init_event(xdbd_t *xdbd); void xdbd_process_events_and_timers(xdbd_t *xdbd); +int xdbd_handle_read_event(xdbd_event_t *rev, unsigned flags); +int xdbd_handle_write_event(xdbd_event_t *wev, unsigned flags); extern unsigned xdbd_event_flags; extern xdbd_event_actions_t xdbd_event_actions;