Goahead编译

Goahead 编译

目录说明

Makefile #顶层Makefile,可以自动检测当前运行平台的环境,并调用projects的mk
projects #子层的Makefile,有各个平台的
test     # web 文件以及路由和配置文件

#可以看到直接make 输出如下
make --no-print-directory -f projects/goahead-linux-default.mk all

# 安装
sudo make install

Ubuntu编译

make

make
sudo make install

selfkey处理

reallin@ubuntu:/work/goahead/goahead-5.0.1$ sudo goahead -v --home /etc/goahead /var/www/goahead
goahead: 0: Unable to read key self.key
goahead: 0: Cannot initialize server. Exiting.

sudo cp ./build/linux-x64-default/bin/self.key /etc/goahead
sudo cp ./build/linux-x64-default/bin/self.crt  /etc/goahead

测试

#./goahead -v --home 配置文件路径 文档路径 绑定IP:监听端口
#./goahead -v --home /etc/goahead /var/www/goahead 0.0.0.0:8888
sudo goahead -v --home /etc/goahead /var/www/goahead


# 下面是运行结果
goahead: 2: Configuration for Embedthis GoAhead Community Edition                           
goahead: 2: ---------------------------------------------                                   
goahead: 2: Version:            5.0.1                                                       
goahead: 2: BuildType:          Debug                                                       
goahead: 2: CPU:                x64                                                         
goahead: 2: OS:                 linux                                                       
goahead: 2: Host:               127.0.1.1                                                   
goahead: 2: Directory:          /etc/goahead                                                
goahead: 2: Documents:          /var/www/goahead                                            
goahead: 2: Configure:          me -d -q -platform linux-x86-default -configure . -gen make 
goahead: 2: ---------------------------------------------                                   
goahead: 2: Started http://*:80                                                             
goahead: 2: Started https://*:443                                                           

具体的install目录

ls /etc/goahead
auth.txt  route.txt  self.crt  self.key

ls /var/www/goahead
favicon.ico  index.html  # 这个就是网页了

交叉编译

# 如果有错误提示 undefined reference to `__stack_chk_fail'  加上这个选项-fno-stack-protector
make CC=arm-linux-gcc LD=arm-linux-ld CFLAGS=-fno-stack-protector

方便测试

  1. cd build/linux-x64-default/bin

  2. cp ../../../src/auth.txt ./

  3. cp ../../../src/route.txt ./

  4. 新建一个myweb文件夹存网页

  5. sudo ./goahead -v ./myweb/

  6. 修改配置文件route.txt

    1.把route uri=/action handler=action注释掉
    	在前面加个#即可
    	然后加一句route uri=/action/ methods=GET|POST handler=action
    2. 把route uri=/ extensions=jst handler=jst改为route uri=/ extensions=jst,asp,html handler=jst
    	如果不做修改那我们在以后写html,asp文件里的action就不能被识别
    

win下编译

顶层目录的make.bat 修改下,因为原来的默认工程找不到路径

projects\windows x64 nmake -f projects/goahead-windows-default.nmake %1 %2 %3 %4 %5 %6 %7 %8 %9

运行之后,打开projects下的goahead-windows-default.sln就可以编译了

如果要调试,需要设置调试目录为 ../../test,加上参数-v即可

可以选择启动项目为test或者goahead.

早期的源码流程

--------------------------------------------------------------------------------------
MAIN(goahead, int argc, char **argv, char **envp)
-------------------------------------初始化过程开始-------------------------------------
|-->for(argv[...]){}  //解析命令行
|-->initPlatform();   //注册信号处理函数
    |-->signal(SIGTERM, sigHandler) ...
|-->websOpen(documents, route)  //初始化服务器
    |-->websOsOpen();         //生成系统启动随机数(标识系统)
    |-->websRuntimeOpen(); //开始系统计时sym、symMax
    |-->websTimeOpen();      //初始化hash结构timeTokens
    |-->logOpen();                //初始化基本日志
    |-->setFileLimits();          //设置最大文件描述符值
    |-->socketOpen();           //初始化WebsSocket **socketList=NULL,socketMax =0,socketHighestFd=-1
    |-->setLocalHost();          //设置服务器的hostname(websHost), 服务器的IP地址(websIpAddr)
    |-->sslOpen();                 //若支持ssl则初始化ssl相关信息
    |-->sessions = hashCreate(-1);   //初始化话hash结构sessions
    |-->websStartEvent(...pruneSessions...);   //启动定时调度函数pruneSessions ,pruneSessions每秒调度清除过期的sessions
    |-->websSetDocuments(documents);        //设置goahead访问根目录websDocuments
    |-->websOpenRoute();     //初始化hash结构handlers,相应函数加入到handlers中.
        |-->websDefineHandler("continue", continueHandler, 0, 0, 0);  //continue的处理函数为continueHandler
        |-->websDefineHandler("redirect", redirectHandler, 0, 0, 0);    //redirect处理函数为redirectHandler
    |-->websCgiOpen();       //定义cgi处理函数加入到handlers中.
        |-->websDefineHandler("cgi", 0, cgiHandler, 0, 0);                 //定义cgi的处理函数为cgiHandler
    |-->websOptionsOpen(); //定义options处理函数加入到handlers中.
        |-->websDefineHandler("options", 0, optionsHandler, 0, 0);     //定义options的处理函数为optionsHandler
    |-->websActionOpen();    //初始化hash结构actionTable,定义action处理函数加入到handlers中,定义action对应值的函数加入到actionTable中. .
        |-->websDefineHandler("action", 0, actionHandler, closeAction, 0);   //定义action的处理函数为actionHandler
        |-->WebActionDefineInit();  //初始化action对应值的处理函数
            |-->websDefineAction("upgrade", ActionDefault); //定义action=upgrade的处理函数为ActionDefault,
            |-->websDefineAction("...", ...);                         //同上的类似函数
    |-->websFileOpen();       //设置默认页面websIndex="index.html",定义action处理函数加入到handlers中
        |-->websDefineHandler("file", 0, fileHandler, fileClose, 0);  //定义file的处理函数为fileHandler
    |-->websUploadOpen();  //设置上传文件路径uploadDir = "/tmp",定义upload处理函数加入到handlers中
        |-->websDefineHandler("upload", 0, uploadHandler, 0, 0);  //定义upload的处理函数为uploadHandler
    |-->websJstOpen();       //初始化hash结构websJstFunctions,定义write处理函数加入到websJstWrite中,定义jst处理函数加入到jstHandler中.
        |-->websDefineJst("write", websJstWrite);                        //定义jst(javascript)的write的处理函数为websJstWrite,支持<% write("text"); %>
        |-->websDefineHandler("jst", 0, jstHandler, closeJst, 0);     //定义jst(javascript)的处理函数为jstHandler
    |-->websOpenAuth(0);   //初始化认证相关处理函数
        |-->websDefineAction("userlogin", ActionUserLoginProc);     //定义action=userlogin的处理函数为ActionUserLoginProc
        |-->websDefineAction("userlogout", ActionUserLogoutProc); //定义action=userlogin的处理函数为ActionUserLoginProc
        |-->verifyPassword = websVerifyPasswordFromFile;            //设置验证密码函数
    |-->websFsOpen(0);   //初始化hash结构romFs,定义ME_ROM相关文件路径
    |-->websLoad(routeFile); //load route.txt配置文件
        |-->route = websAddRoute(uri, handler, -1)  //将结构为WebsRoute的route加入hash结构routes中,初始化route中uri和handler
        |-->websSetRouteMatch(route, dir, protocol, methods, extensions, abilities, redirects); //初始化route中protocol等
        |-->websSetRouteAuth(route, auth)              //初始化route中authType等
    |-->for(websMimeList){hashEnter(websMime)}  //初始化goahead默认支持的content type
    |-->open(accessLog, O_CREAT | O_TRUNC | O_APPEND | O_WRONLY, 0666)  //初始化access.log log日志文件
|-->websLoad(auth)  //load auth.txt配置文件
    |-->websAddRole(name, abilities) //增加管理角色,如role name=manager abilities=view,edit,delete
    |--> websAddUser(username, password, roles)  //增加管理用户,如user name=admin password=xx roles=manager,purchaser
---------------------------------------初始化过程结束-------------------------------------------
|-->logHeader();  //日志打印goahead基本配置信息
|-->websListen(endpoint)  //初始化socket并监听
    |-->socketParseAddress(endpoint, &ip, &port, &secure, 80);  //解析监听ip 端口
    |-->sid = socketListen(ip, port, websAccept, 0)                      //创建socket,并监听,初始化WebsSocket结构加入到socketlist中
    |-->listens[listenMax++] = sid                                              //保存socket的WebsSocket信息到listens中
|-->websGetBackground()  //使用daemon(0, 0)设置后台运行
---------------------------------------主循环处理开始-------------------------------------------
|-->websServiceEvents(&finished);  //while(!finished){}主循环
    |-->socketSelect(-1, delay)  //select socket
        |-->nEvents = select(socketHighestFd + 1, (fd_set *) readFds, (fd_set *) writeFds, (fd_set *) exceptFds, &tv);  //select socket
    |-->socketProcess()            //处理请求
        |-->socketDoEvent(sp);
            |-->socketAccept(sp);   //accept新请求
                |-->newSock = accept(sp->sock, addr, (Socklen*) &len)            //accept 新socket
                |-->nid = socketAlloc(sp->ip, sp->port, sp->accept, sp->flags);  //分配并初始化新的WebsSocket,加入到socketList[nid]
                |-->socketList[nid] ->sock = newSock ...                                   //继续初始化新的socketList[nid]的WebsSocket结构
                |-->(sp->accept)(nid, ipbuf, port, sp->sid)                                //调用websAccept函数, nid为新建请求的socketid, ipbuf为远端IP,port为远端port, sp->sid为本机监听的socketid
                    |-->wid = websAlloc(sid);wp=webs[wid];    //根据参数sid(即nid)分配并初始化新的Webs,加入到webs[wid]
                        |-->initWebs(wp, 0, 0);        //初始化新的webs[wid]的Webs结构 
                             |-->wp->state = WEBS_BEGIN;              //初始化链接状态机初始值
                             |-->bufCreate(&wp->output);                //初始化发送buf
                             |-->bufCreate(&wp->input);                  //初始化接收buf
                    |-->wp->listenSid = listenSid; ...                 //继续初始化新的webs[wid]的Webs结构
                    |-->wp->timeout = websStartEvent(PARSE_TIMEOUT, checkTimeout, (void*) wp);  //设置wp的超时函数
                    |-->socketEvent(sid, SOCKET_READABLE, wp); //
                        |-->readEvent(wp);            //一直调用readEvent读http和处理http,直至处理接收设置SOCKET_WRITABLE才可调用writeEvent
                             |-->nbytes = websRead(wp, (char*) rxbuf->endp, ME_GOAHEAD_LIMIT_BUFFER)                //读取http报文
                             |-->websPump(wp);          //根据wp->state状态机的值处理http报文
                                  |-->case WEBS_BEGIN:       parseIncoming(wp);  
                                       |-->parseFirstLine(wp);           //处理http请求行,并保存到wp结构中
                                       |-->parseHeaders(wp);           //处理http请求头部,并保存到wp结构中
                                       |-->wp->state = (wp->rxChunkState || wp->rxLen > 0) ? WEBS_CONTENT : WEBS_READY;  //设置wp->state状态值
                                       |-->websRouteRequest(wp);    //设置此链接的处理函数
                                  |-->case WEBS_CONTENT:   processContent(wp);
                                       |-->websProcessCgiData(wp);  //设置此链接的处理函数jstHandler、cgiHandler、continueHandler、redirectHandler、actionHandler等   
                                  |-->case WEBS_READY:        websRunRequest(wp);    
                                       |-->(*route->handler->service)(wp);   //执行此链接的处理函数,
                                            |-->hashLookup(actionTable, actionName);(*fn)((void*) wp);  //以actionHandler为例,执行actionTable中对应函数,以ActionDefault为例
                                                 |-->ActionDefault
                                                      |-->websWrite_ex(webs, 0, json_object_to_json_string(obj),token);  //返回页面数据  
                                            |-->jstHandler(Webs *wp);  //以jstHandler为例,执行...      
                                                      |-->...websDone(wp);
                                                           |-->websFlush(wp, 0);  -->wp->state = WEBS_COMPLETE;            
                                                           |-->socketCreateHandler(wp->sid, sp->handlerMask | SOCKET_WRITABLE, socketEvent, wp);                                                                                                  
                                  |-->case WEBS_RUNNING:      /* Nothing to do until websDone is called */
                                  |-->case WEBS_COMPLETE:  complete(wp, 1);                                                   
                             |-->socketCreateHandler(wp->sid, sp->handlerMask | SOCKET_READABLE, socketEvent, wp); //初始化此链接的处理函数sp->handler=socketEvent
                        |-->writeEvent(wp);
                             |-->websFlush(wp, 0);
                                  |-->while(websWriteSocket());  
                                  |-->wp->state = WEBS_COMPLETE;
                        |-->websFree(wp);
            |-->(sp->handler)(sid, sp->handlerMask & sp->currentEvents, sp->handler_data)   //
    |-->websCgiPoll();        //如有cgi,只响应cgi
    |-->websRunEvents();   //执行已加入定时器相关函数
|-->websClose();              //关闭相关资源
posted @ 2019-12-27 19:56  zongzi10010  阅读(1741)  评论(0编辑  收藏  举报