[中秋零献续集] 神州数码802.1x局域网UDP拔号软件MyNet-Gnome源代码大分析(Part4)getaccess线程内的故事

/***
* Author: cc0cc
* E-mail: cc0cc@126.com
* WebSite: http://www.54chen.com * Date: 11 01 2008
* FileName: Mythread.c
* 这个文件要从Access_Thread看起,因为在上一章节里,我们了解了 pthread_create(&getaccess,NULL,Access_Thread,NULL);创建了一个叫getaccess的线程,正是运行的Access_Thread,在Access_Thread里,将完成一系列的过程,802.1x从这里才真正开始了。
***/
#include <gnome.h>
#include <sys/select.h>
#include "Mythread.h"
#include "connect.h"
#include "support.h"
#include "interface.h"

int i=0;
typedef struct{
                  long    tv_sec;        
                  long    tv_uec;       
              }timeval;
           
gint
keeplink(gpointer data)
{ pthread_t keeptest;
    fd_set readfds;
    timeval timeout={5,0};//设置超时
    BYTE recvbuf[1024];
    BYTE cmd;
    CMD_RECORD *cmd_record;
    int recvlen;
    int index=0;
    BYTE tmp=0;
    send_keeplink_request();//这也在connect.c里,用来构造一个包含指令和验证信息的包并发给服务器
    FD_ZERO(&readfds);
    FD_SET(sockfd, &readfds);
    if(1!=select(sockfd + 1,&readfds,NULL,NULL,&timeout))
    {//超时
        Acc_Keep_Link=2;
        g_message("1.keep lost,thread keeptest ok!");
        pthread_create(&keeptest,NULL,Keep_Thread,NULL);
        return FALSE;
    }
    recvlen=recvfrom(sockfd,(char *)recvbuf,sizeof(recvbuf),0,NULL,NULL);
    if (recvlen==-1 ) {
                    Acc_Keep_Link=2;
                    pthread_create(&keeptest,NULL,Keep_Thread,NULL);
                    g_message("2.keep lost,thread keeptest ok!");
                    return FALSE;
    }
    amt_decrypt(recvbuf,recvlen);//与认证过程大同小异
    if(0==check_packet(recvbuf,recvlen))
    {
                    Acc_Keep_Link=2;
                    pthread_create(&keeptest,NULL,Keep_Thread,NULL);
                    g_message("3.keep lost,thread keeptest ok!");
                    return FALSE;
    }
    cmd_record=get_attr(recvbuf);
    cmd=*recvbuf;
    if(cmd==4)    //收到send_keeplink_request对应的包
    {
        index=0;
        tmp=0;
        for (;(index<8)&&(attr_id[index]);index++) {
            if (attr_id[index]==3) {
                if (attr_val[8*(index+4*index)]!=1) {//发送send_keeplink_request失败
                    Acc_Keep_Link=2;
                    pthread_create(&keeptest,NULL,Keep_Thread,NULL);
                    g_message("4.keep lost,thread keeptest ok!");
                    return FALSE;
                }
            }
        }
        //AfxGetMainWnd()->PostMessage(WM_KEEPLINK_RESULT,KEEPLINK_SUCCESSED,NULL);
        g_message("keeplink result success");
    }
    else
    {
                    Acc_Keep_Link=2;
                    pthread_create(&keeptest,NULL,Keep_Thread,NULL);
                    g_message("5.keep lost,thread keeptest ok!");
                    return FALSE;
    }
return TRUE;//至此 全过程结束(当然,你不是按照从上到下读着来的,而是按照我的提示来阅读的话) 未来我会逐步分析connect.c和mdd.c里的几个函数,都是加密和解密的内容,主程序本身的流程关系不大,其中还包含了linux c中使用ASM的方法,敬请关注http://hi.baidu.com/cc0cc
}

void
Link_Thread(void *arg)
{ guint send_timer;
if(Acc_Keep_Link!=1)return;
g_message("keep thread online!");
send_timer=gtk_timeout_add(30000,keeplink,NULL);//802.1x了,每三十秒发送一个认证请求 看keeplink
} 从这里看起↓ void
Access_Thread()
{ if(Acc_Keep_Link!=0)return;//这是个全局的标,任何情况下标被修改都应当退出线程
pthread_t keeplink;//这是一个孙线程的名字,根据协议规则需要在认证通过后定时发包
int times=0;//超时次数
fd_set readfds;//这个东东不知道要去补一下网络编程,异步套接字。文件描述符集,select调用时用的 timeval timeout;//设置超时为5秒 这个timeval struct在本文件有定义
timeout.tv_sec=5;
timeout.tv_uec=0;
FD_ZERO(&readfds);
FD_SET(sockfd, &readfds);   

BYTE recvbuf[1024];
BYTE cmd;
CMD_RECORD *cmd_record;
int recvlen;
int index=0;
BYTE tmp=0;

   
retry://这里没办法,用了个goto 看后面就知道了,大概就是超时两次就置标志位了,最后结束运行
        if (times>=2) {
        Acc_Keep_Link=-1;//ACCESS_FAILED_TIMEOUT;
        return ;
    }
send_access_request();//这是开始发送包给服务器了,将会发送用户名密码MAC等一系列的东西给远端的服务器,另一个文件中(connet.c)将专门来介绍

int rt=select(sockfd + 1,&readfds,NULL,NULL,&timeout);//等着看有没有返回
//g_message("select id :%d",rt);
if(1!=rt)
    {//超时
        g_message("time out this");
        times++;
        goto retry;
    }
//有返回了!
recvlen=recvfrom(sockfd,(char *)recvbuf,sizeof(recvbuf),0,NULL,NULL);//接受返回
    if (recvlen==-1) {
        g_message("recvfrom faild");
       
    }
    amt_decrypt(recvbuf,recvlen);//将收到的recvbuf里的东西去解密 amt_decrypt是原程序中的解密算法,接收到的数据包得经过本函数解密,将在mdd.c中介绍
    if(check_packet(recvbuf,recvlen)==0&&times<2)//check_packet检查解密amt_decrypt完后的数据包是否符合md5摘要
    {   g_message("check_packet bad here");
        times++;
        goto retry;//check_packet失败则重发数据包
    }
    cmd_record=get_attr(recvbuf);//取出对应的指令变成结构体链表CMD_RECORD
    cmd=*recvbuf;
    if(cmd==2)    //收到send_access_request对应的包
    {
        get_spec_attr(cmd_record);//把结构体链表CMD_RECORD里的东西分进全局变量attr_yy里 马上就要用到,attr_id存了cmd指令
        index=0;
        tmp=0;
       
        for (;(index<0x0A)&&(attr_id[index]!=0);index++) {
           
            if (attr_id[index]==3) {
                tmp=attr_val[8*(index+4*index)];////attr_val给每个命令40字节
            }
        }
        if (tmp==1) {//认证成功!
            //g_message("ok");
            gtk_widget_hide_all (linkwindow);
            Acc_Keep_Link=1;
            pthread_create(&keeplink,NULL,Link_Thread,NULL);//认证成功了,再创建一个线程用来保持连接 这回要去看Link_Thread了
            return;
        }
        else
        {   g_message("server_back_err");
            gtk_widget_hide_all (linkwindow);
            Acc_Keep_Link=-1;
            return ;
        }

    }

}

gint
keeptest(gpointer data)
{ pthread_t keeplink;
i++;
g_message("%d",i);
if (i>10){Acc_Keep_Link=-1;g_message("can't keeplink!");return FALSE;}
    fd_set readfds;
    timeval timeout={5,0};//设置超时
    BYTE recvbuf[1024];
    BYTE cmd;
    CMD_RECORD *cmd_record;
    int recvlen;
    int index=0;
    BYTE tmp=0;
    send_keeplink_request();
    FD_ZERO(&readfds);
    FD_SET(sockfd, &readfds);
    if(1!=select(sockfd + 1,&readfds,NULL,NULL,&timeout))
    {//超时
        g_message("1.keep lost,thread keeptest for once!");
        return TRUE;
    }
    recvlen=recvfrom(sockfd,(char *)recvbuf,sizeof(recvbuf),0,NULL,NULL);
    if (recvlen==-1 ) {
                    g_message("2.keep lost,thread keeptest for once!");
                    return TRUE;
    }
    amt_decrypt(recvbuf,recvlen);
    if(0==check_packet(recvbuf,recvlen))
    {
                    g_message("3.keep lost,thread keeptest for once!");
                    return TRUE;
    }
    cmd_record=get_attr(recvbuf);
    cmd=*recvbuf;
    if(cmd==4)    //收到send_keeplink_request对应的包
    {
        index=0;
        tmp=0;
        for (;(index<8)&&(attr_id[index]);index++) {
            if (attr_id[index]==3) {
                if (attr_val[8*(index+4*index)]!=1) {//发送send_keeplink_request失败
                    g_message("4.keep lost,thread keeptest for once!");
                    return TRUE;
                }
            }
        }
            g_message("keeptest result success");
            Acc_Keep_Link=1;
            pthread_create(&keeplink,NULL,Link_Thread,NULL);
            return FALSE;       
    }
    else
    {
                    g_message("5.keep lost,thread keeptest for once!");
                    return TRUE;
    }

return FALSE;
}

void
Keep_Thread()
{guint send_timer;
    if(Acc_Keep_Link!=2)return;
    send_timer=gtk_timeout_add(10000,keeptest,NULL);
} /***
* Author: cc0cc
* E-mail: cc0cc@126.com
* WebSite: http://www.54chen.com * Date: 11 01 2008
* FileName: Mythread.c
***/


原创文章如转载,请注明:转载自五四陈科学院[http://www.54chen.com]

捐款订阅54chen
捐赠说明

Comments