#include #include #include #include #include #include #include #include #include #include #include #include #define LOG_REQ_PORT 10001 #define LOG_TFR_PORT 10002 #define LOG_FRAME_HEADER_MAGIC 0xFF5AFFA5 #define LOG_FRAME_TAIL_MAGIC 0xFFA5FF5A #define FILENAME_LEN 128 #define MD5_LEN 32 #define MAX_LOG_SIZE 0x100000 #pragma pack(push, 1) typedef struct { uint32_t header; uint32_t type; uint32_t sub_type; uint32_t sub_type_1; uint32_t len; uint8_t checksum; } LogFrame; typedef struct { uint8_t request_type; uint32_t log_size; uint8_t log_md5[MD5_LEN]; uint8_t log_filename[FILENAME_LEN]; } LogTfrReq; #pragma pack(pop) static int log_req_socket = -1; static int log_tfr_socket = -1; static pthread_t req_thread_id = 0; static pthread_t tfr_thread_id = 0; #define FRAME_MAX_LEN 0x100000 #define LOG_TFR_MAX_SIZE 512000 #define OTA_LOG_FILENAME "log.zip" static int log_rev_state = 0; static int log_state_len = 0; static int log_rev_len = 0; static uint32_t log_frame_type = 0; static uint32_t log_frame_subtype = 0; static uint32_t log_frame_subtype_1 = 0; static uint32_t log_frame_len = 0; static uint8_t log_frame_checksum = 0; static uint8_t *log_frame_buf; static uint32_t log_file_size; static uint32_t log_file_offset; static uint32_t log_file_framenum = 0; static char log_file_md5[MD5_LEN]; static char log_file_name[FILENAME_LEN]; static uint8_t log_start_req = 1; #define LOG_CHECKSUM(x) ((((x) >> 24) & 0xff) + (((x) >> 16) & 0xff) + (((x) >> 8) & 0xff) + ((x) & 0xff)) static uint8_t calc_log_checksum(uint32_t type, uint32_t subtype, uint32_t subtype_1, uint32_t len) { uint32_t checksum = 0; checksum = LOG_CHECKSUM(type) + LOG_CHECKSUM(subtype) + LOG_CHECKSUM(subtype_1) + LOG_CHECKSUM(len); return 0x100 - (uint8_t)checksum; } static void logSendFrame(int socket, uint32_t type, uint32_t subtype, uint32_t subtype_1, void *data, uint32_t len) { LogFrame *frame = NULL; uint8_t *tmp; int32_t leftsize; int ret; printf("send frame type=0x%x, subtype=0x%x, len=%d.\n", type, subtype, len); frame = (LogFrame*)malloc(sizeof(LogFrame) + len + 4); if (frame) { frame->header = LOG_FRAME_HEADER_MAGIC; frame->type = type; frame->sub_type = subtype; frame->sub_type_1 = subtype_1; frame->len = len; frame->checksum = calc_log_checksum(type, subtype, subtype_1, len); tmp = (uint8_t*)frame + sizeof(LogFrame); if (len) { memcpy(tmp, data, len); tmp += len; } *(uint32_t *)tmp = LOG_FRAME_TAIL_MAGIC; } leftsize = sizeof(LogFrame) + len + 4; tmp = (uint8_t *)frame; while (leftsize > 0) { ret = send(socket, tmp, leftsize, 0); if (ret > 0) { leftsize -= ret; tmp += leftsize; } } free(frame); } static int g_exit = 0; static void RevLogFrameHandler(uint32_t type, uint32_t subtype, uint32_t subtype_1, uint8_t *data, uint32_t len) { printf("rev frame type=0x%x, subtype=0x%x, len=%d.\n", type, subtype, len); switch (type) { case 0x1b: if (subtype == 0x06) { if (data[0] == 0x01) { uint8_t ack[2]; log_file_size = (data[4] << 24) | (data[3] << 16) | (data[2] << 8) | data[1]; memcpy(log_file_md5, data + 5, MD5_LEN); memcpy(log_file_name, data + 5 + MD5_LEN, FILENAME_LEN); ack[0] = 0x01; //positive ack ack[1] = 0x00; //no error logSendFrame(log_req_socket, 0x0b, 0x06, 0, ack, 2); } } break; case 0x1f: if (subtype == 0x01) { int datalen = *(uint32_t*)data; int flag = *(uint16_t*)(data + 4); if (datalen + 6 != len) { printf("invalid datalen %d.\n", datalen); break; } if (flag == 0) { uint8_t ack[130] = {0}; printf("log transfer finish.\n"); if (log_file_framenum == 0) { FILE *fp = fopen(log_file_name, "wb"); if (fp) { printf("create log file %s.\n", log_file_name); fwrite(data + 6, 1, datalen, fp); fclose(fp); } } else { FILE *fp = fopen(log_file_name, "a+"); if (fp) { fwrite(data + 6, 1, datalen, fp); fclose(fp); } } strcpy((char*)ack, log_file_name); ack[128] = 0; //receive successed ack[129] = 0; //no resend logSendFrame(log_req_socket, 0x0f, 0x03, 0, ack, 130); g_exit = 1; break; } else if (flag == 1) { uint8_t ack= 0; // first frame FILE *fp = fopen(log_file_name, "wb"); if (!fp) { printf("create %s fail.\n", log_file_name); ack = 1; //no send next frame logSendFrame(log_req_socket, 0x0f, 0x02, 0, &ack, 1); break; } printf("create log file %s.\n", log_file_name); fwrite(data + 6, 1, datalen, fp); fclose(fp); logSendFrame(log_req_socket, 0x0f, 0x02, 0, &ack, 1); } else { uint8_t ack= 0; FILE *fp = fopen(log_file_name, "a+"); if (!fp) { printf("open %s fail.\n", log_file_name); ack = 1; //no send next frame logSendFrame(log_req_socket, 0x0f, 0x02, 0, &ack, 1); break; } fwrite(data + 6, 1, datalen, fp); fclose(fp); logSendFrame(log_req_socket, 0x0f, 0x02, 0, &ack, 1); } log_file_framenum++; } break; } } static void RevLogDataHandler(uint8_t *buf, int32_t len) { int i; for (i = 0; i < len; i++) { switch (log_rev_state) { case 0: //head receive if (log_state_len == 0 && buf[i] == 0xa5) { log_state_len++; } else if (log_state_len == 1 && buf[i] == 0xff) { log_state_len++; } else if (log_state_len == 2 && buf[i] == 0x5a) { log_state_len++; } else if (log_state_len == 3 && buf[i] == 0xff) { log_rev_state++; log_state_len = 0; log_frame_type = 0; log_frame_subtype = 0; log_frame_subtype_1 = 0; log_frame_len = 0; } else if (buf[i] == 0xff) { log_state_len = 1; } else { log_state_len = 0; } break; case 1: //type receive log_frame_type |= buf[i] << (8 * log_state_len); if (++log_state_len == 4) { log_rev_state++; log_state_len = 0; } break; case 2: //sub_type receive log_frame_subtype |= buf[i] << (8 * log_state_len); if (++log_state_len == 4) { log_rev_state++; log_state_len = 0; } break; case 3: //sub_type_1 receive log_frame_subtype_1 |= buf[i] << (8 * log_state_len); if (++log_state_len == 4) { log_rev_state++; log_state_len = 0; } break; case 4: //data len receive log_frame_len |= buf[i] << (8 * log_state_len); if (++log_state_len == 4) { if (log_frame_len > FRAME_MAX_LEN) { printf("Invalid NCM frame len 0x%x.\n", log_frame_len); } if (log_frame_len == 0) log_rev_state += 2; else log_rev_state++; log_rev_len = 0; log_state_len = 0; } break; case 5: //checksum receive log_frame_checksum = buf[i]; if (log_frame_checksum != calc_log_checksum(log_frame_type, log_frame_subtype, log_frame_subtype_1, log_frame_len)) { printf("log frame checksum fail.\n"); log_rev_state = 0; } else { log_rev_state++; } break; case 6: //data receive if (log_rev_len < FRAME_MAX_LEN) log_frame_buf[log_rev_len] = buf[i]; if (++log_rev_len == log_frame_len) log_rev_state++; break; case 7: //tail receive if (log_state_len == 0 && buf[i] == 0x5a) { log_state_len++; } else if (log_state_len == 1 && buf[i] == 0xff) { log_state_len++; } else if (log_state_len == 2 && buf[i] == 0xa5) { log_state_len++; } else if (log_state_len == 3 && buf[i] == 0xff) { RevLogFrameHandler(log_frame_type, log_frame_subtype, log_frame_subtype_1, log_frame_buf, log_frame_len); log_rev_state = 0; log_state_len = 0; } else { log_state_len = 0; } break; default: break; } } } void print_hex(unsigned char *data, int len, const char* tag) { unsigned long i, j, l; unsigned char tmp_str[140]; unsigned char tmp_str1[10]; for (i = 0; i < len; i += 16) { int n ; tmp_str[0] = '\0'; n = i ; for (j = 0; j < 4; j++) { l = n % 16; if (l >= 10) tmp_str[3 - j] = (unsigned char)('A' + l - 10); else tmp_str[3 - j] = (unsigned char)(l + '0'); n >>= 4 ; } tmp_str[4] = '\0'; strcat((char *) tmp_str, ": "); /* Output the hex bytes */ for (j = i; j < (i + 16); j ++) { int m ; if (j < len) { m = ((unsigned int)((unsigned char) * (data + j))) / 16 ; if (m >= 10) tmp_str1[0] = 'A' + (unsigned char) m - 10; else tmp_str1[0] = (unsigned char) m + '0'; m = ((unsigned int)((unsigned char) * (data + j))) % 16 ; if (m >= 10) tmp_str1[1] = 'A' + (unsigned char) m - 10; else tmp_str1[1] = (unsigned char) m + '0'; tmp_str1[2] = '\0'; strcat((char *) tmp_str, (char *) tmp_str1); strcat((char *) tmp_str, " "); } else { strcat((char *) tmp_str, " "); } } strcat((char *) tmp_str, " "); l = strlen((char *) tmp_str); /* Output the ASCII bytes */ for (j = i; j < (i + 16); j++) { if (j < len) { char c = * (data + j); if (c < ' ' || c > 'z') { c = '.'; } tmp_str[l ++] = c; } else { tmp_str[l ++] = ' '; } } tmp_str[l ++] = '\r'; tmp_str[l ++] = '\n'; tmp_str[l ++] = '\0'; printf("%s\r\n", (const char *) tmp_str); } } static void *tcp_server_handler(void *arg) { int domain = AF_INET; int type = SOCK_STREAM; int protocol = 0; int ret = -1; int nListenFd = -1; int port = *(int*)arg; struct sockaddr_in addr_in; int backlog = 5; // 默认是128 int len = 0; char chBuffer[1024] = {0}; int flags = 0; int nClientSocket = -1; int nMaxFd = -1; int i = 0; fd_set readfds; static const int kOn = 1; nListenFd = socket(domain, type, protocol); if (nListenFd < 0) { printf("socket failed ! errno[%d] err[%s]\n", errno, strerror(errno)); return NULL; } setsockopt(nListenFd, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn)); memset(&addr_in, 0, sizeof(struct sockaddr_in)); addr_in.sin_family = AF_INET; addr_in.sin_port = htons(port); //htons的返回值是16位的网络字节序整型数 htons尾的字母s代表short addr_in.sin_addr.s_addr = htonl(INADDR_ANY); ret = bind(nListenFd, (struct sockaddr *)(&addr_in), sizeof(struct sockaddr_in)); if (ret < 0) { printf("bind failed ! errno[%d] err[%s]\n", errno, strerror(errno)); close(nListenFd); //避免资源泄漏 return NULL; } ret = listen(nListenFd, backlog); if (ret < 0) { printf("listen failed ! errno[%d] err[%s]\n", errno, strerror(errno)); close(nListenFd); //避免资源泄漏 return NULL; } nMaxFd = nListenFd; while (!g_exit) { struct timeval stuTime; int time_out_ms = 3000; int num = 0; FD_ZERO(&readfds); FD_SET(nListenFd, &readfds); if (nClientSocket != -1) FD_SET(nClientSocket, &readfds); memset(&stuTime, 0, sizeof(struct timeval)); stuTime.tv_sec = time_out_ms / 1000; stuTime.tv_usec = 1000 * (time_out_ms % 1000); num = select(nMaxFd + 1, &readfds, NULL, NULL, &stuTime); if (num > 0) { if (nClientSocket != -1 && FD_ISSET(nClientSocket, &readfds)) { len = recv(nClientSocket, chBuffer, sizeof(chBuffer), flags); //flags为0,阻塞模式 if (len == 0) { printf("Recv ret:%d errno:%d\n", ret, errno); printf("recv error:%s\n", strerror(errno)); //server close or recv timeout printf("recv failed ! errno[%d] err[%s] len[%d]\n", errno, strerror(errno), len); close(nClientSocket); FD_CLR(nClientSocket, &readfds); nClientSocket = -1; } else if (len < 0) { if (!(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) { printf("recv error:%s\n", strerror(errno)); printf("recv failed ! errno[%d] err[%s] len[%d]\n", errno, strerror(errno), len); close(nClientSocket); FD_CLR(nClientSocket, &readfds); nClientSocket = -1; } } else { //print_hex(chBuffer, sizeof(chBuffer), NULL); RevLogDataHandler(chBuffer, len); } } if (FD_ISSET(nListenFd, &readfds)) { nClientSocket = accept(nListenFd, (struct sockaddr *)NULL, NULL); //阻塞模式 if (nClientSocket < 0) { printf("accept failed ! errno[%d] err[%s]\n", errno, strerror(errno)); //close(nListenFd); //避免资源泄漏 break; } printf("new client nClientSocket[%d]\n", nClientSocket); if (port == LOG_REQ_PORT && log_start_req == 1) { logSendFrame(nClientSocket, 0x0a, 0x10, 0, &log_start_req, sizeof(log_start_req)); log_start_req = 0; } if (nClientSocket > nMaxFd) nMaxFd = nClientSocket; if (port == LOG_REQ_PORT) log_req_socket = nClientSocket; else if (port == LOG_TFR_PORT) log_tfr_socket = nClientSocket; } } else if (num == 0) { //printf("\n time out \n"); //return 0; } else { printf("error \n"); //return -1; } } printf("tcp_server_handler port=%d exit.\n", port); if (nClientSocket != -1) close(nClientSocket); close(nListenFd); return 0; } void exit_sighandler(int signo) { printf("exit_handler\n"); g_exit = 1; } int main(int argc ,char *argv[]) { int reqport = LOG_REQ_PORT; int tfrport = LOG_TFR_PORT; log_frame_buf = malloc(FRAME_MAX_LEN); if (!log_frame_buf) { printf("log_frame_buf malloc fail.\n"); return -1; } signal(SIGTERM, exit_sighandler); signal(SIGINT, exit_sighandler); pthread_create(&req_thread_id, NULL, tcp_server_handler, &reqport); pthread_create(&tfr_thread_id, NULL, tcp_server_handler, &tfrport); pthread_join(req_thread_id, NULL); pthread_join(tfr_thread_id, NULL); free(log_frame_buf); return 0; }