Monday, November 08, 2010 at 12:03 AM.


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 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 ()
						<<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
								<<new (tableType, @paramTable)
								<<paramTable.request = ""
								<<paramTable.client = tcp.addressDecode (tcp.getPeerAddress (stream))
								<<paramTable.ready = true
								<<paramTable.refcon = refcon
								<< = stream
								<<paramTable.inetdConfigTableAdr = user.inetd.listens.[refcon].adrTable
								<<paramTable.port = paramTable.inetdConfigTableAdr^.port
								<<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)
								<<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"
									<<if status == "INACTIVE"
									<<if clock.ticks () > tcTimeout
									<<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
								<<addToErrorLog ("Waiting for data", tryError)
								<<return (true) //don't terminate the listener
						<<bundle //call the daemon
								<<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
											<<if sizeof (returnData) <= chunksize
												<<tcp.writeStream (stream, returnData)
											<<tcp.writeStream (stream, string.mid (returnData, 1, chunkSize))
											<<tcLastWrite = clock.ticks ()
											<<returnData = string.delete (returnData, 1, chunkSize)
											<<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
												<<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)
								<<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.