20170220_jeffrey - silenceuncrio/diary GitHub Wiki

0930

review

1005

利用 ASCIIFlow 來幫 webModuleInitWeb() 畫個流程示意圖

+---------------------+
|InitWeb              |
|  LoadDefault()      |
|  SysParsorTextFile()|
|                     |    +----------------------+
|  InitWebIptables()+------>InitWebIptables       |
|                     |    |  IPTF_JOIN_AND_NEW() |
|  ApplyWebSetting()  |    |  IP6TF_JOIN_AND_NEW()|
+---------------------+    +----------------------+

1020

繼續追 ApplyWebSetting()

webcfg.c

static int ApplyWebSetting(int flag, int index, void* pStruct, int structSize) {
    sWebConfig *pCfg = (sWebConfig *)pStruct;
    SysSaveBinaryFile(WEB_TMP_BIN_FILE, pCfg, sizeof(*pCfg));

    if (!IsBootInitProcess()) {
        LocSaveConfigTxt(WEB_TMP_CFG_FILE, pCfg);
        SysCopyFile(WEB_TMP_CFG_FILE, WEB_ETC_CFG_FILE);
    }

    ICOS_msg_sendto(MODULE_WEB,MODULE_WEB,pCfg,sizeof(sWebConfig),ICOS_UCAST_MODULE_APPLY);

    return ICOS_SUCCESS;
}

1025

ICOS_msg_sendto(MODULE_WEB,MODULE_WEB,pCfg,sizeof(sWebConfig),ICOS_UCAST_MODULE_APPLY)

icos_ipc.c

int ICOS_msg_sendto(int src_id, int dst_id, void *data, unsigned short data_sz, unsigned short event_id)
{
    int sending_sz = 0;
    int fd=-1, rc=0;
    PRO_EVENT promsg, *pmsg=NULL;

    pmsg = &promsg;
    pmsg->src_id = src_id;
    pmsg->dst_id = dst_id;
    pmsg->msg_len = data_sz;
    pmsg->event_id = event_id;
    pmsg->usret[0] = 0;
    if (data_sz>0)
        memcpy(pmsg->msg, data, data_sz);
    sending_sz = MSG_HEADER_LEN+data_sz;

    fd=socket(AF_UNIX, SOCK_DGRAM, 0);
    if (fd>=0)
    {
        struct sockaddr_un to;
        to.sun_family=AF_UNIX;
        snprintf(to.sun_path, UNIX_PATH_MAX, "%s/%s", PRO_USOCK_PATH, USOCKNAME_EVENT);
        rc=sendto(fd, pmsg, sending_sz, MSG_DONTROUTE|MSG_DONTWAIT, (struct sockaddr *)&to, sizeof(struct sockaddr_un));
        close(fd);
        goto END_RETURN;
    }
    rc = -2;

END_RETURN:
    if(data_sz > MAX_MSG_LEN && pmsg)
        free(pmsg);

    return rc;
}

ICOS_msg_sendto() 利用了 sockets 的技術

參考 Linux Programming Interface - 56. Sockets: Introduction

Sockets are a method of IPC that allow data to be exchanged between applications, either on the same host (computer) or on different hosts connected by a network.

使用 ICOS_msg_sendto() 的角色相當於一個 Client

那誰是 Server 的角色呢?

Server 提供了甚麼服務呢?

1110

M300 是由 icospromsg 扮演 Server 的角色

static int uscok_delete(int usock_fd)
{
    ...
    close(usock_fd);
    ...
    return 0;
}

static int uscok_create()
{
    struct sockaddr_un skadr_un;
    int svrsock;

    svrsock = socket(AF_UNIX, SOCK_DGRAM, 0);

    skadr_un.sun_family = AF_UNIX;
    sprintf(skadr_un.sun_path, "%s/%s", PRO_USOCK_PATH, USOCKNAME_EVENT);

    svrsock = socket(AF_UNIX, SOCK_DGRAM, 0);
    ...
    bind(svrsock, (struct sockaddr*)(&skadr_un), sizeof(struct sockaddr_un));
    ...
    return svrsock;
}

int main(int argc, char **argv)
{
    ...
    usock_fd=uscok_create();

    while (!G_loop_exit)
    {
        ...
    }//End_while

    uscok_delete(usock_fd);

    exit(0);
    return 0;
}

1305

ariel 反應 frimware upgrade 還是有問題

ariel 表示從 browser 的 console 看到

TypeError: Cannot read property 'curr_time' of undefined
    at firmware.js:68
...

我試著分析一下目前的 firmware.js

function firmwareController($route, $scope, $timeout, $location, icos, Upload, progress) {
    var vm = this;

    vm.progress = progress;

    vm.upgrade = function(_file) {
        if (_file) {
            ...
            Upload.upload({ url: 'api/firmwareUpload', data: data })
            .then(function(resp) {
                vm.progress = resp.data.info;
                return icos.firmware.upgrade();
            })
            .then(function(resp) {
                ...
                vm.timeout_2sec();
            });
        }
    }

    var timer_2sec;

    vm.timeout_2sec = function () {
        timer_2sec = $timeout(2000);
        timer_2sec.then(function () {
            icos.firmware.progress()
            .then(function(response) {
                vm.progress = response.data.progress;
                var busy_sec = (Date.parse(vm.progress.curr_time) - Date.parse(vm.progress.init_time))/1000
                ...
            });
        });
    }

}

vm.progress.curr_time 不存在的狀況下的確會造成問題

1400

發現是被我的 local.conf 害的

IMAGE_INSTALL_append += "nfs-utils vim jq curl"

目前 git server 上並沒有把 jq 加上去

也就是從 git server checkout 的 code build 完並沒有 jq 這個 tool 可以用

這會導致使用 jq 的 shell script 失敗

我先把自己的 local.conf 刪掉

把目前 Local 端的修改刪除

修改 prosrc_0.1.bb - 加上 jq

diff --git a/meta-proscend/recipes-core/prosrc/prosrc_0.1.bb b/meta-proscend/recipes-core/prosrc/prosrc_0.1.bb
old mode 100644
new mode 100755
index bce1618..14aa913
--- a/meta-proscend/recipes-core/prosrc/prosrc_0.1.bb
+++ b/meta-proscend/recipes-core/prosrc/prosrc_0.1.bb
@@ -16,7 +16,7 @@ INSANE_SKIP_${PN} += "already-stripped"
 INSANE_SKIP_${PN} += "installed-vs-shipped "

 # Runtime dependence
-RDEPENDS_${PN} += "ppp ppp-oe iptables iperf dnsmasq pptp-linux bridge-utils dhcp-server dhcp-client openvpn openssl openssl-conf iproute2 iproute2-tc procps socat strongswan cryptodev-module mtd-utils mtd-utils-ubifs imx-kobs tar bzip2"
+RDEPENDS_${PN} += "ppp ppp-oe iptables iperf dnsmasq pptp-linux bridge-utils dhcp-server dhcp-client openvpn openssl openssl-conf iproute2 iproute2-tc procps socat strongswan cryptodev-module mtd-utils mtd-utils-ubifs imx-kobs tar bzip2 jq"

 # Build dependence
 DEPENDS = "json-c rp-pppoe apr libxml2 libpcap sqlite3 xz"

1450

繼續 trace

M300 是由 icospromsg 扮演 Server 的角色

icospromsg 是怎麼處理來自於 ApplyWebSetting() 送來的 message 呢?

icospromsg.c

int main(int argc, char **argv)
{
    int usfd = -1, maxfd=0;
    int sel_ret = 0, read_bytes=0;
    struct timeval timeout;
    fd_set rdset;
    int usock_fd;
    static unsigned char *msg_buffer=NULL;

    usock_fd=uscok_create();
    usfd=usock_fd;
    fcntl(usock_fd, F_SETFD, FD_CLOEXEC);

    msg_buffer = (unsigned char *)malloc(FULL_MSG_LEN);

    while (!G_loop_exit)
    {
        timeout.tv_sec = 1;
        timeout.tv_usec = 0;
        FD_ZERO(&rdset);
        FD_SET(usfd, &rdset);
        maxfd=usfd;

        proc_FdSet(&rdset, &maxfd);

        sel_ret=0;
        sel_ret=select(maxfd+1, &rdset, 0, 0, &timeout);

        if (sel_ret > 0)
        {
            if (FD_ISSET(usfd, &rdset))
            {
                PRO_EVENT *pmsg=NULL;
                unsigned char *sp=msg_buffer;
                read_bytes = recv(usfd, sp, sizeof(PRO_EVENT),MSG_DONTWAIT | MSG_NOSIGNAL);
                pmsg = (PRO_EVENT*)sp;

                if (pmsg->dst_id == 0) // 0: means broadcast
                {
                    BroadcastHandle(pmsg);
                }
                else
                {
                    NotifyHandle(pmsg);
                }
            }
        }
    }//End_while

}

ApplyWebSetting() 送來的 message 會觸發 icospromsgNotifyHandle()

icospromsg.c

int NotifyHandle(PRO_EVENT *pmsg)
{
    int res=0;
    sIcosModule *pIcosModule;
    pIcosModule=GetIcosModule(pmsg->dst_id);

    if (pIcosModule->NotifyHandler)
    {
        res=pIcosModule->NotifyHandler(pmsg);
    }
    return res;
}

會發現 webModuleApplyWebSetting() 利用 ICOS_msg_sendto() 把 message 送到 icospromsg

然後 icospromsg 只是透過 message 內含的資訊又把 webModulenotify_web() 叫起來做事

不過要記住 webModule 不過是個 icos library

sIcosModule webModule={
    "web",                        // Name
    InitWeb,                      // Init
    ExitWeb,                      // Exit
    ApplyWebSetting,              // Apply
    GetWebSetting,                // GetSetting
    SetWebSetting,                // SetSetting
    VerifyWebSetting,             // VerifySetting
    0,                            // GetStatus
    0,                            // GetStatus
    facotry_default_web_setting,
    0,//period_ddns,
    notify_web,
    msgcb_web,
    termcb_web,
};

要有人呼叫才會做事的

所以重點在於是誰用它來做事

再回去看 rc.local

...
/usr/sbin/icospromsg &
/usr/sbin/icosconfig bootinit
...

icospromsg 先被叫起來常駐在背景執行

icosconfig bootinit 在被執行的當下

icospromsg 已經準備好處理任何利用 ICOS_msg_sendto() 所送來的 message 了

1550

試著來解析一下 /home/log/web.log

root@Mobile Router:/home/log# cat web.log
1487572072[20170220 6:27:52] [notify_web:871]IN(E82|S44|D44)
1487572072[20170220 6:27:52] [notify_web:880]module init
1487572079[20170220 6:27:59] [notify_web:871]IN(E62|S00|D00)
1487572079[20170220 6:27:59] [notify_web:905]boot init done
1487572079[20170220 6:27:59] [web_dump:609]===init config===
1487572079[20170220 6:27:59] [web_dump:619][COM]conn_mgr=1,mod_init_done:1.
1487572079[20170220 6:27:59] [web_dump:640][CFG]mode=httpd,httpd_port=80,https_port=443,refreshperiod=2,sport=80,intf=all,secure=all,clienip=0.0.0.0
1487572079[20170220 6:27:59] [web_dump:648][DMN0]active=1,pid=-1,status=0,flag=0x0,DID0
1487572079[20170220 6:27:59] [web_dump:648][DMN1]active=1,pid=-1,status=0,flag=0x0,DID1
1487572079[20170220 6:27:59] [web_dump:653][RTI]wan4_ifname=,wan6_ifname=.
1487572079[20170220 6:27:59] [daemon_restart:756][DID0] remain IP server retry for 6 times.
1487572079[20170220 6:27:59] [create_daemon_conf:664]IN
1487572079[20170220 6:27:59] [create_daemon_conf:675]cmd_buf=>dir=/
1487572079[20170220 6:27:59] [create_daemon_conf:680]cmd_buf=>cgipat=cgi-bin/**
1487572079[20170220 6:27:59] [create_daemon_conf:685]cmd_buf=>chroot
1487572079[20170220 6:27:59] [create_daemon_conf:690]cmd_buf=>user=root
1487572079[20170220 6:27:59] [create_daemon_conf:695]cmd_buf=>max_age=0
1487572079[20170220 6:27:59] [create_daemon_conf:700]cmd_buf=>debug
1487572079[20170220 6:27:59] [daemon_restart:781][DMN]Lanch=>/usr/sbin/iweb  -p 80 -d /www
1487572079[20170220 6:27:59] [daemon_restart:756][DID1] remain IP server retry for 6 times.
1487572079[20170220 6:27:59] [web_dump:609]===cfg not allowed===
1487572079[20170220 6:27:59] [web_dump:640][CFG]mode=httpd,httpd_port=80,https_port=443,refreshperiod=2,sport=80,intf=all,secure=all,clienip=0.0.0.0
1487572079[20170220 6:27:59] [web_dump:648][DMN0]active=1,pid=775,status=1,flag=0x0,DID0
1487572079[20170220 6:27:59] [web_dump:648][DMN1]active=1,pid=-1,status=0,flag=0x1,DID1
1487572079[20170220 6:27:59] [web_dump:609]===After daemon restart===
1487572079[20170220 6:27:59] [web_dump:619][COM]conn_mgr=1,mod_init_done:1.
1487572079[20170220 6:27:59] [web_dump:640][CFG]mode=httpd,httpd_port=80,https_port=443,refreshperiod=2,sport=80,intf=all,secure=all,clienip=0.0.0.0
1487572079[20170220 6:27:59] [web_dump:648][DMN0]active=1,pid=775,status=1,flag=0x0,DID0
1487572079[20170220 6:27:59] [web_dump:648][DMN1]active=1,pid=-1,status=0,flag=0x0,DID1
1487572079[20170220 6:27:59] [web_dump:653][RTI]wan4_ifname=,wan6_ifname=.
1487572079[20170220 6:27:59] [notify_web:871]IN(E50|S59|D00)
1487572082[20170220 6:28:2] [msgcb_web:1155]IN(DID0,pid 775)
<--
Icos_user_root.session_ttl: 300 sec
Icos_user_root.user: root
Icos_user_root.pass: $1$$2Dg0uARUa9gcTJ9I5/iKb/
Starting iweb on port 80, serving /www
-->
1487572082[20170220 6:28:2] [notify_web:871]IN(E53|S50|D00)
1487572082[20170220 6:28:2] [notify_web:871]IN(E02|S56|D00)
1487572083[20170220 6:28:3] [notify_web:871]IN(E01|S56|D00)
1487572084[20170220 6:28:4] [notify_web:871]IN(E43|S35|D00)

直接從第一行看起 1487572072[20170220 6:27:52] [notify_web:871]IN(E82|S44|D44)

這是由目前 webcfg.c 的 第 871 行的 WEB_INFO 所打印的

#define WEB_INFO(FMT, ARG...)     IPC_filelog_v2(WEB_LOG,IPCF_LOGMAX, __FUNCTION__, __LINE__,IPCFv2_SHOW_TIME, FMT, ##ARG)

static int notify_web(PRO_EVENT *pevent)
{
    ...
    WEB_INFO("IN(E%02d|S%02d|D%02d)\n",pevent->event_id,pevent->src_id,pevent->dst_id);
    ...
}

來看 1487572072[20170220 6:27:52] [notify_web:871]IN(E82|S44|D44) 裡的 (E82|S44|D44)

先看 E82 - event_id = 82

定義在 icos_shm.h

// All Events ID
typedef enum
{
// COMMON_GRP
    ICOS_CHG_WPROTO = 1,
    ICOS_CHG_CONN_TYPE,
//SYSTEM_GRP
    ICOS_AC_ADAPTER=10,
    ICOS_WAN_SWITCH,  // Switch Router / Bridge mode
    ICOS_SYSTEM_SHUTDOWN,
    ICOS_SYSTEM_REBOOT,
    ICOS_IPV6_FUNCTION,
//LTE_GRP
    ICOS_WLTE_PPP_UP=20,
    ICOS_WLTE_PPP_DOWN,
//WWIFI_GRP
    ICOS_WWIFI_LOST_ASSOCIATION=30, //lost association then wifi just stop
    ICOS_WWIFI_GOT_CONNECTION,
    ICOS_WWIFI_ENABLE,
    ICOS_WWIFI_DISABLE,
    ICOS_WWIFI_REAUTH,
//ETHERNET_GRP: Please with interface name and length as argument
    ICOS_WETH_LINK_DOWN=40, // Wan cable plug out
    ICOS_WETH_LINK_UP, // Wan cable plug in
    ICOS_ETH_LINK_DOWN, // Lan cable plug out
    ICOS_ETH_LINK_UP, // Lan cable plug in
    ICOS_WETH_PPP_UP,
    ICOS_WETH_PPP_DOWN,
// IP_UPDATE_GRP
    ICOS_LAN_IP_UPDATE=50,
    ICOS_WAN_IP_UPDATE,
    ICOS_WAN_LOST_CONNECTION,
    ICOS_LAN6_IP_UPDATE,
    ICOS_WAN6_IP_UPDATE,
    ICOS_WAN6_LOST_CONNECTION,
    ICOS_WAN_CFG_UPDATE,   //For dns decision wan is static or dynamic IP, John20160406
    ICOS_WAN_GATEWAY_UPDATE,
    ICOS_WAN6_GATEWAY_UPDATE,
// LAUNCH PROCESS
    ICOS_LAUNCH_PROCESS=60,  // launch process
    ICOS_KILL_PROCESS,  // kill process
    ICOS_BOOTINIT_DONE,  // icos module init done
//=====NOT broadcast event======
// MODULE ACTION
    ICOS_UCAST_MODULE_INIT=80,   //Module Init indication; NOT broadcast event
    ICOS_UCAST_MODULE_EXIT,   	// 81:Module Exit indication; NOT broadcast event
    ICOS_UCAST_MODULE_APPLY,  	// 82:Module Apply indication; NOT broadcast event
    ICOS_UCAST_CHG_WPROTO,    	// 83:Web UI -> connmgr to change active wan protocol
    ICOS_UCAST_JSON_DATA,  // 84:JSON data unicast notification
    ICOS_UCAST_WLTE_MODEM_READ_DONE, // 85:read_modem -> lte module
    ICOS_UCAST_WLTE_PPPD_LAUNCH, // 86:lte connect thread -> lte module
    ICOS_UCAST_WLTE_CONNECT_ACTION,  // 87:lte module only
    ICOS_UCAST_NWST_EVT_UPDATE, // 88:netmon -> netmond
    ICOS_UCAST_NWST_CFG_UPDATE, // 89:netmon -> netmond
    ICOS_UCAST_DNS_CFG_UPDATE,	// 90:dns_ext6 -> wan static
    ICOS_UCAST_WLTE_CHG_NETMODE, // 91:lte_t -> lte (1: LTE only; 2: 3G only; 3: GSM only; others: AUTO
    ICOS_UCAST_WLTE_DISCONNECT,  // 92:lte_t -> lte (test disconnect and then automatically reconnect)
} ICOS_EVENT_ID_E;

E82 表示 event_id = ICOS_UCAST_MODULE_APPLY

再看 S44 - src_id = 44

icos_module.h

// *********************************************************************************
// *   Module ID
// *********************************************************************************
enum
{
    ...
    MODULE_WEB,
    MODULE_WIFI,  // 45
    ...
    MODULE_MAX,  // Ariel: MAX has to be the last items
};

S44 表示 src_id = MODULE_WEB

再看 D44 - dst_id = 44

D44 表示 dst_id = MODULE_WEB

簡單說第一行 1487572072[20170220 6:27:52] [notify_web:871]IN(E82|S44|D44) 表示

  • event_id = ICOS_UCAST_MODULE_APPLY
  • src_id = MODULE_WEB
  • dst_id = MODULE_WEB