# HG changeset patch # User Mike Pavone # Date 1290375197 18000 # Node ID 7bbdc034e347eab6af39868edd419907b81cbaa4 # Parent f2cb85c53ced2d27ae5a0bf20711bfccda1f74ce Fix some bugs. Get basic network code working (epoll listener + accept connections). Start porting webserver. diff -r f2cb85c53ced -r 7bbdc034e347 cbackend_c.rhope --- a/cbackend_c.rhope Sat Nov 20 17:48:22 2010 -0500 +++ b/cbackend_c.rhope Sun Nov 21 16:33:17 2010 -0500 @@ -154,11 +154,17 @@ [[type]Name >>]Slice[3] {} { typename <- [["int"]Append[~]]Append["_t"] } }{ - ,regulartype <- [("UInt64","UInt32","UInt16","UInt8")]Find[=[[type]Name >>,?]] + [("UInt64","UInt32","UInt16","UInt8")]Find[=[[type]Name >>,?]] { primitive <- Yes [[type]Name >>]Slice[4] {} { typename <- [["uint"]Append[~]]Append["_t"] } + }{ + ,regulartype <- If[[[type]Name >>]=["Context"]] + { + typename <- "context *" + primitive <- Yes + } } } } @@ -778,6 +784,15 @@ { worker <- Make Op[Strip Addref[to call], func] rargs <- Map[args, Make Op[?, func]] + + If[[[[func]Variables >>]Length]+[[[func]Outputs >>]Length]] + { + valcall <- "ValCall(" + postlude <- "ValCallPostlude(" + }{ + valcall <- "ValCallNoLocals(" + postlude <- "ValCallNoLocalsPostlude(" + } If[[[func]Last NumParams >>] = [-1]] { @@ -803,7 +818,7 @@ out <- [[[[Fold[_Val Function Arg C[?, ?, ?, worker], prepped, rargs] ]Add Raw Line[ - [[[[[[[["ValCall(" + [[[[[[[[valcall ]Append[worker] ]Append[", "] ]Append[String[[rargs]Length]] @@ -814,7 +829,7 @@ ]Append[")"]] ]Add Raw Line["DISPATCH"] ]Add Raw Line[ - [[[["ValCallPostlude(" + [[[[postlude ]Append[String[[func]Resume Index >>]] ]Append[", "] ]Append[Escape Rhope Name[[func]Name >>,[func]Escape Pattern >>]] @@ -845,10 +860,14 @@ } } -Func Base@C Function[func,tocall,args,type:out] +Func Base@C Function[func,tocall,args,rtype:out] { Print[ [[func]Name >>]Append[ [": Func Base("]Append[tocall] ] ] rargs <- Map[args, Make Op[?, func]] + + If[[[[func]Variables >>]Length]+[[[func]Outputs >>]Length]] + { type <- Val[rtype] } + { type <- [rtype]Append["NoLocals"] } If[[[rargs]Length] > [[func]Last NumParams >>]] { @@ -1131,24 +1150,25 @@ } fname <- Escape Rhope Name[[func]Name >>,[func]Escape Pattern >>] param check <- Fold[Check Param Type C[?, ?, ?, func], "", [func]Input Types >>] + If[[[func]Last NumParams >>] = [-1]] + { + freecall <- "" + }{ + freecall <- "\n\tFreeCall\n" + } If[ [ [[[[func]Variables >>]Length]+[[[func]Outputs >>]Length]]+[[[func]Uses >>]Length] ] = [0] ] { - out <- [[[[[[[[ [type]Append["NoLocals("] + out <- [[[[[[[[[ [type]Append["NoLocals("] ]Append[cname] ]Append[",\n\tNumParams "] ]Append[ String[[[func]Inputs >>]Length] ] ]Append[")\n\n"] ]Append[param check] ]Append[ [[func]Statements >>]Join[""] ] + ]Append[freecall] ]Append["EndFuncNoLocals\n"] ]Append["DISPATCH"] }{ - If[[[func]Last NumParams >>] = [-1]] - { - freecall <- "" - }{ - freecall <- "\n\tFreeCall\n" - } If[[[func]Uses >>]Length] { begin trans <- [[[["\tbegin_transaction(ct, "]Append[ String[[[func]Uses >>]Length] ]]Append[", "]]Append[ [Map[Map[[func]Uses >>, Escape Rhope Name[?, [func]Escape Pattern >>]], ["gs_"]Append[?]]]Join[", "] ]]Append[");\n"] diff -r f2cb85c53ced -r 7bbdc034e347 ctobin --- a/ctobin Sat Nov 20 17:48:22 2010 -0500 +++ b/ctobin Sun Nov 21 16:33:17 2010 -0500 @@ -20,8 +20,8 @@ file=$1 shift -echo "$CC -o $bin $@ $file.c blueprint.c context.c fixed_alloc.c object.c transaction.c" -$CC -o $bin $@ "$file.c" blueprint.c context.c fixed_alloc.c object.c transaction.c +echo "$CC -o $bin $@ $file.c blueprint.c context.c fixed_alloc.c object.c transaction.c net.c" +$CC -o $bin $@ "$file.c" blueprint.c context.c fixed_alloc.c object.c transaction.c net.c cd .. diff -r f2cb85c53ced -r 7bbdc034e347 kernel.rhope --- a/kernel.rhope Sat Nov 20 17:48:22 2010 -0500 +++ b/kernel.rhope Sun Nov 21 16:33:17 2010 -0500 @@ -290,7 +290,7 @@ _Call Async[func,cont:out] { Resume[cont,0] - { out <- Call[func] } + { out <- Call[func,0] } } Call Async[func:out] { diff -r f2cb85c53ced -r 7bbdc034e347 net.rhope --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/net.rhope Sun Nov 21 16:33:17 2010 -0500 @@ -0,0 +1,253 @@ + +Foreign C:libc +{ + setsockopt[sockfd(Int32,Naked),level(Int32,Naked),optname(Int32,Naked),optval(Int32,Raw Pointer),optlen(Int32,Naked):out(Int32,Naked)] + listen[sockfd(Int32,Naked),backlog(Int32,Naked):out(Int32,Naked)] + send[sockfd(Int32,Naked),data(Array,Raw Pointer),datalen(Int64,Naked):out(Int32,Naked)] + recv[sockfd(Int32,Naked),data(Array,Raw Pointer,Mutable),maxlen(Int64,Naked):out(Int32,Naked),data] + fcntl[fd(Int32,Naked),command(Int32,Naked),value(Int64,Naked):out(Int32,Naked)] + pipe[descriptors(Array,Raw Pointer,Mutable):out(Int32,Naked),descriptors] + epoll_create[size(Int32,Naked):status(Int32,Naked)] + epoll_ctl[epfd(Int32,Naked),operation(Int32,Naked),fd(Int32,Naked),event(epoll_event,Raw Pointer):status(Int32,Naked)] + epoll_wait[epfd(Int32,Naked),events(Array,Raw Pointer,Mutable),maxevents(Int32,Naked),timeout(Int32,Naked):out(Int32,Naked),events] +} + + +//Note: port numbers would more properly be UInt16, think about changing later +Foreign C:runtime +{ + _internal_bindnewsocket[port(Int32,Naked),setreuse(Int32,Naked):socket(Int32,Naked)] + _internal_accept[sockfd(Int32,Naked),addrbuf(Array,Raw Pointer,Mutable),buflen(Int32,Naked):consock(Int32,Naked),addrbuf] +} + +Blueprint epoll_event +{ + events(UInt32,Naked) + data(Int64,Naked) +} + +//EPOLLIN 1 +//EPOLLOUT 4 +//EPOLLPRI 2 +//EPOLL_CTL_ADD 1 +//EPOLL_CTL_DEL 2 +//EPOLL_CTL_MOD 3 + +_Add New FDs[epfd,pipefd:out] +{ + count,rdata <- read[pipefd, _internal_array_allocnaked[2,Int32()], 8i64] + ,out <- If[[count]=[8i64]] + { + data <- [rdata]Length <<[2] + epoll_ctl[epfd, 1i32, [data]Index[0], [[Build[epoll_event()]]events <<[Abs UInt[[data]Index[1]]]]data <<[Int64[[data]Index[0]]]] + { out <- _Add New FDs[epfd,pipefd] } + }{ + //TODO: Properly deal with the case when count > 0 but < 8 + If[[count]>[0i64]] + { + Print[["read of listener pipe returned unexpected number of bytes: "]Append[String[count]]] + } + } +} + +_Get IO Context[fd:out,notfound] uses socklisten +{ + out,notfound <- [socklisten::fdlookup]Index[fd] +} + +_Handle Events[epfd,pipefd,buf,cur:out] +{ + event,out <- [buf]Index[cur] + { + If[[event]data >>] + { + activefd <- Trunc Int32[[event]data >>] + epoll_ctl[epfd, 2, activefd, Build[epoll_event()]] + { + If[[[event]events >>]&[8216u32]] + { res <- No } + { res <- Yes } + ct,cont <- _Get IO Context[activefd] + { + }{ Print["Could not find context for IO event"] } + ,cont <- Resume[ct,res] + { + cont <- Yield[] + }{ + Print["could not resume context for IO event"] + } + } + }{ + cont <- _Add New FDs[epfd,pipefd] + } + Val[cont] + { + out <- _Handle Events[epfd,pipefd,buf,[cur]+[1]] + } + } +} + +_Wait Active[epfd,pipefd,buf] +{ + workaround <- Yield[] + Val[workaround] + { + count,newbuf <- epoll_wait[epfd,buf,[buf]Storage >>,-1] + If[[count]=[-1]] + { + Print["epoll_wait returned error"] + }{ + If[[count]=[0]] + { + //Shouldn't happen normally, but perhaps if there was a signal + _Wait Active[epfd,pipefd,buf] + }{ + _Handle Events[epfd,pipefd,[newbuf]Length <<[count],0] + { _Wait Active[epfd,pipefd,buf] } + } + } + } +} + +_Sock Listener[pipefd] +{ + epfd <- epoll_create[16] + If[[epfd]=[-1]] + { + Print["Error creating epoll file descriptor"] + }{ + If[[epoll_ctl[epfd,1i32,pipefd,[[Build[epoll_event()]]events <<[1u32]]data <<[0i64]]]=[-1]] + { + Print["Error adding pipe to epoll fd"] + }{ + _Wait Active[epfd, pipefd, _internal_array_allocnaked[8,epoll_event()]] + } + } +} + +Globals socklisten +{ + listener started <- No + fdlookup <- () + pipefd <- -1 +} + +_Add FD to Listener[fd,context:pipefd,err] uses socklisten +{ + If[socklisten::listener started] + { + pipefd <- socklisten::pipefd + do add <- Yes + }{ + //Calling a function with side effects inside a transaction is BAD + //Need to do something about this + ret,des <- pipe[[Array[]]Set[1, 0i32]] + If[[ret]=[-1]] + { + err <- "Error creating pipe for waking up socket listener" + }{ + socklisten::pipefd <- [des]Index[1] + pipefd <- [des]Index[1] + //fcntl[fd, F_SETFL, O_NONBLOCK] + //Set both ends of the pipe to non blocking + fcntl[[des]Index[0], 4i32, 2048i64] + fcntl[[des]Index[1], 4i32, 2048i64] + socklisten::listener started <- Yes + Call Async[_Sock Listener[[des]Index[0],?]] + do add <- Yes + } + } + Val[do add] + { + socklisten::fdlookup <- [socklisten::fdlookup]Set[fd, context] + } +} + +_Write to Listener Pipe[pipefd,data] +{ + res <- write[pipefd, data, 8i64] + If[[res]!=[8i32]] + { + workaround <- Yield[] + Val[workaround] + { _Write to Listener Pipe[pipefd,data] } + } +} + +_Wait for IO[fd,type,context] +{ + _Add FD to Listener[fd,context] + { + _Write to Listener Pipe[~,[[Array[]]Append[fd]]Append[type]] + }{ + Print[~] + { Resume[context,No] } + } +} + +Wait for IO[fd,type:out] +{ + out <- Pause[_Wait for IO[fd,type,?]] +} + +_Do Con Call[newfd,address,tocall] +{ + [tocall]Call[newfd,address] +} + +_Null Term[raw str,cur:out] +{ + [raw str]Index[cur] + { + If[[~]=[0u8]] + { + out <- String[[raw str]Length <<[cur]] + }{ + out <- _Null Term[raw str, [cur]+[1]] + } + }{ + out <- String[raw str] + } +} + +_Port Wait[fd,tocall:out] +{ + con <- _internal_accept[fd,_internal_array_allocnaked[40,UInt8()],40] {} + { address <- _Null Term[[~]Length <<[40], 0i32] } + If[[con]=[-1]] + { + If[Wait for IO[fd, 1i32]] + { + out <- _Port Wait[fd,tocall] + }{ + Print["Error waiting for connection"] + } + }{ + Call Async[_Do Con Call[con,address,tocall,?]] + { + out <- _Port Wait[fd,tocall] + } + } +} + +Listen on Port[port(Int32),tocall:out] +{ + fd <- _internal_bindnewsocket[port,1] + //fcntl[fd, F_SETFL, O_NONBLOCK] + //Set listen socket to non blocking + If[[fd]=[-1]] + { out <- No } + { + fcntl[fd, 4i32, 2048i64] + { listen[fd,8] + { out <- Call Async[_Port Wait[fd,tocall,?]] }} + } +} + +//This effectively leaks a context and thus any data on the stack of that context +//Need either handle cleanup of contexts or find a better way to accomplish this +Wait Forever[] +{ + Pause[Val[?]] +} + diff -r f2cb85c53ced -r 7bbdc034e347 nworker_c.rhope --- a/nworker_c.rhope Sat Nov 20 17:48:22 2010 -0500 +++ b/nworker_c.rhope Sun Nov 21 16:33:17 2010 -0500 @@ -1069,7 +1069,7 @@ Node Result Vars[vars,node,index:out] { - [("call","getfield","setfield")]Find[=[[node]Type >>, ?]] + [("call","getfield","setfield","getglobal")]Find[=[[node]Type >>, ?]] { If[[[node]Type >>]=["call"]] { diff -r f2cb85c53ced -r 7bbdc034e347 parser_old_c.rhope --- a/parser_old_c.rhope Sat Nov 20 17:48:22 2010 -0500 +++ b/parser_old_c.rhope Sun Nov 21 16:33:17 2010 -0500 @@ -1056,7 +1056,8 @@ value,after <- Parse Number[name, params] }{ delims <- [[[[[[[("\n")]Append[[params]Block Begin >>]]Append[[params]Block End >>]]Append[[params]Empty Block >>]]Append[[params]Arg End >>]]Append[[params]List Delim >>]]Append[[params]List End >>]]Append[[params]List Begin >>] - afterdelim,raw before,delim,nodelim <- [name]Get Comment DString[delims, params] + afterdelim,raw before,delim,nodelim <- [name]Get Comment DString[delims, params] {} {} {} + { delim <- "" } before <- Trim[raw before, "\r\n\t "] If[[delim] = [[params]List Begin >>]] @@ -1435,9 +1436,12 @@ } Val[valstring] { + Print[["Parsing initial value: "]Append[valstring]] value <- [Named Pipe or Literal[Trim[~, "\r\n\t "], params]]Value >> next store <- [store]Vars <<[ [[store]Vars >>]Set[varname, value] ] } + }{ + Print[["Expected assignment operator in global var block, found "]Append[trimmed]] } }{ out <- store diff -r f2cb85c53ced -r 7bbdc034e347 runtime/context.c --- a/runtime/context.c Sat Nov 20 17:48:22 2010 -0500 +++ b/runtime/context.c Sun Nov 21 16:33:17 2010 -0500 @@ -34,12 +34,14 @@ int32_t put_cqueue(context * ct) { rh_lock(cq_lock); - if ((cq_writeloc+1)&31 == cq_readloc) - { + if (((cq_writeloc+1)&31) == cq_readloc) + { rh_unlock(cq_lock); return 0; } contextqueue[cq_writeloc++] = ct; + if(cq_writeloc == 32) + cq_writeloc = 0; rh_unlock(cq_lock); return 1; } diff -r f2cb85c53ced -r 7bbdc034e347 runtime/func.h --- a/runtime/func.h Sat Nov 20 17:48:22 2010 -0500 +++ b/runtime/func.h Sun Nov 21 16:33:17 2010 -0500 @@ -287,6 +287,24 @@ my_cdata = cdata->lastframe;\ RESUME_SELF +#define CallNoLocals(tocall, numparams, resumeto, myname)\ + cdata->func = RES_ ## resumeto ## _ ## myname;\ + cdata->num_params = numparams;\ + if(FUNC_ ## tocall == FUNC_ ## myname) {\ + PAUSE_SELF\ + AND_TOTAL\ + } else if (FUNC_ ## tocall != FUNC_PL_ && FUNC_ ## tocall != FUNC_MN_ && FUNC_ ## tocall != FUNC_TM_ && FUNC_ ## tocall != FUNC_DV_ && FUNC_ ## tocall != FUNC_If) {\ + PAUSE_SELF\ + }\ + goto sf_ ## tocall;\ +r ## resumeto ## _ ## myname:\ + my_cdata = cdata->lastframe;\ + if(FUNC_ ## tocall == FUNC_ ## myname) {\ + RESUME_SELF\ + AND_RESUME_TOTAL\ + } else if (FUNC_ ## tocall != FUNC_PL_ && FUNC_ ## tocall != FUNC_MN_ && FUNC_ ## tocall != FUNC_TM_ && FUNC_ ## tocall != FUNC_DV_ && FUNC_ ## tocall != FUNC_If) {\ + RESUME_SELF\ + } #define Call(tocall, numparams, resumeto, myname)\ cdata->func = RES_ ## resumeto ## _ ## myname;\ diff -r f2cb85c53ced -r 7bbdc034e347 runtime/net.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/runtime/net.c Sun Nov 21 16:33:17 2010 -0500 @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include +#include + +int _internal_accept(int sockfd, char * addrbuf, int buflen) +{ + int retfd; + socklen_t addr_size; + struct sockaddr_storage remote_addr; + addr_size = sizeof(remote_addr); + retfd = accept(sockfd, (struct sockaddr *)&remote_addr, &addr_size); + if (addrbuf && buflen) + { + addrbuf[0] = '\0'; + if(retfd == -1) + return retfd; + switch(remote_addr.ss_family) + { + case AF_INET: + inet_ntop(AF_INET, &(((struct sockaddr_in *)&remote_addr)->sin_addr), addrbuf, buflen); + break; + case AF_INET6: + inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)&remote_addr)->sin6_addr), addrbuf, buflen); + break; + } + } + return retfd; +} + + +int _internal_bindnewsocket(unsigned int port, int setreuse) +{ + char portstr[6]; + int sockfd,flag=1; + struct addrinfo hints, *localaddr; + + snprintf(portstr, 6, "%d", port & 0XFFFF); + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + + getaddrinfo(NULL, portstr, &hints, &localaddr); + + sockfd = socket(localaddr->ai_family, localaddr->ai_socktype, localaddr->ai_protocol); + if (sockfd == -1) + { + freeaddrinfo(localaddr); + return sockfd; + } + if(setreuse) + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,&flag,sizeof(int)); + if(-1 == bind(sockfd, localaddr->ai_addr, localaddr->ai_addrlen)) + { + close(sockfd); + sockfd = -1; + } + freeaddrinfo(localaddr); + return sockfd; +} + diff -r f2cb85c53ced -r 7bbdc034e347 webserver.rhope --- a/webserver.rhope Sat Nov 20 17:48:22 2010 -0500 +++ b/webserver.rhope Sun Nov 21 16:33:17 2010 -0500 @@ -1,4 +1,3 @@ -Import extendlib.rhope Get Content Type[path:out] { @@ -42,7 +41,7 @@ default headers <- [start headers]Set["Content-Length", content length] } - out <- [client]Put String@Net Client[ + out <- [client]Put String[ [ [ [ @@ -87,13 +86,14 @@ ,newpath <- [path]Slice[1] If[[newpath] = ["default.css"]] { - file <- [0]] { - junk,data <- [file]Get FString[content length] + data <- [file]Read[content length] [HTTP OK[client, Get Content Type[path], content length, Dictionary[]] - ]Put String@Net Client[data] + ]Write[data] + { Close[file] } }{ HTTP Not Found[client] } @@ -118,12 +118,12 @@ Connection Start[con,handlers] { - client, request <- [con]Get DString@Net Client["\r\n"] - parts <- [request]Split@String[" "] + client, request <- [con]Get DString["\r\n"] + parts <- [request]Split[" "] Print[request] - [client]Get DString@Net Client["\r\n\r\n"] + [client]Get DString["\r\n\r\n"] { - Handle Request[~, [parts]Index@List[0], [parts]Index@List[1], headers, handlers] + Handle Request[~, [parts]Index[0], [parts]Index[1], headers, handlers] }{ headers <- Map[Dict Split[~, ":", "\r\n"], ["Trim"]Set Input[1, " \t"]] }