Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:22613 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 3705 invoked by uid 1010); 29 Mar 2006 05:35:42 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 3689 invoked from network); 29 Mar 2006 05:35:42 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 29 Mar 2006 05:35:42 -0000 X-Host-Fingerprint: 63.240.77.84 sccrmhc14.comcast.net NetCache Data OnTap 5.x Received: from ([63.240.77.84:33146] helo=sccrmhc14.comcast.net) by pb1.pair.com (ecelerity 2.0 beta r(6323M)) with SMTP id 3C/BB-14993-DAC1A244 for ; Wed, 29 Mar 2006 00:35:41 -0500 Received: from [10.10.10.102] (c-67-174-105-139.hsd1.co.comcast.net[67.174.105.139]) by comcast.net (sccrmhc14) with SMTP id <2006032905353701400c526ee>; Wed, 29 Mar 2006 05:35:37 +0000 To: internals@lists.php.net In-Reply-To: <4e89b4260603281731n13ee3f57u7f52d5107529e08b@mail.gmail.com> References: <032820062059.19729.4429A3AC0005601D00004D112200762194CEC7CE9D0E9B9C0A9A09019D@comcast.net> <4e89b4260603281731n13ee3f57u7f52d5107529e08b@mail.gmail.com> Content-Type: text/plain Date: Tue, 28 Mar 2006 22:35:36 +0000 Message-ID: <1143585336.32171.62.camel@localhost.localdomain> Mime-Version: 1.0 X-Mailer: Evolution 2.2.2 (2.2.2-5) Content-Transfer-Encoding: 7bit Subject: Re: [PHP-DEV] can Php - Fast-CGI and STDIN be used? From: roguestar191@comcast.net (Matthew) Sorry for sending twice wez, I meant to send it here in the first place. No I'm not familiar with the fcgi spec.. I just by myself wrote an fcgi interface, that's all. ok you're right, _just_ a dup2 would be insufficient, even if it uses pipes behind the scenes it's not much different from below. please Consider the following, and this is pretty keeping it simple: --- Oh and in the example below I screwed up, padding is only fcgibuf[6], I forgot it's only 1 byte to indicate the size of the padding. (Fixed in this example) Now this won't do _everything_ but it's a start :-P struct FastCGI { std::string stdin; void stdout(std::string&); // wrap in fcgi header, print to socket int socket; std::string fcgibuf; void parseOneRequest(std::string&); int pipeforstdin; int pipeforstdout; } void FastCGI::parseOneRequest(std::string&in) { fcgibuf += in; if(fcgibuf.size() < FCGI_HEADER_SIZE) return; //fast_cgiheader = fcgibuf[0]-fcgibuf[7]; //FCGI_HEADER_SIZE = 8 size_t contentsize = (fcgibuf[4]<<8)+fcgibuf[5]; unsigned char padding = fcgibuf[6]; size_t totalsize = contentsize+padding+FCGI_HEADER_SIZE; if(fcgibuf.size() < totalsize) return; int type = request[1]; size_t requestid = (b[2]<<8 )+b[1]; std::string content = ""; if(contentsize() > 0) content = fcgibuf.substr(FCGI_HEADER_SIZE, contentsize); fcgibuf.replace(0, totalsize, ""); // Clear it out for next request. // We have a full request, the type, all the data, and the request id. if(type == BEGIN_REQUEST) { int childstdin[2]; int childstdout[2]; pipe(childstdin); // may fail pipe(childstdout); // may fail stdin = childstdin[1]; stdout = childstdout[0]; BytecodeController.prepare_thread_for_request(requestid, childstdin[0], childstdout[1]); // [0] for reading [1] for writing. return; } if(type == FCGI_STDIN) { write(childstdin, content.c_str(), content.size()); // If when a child now calls fgets(stdin) it can read to a valid pipe. return; } if(type == FCGI_PARAMS) { BytecodeController.EnviromentalControls(requestid,content); // "environment variables" return; } if(type == FCGI_ABORT_REQUEST) { // respond with request aborted, kill script continue on } } class FCGIParse { public: static std::vector fastcgiusers; static void ParseFCGI(int &socket, std::string &request); static void close(int &socket); static void doAllStdOuts(); // do a non-blocking read on all the stdout pipes, wrap a response if any is found in an fcgi header and send them out. } FCGIParse::ParseFCGI(int &socket, std::string &request) { std::vector::iterator iter = fastcgiusers.begin(), end = fastcgiusers.end(); for(;iter::iterator iter = fastcgiusers.begin(), end = fastcgiusers.end(); for(;iterbindserversocket(); } RunFCGIHandler::run() { // Main loop setup(); while(RUNNING() ){ std::vector &packets = socks->listen(); std::vector::iterator iter = packets.begin(), end = packets.end(); FCGIParse::doAllStdOuts(); for(;iter users; std::vector listen() { fdset rmask; FD_SET(serverfd, &rmask); if(users.size() > 0) { std::vector::iterator iter = users.begin(), end = users.end(); for(;iter ret; if(FD_ISSET(ssd)) { accept, push back new user } if(nfound > 0) { std::vector::iterator iter = users.begin(), end = users.end(); for(;iter0) { aPacket np; np.socket = (*(iter)).socket; np.close = false; for(int c = 0;c>>>>>>>>>>>>>>>>>>>>>>>>> If you're that familiar with the fcgi spec, then you'll realize that a simple dup2() is not sufficient. It's still better to tackle the problem "the right way" instead of trying to force something to work in a way that it doesn't. Hence the term "abuse". Advocating the use of threads to "solve" this is also a bad idea, likewise, where are you going to fit the dispatcher for multiplexing? Take my advice: take a step back, take a deep breath and look at the problem again, and remember: KISS. --Wez. On 3/28/06, roguestar191@comcast.net wrote: > sorry the word abuse pissed me off. I'm not abusing anything the protocols weren't designed to support (even if they don't know it, but then, they do know it). I can understand if nobody ever thought of this use of it before and is why there is no support for using fcgistdin with php, even tho any other programming language can use it if it properly and _fully_ supports the fast-cgi protocol. > > The easiest way I can think of to make a fast-cgi client application would be to simple close socket 0, and socket 1 (stdin and stdout), then dup2ing to the end of a pipe, cout data would be grabbed from the end of one of the pipes, wrapped in a fast-cgi header, printed to the server, stdin data from the server would come in to a second thread (or a multiplexing select() core), using the request id it finds the proper stdin pipe and just sends the data there. > > That's not hard to do, that's not off from the fast-cgi protocol, that's not an abuse, and that would allow the very simple stdin/stdout protocols to work for the easiest, most extendable server scripting ever convieved. > > -------------- Original message -------------- > From: "Wez Furlong" > > > IMO, you're better off using stream_socket_server() and writing a > > "real" daemon for that. Abusing fastcgi/cgi to work in that way is > > only going to bite you in the ass. > > > > --Wez > > > > On 3/24/06, Matthew wrote: > > > I'm sorry if this is the wrong place for this post, I just don't know where > > > else to go. > > > > > > I need some help figuring out how to use FCGI_STDIN with a running php > > > script. > > > > > > I have written a server in c++, which for a while been running php through > > > it's plain old cgi interface. I have been using php for 2 things, the > > > obvious one, web pages, and the not so obvious, safe command/server > > > scripting. I have just implimented a fast-cgi interface to replace the cgi > > > interface, however, the scripting stuff i had that worked over regular cgi > > > just doesn't want to work with fast-cgi. > > > > > > Basically, the php script outputs a command and arguments, all commands > > > start with a %, so: > > > $var = "%print"; > > > printf("%s hello world\n", $var); > > > Can be used to print to the user calling the script. > > > > > > That part still works fine of course :). > > > > > > It doesn't stop there however, some of the %callbacks will return strings of > > > data over stdin so they can be $var = trim(fgets($STDIN)) for a very simple > > > and effective method of communicating with the server. > > > > > > I've tried doing the same with fast-cgi, but it seems > > > fopen("php://stdin","r") is not the right place to be reading from. > > > > > > I'm sending: > > > > > > (C++) > > > // loops over ever line of input, test it > > > std::string response = processALineFromCGI-OrFastCGIScript(oneLine) > > > if(response.compare("NOCMD") == 0) > > > buffer_to_print_to_user_who_called_this_when_request_finishs(); > > > else if(response.size() > 0) { > > > std::string sendout = FCGI_Headerize(response, FCGI_STDIN, ..); > > > non-blocking_send(sendout); > > > } > > > oneLine.erase(); > > > I use the same function to build the headers for FCGI_BEGIN_REQUEST, > > > FCGI_PARAMS, FCGI_STDIN on POST input, it works great there(now) > > > > > > > > > Also, is it possible to keep the connection open to php-cgi to avoid > > > connect/accept calls? Even if it's only fifo so only 1 request can go at a > > > time? > > > > > > If I must I could create a special c++ fast-cgi server that binds a second > > > port to pipe requests from php streams to the server, but would be a MAJOR > > > hack for what I'm trying to do.. :-D > > > > > > Thanks in advance! > > > > > > -- > > > PHP Internals - PHP Runtime Development Mailing List > > > To unsubscribe, visit: http://www.php.net/unsub.php > > > > > > > On Tue, 2006-03-28 at 20:31 -0500, Wez Furlong wrote: > If you're that familiar with the fcgi spec, then you'll realize that a > simple dup2() is not sufficient. > > It's still better to tackle the problem "the right way" instead of > trying to force something to work in a way that it doesn't. Hence the > term "abuse". > > Advocating the use of threads to "solve" this is also a bad idea, > likewise, where are you going to fit the dispatcher for multiplexing? > > Take my advice: take a step back, take a deep breath and look at the > problem again, and remember: KISS. > > --Wez. > > On 3/28/06, roguestar191@comcast.net wrote: > > sorry the word abuse pissed me off. I'm not abusing anything the > protocols weren't designed to support (even if they don't know it, but > then, they do know it). I can understand if nobody ever thought of > this use of it before and is why there is no support for using > fcgistdin with php, even tho any other programming language can use it > if it properly and _fully_ supports the fast-cgi protocol. > > > > The easiest way I can think of to make a fast-cgi client application > would be to simple close socket 0, and socket 1 (stdin and stdout), > then dup2ing to the end of a pipe, cout data would be grabbed from the > end of one of the pipes, wrapped in a fast-cgi header, printed to the > server, stdin data from the server would come in to a second thread > (or a multiplexing select() core), using the request id it finds the > proper stdin pipe and just sends the data there. > > > > That's not hard to do, that's not off from the fast-cgi protocol, > that's not an abuse, and that would allow the very simple stdin/stdout > protocols to work for the easiest, most extendable server scripting > ever convieved. > > > > -------------- Original message -------------- > > From: "Wez Furlong" > > > > > IMO, you're better off using stream_socket_server() and writing a > > > "real" daemon for that. Abusing fastcgi/cgi to work in that way is > > > only going to bite you in the ass. > > > > > > --Wez > > > > > > On 3/24/06, Matthew wrote: > > > > I'm sorry if this is the wrong place for this post, I just don't > know where > > > > else to go. > > > > > > > > I need some help figuring out how to use FCGI_STDIN with a > running php > > > > script. > > > > > > > > I have written a server in c++, which for a while been running > php through > > > > it's plain old cgi interface. I have been using php for 2 > things, the > > > > obvious one, web pages, and the not so obvious, safe > command/server > > > > scripting. I have just implimented a fast-cgi interface to > replace the cgi > > > > interface, however, the scripting stuff i had that worked over > regular cgi > > > > just doesn't want to work with fast-cgi. > > > > > > > > Basically, the php script outputs a command and arguments, all > commands > > > > start with a %, so: > > > > $var = "%print"; > > > > printf("%s hello world\n", $var); > > > > Can be used to print to the user calling the script. > > > > > > > > That part still works fine of course :). > > > > > > > > It doesn't stop there however, some of the %callbacks will > return strings of > > > > data over stdin so they can be $var = trim(fgets($STDIN)) for a > very simple > > > > and effective method of communicating with the server. > > > > > > > > I've tried doing the same with fast-cgi, but it seems > > > > fopen("php://stdin","r") is not the right place to be reading > from. > > > > > > > > I'm sending: > > > > > > > > (C++) > > > > // loops over ever line of input, test it > > > > std::string response = > processALineFromCGI-OrFastCGIScript(oneLine) > > > > if(response.compare("NOCMD") == 0) > > > > buffer_to_print_to_user_who_called_this_when_request_finishs(); > > > > else if(response.size() > 0) { > > > > std::string sendout = FCGI_Headerize(response, FCGI_STDIN, ..); > > > > non-blocking_send(sendout); > > > > } > > > > oneLine.erase(); > > > > I use the same function to build the headers for > FCGI_BEGIN_REQUEST, > > > > FCGI_PARAMS, FCGI_STDIN on POST input, it works great there(now) > > > > > > > > > > > > Also, is it possible to keep the connection open to php-cgi to > avoid > > > > connect/accept calls? Even if it's only fifo so only 1 request > can go at a > > > > time? > > > > > > > > If I must I could create a special c++ fast-cgi server that > binds a second > > > > port to pipe requests from php streams to the server, but would > be a MAJOR > > > > hack for what I'm trying to do.. :-D > > > > > > > > Thanks in advance! > > > > > > > > -- > > > > PHP Internals - PHP Runtime Development Mailing List > > > > To unsubscribe, visit: http://www.php.net/unsub.php > > > > > > > > > > >