title: Goahead編譯
date: 2019/11/6 09:45:01
toc: true
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
方便測試
-
cd build/linux-x64-default/bin
-
cp ../../../src/auth.txt ./
-
cp ../../../src/route.txt ./
-
新建一個
myweb
文件夾存網頁 -
sudo ./goahead -v ./myweb/
-
修改配置文件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(); //關閉相關資源