added some experimental code
This commit is contained in:
		@ -269,6 +269,169 @@ class HttpServer(Object)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class HttpListener2(Socket)
 | 
			
		||||
{
 | 
			
		||||
	var(#get) server := nil.
 | 
			
		||||
	var(#get) rid := -1.
 | 
			
		||||
	var sem.
 | 
			
		||||
 | 
			
		||||
	method initialize
 | 
			
		||||
	{
 | 
			
		||||
		super initialize.
 | 
			
		||||
		self.sem := Semaphore new.
 | 
			
		||||
		self.sem signalAction: [:sem |
 | 
			
		||||
			| cliaddr clisck cliact fd |
 | 
			
		||||
			cliaddr := SocketAddress new.
 | 
			
		||||
 | 
			
		||||
			fd := self _accept: cliaddr.
 | 
			
		||||
			##if (fd >= 0)
 | 
			
		||||
			if (fd notNil)
 | 
			
		||||
			{
 | 
			
		||||
				clisck := (self acceptedSocketClass) __with: fd.
 | 
			
		||||
				clisck beWatched.
 | 
			
		||||
				self onSocketAccepted: clisck from: cliaddr.
 | 
			
		||||
			}.
 | 
			
		||||
		].
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
(*
 | 
			
		||||
	method onSocketAccepted: clisck from: cliaddr
 | 
			
		||||
	{
 | 
			
		||||
		| rid |
 | 
			
		||||
 | 
			
		||||
		'CLIENT accepted ..............' dump.
 | 
			
		||||
clisck dump.
 | 
			
		||||
		cliaddr dump.
 | 
			
		||||
 | 
			
		||||
		if (self.server notNil)
 | 
			
		||||
		{
 | 
			
		||||
			server addConnection: clisck.
 | 
			
		||||
			if (clisck isKindOf: SyncSocket)
 | 
			
		||||
			{
 | 
			
		||||
'SERVICE READLLY STARTING' dump.
 | 
			
		||||
				[clisck runService] fork.
 | 
			
		||||
			}
 | 
			
		||||
		}.
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method acceptedSocketClass
 | 
			
		||||
	{
 | 
			
		||||
		##^if (self currentAddress port == 80) { HttpSocket } else { HttpSocket }.
 | 
			
		||||
		^HttpSocket.
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method server: server rid: rid
 | 
			
		||||
	{
 | 
			
		||||
		self.server := server.
 | 
			
		||||
		self.rid := rid.
 | 
			
		||||
	}
 | 
			
		||||
*)
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class HttpServer2(Object)
 | 
			
		||||
{
 | 
			
		||||
	var listeners.
 | 
			
		||||
	var connreg.
 | 
			
		||||
	var sg.
 | 
			
		||||
 | 
			
		||||
	method initialize
 | 
			
		||||
	{
 | 
			
		||||
		super initialize.
 | 
			
		||||
		self.sg := SemaphoreGroup new.
 | 
			
		||||
		self.listeners := HttpConnReg new.
 | 
			
		||||
		self.connreg := HttpConnReg new.
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method run: laddr
 | 
			
		||||
	{
 | 
			
		||||
		| listener sem ss |
 | 
			
		||||
 | 
			
		||||
		if (laddr class == Array)
 | 
			
		||||
		{
 | 
			
		||||
			laddr do: [:addr |
 | 
			
		||||
				listener := HttpListener2 family: (addr family) type: Socket.Type.STREAM.
 | 
			
		||||
				if ((self addListener: listener) notError)
 | 
			
		||||
				{
 | 
			
		||||
					listener bind: addr.
 | 
			
		||||
					listener _listen: 128.
 | 
			
		||||
				}
 | 
			
		||||
			].
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			listener := HttpListener2 family: (laddr family) type: Socket.Type.STREAM.
 | 
			
		||||
			if ((self addListener: listener) notError)
 | 
			
		||||
			{
 | 
			
		||||
				listener bind: laddr.
 | 
			
		||||
				listener _listen: 128.
 | 
			
		||||
			}
 | 
			
		||||
		}.
 | 
			
		||||
 | 
			
		||||
		while (true) 
 | 
			
		||||
		{
 | 
			
		||||
			ss := self.sg wait.
 | 
			
		||||
			if (ss isError) { break }.
 | 
			
		||||
		}.
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method close
 | 
			
		||||
	{
 | 
			
		||||
		self.listeners do: [:listener |
 | 
			
		||||
			listener close.
 | 
			
		||||
		].
 | 
			
		||||
 | 
			
		||||
		self.connreg do: [:conn |
 | 
			
		||||
			conn close.
 | 
			
		||||
		].
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method addConnection: conn
 | 
			
		||||
	{
 | 
			
		||||
		| rid |
 | 
			
		||||
		rid := self.connreg add: conn.
 | 
			
		||||
		if (rid isError)
 | 
			
		||||
		{
 | 
			
		||||
			'ERROR - CANNOT REGISTER NEW CONNECTION >>>>>>>>>> ' dump.
 | 
			
		||||
			conn close.
 | 
			
		||||
			^rid.
 | 
			
		||||
		}.
 | 
			
		||||
 | 
			
		||||
('ADD NEW CONNECTION ' & rid asString) dump.
 | 
			
		||||
		conn server: self rid: rid.
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method removeConnection: conn
 | 
			
		||||
	{
 | 
			
		||||
		self.connreg remove: (conn rid).
 | 
			
		||||
		conn server: nil rid: -1.
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	method addListener: listener
 | 
			
		||||
	{
 | 
			
		||||
		| rid |
 | 
			
		||||
		rid := self.listeners add: listener.
 | 
			
		||||
		if (rid isError)
 | 
			
		||||
		{
 | 
			
		||||
			'ERROR - CANNOT REGISTER NEW LISTENER >>>>>>>>>> ' dump.
 | 
			
		||||
			listener close.
 | 
			
		||||
			^rid.
 | 
			
		||||
		}.
 | 
			
		||||
 | 
			
		||||
('ADD NEW LISTENER ' & rid asString) dump.
 | 
			
		||||
		listener server: self rid: rid.
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method removeListener: listener
 | 
			
		||||
	{
 | 
			
		||||
		self.listeners remove: (listener rid).
 | 
			
		||||
		listener server: nil rid: -1.
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class MyObject(Object)
 | 
			
		||||
{
 | 
			
		||||
	method(#class) start_server_socket
 | 
			
		||||
@ -405,7 +568,7 @@ class MyObject(Object)
 | 
			
		||||
		'----- END OF ANOTHER PROC ------' dump.
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	method(#class) main
 | 
			
		||||
	method(#class) main222
 | 
			
		||||
	{
 | 
			
		||||
		| httpd addr |
 | 
			
		||||
 | 
			
		||||
@ -446,4 +609,24 @@ httpd connect: addr.
 | 
			
		||||
 | 
			
		||||
		'----- END OF MAIN ------' dump.
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method(#class) main
 | 
			
		||||
	{
 | 
			
		||||
		| httpd addr |
 | 
			
		||||
 | 
			
		||||
		[
 | 
			
		||||
			httpd := HttpServer2 new.
 | 
			
		||||
			[
 | 
			
		||||
				httpd run: %(
 | 
			
		||||
					SocketAddress fromString: '[::]:7777',
 | 
			
		||||
					SocketAddress fromString: '0.0.0.0:7776'
 | 
			
		||||
				).
 | 
			
		||||
			] ensure: [ 
 | 
			
		||||
				if (httpd notNil) { httpd close } 
 | 
			
		||||
			]
 | 
			
		||||
 | 
			
		||||
		] on: Exception do: [:ex | ('Exception - '  & ex messageText) dump].
 | 
			
		||||
 | 
			
		||||
		'----- END OF MAIN ------' dump.
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -722,6 +722,100 @@ class AsyncServerSocket(AsyncSocket)
 | 
			
		||||
 | 
			
		||||
	method acceptedSocketClass
 | 
			
		||||
	{
 | 
			
		||||
		^Socket
 | 
			
		||||
		^AsyncSocket
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Mux(SemaphoreGroup)
 | 
			
		||||
{
 | 
			
		||||
	method addSocket: sck
 | 
			
		||||
	{
 | 
			
		||||
		self addSemaphore: (sck inreadysem).
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method removeSocket: sck 
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class ListenerSocket(Socket)
 | 
			
		||||
{
 | 
			
		||||
	var inreadysem.
 | 
			
		||||
 | 
			
		||||
	method initialize
 | 
			
		||||
	{
 | 
			
		||||
'Server Socket initialize...........' dump.
 | 
			
		||||
		super initialize.
 | 
			
		||||
 | 
			
		||||
		self.inreadysem signalAction: [ :sem |
 | 
			
		||||
			| cliaddr clisck cliact fd |
 | 
			
		||||
			cliaddr := SocketAddress new.
 | 
			
		||||
 | 
			
		||||
			fd := self _accept: cliaddr.
 | 
			
		||||
			##if (fd >= 0)
 | 
			
		||||
			if (fd notNil)
 | 
			
		||||
			{
 | 
			
		||||
				clisck := (self acceptedSocketClass) __with: fd.
 | 
			
		||||
 | 
			
		||||
				sg addSemaphore: self.inreadysem.
 | 
			
		||||
				self.inreadysem signalOnInput: self.handle.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
				self onSocketAccepted: clisck from: cliaddr.
 | 
			
		||||
			}.
 | 
			
		||||
		].
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method close
 | 
			
		||||
	{
 | 
			
		||||
'CLOSING SERVER SOCEKT.... ' dump.
 | 
			
		||||
		| sg |
 | 
			
		||||
		if (self.inreadysem notNil)
 | 
			
		||||
		{
 | 
			
		||||
			self.inreadysem unsignal.
 | 
			
		||||
			sg := self.inreadysem _group.
 | 
			
		||||
			if (sg notNil) { sg removeSemaphore: self.inreadysem }.
 | 
			
		||||
			self.inreadysem := nil.
 | 
			
		||||
		}.
 | 
			
		||||
 | 
			
		||||
		^super close.
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method listen: backlog
 | 
			
		||||
	{
 | 
			
		||||
		| n |
 | 
			
		||||
 | 
			
		||||
		## If listen is called before the socket handle is
 | 
			
		||||
		## added to the multiplexer, a spurious hangup event might
 | 
			
		||||
		## be generated. At least, such behavior was observed
 | 
			
		||||
		## in linux with epoll in the level trigger mode.
 | 
			
		||||
		##    self.inreadysem signalOnInput: self.handle.
 | 
			
		||||
		##    thisProcess addAsyncSemaphore: self.inreadysem.
 | 
			
		||||
		##    self _listen: backlog.
 | 
			
		||||
 | 
			
		||||
		n := self _listen: backlog.
 | 
			
		||||
 | 
			
		||||
		self.inreadysem signalOnInput: self.handle.
 | 
			
		||||
		sg addemaphore: self.inreadysem.
 | 
			
		||||
 | 
			
		||||
		^n.
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method accept
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method onSocketAccepted: clisck from: cliaddr
 | 
			
		||||
	{
 | 
			
		||||
		## close the accepted client socket immediately.
 | 
			
		||||
		## a subclass must override this to avoid it.
 | 
			
		||||
		clisck close.
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	method acceptedSocketClass
 | 
			
		||||
	{
 | 
			
		||||
		^Socket
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user