1 Star 0 Fork 1

xiaodingding / goActionServer

forked from Sean / goActionServer 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
udialserver.c 24.21 KB
一键复制 编辑 原始数据 按行查看 历史
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
/*********************************************************************************************************
**
** 中国软件开源组织
**
** 嵌入式实时操作系统
**
** SylixOS(TM)
**
** Copyright All Rights Reserved
**
**--------------文件信息--------------------------------------------------------------------------------
**
** 文 件 名: udialserver.c
**
** 创 建 人: Wu.PengCheng (吴鹏程)
**
** 文件创建日期: 2018 年 4 月 19 日
**
** 描 述: Web后台接口拨号处理线程
*********************************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <spawn.h>
#include "lwip/netif.h"
#include "netdev.h"
#include "uORB.h"
#include "poll.h"
#include "iniparser/iniparser.h"
#include "iniparser/dictionary.h"
#include "net/lwip/event/lwip_netevent.h"
/*********************************************************************************************************
与goahead通信宏
*********************************************************************************************************/
#define UDIAL_FIFO_NAME "/dev/fifo" /* 有名管道名称 */
#define UDIAL_PID_FIFO "/dev/pidfifo" /* 有名管道名称 */
/*********************************************************************************************************
拨号ini配置文件相关宏
*********************************************************************************************************/
#define UDIAL_INI_FILE "/etc/ppp/ppp.ini" /* 拨号ini配置文件名称 */
#define UDIAL_FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) /* 拨号ini配置文件操作权限 */
#define UDIAL_INI_SECTION "pppoe_" /* 拨号ini配置文件section前缀 */
/*********************************************************************************************************
ini配置文件内section对应的key(拷贝udial.c源码)
*********************************************************************************************************/
#define UKEY_IFNAME "netif"
#define UKEY_MODEM "modem"
#define UKEY_BAUD "baud"
#define UKEY_INIT1 "init1"
#define UKEY_INIT2 "init2"
#define UKEY_INIT3 "init3"
#define UKEY_INIT4 "init4"
#define UKEY_INIT5 "init5"
#define UKEY_AREA_CODE "area code"
#define UKEY_PHONE "phone"
#define UKEY_USRNAME "username"
#define UKEY_PASSWORD "password"
#define UKEY_DIAL_CMD "dial command"
#define UKEY_RESP_WAIT "resp wait"
#define UKEY_DEFAULT_IF "default interface"
#define UKEY_AUTO_RECONN "auto reconnect"
/*********************************************************************************************************
拨号处理方式宏
*********************************************************************************************************/
#define UDIAL_CHECK 0 /* 关闭拨号 */
#define UDIAL_START 1 /* 开始拨号 */
#define UDIAL_END 0 /* 关闭拨号 */
/*********************************************************************************************************
后台拨号信息管理结构
*********************************************************************************************************/
struct udialServerInfo {
char pcNetifName[NETIF_NAMESIZE]; /* 网卡名称 */
void *pUdialCfgInfo; /* 拨号功能的配置信息 */
void *pPPPNetIfIp; /* PPP网卡IP地址 */
void *pPPPNetIfNetMk; /* PPP网卡掩码地址 */
void *pPPPNetIfGw; /* PPP网卡网关地址 */
pid_t pid;
char cConnectFlag; /* 当前拨号状态 */
struct udialServerInfo *pUdialInfoNext;
};
typedef struct udialServerInfo __UDIAL_SERVER_INFO;
typedef struct udialServerInfo *__PUDIAL_SERVER_INFO;
/*********************************************************************************************************
前台拨号信息管理结构
*********************************************************************************************************/
struct udialWebInfo {
INT iNetifIndex; /* 网卡序号 */
char cNetifName[NETIF_NAMESIZE]; /* 网卡名称 */
char *pcUserName; /* 拨号账户 */
char *pcPassWord; /* 拨号密码 */
char cDefaultFace; /* 是否设置为默认网口 */
char cAutoConnect; /* 是否设置为自动重连 */
char cHandleFlag; /* 当前处理方法 */
};
typedef struct udialWebInfo __UDIAL_WEB_INFO;
typedef struct udialWebInfo *__PUDIAL_WEB_INFO;
/*********************************************************************************************************
后台拨号信息管理结构链表头
*********************************************************************************************************/
static INT _G_iFifoFd;
static INT _G_iPidFifoFd;
__PUDIAL_SERVER_INFO pUdialServerListHead = LW_NULL;
/*********************************************************************************************************
申明调用的真正拨号线程
*********************************************************************************************************/
extern PVOID udialPPPoEEntry (PVOID parg);
extern VOID udialPPPoEQuit (PVOID pPPPoECfgInfo);
#define UDIAL_RESP_SIZE 1024
typedef struct {
int evt_num;
char if_name[IF_NAMESIZE];
} ppp_evt_t;
/*********************************************************************************************************
** 函数名称: __udialServerExitHandle
** 功能描述: 线程退出操作
** 输 入 : NONE
** NONE
** 输 出 : NONE
** 返 回 : none
*********************************************************************************************************/
static void __udialServerExitHandle (int i)
{
close(_G_iFifoFd);
unlink(UDIAL_FIFO_NAME);
}
/*
* return:
* 0: it's a ppp event
* -1: it isn't a ppp event, caller should ignore
*/
static int udial_parse_ppp_evt (ppp_evt_t *out, char *evt_buf)
{
unsigned int evt;
unsigned char *buf = (unsigned char *)evt_buf;
/*
* evt is make in big-endian
*/
evt = (((unsigned int)buf[0]) << 24)
| (((unsigned int)buf[1]) << 16)
| (((unsigned int)buf[2]) << 8)
| (((unsigned int)buf[3]) << 0);
if (evt >= NET_EVENT_PPP_DEAD && evt <= NET_EVENT_PPP_DISCONN) {
out->evt_num = evt;
out->if_name[0] = buf[4];
out->if_name[1] = buf[5];
out->if_name[2] = buf[6];
out->if_name[3] = 0;
return 0;
}
return -1;
}
/*********************************************************************************************************
** 函数名称: __udialPPPoEMonitorThread
** 功能描述: 拨号状态更新线程
** 输 入 : NONE
** NONE
** 输 出 : NONE
** 返 回 : none
*********************************************************************************************************/
static int __udialPPPoEMonitorThread (void *arg)
{
int fd;
char evt_buf[UDIAL_RESP_SIZE];
ssize_t read_len;
ppp_evt_t evt;
int ret;
__PUDIAL_SERVER_INFO pUdialServerInfo = LW_NULL; /* 状态变化结点 */
fd = open("/dev/netevent", O_RDONLY);
if (fd < 0) {
printf("open /dev/netevent failed, can't monitor the ppp link status!\r\n");
return -1;
}
while (1) {
read_len = read(fd, evt_buf, UDIAL_RESP_SIZE);
if (read_len > 0) {
ret = udial_parse_ppp_evt(&evt, evt_buf); /* 判断当前是不是与ppp相关事件 */
if (NET_EVENT_PPP_RUN == evt.evt_num) {
/*
* 遍历链表找到对应结点
*/
/*
* todo:枷锁
*/
for (pUdialServerInfo = pUdialServerListHead;
LW_NULL != pUdialServerInfo; ) {
/*
* 找到对应网口
*/
if (0 == strcmp(pUdialServerInfo->pcNetifName, evt.if_name)) {
pUdialServerInfo->pUdialCfgInfo = 1;
break;
} else {
pUdialServerInfo = pUdialServerInfo->pUdialInfoNext;
}
}
}
printf("evt.evt_num = %d\r\n", evt.evt_num);
if (ret == 0) { /* 是与ppp相关事件 */
switch (evt.evt_num) {
case NET_EVENT_PPP_DEAD:
printf("ppp link is dead");
break;
case NET_EVENT_PPP_INIT:
printf("ppp is doing initializing");
break;
case NET_EVENT_PPP_AUTH:
printf("ppp is doing authing");
break;
case NET_EVENT_PPP_RUN:
printf("ppp linked and is running");
break;
case NET_EVENT_PPP_DISCONN:
printf("ppp link is disconnect");
break;
default:
printf("unknow ppp event");
break;
}
} else {
continue;
}
}
if (read_len < 0) {
printf("monidor netevent error, it seems the /dev/netevent device error!\r\n");
close(fd);
return -1;
}
}
return 0;
}
/*********************************************************************************************************
** 函数名称: __udialIniFileHandle
** 功能描述: 对pppoe的ini配置文件进行处理
** 输 入 : argc 参数个数
** argv 参数
** 输 出 : NONE
** 返 回 : none
*********************************************************************************************************/
static INT __udialIniFileHandle (__UDIAL_WEB_INFO udialWebInfo)
{
CHAR cNewSecton[50];
CHAR *pcIniNetifName;
CHAR cIniNetifBuf[50];
CHAR cPassBuf[50];
CHAR cUserBuf[50];
CHAR cAutoBuf[50];
CHAR cDefaultBuf[50];
INT iSectionNum = 0;
INT iSectionCnt = 0;
INT iFd;
FILE * fppp;
dictionary *dict;
INT i;
CHAR cFlag = 0;
printf("__udialIniFileHandle.\n");
if(-1 == (access(UDIAL_INI_FILE, F_OK))) { /* 不存在这个文件 */
iFd = open(UDIAL_INI_FILE, O_RDWR | O_CREAT | O_TRUNC, UDIAL_FILE_MODE);
if (iFd < 0) {
printf("Create file failed.\n");
return (PX_ERROR);
}
close(iFd);
}
dict = iniparser_load(UDIAL_INI_FILE); /* 加载配置文件 */
if (LW_NULL == dict) {
printf("iniparser_load file error\n");
return (PX_ERROR);
}
iSectionNum = iniparser_getnsec(dict); /* 获取section个数 */
if (0 != iSectionNum) { /* 判断当前的拨号信息是否存在 */
for (i = 0; i < iSectionNum; i++) {
sprintf(cIniNetifBuf, "%s:%s", iniparser_getsecname(dict, i), UKEY_IFNAME);
pcIniNetifName = iniparser_getstring(dict, cIniNetifBuf, "NULL");
if (0 == strcmp(pcIniNetifName, udialWebInfo.cNetifName)) { /* 已经存在拨号信息 */
iSectionCnt = i;
cFlag = 1; /* 有对应信息 */
break;
}
}
}
if (UDIAL_START == udialWebInfo.cHandleFlag) { /* 需要进行拨号操作 */
if (0 == cFlag) { /* 之前没有对应的拨号信息 */
iniparser_freedict(dict); /* 把之前的dictionary先删除 */
fppp = fopen(UDIAL_INI_FILE, "r+"); /* r+ 格式打开配置文件 */
if (fppp < 0) {
printf("Create file failed.\n");
return (PX_ERROR);
}
fseek(fppp, 0L, SEEK_END); /* 移动到文件末尾 */
/*
* 添加一个新的section
*/
sprintf(cNewSecton, "%s%s", UDIAL_INI_SECTION, udialWebInfo.cNetifName);
fprintf(fppp, "\n[%s]\n", cNewSecton);
fclose (fppp);
dict = iniparser_load(UDIAL_INI_FILE); /* 重新获取dictionary */
if (LW_NULL == dict) {
printf("iniparser_load file error\n");
return (PX_ERROR);
}
iSectionCnt = iSectionNum; /* 设置最新的section的位置 */
}
/*
* 至此,找到对应的section了,现在不管现在的账号与密码是否与ini文件中的一致,都直接更新一下
*/
sprintf(cIniNetifBuf, "%s:%s", iniparser_getsecname(dict, iSectionCnt), UKEY_IFNAME);
sprintf(cUserBuf, "%s:%s", iniparser_getsecname(dict, iSectionCnt), UKEY_USRNAME);
sprintf(cPassBuf, "%s:%s", iniparser_getsecname(dict, iSectionCnt), UKEY_PASSWORD);
sprintf(cAutoBuf, "%s:%s", iniparser_getsecname(dict, iSectionCnt), UKEY_AUTO_RECONN);
sprintf(cDefaultBuf, "%s:%s", iniparser_getsecname(dict, iSectionCnt), UKEY_DEFAULT_IF);
/*
* 这里用dictionary_set接口,保证大小写不变;
* iniparser_set接口会把字符串变成小写
*/
dictionary_set(dict, cIniNetifBuf, udialWebInfo.cNetifName);
dictionary_set(dict, cUserBuf, udialWebInfo.pcUserName);
dictionary_set(dict, cPassBuf, udialWebInfo.pcPassWord);
dictionary_set(dict, cAutoBuf, udialWebInfo.cAutoConnect ? "yes" : "no");
dictionary_set(dict, cDefaultBuf, udialWebInfo.cDefaultFace ? "yes" : "no");
fppp = fopen(UDIAL_INI_FILE, "w+"); /* 清空文件打开 */
if (fppp < 0) {
printf("Create file failed, ini has cleared.\n");
iniparser_freedict(dict); /* 释放dictionar */
return (PX_ERROR);
}
iniparser_dump_ini(dict, fppp); /* 把dictionar写入ini文件 */
iniparser_freedict(dict); /* 释放dictionary */
fclose (fppp);
return (ERROR_NONE);
} else {
if (0 == cFlag) { /* 之前没有对应的拨号信息 */
iniparser_freedict(dict); /* 释放dictionary */
printf("Ini file has no msg.\n");
return (PX_ERROR);
} else {
fppp = fopen(UDIAL_INI_FILE, "w+"); /* 清空文件打开 */
if (fppp < 0) {
printf("Create file failed.\n");
iniparser_freedict(dict); /* 释放dictionar */
return (PX_ERROR);
}
for (i = 0; i < iSectionNum; i++) {
if (i != iSectionCnt) { /* 把需要删除的section剔除 */
iniparser_dumpsection_ini(dict, iniparser_getsecname(dict, i), fppp);
}
}
iniparser_freedict(dict); /* 释放dictionar */
fclose (fppp);
return (ERROR_NONE);
}
}
}
/*********************************************************************************************************
** 函数名称: main
** 功能描述: 拨号处理线程入口
** 输 入 : argc 参数个数
** argv 参数
** 输 出 : NONE
** 返 回 : none
*********************************************************************************************************/
INT main (int argc, char **argv)
{
INT ret;
pthread_t tid;
pthread_attr_t attr;
struct sched_param schedparam;
posix_spawnattr_t spawnattr;
pid_t pid;
__UDIAL_WEB_INFO udialWebInfo; /* 保存前台传过来的信息 */
__PUDIAL_SERVER_INFO pUdialServerInfo = LW_NULL; /* 当前新建的拨号信息 */
__PUDIAL_SERVER_INFO pUdialListTmp = LW_NULL; /* 上一次的拨号信息 */
__PUDIAL_SERVER_INFO pUdialServerDelInfo = LW_NULL; /* 当前新建的拨号信息 */
__PUDIAL_SERVER_INFO pUdialListDelTmp = LW_NULL; /* 上一次的拨号信息 */
__PUDIAL_SERVER_INFO pUdialServerCheckInfo = LW_NULL; /* 监测拨号信息 */
CHAR cSectionBuf[50] = {0};
CHAR cPidBuf[10] = {0};
CHAR *cCmdArg[7];
cCmdArg[0] = "udial";
cCmdArg[1] = "-p";
cCmdArg[2] = "-e";
cCmdArg[3] = "-d";
cCmdArg[4] = "-c";
cCmdArg[5] = cSectionBuf;
cCmdArg[6] = NULL;
ret = pthread_attr_init(&attr);
if (ret != 0) {
printf("pthread attr init failed.\n");
return (PX_ERROR);
}
ret = pthread_create(&tid, &attr, __udialPPPoEMonitorThread, NULL);
if (ret != 0) {
printf("pthread create failed.\n");
return (PX_ERROR);
}
ret = mkfifo(UDIAL_FIFO_NAME, O_RDWR | O_CREAT | O_TRUNC); /* 创建有名管道 */
if (ret < 0) {
perror("mkfifo");
return (PX_ERROR);
}
_G_iFifoFd = open(UDIAL_FIFO_NAME, O_RDWR); /* 打开有名管道 */
if (_G_iFifoFd < 0) {
printf( "open fifo error.\n");
return (PX_ERROR);
}
signal(SIGQUIT, __udialServerExitHandle);
signal(SIGABRT, __udialServerExitHandle);
signal(SIGSEGV, __udialServerExitHandle);
atexit((void (*)(void))__udialServerExitHandle);
while (1) {
ret = read(_G_iFifoFd, &udialWebInfo, sizeof(udialWebInfo));
if (ret < 0) {
printf( "read failed.\n");
break;
}
if (PX_ERROR == __udialIniFileHandle(udialWebInfo)) { /* 对拨号配置文件进行操作失败 */
continue;
}
/*
* 只要是对已有的拨号会先将其删掉
*/
for (pUdialServerDelInfo = pUdialListDelTmp = pUdialServerListHead;
LW_NULL != pUdialServerDelInfo; ) {
/*
* 找到需要删除的网口
*/
if (0 == strcmp(pUdialServerDelInfo->pcNetifName, udialWebInfo.cNetifName)) {
/*
* 删除之前操作的对应拨号进程
*/
bzero(cPidBuf, sizeof(cPidBuf));
sprintf(cPidBuf, "kill -n 3 %d", pUdialServerDelInfo->pid);
system(cPidBuf);
if (pUdialServerDelInfo == pUdialServerListHead) { /* 头结点被删除 */
pUdialServerListHead = pUdialServerDelInfo->pUdialInfoNext;
} else {
pUdialListDelTmp->pUdialInfoNext = pUdialServerDelInfo->pUdialInfoNext;
}
free(pUdialServerDelInfo);
break;
} else {
pUdialListDelTmp = pUdialServerDelInfo;
pUdialServerDelInfo = pUdialServerDelInfo->pUdialInfoNext;
}
}
if (UDIAL_START == udialWebInfo.cHandleFlag) { /* 需要进行拨号 */
pUdialServerInfo = (__PUDIAL_SERVER_INFO)malloc(sizeof(__UDIAL_SERVER_INFO));
if (LW_NULL == pUdialServerInfo) {
printf("udial info malloc error\n");
return (PX_ERROR);
}
bzero(pUdialServerInfo, sizeof(__UDIAL_SERVER_INFO));
if (LW_NULL == pUdialServerListHead) {
pUdialServerListHead = pUdialServerInfo;
} else {
for (pUdialListTmp = pUdialServerListHead;
LW_NULL != pUdialListTmp->pUdialInfoNext;
pUdialListTmp = pUdialListTmp->pUdialInfoNext) {
} /* 找到最后一个结点 */
pUdialListTmp->pUdialInfoNext = pUdialServerInfo; /* 尾插 */
}
/*
* 保存当前的拨号信息
*/
memcpy(pUdialServerInfo->pcNetifName,
udialWebInfo.cNetifName,
sizeof(udialWebInfo.cNetifName));
pUdialServerInfo->cConnectFlag = 0;
/*
* 初始化进程属性对象
*/
if (posix_spawnattr_init(&spawnattr) != 0) {
printf( "init posix_spawnattr_t failed\n");
return (PX_ERROR);
}
/*
* 新建进程优先级为 NORMAL
*/
schedparam.sched_priority = PX_PRIORITY_CONVERT(LW_PRIO_NORMAL);
posix_spawnattr_setschedparam(&spawnattr, &schedparam);
posix_spawnattr_setflags(&spawnattr, POSIX_SPAWN_SETSCHEDPARAM);
bzero(cSectionBuf, sizeof(cSectionBuf));
sprintf(cSectionBuf, "pppoe_%s", udialWebInfo.cNetifName);
if (posix_spawnp(&pid, "udial", NULL,
&spawnattr, cCmdArg, NULL) != 0) { /* 启动进程 */
free(pUdialServerInfo);
/*
* todo:向管道写error
*/
} else {
/*
* todo:向管道写ok
*/
pUdialServerInfo->pid = pid;
}
posix_spawnattr_destroy(&spawnattr);
} else if (UDIAL_END == udialWebInfo.cHandleFlag) { /* 需要删除拨号 */
/*
* 因为整个if语句操作前已经删除对应网口,因此无需重复删除
*/
/*
* todo:向管道写ok
*/
} else if (UDIAL_CHECK == udialWebInfo.cHandleFlag) { /* 需要检查拨号状态 */
pppGetPhase();
for (pUdialServerCheckInfo = pUdialServerListHead;
LW_NULL != pUdialServerCheckInfo; ) {
/*
* 找到需要的网口
*/
if (0 == strcmp(pUdialServerCheckInfo->pcNetifName, udialWebInfo.cNetifName)) {
//write(_G_iFifoFd, &(pUdialServerCheckInfo->cConnectFlag), sizeof(char));
break;
}
pUdialServerCheckInfo = pUdialServerCheckInfo->pUdialInfoNext;
}
}
}
return (0);
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C
1
https://gitee.com/xiaodingding/goActionServer.git
git@gitee.com:xiaodingding/goActionServer.git
xiaodingding
goActionServer
goActionServer
master

搜索帮助

344bd9b3 5694891 D2dac590 5694891