Edit File by line
/home/barbar84/public_h.../wp-conte.../plugins/sujqvwi/AnonR/anonr.TX.../opt/alt/ruby18/lib64/ruby/1.8
File: gserver.rb
#
[0] Fix | Delete
# Copyright (C) 2001 John W. Small All Rights Reserved
[1] Fix | Delete
#
[2] Fix | Delete
# Author:: John W. Small
[3] Fix | Delete
# Documentation:: Gavin Sinclair
[4] Fix | Delete
# Licence:: Freeware.
[5] Fix | Delete
#
[6] Fix | Delete
# See the class GServer for documentation.
[7] Fix | Delete
#
[8] Fix | Delete
[9] Fix | Delete
require "socket"
[10] Fix | Delete
require "thread"
[11] Fix | Delete
[12] Fix | Delete
#
[13] Fix | Delete
# GServer implements a generic server, featuring thread pool management,
[14] Fix | Delete
# simple logging, and multi-server management. See HttpServer in
[15] Fix | Delete
# <tt>xmlrpc/httpserver.rb</tt> in the Ruby standard library for an example of
[16] Fix | Delete
# GServer in action.
[17] Fix | Delete
#
[18] Fix | Delete
# Any kind of application-level server can be implemented using this class.
[19] Fix | Delete
# It accepts multiple simultaneous connections from clients, up to an optional
[20] Fix | Delete
# maximum number. Several _services_ (i.e. one service per TCP port) can be
[21] Fix | Delete
# run simultaneously, and stopped at any time through the class method
[22] Fix | Delete
# <tt>GServer.stop(port)</tt>. All the threading issues are handled, saving
[23] Fix | Delete
# you the effort. All events are optionally logged, but you can provide your
[24] Fix | Delete
# own event handlers if you wish.
[25] Fix | Delete
#
[26] Fix | Delete
# === Example
[27] Fix | Delete
#
[28] Fix | Delete
# Using GServer is simple. Below we implement a simple time server, run it,
[29] Fix | Delete
# query it, and shut it down. Try this code in +irb+:
[30] Fix | Delete
#
[31] Fix | Delete
# require 'gserver'
[32] Fix | Delete
#
[33] Fix | Delete
# #
[34] Fix | Delete
# # A server that returns the time in seconds since 1970.
[35] Fix | Delete
# #
[36] Fix | Delete
# class TimeServer < GServer
[37] Fix | Delete
# def initialize(port=10001, *args)
[38] Fix | Delete
# super(port, *args)
[39] Fix | Delete
# end
[40] Fix | Delete
# def serve(io)
[41] Fix | Delete
# io.puts(Time.now.to_i)
[42] Fix | Delete
# end
[43] Fix | Delete
# end
[44] Fix | Delete
#
[45] Fix | Delete
# # Run the server with logging enabled (it's a separate thread).
[46] Fix | Delete
# server = TimeServer.new
[47] Fix | Delete
# server.audit = true # Turn logging on.
[48] Fix | Delete
# server.start
[49] Fix | Delete
#
[50] Fix | Delete
# # *** Now point your browser to http://localhost:10001 to see it working ***
[51] Fix | Delete
#
[52] Fix | Delete
# # See if it's still running.
[53] Fix | Delete
# GServer.in_service?(10001) # -> true
[54] Fix | Delete
# server.stopped? # -> false
[55] Fix | Delete
#
[56] Fix | Delete
# # Shut the server down gracefully.
[57] Fix | Delete
# server.shutdown
[58] Fix | Delete
#
[59] Fix | Delete
# # Alternatively, stop it immediately.
[60] Fix | Delete
# GServer.stop(10001)
[61] Fix | Delete
# # or, of course, "server.stop".
[62] Fix | Delete
#
[63] Fix | Delete
# All the business of accepting connections and exception handling is taken
[64] Fix | Delete
# care of. All we have to do is implement the method that actually serves the
[65] Fix | Delete
# client.
[66] Fix | Delete
#
[67] Fix | Delete
# === Advanced
[68] Fix | Delete
#
[69] Fix | Delete
# As the example above shows, the way to use GServer is to subclass it to
[70] Fix | Delete
# create a specific server, overriding the +serve+ method. You can override
[71] Fix | Delete
# other methods as well if you wish, perhaps to collect statistics, or emit
[72] Fix | Delete
# more detailed logging.
[73] Fix | Delete
#
[74] Fix | Delete
# connecting
[75] Fix | Delete
# disconnecting
[76] Fix | Delete
# starting
[77] Fix | Delete
# stopping
[78] Fix | Delete
#
[79] Fix | Delete
# The above methods are only called if auditing is enabled.
[80] Fix | Delete
#
[81] Fix | Delete
# You can also override +log+ and +error+ if, for example, you wish to use a
[82] Fix | Delete
# more sophisticated logging system.
[83] Fix | Delete
#
[84] Fix | Delete
class GServer
[85] Fix | Delete
[86] Fix | Delete
DEFAULT_HOST = "127.0.0.1"
[87] Fix | Delete
[88] Fix | Delete
def serve(io)
[89] Fix | Delete
end
[90] Fix | Delete
[91] Fix | Delete
@@services = {} # Hash of opened ports, i.e. services
[92] Fix | Delete
@@servicesMutex = Mutex.new
[93] Fix | Delete
[94] Fix | Delete
def GServer.stop(port, host = DEFAULT_HOST)
[95] Fix | Delete
@@servicesMutex.synchronize {
[96] Fix | Delete
@@services[host][port].stop
[97] Fix | Delete
}
[98] Fix | Delete
end
[99] Fix | Delete
[100] Fix | Delete
def GServer.in_service?(port, host = DEFAULT_HOST)
[101] Fix | Delete
@@services.has_key?(host) and
[102] Fix | Delete
@@services[host].has_key?(port)
[103] Fix | Delete
end
[104] Fix | Delete
[105] Fix | Delete
def stop
[106] Fix | Delete
@connectionsMutex.synchronize {
[107] Fix | Delete
if @tcpServerThread
[108] Fix | Delete
@tcpServerThread.raise "stop"
[109] Fix | Delete
end
[110] Fix | Delete
}
[111] Fix | Delete
end
[112] Fix | Delete
[113] Fix | Delete
def stopped?
[114] Fix | Delete
@tcpServerThread == nil
[115] Fix | Delete
end
[116] Fix | Delete
[117] Fix | Delete
def shutdown
[118] Fix | Delete
@shutdown = true
[119] Fix | Delete
end
[120] Fix | Delete
[121] Fix | Delete
def connections
[122] Fix | Delete
@connections.size
[123] Fix | Delete
end
[124] Fix | Delete
[125] Fix | Delete
def join
[126] Fix | Delete
@tcpServerThread.join if @tcpServerThread
[127] Fix | Delete
end
[128] Fix | Delete
[129] Fix | Delete
attr_reader :port, :host, :maxConnections
[130] Fix | Delete
attr_accessor :stdlog, :audit, :debug
[131] Fix | Delete
[132] Fix | Delete
def connecting(client)
[133] Fix | Delete
addr = client.peeraddr
[134] Fix | Delete
log("#{self.class.to_s} #{@host}:#{@port} client:#{addr[1]} " +
[135] Fix | Delete
"#{addr[2]}<#{addr[3]}> connect")
[136] Fix | Delete
true
[137] Fix | Delete
end
[138] Fix | Delete
[139] Fix | Delete
def disconnecting(clientPort)
[140] Fix | Delete
log("#{self.class.to_s} #{@host}:#{@port} " +
[141] Fix | Delete
"client:#{clientPort} disconnect")
[142] Fix | Delete
end
[143] Fix | Delete
[144] Fix | Delete
protected :connecting, :disconnecting
[145] Fix | Delete
[146] Fix | Delete
def starting()
[147] Fix | Delete
log("#{self.class.to_s} #{@host}:#{@port} start")
[148] Fix | Delete
end
[149] Fix | Delete
[150] Fix | Delete
def stopping()
[151] Fix | Delete
log("#{self.class.to_s} #{@host}:#{@port} stop")
[152] Fix | Delete
end
[153] Fix | Delete
[154] Fix | Delete
protected :starting, :stopping
[155] Fix | Delete
[156] Fix | Delete
def error(detail)
[157] Fix | Delete
log(detail.backtrace.join("\n"))
[158] Fix | Delete
end
[159] Fix | Delete
[160] Fix | Delete
def log(msg)
[161] Fix | Delete
if @stdlog
[162] Fix | Delete
@stdlog.puts("[#{Time.new.ctime}] %s" % msg)
[163] Fix | Delete
@stdlog.flush
[164] Fix | Delete
end
[165] Fix | Delete
end
[166] Fix | Delete
[167] Fix | Delete
protected :error, :log
[168] Fix | Delete
[169] Fix | Delete
def initialize(port, host = DEFAULT_HOST, maxConnections = 4,
[170] Fix | Delete
stdlog = $stderr, audit = false, debug = false)
[171] Fix | Delete
@tcpServerThread = nil
[172] Fix | Delete
@port = port
[173] Fix | Delete
@host = host
[174] Fix | Delete
@maxConnections = maxConnections
[175] Fix | Delete
@connections = []
[176] Fix | Delete
@connectionsMutex = Mutex.new
[177] Fix | Delete
@connectionsCV = ConditionVariable.new
[178] Fix | Delete
@stdlog = stdlog
[179] Fix | Delete
@audit = audit
[180] Fix | Delete
@debug = debug
[181] Fix | Delete
end
[182] Fix | Delete
[183] Fix | Delete
def start(maxConnections = -1)
[184] Fix | Delete
raise "running" if !stopped?
[185] Fix | Delete
@shutdown = false
[186] Fix | Delete
@maxConnections = maxConnections if maxConnections > 0
[187] Fix | Delete
@@servicesMutex.synchronize {
[188] Fix | Delete
if GServer.in_service?(@port,@host)
[189] Fix | Delete
raise "Port already in use: #{host}:#{@port}!"
[190] Fix | Delete
end
[191] Fix | Delete
@tcpServer = TCPServer.new(@host,@port)
[192] Fix | Delete
@port = @tcpServer.addr[1]
[193] Fix | Delete
@@services[@host] = {} unless @@services.has_key?(@host)
[194] Fix | Delete
@@services[@host][@port] = self;
[195] Fix | Delete
}
[196] Fix | Delete
@tcpServerThread = Thread.new {
[197] Fix | Delete
begin
[198] Fix | Delete
starting if @audit
[199] Fix | Delete
while !@shutdown
[200] Fix | Delete
@connectionsMutex.synchronize {
[201] Fix | Delete
while @connections.size >= @maxConnections
[202] Fix | Delete
@connectionsCV.wait(@connectionsMutex)
[203] Fix | Delete
end
[204] Fix | Delete
}
[205] Fix | Delete
client = @tcpServer.accept
[206] Fix | Delete
@connections << Thread.new(client) { |myClient|
[207] Fix | Delete
begin
[208] Fix | Delete
myPort = myClient.peeraddr[1]
[209] Fix | Delete
serve(myClient) if !@audit or connecting(myClient)
[210] Fix | Delete
rescue => detail
[211] Fix | Delete
error(detail) if @debug
[212] Fix | Delete
ensure
[213] Fix | Delete
begin
[214] Fix | Delete
myClient.close
[215] Fix | Delete
rescue
[216] Fix | Delete
end
[217] Fix | Delete
@connectionsMutex.synchronize {
[218] Fix | Delete
@connections.delete(Thread.current)
[219] Fix | Delete
@connectionsCV.signal
[220] Fix | Delete
}
[221] Fix | Delete
disconnecting(myPort) if @audit
[222] Fix | Delete
end
[223] Fix | Delete
}
[224] Fix | Delete
end
[225] Fix | Delete
rescue => detail
[226] Fix | Delete
error(detail) if @debug
[227] Fix | Delete
ensure
[228] Fix | Delete
begin
[229] Fix | Delete
@tcpServer.close
[230] Fix | Delete
rescue
[231] Fix | Delete
end
[232] Fix | Delete
if @shutdown
[233] Fix | Delete
@connectionsMutex.synchronize {
[234] Fix | Delete
while @connections.size > 0
[235] Fix | Delete
@connectionsCV.wait(@connectionsMutex)
[236] Fix | Delete
end
[237] Fix | Delete
}
[238] Fix | Delete
else
[239] Fix | Delete
@connections.each { |c| c.raise "stop" }
[240] Fix | Delete
end
[241] Fix | Delete
@tcpServerThread = nil
[242] Fix | Delete
@@servicesMutex.synchronize {
[243] Fix | Delete
@@services[@host].delete(@port)
[244] Fix | Delete
}
[245] Fix | Delete
stopping if @audit
[246] Fix | Delete
end
[247] Fix | Delete
}
[248] Fix | Delete
self
[249] Fix | Delete
end
[250] Fix | Delete
[251] Fix | Delete
end
[252] Fix | Delete
[253] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function