Monday, November 08, 2010 at 12:03 AM.
system.verbs.builtins.inetd.supervisor
on supervisor (stream, refcon) { <<This is the callback that receives incoming requests for all inetd servers. <<It calls the appropriate daemon script then returns data to the client. <<Change Notes <<Saturday, December 20, 1997 at 3:29:57 PM by PBS <<Modified to work with tcp verbs. <<Friday, February 27, 1998 at 9:03:42 AM by DW and RAB <<Major update, added error log, everything within a try. <<Friday, February 27, 1998 at 12:18:30 PM by RAB <<Updated read data condensing it into 1 loop and allowing a yield to give time for the winsock buffer to refil <<It no longer uses bytespending == 0 to terminate the read data loop <<Updated the write on info from Dave Habermann to allow a yield on the writes to give a chance <<for the buffers to be cleared before the next write. <<Monday, March 9, 1998 at 3:15:00 PM by RAB <<Added a thread sleep so as to yeild some time. <<Thursday, March 12, 1998 at 9:31:15 PM by WF/RAB <<Fixed bug where clocks.now was used instead of clock.ticks <<Thursday, November 11, 1999 at 2:38:45 AM by AR <<Implemented as a kernel verb in Frontier 6.1. <<Old code <<on supervisor (stream, refcon) << <<if stream < 0 //an internal Frontier error, should never happen? <<return (true) //don't terminate the listener << <<if user.inetd.shutdown //you can turn off inetd by setting this global <<tcp.closeStream (stream) <<inetd.stop () <<return << <<on addToErrorLog (whatWereWeDoing, errorString) <<local (adrtable = log.addToGuestDatabase ("inetd", flHourlyRoll:true)) <<adrtable^.stream = stream <<try {adrtable^.port = paramTable.port} <<try {adrtable^.client = paramtable.client} <<adrtable^.whatWentWrong = errorstring <<adrtable^.whatWereWeDoing = whatWereWeDoing <<try {tcp.closeStream (stream)} << <<local (paramTable) <<bundle //initialize paramtable <<try <<new (tableType, @paramTable) <<paramTable.request = "" <<paramTable.client = tcp.addressDecode (tcp.getPeerAddress (stream)) <<paramTable.ready = true <<paramTable.refcon = refcon <<paramTable.stream = stream <<paramTable.inetdConfigTableAdr = user.inetd.listens.[refcon].adrTable <<paramTable.port = paramTable.inetdConfigTableAdr^.port <<else <<addToErrorLog ("Initializing paramtable", tryError) <<try {tcp.closeStream (stream)} <<return (true) //don't terminate the listener << <<local (noWait) <<try {noWait = paramTable.inetdConfigTableAdr^.noWait} else {noWait = false} << <<local (timeoutSecs) <<try {timeoutSecs = paramTable.inetdConfigTableAdr^.timeout} else {timeoutSecs = user.inetd.prefs.defaultTimeoutSecs} <<paramTable.timeout = timeoutSecs <<local (tcTimeout = clock.ticks () + (60 * timeoutsecs)) << <<if not noWait //wait for the whole stream to come in <<local (bytespending, status) <<try <<loop //wait for data to read <<status = tcp.statusStream (stream, @bytespending) <<if (bytespending > 0) and (status == "DATA") <<paramTable.request = paramTable.request + tcp.readStream (stream, bytespending) <<tcTimeout = clock.ticks () + 30 //Now give only 1/2 second to get more data <<if status == "CLOSED" <<break <<if status == "INACTIVE" <<break <<if clock.ticks () > tcTimeout <<break <<if status == "OPEN" <<sys.systemTask () //yield a little within this thread for the system <<thread.sleepfor (1) //yield this thread for a second to allow normal Frontier processing <<else <<addToErrorLog ("Waiting for data", tryError) <<return (true) //don't terminate the listener << <<bundle //call the daemon <<try <<local (adrScript = @paramTable.inetdConfigTableAdr^.daemon) <<if typeOf (adrScript^) == addressType //allow for indirect daemon scripts <<adrScript = adrScript^ <<local (returnData = string (adrScript^ (@paramTable))) <<if sizeof (returnData) > 0 //there is data to return <<local (chunksize = user.inetd.prefs.returnChunkSize) <<local (tcLastWrite = clock.ticks ()) <<loop //return data to the client <<try <<if sizeof (returnData) <= chunksize <<tcp.writeStream (stream, returnData) <<break <<tcp.writeStream (stream, string.mid (returnData, 1, chunkSize)) <<tcLastWrite = clock.ticks () <<returnData = string.delete (returnData, 1, chunkSize) <<else <<if (tryerror contains "10035") && (clock.ticks () < (tcLastWrite + (60*5))) //10035 means the socket buffers are not ready, give them upto 5 second <<sys.systemTask() //yield a little within this thread for the system <<thread.sleepfor (1) //yield this thread for a second to allow normal frontier processing <<else <<addToErrorLog ("Returning data", tryError) <<return (true) //don't terminate the listener <<if sizeof (returnData) > 0 //there is data to return <<tcp.writeStringToStream (stream, returnData, user.inetd.prefs.returnChunkSize, 10) <<else <<addToErrorLog ("Calling the daemon", tryError) <<return (true) //don't terminate the listener << <<try {tcp.closeStream (stream)} <<return (true) kernel (inetd.supervisor)}
This listing is for code that runs in the OPML Editor environment. I created these listings because I wanted the search engines to index it, so that when I want to look up something in my codebase I don't have to use the much slower search functionality in my object database. Dave Winer.