heyuanjie87 6 лет назад
Сommit
ae53829ca5
9 измененных файлов с 1062 добавлено и 0 удалено
  1. 20 0
      README.md
  2. 22 0
      SConscript
  3. 150 0
      examples/msgrs.c
  4. 48 0
      examples/wm_fwup.c
  5. 24 0
      examples/wm_fwup.h
  6. 507 0
      ipmsg.c
  7. 74 0
      ipmsg.h
  8. 160 0
      ipmsg_filerecv.c
  9. 57 0
      ipmsgdef.h

+ 20 - 0
README.md

@@ -0,0 +1,20 @@
+# ipmsg(飞鸽传书) implementation in RT-Thread
+
+## 1. 功能
+- 收发文本消息
+- 接收文件(单个每次)
+
+## 2. 配置
+```
+//rtconfig.h
+
+#define IPMSG_MSGRS_ENABLE    //启用ipmsg
+#define IPMSG_FILERECV_ENABLE //启用文件接收服务
+
+#define IPMSG_MSG_BUFSZ 300   //消息缓冲区,不定义默认300字节
+#define IPMSG_FILERECV_BUFSZ   1024 //文件接收缓冲区,不定义默认1024字节
+
+```
+
+## 3. 示例
+- [消息收发服务](examples/msgrs.c)

+ 22 - 0
SConscript

@@ -0,0 +1,22 @@
+Import('RTT_ROOT')
+Import('rtconfig')
+from building import *
+
+cwd = GetCurrentDir()
+CPPPATH = [cwd]
+
+src = Split('''
+        ipmsg.c
+        ''')
+
+if GetDepend('IPMSG_MSGRS_ENABLE'):
+    src += ['examples/msgrs.c']
+    if GetDepend('SOC_W600_A8xx'):
+        src += ['examples/wm_fwup.c']
+
+if GetDepend('IPMSG_FILERECV_ENABLE'):
+    src += ['ipmsg_filerecv.c']
+
+group = DefineGroup('ipmsg', src, depend = ['PKG_USING_IPMSG'], CPPPATH = CPPPATH)
+
+Return('group')

+ 150 - 0
examples/msgrs.c

@@ -0,0 +1,150 @@
+#include <rtthread.h>
+#include "../ipmsg.h"
+#include <string.h>
+
+#define DBG_TAG "msgrs"
+#define DBG_LVL DBG_LOG
+#include <rtdbg.h>
+
+#if (defined(SOC_W600_A8xx))
+#include "wm_fwup.h"
+static T_BOOTER _booter;
+
+static int file_notify(struct ipmsg_filehandler *h, ipmsg_fileevent_t e, void *arg)
+{
+    LOG_I("notify %d", e);
+
+    switch (e)
+    {
+    case IPMSG_FE_OPEN:
+        h->usrdata = 0;
+        h->param = 0;
+        break;
+    case IPMSG_FE_COMPLETE:
+        tls_fwup_img_update_header(&_booter);
+        break;
+    }
+
+    return 0;
+}
+
+static int file_data(struct ipmsg_filehandler *h, void *buf, int size)
+{
+    if (h->usrdata == 0)
+    {
+        memcpy(&_booter, buf, sizeof(_booter));
+        tls_fwup_img_write(h->usrdata, (char*)buf + sizeof(_booter), size - sizeof(_booter));
+        h->usrdata += (size - sizeof(_booter));
+    }
+    else
+    {
+        tls_fwup_img_write(h->usrdata, buf, size);
+        h->usrdata += size;
+    }
+
+    return size;
+}
+#else
+static int file_notify(struct ipmsg_filehandler *h, ipmsg_fileevent_t e, void *arg)
+{
+    LOG_I("notify %d", e);
+
+    return 0;
+}
+
+static int file_data(struct ipmsg_filehandler *h, void *buf, int size)
+{
+    LOG_I("data %d", size);
+
+    return size;
+}
+#endif
+
+static void text_msg(ipmsg_t *im, uint32_t ip, const char *buf)
+{
+    if (strncmp(buf, "rename ", 7) == 0)
+    {
+        ipmsg_user_set(im, buf + 7);
+
+        ipmsg_msg_send(im, ip, "YiJingGaiLe");
+        return;
+    }
+
+    if (strncmp(buf, "reboot", 7) == 0)
+    {
+        ipmsg_msg_send(im, ip, "ShaoHouChongQi");
+
+        rt_thread_mdelay(100);
+        rt_hw_cpu_reset();
+        return;
+    }
+
+    ipmsg_msg_send(im, ip, "ShouDao");
+}
+
+static int fileattach_msg(ipmsg_t *im, ipmsg_filehandler_t *fh)
+{
+    int ret = 0;
+
+    fh->data = file_data;
+    fh->notify = file_notify;
+
+    return ret;
+}
+
+static const ipmsg_msghandler_t _h =
+{
+    text_msg,
+    fileattach_msg,
+};
+
+static void msg_server(void *p)
+{
+    ipmsg_t im;
+    rt_tick_t t = 0;
+
+    while (1)
+    {
+        rt_thread_mdelay(5000);
+
+        if (ipmsg_msgserver_init(&im, 2425) == 0)
+            break;
+    }
+
+    LOG_D("login");
+    ipmsg_login(&im);
+
+    while (1)
+    {
+        if ((rt_tick_get() - t) > (RT_TICK_PER_SECOND * 60))
+        {
+            t = rt_tick_get();
+            ipmsg_login(&im);
+        }
+
+        ipmsg_msg_recv(&im, 100, &_h);
+    }
+
+    ipmsg_msgserver_deinit(&im);
+}
+
+int ipmsg_msgrs_init(void)
+{
+    rt_thread_t tid;
+    int ret = -1;
+
+    tid = rt_thread_create("ipmsg-m",
+                           msg_server,
+                           0,
+                           2048,
+                           22,
+                           20);
+
+    if (tid)
+    {
+        ret = rt_thread_startup(tid);
+    }
+
+    return ret;
+}
+INIT_APP_EXPORT(ipmsg_msgrs_init);

+ 48 - 0
examples/wm_fwup.c

@@ -0,0 +1,48 @@
+#include "wm_internal_flash.h"
+#include "wm_flash.h"
+#include "wm_crypto_hard.h"
+#include "wm_flash_map.h"
+#include "wm_fwup.h"
+
+#define CODE_UPD_HEADER_ADDR    0x80FC000
+#define WM_UPDATE_BASE  (0x8090000)
+
+void tls_fwup_img_update_header(T_BOOTER* img_param)
+{
+	unsigned char current_img;	
+	psCrcContext_t	crcContext;
+	T_BOOTER imgheader[2];
+
+	tls_fls_read(CODE_RUN_HEADER_ADDR, (unsigned char *)&imgheader[0], sizeof(T_BOOTER));
+	tls_fls_read(CODE_UPD_HEADER_ADDR, (unsigned char *)&imgheader[1], sizeof(T_BOOTER));
+
+	//将两个upd_no中较大的那个值取出来,再将其加1后赋值给 CODE_UPD_HEADER_ADDR 处的header;
+	if (tls_fwup_img_header_check(&imgheader[1]))
+	{
+		current_img = (imgheader[1].upd_no > imgheader[0].upd_no);
+	}
+	else
+	{
+		current_img = 0;
+	}
+	img_param->upd_no = imgheader[current_img].upd_no + 1;
+
+	tls_crypto_crc_init(&crcContext, 0xFFFFFFFF, CRYPTO_CRC_TYPE_32, 3);
+	tls_crypto_crc_update(&crcContext, (unsigned char *)img_param, sizeof(T_BOOTER)-4);
+	tls_crypto_crc_final(&crcContext, &img_param->hd_checksum);
+	tls_fls_write(CODE_UPD_HEADER_ADDR,  (unsigned char *)img_param,  sizeof(T_BOOTER));
+}
+
+int tls_fwup_img_write(unsigned int offset, void *buf, int size)
+{
+    uint32_t addr = WM_UPDATE_BASE + offset;
+
+    return tls_fls_write(addr, buf, size);
+}
+
+int tls_fwup_flash_erase(unsigned int offset)
+{
+    uint32_t addr = WM_UPDATE_BASE + offset;
+
+    return tls_fls_erase(addr/4096);
+}

+ 24 - 0
examples/wm_fwup.h

@@ -0,0 +1,24 @@
+#ifndef _WM_FWUP_H
+#define _WM_FWUP_H
+
+typedef struct __T_BOOTER
+{
+	unsigned int   	magic_no;
+	unsigned short 	img_type;			
+	unsigned short 	zip_type;				/** image type zip flag, 0: non-zip, 1:zip*/
+	unsigned int   	run_img_addr;         	/** run area image start address */
+	unsigned int   	run_img_len;			/** run area image length */
+	unsigned int	run_org_checksum; 		/** run area image checksum */
+	unsigned int    upd_img_addr;			/** upgrade area image start address*/
+	unsigned int    upd_img_len;			/** upgrade area image length*/
+	unsigned int 	upd_checksum;			/** upgrade area image checksum */
+	unsigned int   	upd_no;
+	unsigned char  	ver[16];
+	unsigned int 	hd_checksum;
+} T_BOOTER;
+
+void tls_fwup_img_update_header(T_BOOTER* img_param);
+int tls_fwup_img_write(unsigned int offset, void *buf, int size);
+int tls_fwup_flash_erase(unsigned int offset);
+
+#endif

+ 507 - 0
ipmsg.c

@@ -0,0 +1,507 @@
+
+/*
+ * Copyright (c) 2018, Real-Thread Information Technology Ltd
+ * All rights reserved
+ *
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2019-04-24     heyuanjie87  the first version
+ */
+
+#include <sys/socket.h>
+#include "netdb.h"
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#include "ipmsg.h"
+#include "ipmsgdef.h"
+
+#define DBG_TAG "ipmsg"
+#define DBG_LVL DBG_INFO /* DBG_ERROR */
+#include <rtdbg.h>
+
+#ifndef IPMSG_MSG_BUFSZ
+#define IPMSG_MSG_BUFSZ 300
+#endif
+
+typedef struct
+{
+    char *ver;
+    char *id;
+    char *user;
+    char *host;
+    uint32_t cmd;
+    char *ext;
+    char *attach;
+    int asz;
+} ipmsg_msgfm_t;
+
+static int udp_send(ipmsg_t *im, uint32_t ip, void *buf, int size)
+{
+    struct sockaddr_in addr;
+
+    memset(&addr, 0, sizeof(addr));
+
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons(im->port);
+    addr.sin_addr.s_addr = ip;
+
+    // Send string to address to
+    if ((sendto(im->skudp, buf, size, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr))) == -1)
+    {
+        LOG_E("udp send");
+        return -1;
+    }
+
+    return 0;
+}
+
+static int udp_recv(ipmsg_t *im, uint32_t *ip, void *buf, int size)
+{
+    struct sockaddr_in addr;
+    socklen_t al = sizeof(struct sockaddr);
+    int ret;
+
+    ret = recvfrom(im->skudp, buf, size, 0, (struct sockaddr *)&addr, &al);
+    *ip = addr.sin_addr.s_addr;
+
+    return ret;
+}
+
+static char *strtokc(char *str, char d, char **save)
+{
+    char *p;
+    char *ret;
+
+    if (str)
+        p = str;
+    else
+        p = *save;
+    ret = p;
+
+    while (*p)
+    {
+        if (*p == d)
+        {
+            *p = 0;
+            p++;
+            *save = p;
+            break;
+        }
+        p++;
+    }
+
+    if (ret == p)
+        ret = NULL;
+
+    return ret;
+}
+
+static int msg_unpack(char *buf, int size, ipmsg_msgfm_t *fm)
+{
+    char *str = buf;
+    char *save = NULL;
+    char *p;
+    int item = 0;
+    int s1len;
+
+    while ((item < 6) && ((p = strtokc(str, ':', &save)) != NULL))
+    {
+        switch (item)
+        {
+        case 1:
+            fm->id = p;
+        case 4:
+            fm->cmd = (uint32_t)atoi(p);
+            break;
+        case 5:
+            fm->ext = p;
+            break;
+        }
+
+        item++;
+        str = NULL;
+    }
+
+    if (item == 5)
+    {
+        fm->ext = save;
+        item++;
+    }
+
+    s1len = save - buf;
+    if (size > s1len)
+    {
+        fm->attach = ++save;
+        fm->asz = size - s1len;
+    }
+    else
+    {
+        fm->attach = NULL;
+        fm->asz = 0;
+    }
+
+    return (item == 6);
+}
+
+#ifdef IPMSG_FILERECV_ENABLE
+static uint32_t htoud(char *str)
+{
+    uint32_t ret = 0;
+    int len;
+    char *p;
+    int pos;
+
+    len = strlen(str);
+    p = str + len;
+    if (len > 8)
+        len = 8;
+
+    for (pos = 0; pos < len; pos++)
+    {
+        uint32_t v = 0;
+
+        p--;
+        if ((*p >= '0') && (*p <= '9'))
+            v = *p - '0';
+        else if ((*p >= 'a') && (*p <= 'f'))
+            v = *p - 'a' + 10;
+        else if ((*p >= 'A') && (*p <= 'F'))
+            v = *p - 'A' + 10;
+
+        v = (v << (pos * 4));
+        ret |= v;
+    }
+
+    return ret;
+}
+
+static int _fileinfo_get(ipmsg_fileinfo_t *fi, char *src, int *pos)
+{
+    char *str;
+    char *save = NULL;
+    char *p;
+    int item = 0;
+
+    str = &src[*pos];
+    while ((item < 5) && ((p = strtokc(str, ':', &save)) != NULL))
+    {
+        switch (item)
+        {
+        case 0:
+            fi->id = (uint32_t)atoi(p);
+        case 1:
+            fi->name = p;
+            break;
+        case 2:
+            fi->size = htoud(p);
+            break;
+        case 3:
+            break;
+        case 4:
+            fi->attr = htoud(p);
+            break;
+        }
+
+        item++;
+        str = NULL;
+    }
+
+    return (item >= 5);
+}
+
+static ipmsg_filehandler_t *fileinfo_unpack(char *str, int size)
+{
+    ipmsg_fileinfo_t fi = {0};
+    int pos = 0;
+    ipmsg_filehandler_t *fh = NULL;
+
+    LOG_I("[file] %s \n[%d]", str, size);
+
+    if ((fh = rt_calloc(1, sizeof(*fh))) == NULL)
+        return NULL;
+
+    if (_fileinfo_get(&fi, str, &pos))
+    {
+        ipmsg_fileinfo_t *p;
+        /* only surpport FILE */
+        if (fi.attr != IPMSG_FILE_REGULAR)
+            goto _out;
+
+        p = rt_malloc(sizeof(*p) + strlen(fi.name) + 1);
+        if (p)
+        {
+            *p = fi;
+            p->name = (char *)((char *)p + sizeof(*p));
+            strcpy(p->name, fi.name);
+
+            fh->fi = p;
+        }
+    }
+
+_out:
+    if (fh->fi == NULL)
+    {
+        ipmsg_filehandler_free(fh);
+        fh = NULL;
+    }
+
+    return fh;
+}
+#endif
+
+static char *make_msg(ipmsg_t *im, uint32_t cmd, char *ext, char *group, int *len)
+{
+    *len = IPMSG_MSG_BUFSZ;
+    return ipmsg_msg_make(im, cmd, ext, group, im->msgbuf, len);
+}
+
+static int msg_send(ipmsg_t *im, uint32_t ip, uint32_t cmd, char *ext, char *group)
+{
+    char *str;
+    int size;
+
+    str = make_msg(im, cmd, ext, group, &size);
+    if (str == NULL)
+        return 0;
+
+    return udp_send(im, ip, str, size);
+}
+
+int ipmsg_sock_wait(int socket, long ms)
+{
+    struct timeval timeout;
+    fd_set fds;
+
+    timeout.tv_sec = 0;
+    timeout.tv_usec = ms * 1000;
+
+    FD_ZERO(&fds);
+    FD_SET(socket, &fds);
+
+    return select(socket + 1, &fds, 0, 0, &timeout);
+}
+
+char *ipmsg_msg_make(ipmsg_t *im, uint32_t cmd, char *ext, char *group, char *dst, int *len_io)
+{
+    uint32_t id;
+    int n, l = 0;
+    char *p;
+    int bufsz = *len_io;
+
+    p = dst;
+    id = rt_tick_get();
+    n = snprintf(p, *len_io, "1:%d:%s:%s:%d:",
+                 id, im->user, im->host, cmd);
+
+    if (ext)
+    {
+        l = strlen(ext);
+        if ((n + l) > bufsz)
+            return NULL;
+        p += n;
+        strcat(p, ext);
+        p += l;
+        *p = 0;
+        p++;
+        l += 1;
+
+        *len_io = n + l;
+    }
+
+    if (group)
+    {
+        l += strlen(group);
+        if ((n + l) <= bufsz)
+        {
+            *p = 0;
+            strcat(p, group);
+            l += 1;
+
+            *len_io = n + l;
+        }
+    }
+
+    return dst;
+}
+
+int ipmsg_msgserver_init(ipmsg_t *im, short port)
+{
+    struct sockaddr_in server_addr;
+    int broadcast = 1;
+
+    strcpy(im->user, "user");
+    strcpy(im->host, "rtthread");
+    strcpy(im->group, "iot");
+    im->port = port;
+
+    if ((im->skudp = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
+    {
+        LOG_E("Create socket error");
+        return -1;
+    }
+
+    server_addr.sin_family = AF_INET;
+    server_addr.sin_port = htons(port);
+    server_addr.sin_addr.s_addr = INADDR_ANY;
+    memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
+
+    if (bind(im->skudp, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
+    {
+        LOG_E("Unable to bind");
+        goto _exit;
+    }
+
+    // Enable broadcast option
+    if ((setsockopt(im->skudp, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast))) == -1)
+    {
+        LOG_E("setsockopt(udp, SO_BROADCAST)");
+        goto _exit;
+    }
+
+    if ((im->msgbuf = rt_malloc(IPMSG_MSG_BUFSZ * 2 + 2)) == 0)
+    {
+        LOG_E("no mem");
+        goto _exit;
+    }
+    im->mrbuf = im->msgbuf + IPMSG_MSG_BUFSZ + 1;
+
+    return 0;
+
+_exit:
+    closesocket(im->skudp);
+
+    return -1;
+}
+
+void ipmsg_msgserver_deinit(ipmsg_t *im)
+{
+    closesocket(im->skudp);
+    rt_free(im->msgbuf);
+}
+
+int ipmsg_login(ipmsg_t *im)
+{
+    int ret;
+
+    ret = msg_send(im, 0xFFFFFFFF, IPMSG_BR_ENTRY, im->user, im->group);
+
+    return ret;
+}
+
+int ipmsg_msg_recv(ipmsg_t *im, int ms, const ipmsg_msghandler_t *h)
+{
+    int ret;
+
+    ret = ipmsg_sock_wait(im->skudp, ms);
+    if (ret > 0)
+    {
+        uint32_t ip;
+        ipmsg_msgfm_t fm;
+
+        ret = udp_recv(im, &ip, im->mrbuf, IPMSG_MSG_BUFSZ + 1);
+        if (ret <= 0)
+            return -1;
+        if (ret == (IPMSG_MSG_BUFSZ + 1))
+            return ret;
+        if (!msg_unpack(im->mrbuf, ret, &fm))
+        {
+            LOG_W("frame err");
+            return ret;
+        }
+
+        switch (fm.cmd & 0xff)
+        {
+        case IPMSG_BR_ENTRY:
+        {
+            msg_send(im, ip, IPMSG_ANSENTRY, im->user, im->group);
+        }
+        break;
+        case IPMSG_ANSENTRY:
+        {
+        }
+        break;
+        case IPMSG_SENDMSG:
+        {
+            msg_send(im, ip, IPMSG_RECVMSG, fm.id, im->group);
+
+            if (fm.cmd & IPMSG_FILEATTACHOPT)
+            {
+#ifdef IPMSG_FILERECV_ENABLE
+                if (h->fileattach)
+                {
+                    ipmsg_filehandler_t *fh;
+
+                    if ((fh = fileinfo_unpack(fm.attach, fm.asz)) == NULL)
+                    {
+                        LOG_E("fileinfo");
+                        break;
+                    }
+
+                    fh->ip = ip;
+                    fh->im = im;
+                    fh->packetid = (uint32_t)atoi(fm.id);
+                    ret = h->fileattach(im, fh);
+                    if ((ret == 0) && fh->notify && fh->data)
+                        ret = ipmsg_filerecv_start(fh);
+                    else
+                        ret = 1;
+
+                    if (ret != 0)
+                        ipmsg_filehandler_free(fh);
+                }
+#endif
+            }
+            else
+            {
+                if (h->msg)
+                    h->msg(im, ip, fm.ext);
+            }
+        }
+        break;
+        case IPMSG_RECVMSG:
+        {
+        }
+        break;
+        case IPMSG_BR_EXIT:
+        {
+        }
+        break;
+        case IPMSG_READMSG:
+        {
+        }
+        break;
+        default:
+        {
+            LOG_W("msgrecv cmd 0x%X", fm.cmd);
+        }
+        break;
+        }
+    }
+
+    return ret;
+}
+
+void ipmsg_filehandler_free(ipmsg_filehandler_t *h)
+{
+    rt_free(h->fi);
+    rt_free(h);
+}
+
+int ipmsg_msg_send(ipmsg_t *im, uint32_t ip, const char *str)
+{
+    return msg_send(im, ip, IPMSG_SENDMSG, (char *)str, NULL);
+}
+
+int ipmsg_user_set(ipmsg_t *im, const char *name)
+{
+    strncpy(im->user, name, 24);
+
+    return 0;
+}

+ 74 - 0
ipmsg.h

@@ -0,0 +1,74 @@
+#ifndef _IPMSG_H_
+#define _IPMSG_H_
+
+#include <stdint.h>
+
+typedef struct
+{
+    int skudp;
+    short port;
+    char *msgbuf;
+    char *mrbuf;
+    char user[24+1];
+    char host[24+1];
+    char group[24+1];
+
+    long usrdata;
+} ipmsg_t;
+
+typedef struct ipmsg_fileinfo
+{
+    uint32_t id;
+    char *name;
+    uint32_t size;
+    uint32_t attr;
+
+    struct ipmsg_fileinfo *next;
+}ipmsg_fileinfo_t;
+
+typedef enum
+{
+    IPMSG_FE_ENTER,
+    IPMSG_FE_EXIT,
+    IPMSG_FE_OPEN,
+    IPMSG_FE_CLOSE,
+    IPMSG_FE_COMPLETE,
+}ipmsg_fileevent_t;
+
+typedef struct ipmsg_filehandler
+{
+    ipmsg_t *im;
+    ipmsg_fileinfo_t *fi;
+    uint32_t ip;
+    uint32_t packetid;
+
+    /* used by user */
+    long usrdata;
+    uint32_t param;
+
+    /* init by user */
+    int (*notify)(struct ipmsg_filehandler *h, ipmsg_fileevent_t e, void *arg);
+    int (*data)(struct ipmsg_filehandler *h, void *buf, int size);
+}ipmsg_filehandler_t;
+
+typedef struct
+{
+    void (*msg)(ipmsg_t *im, uint32_t ip, const char *str);
+    int (*fileattach)(ipmsg_t *im, ipmsg_filehandler_t *fh);
+}ipmsg_msghandler_t;
+
+int ipmsg_msgserver_init(ipmsg_t *im, short port); /* default port = 2425 */
+void ipmsg_msgserver_deinit(ipmsg_t *im);
+int ipmsg_login(ipmsg_t *im);
+int ipmsg_msg_recv(ipmsg_t *im, int ms, const ipmsg_msghandler_t *h);
+int ipmsg_msg_send(ipmsg_t *im, uint32_t ip, const char *str);
+int ipmsg_user_set(ipmsg_t *im, const char *name);
+void ipmsg_filehandler_free(ipmsg_filehandler_t *h);
+
+char *ipmsg_msg_make(ipmsg_t *im, uint32_t cmd, char *ext, char *group, char *dst, int *len_io);
+
+int ipmsg_sock_wait(int socket, long ms);
+
+int ipmsg_filerecv_start(ipmsg_filehandler_t *h);
+
+#endif

+ 160 - 0
ipmsg_filerecv.c

@@ -0,0 +1,160 @@
+#include <rtthread.h>
+#include "ipmsg.h"
+#include "ipmsgdef.h"
+
+#include <sys/socket.h>
+#include "netdb.h"
+
+#define DBG_TAG "ipmsgfr"
+#define DBG_LVL DBG_LOG
+#include <rtdbg.h>
+
+#ifndef IPMSG_FILERECV_BUFSZ
+#define IPMSG_FILERECV_BUFSZ 1024
+#endif
+
+#ifdef IPMSG_FILERECV_ENABLE
+
+static int ipmsg_getdata_req(int sk, ipmsg_filehandler_t *fh, ipmsg_fileinfo_t *fi, char *buf, int bufsz)
+{
+    char *msg;
+    char ext[24];
+    int len;
+
+    sprintf(ext, "%x:%x:0", fh->packetid, fi->id);
+    msg = ipmsg_msg_make(fh->im, IPMSG_GETFILEDATA, ext, NULL, buf, &bufsz);
+    len = send(sk, msg, bufsz, 0);
+
+    return (len == bufsz);
+}
+
+static int ipmsg_data_recv(int sk, ipmsg_filehandler_t *fh, ipmsg_fileinfo_t *fi, char *buf, int bufsz)
+{
+    int len;
+    int ret = -1;
+
+    if (ipmsg_sock_wait(sk, 2000) <= 0)
+        return 0;
+
+    len = recv(sk, buf, bufsz, 0);
+    if (len > 0)
+    {
+        ret = fh->data(fh, buf, len);
+        if (ret <= 0)
+            ret = 0;
+        else if (ret > 0)
+            fi->size -= ret;
+    }
+
+    if (fi->size == 0)
+    {
+        fh->notify(fh, IPMSG_FE_COMPLETE, fi);
+        ret = 0;
+    }
+
+    return (ret == len);
+}
+
+static int sock_init(ipmsg_filehandler_t *fh)
+{
+    struct sockaddr_in server_addr = {0};
+    int sock;
+
+    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+    {
+        LOG_E("Create socket error");
+        return -1;
+    }
+
+    server_addr.sin_family = AF_INET;
+    server_addr.sin_port = htons(fh->im->port);
+    server_addr.sin_addr.s_addr = fh->ip;
+
+    if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
+    {
+        LOG_E("Connect fail!");
+        closesocket(sock);
+        return -1;
+    }
+
+    return sock;
+}
+
+static void msg_server(void *p)
+{
+    int sock;
+    char *buf;
+    ipmsg_filehandler_t *fh = p;
+    int ret;
+    int stage = 0;
+
+    fh->notify(fh, IPMSG_FE_ENTER, NULL);
+
+    if ((sock = sock_init(fh)) < 0)
+        goto __exit;
+    if ((buf = rt_malloc(IPMSG_FILERECV_BUFSZ)) == NULL)
+        goto _out;
+
+    while (1)
+    {
+        switch (stage)
+        {
+        case 0:
+        {
+            if (fh->notify(fh, IPMSG_FE_OPEN, fh->fi) != 0)
+                goto _out;
+
+            if (ipmsg_getdata_req(sock, fh, fh->fi, buf, IPMSG_FILERECV_BUFSZ))
+                stage++;
+            else
+            {
+                //error
+                stage = 2;
+            }
+        }
+        break;
+        case 1:
+        {
+            if (!ipmsg_data_recv(sock, fh, fh->fi, buf, IPMSG_FILERECV_BUFSZ))
+            {
+                stage++;
+            }
+        }
+        break;
+        case 2:
+        {
+            fh->notify(fh, IPMSG_FE_CLOSE, fh->fi);
+        }
+            goto _out;
+        }
+    }
+
+_out:
+    closesocket(sock);
+    rt_free(buf);
+
+__exit:
+    fh->notify(fh, IPMSG_FE_EXIT, NULL);
+    ipmsg_filehandler_free(fh);
+}
+
+int ipmsg_filerecv_start(ipmsg_filehandler_t *h)
+{
+    rt_thread_t tid;
+    int ret = -1;
+
+    tid = rt_thread_create("ipmsg-r",
+                           msg_server,
+                           h,
+                           2048,
+                           22,
+                           20);
+
+    if (tid)
+    {
+        ret = rt_thread_startup(tid);
+    }
+
+    return ret;
+}
+#endif

+ 57 - 0
ipmsgdef.h

@@ -0,0 +1,57 @@
+#ifndef _IPMSGDEF_H
+#define _IPMSGDEF_H
+
+
+/*  command  */
+
+#define IPMSG_NOOPERATION		0x00000000UL
+#define IPMSG_BR_ENTRY			0x00000001UL
+#define IPMSG_BR_EXIT			0x00000002UL
+#define IPMSG_ANSENTRY			0x00000003UL
+#define IPMSG_BR_ABSENCE		0x00000004UL
+
+#define IPMSG_SENDMSG			0x00000020UL
+#define IPMSG_RECVMSG			0x00000021UL
+#define IPMSG_READMSG			0x00000030UL
+#define IPMSG_DELMSG			0x00000031UL
+#define IPMSG_ANSREADMSG		0x00000032UL
+
+#define IPMSG_GETFILEDATA		0x00000060UL
+#define IPMSG_RELEASEFILES		0x00000061UL
+#define IPMSG_GETDIRFILES		0x00000062UL
+
+/*  option for all command  */
+#define IPMSG_ABSENCEOPT		0x00000100UL
+#define IPMSG_SERVEROPT			0x00000200UL
+#define IPMSG_DIALUPOPT			0x00010000UL
+#define IPMSG_FILEATTACHOPT		0x00200000UL
+#define IPMSG_ENCRYPTOPT		0x00400000UL
+#define IPMSG_UTF8OPT			0x00800000UL
+#define IPMSG_CAPUTF8OPT		0x01000000UL
+#define IPMSG_ENCEXTMSGOPT		0x04000000UL
+#define IPMSG_CLIPBOARDOPT		0x08000000UL
+
+/*  option for send command  */
+#define IPMSG_SENDCHECKOPT		0x00000100UL
+#define IPMSG_SECRETOPT			0x00000200UL
+#define IPMSG_BROADCASTOPT		0x00000400UL
+#define IPMSG_MULTICASTOPT		0x00000800UL
+#define IPMSG_AUTORETOPT		0x00002000UL
+#define IPMSG_RETRYOPT			0x00004000UL
+#define IPMSG_PASSWORDOPT		0x00008000UL
+#define IPMSG_NOLOGOPT			0x00020000UL
+#define IPMSG_NOADDLISTOPT		0x00080000UL
+#define IPMSG_READCHECKOPT		0x00100000UL
+#define IPMSG_SECRETEXOPT		(IPMSG_READCHECKOPT|IPMSG_SECRETOPT)
+
+/* file types for fileattach command */
+#define IPMSG_FILE_REGULAR 0x00000001UL
+#define IPMSG_FILE_DIR 0x00000002UL
+#define IPMSG_FILE_RETPARENT 0x00000003UL  // return parent directory
+#define IPMSG_FILE_SYMLINK 0x00000004UL
+#define IPMSG_FILE_CDEV 0x00000005UL     // for UNIX
+#define IPMSG_FILE_BDEV 0x00000006UL     // for UNIX
+#define IPMSG_FILE_FIFO 0x00000007UL     // for UNIX
+#define IPMSG_FILE_RESFORK 0x00000010UL  // for Mac
+
+#endif