Methods
- accept_connection
- add_periodic_timer
- add_timer
- cancel_timer
- check_for_timer_events
- complete_connection
- configure_socket_options
- connect
- decorate_handler
- handle_external_messages
- handle_internal_messages
- immediate_complete
- initialize_handler
- new
- read_external_socket
- reconnect
- remove_connection
- shutdown
- socket_really_connected?
- start_reactor
- start_server
- terminate_me
- user_thread_window
Included Modules
Public Class methods
[ show source ]
# File framework/core.rb, line 220
220: def initialize
221: @read_ios ||= []
222: @write_ios ||= []
223: @connection_completion_awaited ||= {}
224: @connections ||= {}
225: @listen_sockets ||= {}
226:
227: # @timer_hash = Packet::TimerStore
228: @timer_hash ||= {}
229: end
Public Instance methods
[ show source ]
# File framework/core.rb, line 65
65: def accept_connection(sock_opts)
66: sock_io = sock_opts[:socket]
67: begin
68: client_socket,client_sockaddr = sock_io.accept_nonblock
69: client_socket.setsockopt(Socket::IPPROTO_TCP,Socket::TCP_NODELAY,1)
70: rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
71: puts "not ready yet"
72: return
73: end
74: read_ios << client_socket
75: decorate_handler(client_socket,true,client_sockaddr,sock_opts[:module],&sock_opts[:block])
76: end
[ show source ]
# File framework/core.rb, line 203
203: def add_periodic_timer(interval,&block)
204: t_timer = PeriodicEvent.new(interval,&block)
205: @timer_hash[t_timer.timer_signature] = t_timer
206: return t_timer
207: end
[ show source ]
# File framework/core.rb, line 209
209: def add_timer(elapsed_time,&block)
210: t_timer = Event.new(elapsed_time,&block)
211: # @timer_hash.store(timer)
212: @timer_hash[t_timer.timer_signature] = t_timer
213: return t_timer
214: end
[ show source ]
# File framework/core.rb, line 216
216: def cancel_timer(t_timer)
217: @timer_hash.delete(t_timer.timer_signature)
218: end
[ show source ]
# File framework/core.rb, line 231
231: def check_for_timer_events
232: @timer_hash.each do |key,timer|
233: @timer_hash.delete(key) if timer.cancel_flag
234: if timer.run_now?
235: timer.run
236: @timer_hash.delete(key) if !timer.respond_to?(:interval)
237: end
238: end
239: end
[ show source ]
# File framework/core.rb, line 78
78: def complete_connection(t_sock,sock_opts)
79: actually_connected = true
80: begin
81: t_sock.connect_nonblock(sock_opts[:sock_addr])
82: rescue Errno::EISCONN
83: puts "Socket already connected"
84: rescue Errno::ECONNREFUSED
85: actually_connected = false
86: end
87:
88: read_ios << t_sock if actually_connected
89: write_ios.delete(t_sock)
90: decorate_handler(t_sock,actually_connected,sock_opts[:sock_addr],\
91: sock_opts[:module],&sock_opts[:block])
92: connection_completion_awaited.delete(t_sock.fileno)
93: end
[ show source ]
# File framework/core.rb, line 112
112: def configure_socket_options
113: case RUBY_PLATFORM
114: when /linux/
115: # 9 is currently TCP_DEFER_ACCEPT
116: @tcp_defer_accept_opts = [Socket::SOL_TCP, 9, 1]
117: @tcp_cork_opts = [Socket::SOL_TCP, 3, 1]
118: when /freebsd(([1-4]\..{1,2})|5\.[0-4])/
119: # Do nothing, just closing a bug when freebsd <= 5.4
120: when /freebsd/
121: # Use the HTTP accept filter if available.
122: # The struct made by pack() is defined in /usr/include/sys/socket.h as accept_filter_arg
123: unless `/sbin/sysctl -nq net.inet.accf.http`.empty?
124: @tcp_defer_accept_opts = [Socket::SOL_SOCKET, Socket::SO_ACCEPTFILTER, ['httpready', nil].pack('a16a240')]
125: end
126: end
127: end
method
[ show source ]
# File framework/core.rb, line 37
37: def connect(ip,port,t_module,&block)
38: t_socket = Socket.new(Socket::AF_INET,Socket::SOCK_STREAM,0)
39: t_sock_addr = Socket.sockaddr_in(port,ip)
40: t_socket.setsockopt(Socket::IPPROTO_TCP,Socket::TCP_NODELAY,1)
41:
42: connection_completion_awaited[t_socket.fileno] =
43: { :sock_addr => t_sock_addr, :module => t_module,:block => block }
44: begin
45: t_socket.connect_nonblock(t_sock_addr)
46: immediate_complete(t_socket,t_sock_addr,t_module,&block)
47: rescue Errno::EINPROGRESS
48: write_ios << t_socket
49: end
50: end
[ show source ]
# File framework/core.rb, line 252
252: def decorate_handler(t_socket,actually_connected,sock_addr,t_module,&block)
253: handler_instance = initialize_handler(t_module)
254: connection_callbacks[:after_connection].each { |t_callback| self.send(t_callback,handler_instance,t_socket)}
255: handler_instance.invoke_init unless handler_instance.initialized
256: unless actually_connected
257: handler_instance.unbind if handler_instance.respond_to?(:unbind)
258: return
259: end
260: t_signature = Guid.hexdigest
261: handler_instance.signature = t_signature
262: connections[t_socket.fileno] =
263: OpenStruct.new(:socket => t_socket, :instance => handler_instance, :signature => t_signature,:sock_addr => sock_addr)
264: block.call(handler_instance) if block
265: handler_instance.connection_completed if handler_instance.respond_to?(:connection_completed)
266: end
[ show source ]
# File framework/core.rb, line 180
180: def handle_external_messages(t_sock)
181: sock_fd = t_sock.fileno
182: if sock_opts = listen_sockets[sock_fd]
183: accept_connection(sock_opts)
184: elsif extern_opts = connection_completion_awaited[sock_fd]
185: complete_connection(t_sock,extern_opts)
186: else
187: read_external_socket(t_sock)
188: end
189: end
[ show source ]
# File framework/core.rb, line 176
176: def handle_internal_messages(t_sock)
177: raise "Method should be implemented by concerned classes"
178: end
[ show source ]
# File framework/core.rb, line 58
58: def immediate_complete(t_socket,sock_addr,t_module,&block)
59: read_ios << t_socket
60: write_ios.delete(t_socket)
61: decorate_handler(t_socket,true,sock_addr,t_module,&block)
62: connection_completion_awaited.delete(t_socket.fileno)
63: end
[ show source ]
# File framework/core.rb, line 241
241: def initialize_handler(p_module)
242: return p_module if(!p_module.is_a?(Class) and !p_module.is_a?(Module))
243: handler =
244: if(p_module and p_module.is_a?(Class))
245: p_module
246: else
247: Class.new(Connection) { p_module and include p_module }
248: end
249: return handler.new
250: end
[ show source ]
# File framework/core.rb, line 191
191: def read_external_socket(t_sock)
192: handler_instance = connections[t_sock.fileno].instance
193: begin
194: t_data = read_data(t_sock)
195: handler_instance.receive_data(t_data) if handler_instance.respond_to?(:receive_data)
196: rescue DisconnectError => sock_error
197: handler_instance.unbind if handler_instance.respond_to?(:unbind)
198: connections.delete(t_sock.fileno)
199: read_ios.delete(t_sock)
200: end
201: end
[ show source ]
# File framework/core.rb, line 52
52: def reconnect(server,port,handler)
53: raise "invalid handler" unless handler.respond_to?(:connection_completed)
54: return handler if connections.keys.include?(handler.connection.fileno)
55: connect(server,port,handler)
56: end
method removes the connection and closes the socket
[ show source ]
# File framework/core.rb, line 96
96: def remove_connection(t_sock)
97: @read_ios.delete(t_sock)
98: @write_ios.delete(t_sock)
99: connections.delete(t_sock.fileno)
100: t_sock.close
101: end
[ show source ]
# File framework/core.rb, line 171
171: def shutdown
172: # FIXME: close the open sockets
173: exit
174: end
[ show source ]
# File framework/core.rb, line 103
103: def socket_really_connected?(t_sock)
104: begin
105: t_data = read_data(t_sock)
106: return true
107: rescue DisconnectError
108: return false
109: end
110: end
method starts event loop in the process
[ show source ]
# File framework/core.rb, line 140
140: def start_reactor
141: Signal.trap("TERM") { terminate_me }
142: Signal.trap("INT") { shutdown }
143: loop do
144: check_for_timer_events
145: user_thread_window #=> let user level threads run for a while
146: ready_fds = select(@read_ios,@write_ios,nil,0.005)
147: #next if ready_fds.blank?
148:
149: next if !ready_fds or ready_fds.empty?
150:
151: ready_fds = ready_fds.flatten.compact
152: ready_fds.each do |t_sock|
153: if t_sock.is_a? UNIXSocket
154: handle_internal_messages(t_sock)
155: else
156: handle_external_messages(t_sock)
157: end
158: end
159: end
160: end
method opens a socket for listening
[ show source ]
# File framework/core.rb, line 130
130: def start_server(ip,port,t_module,&block)
131: BasicSocket.do_not_reverse_lookup = true
132: # configure_socket_options
133: t_socket = TCPServer.new(ip,port.to_i)
134: # t_socket.setsockopt(*@tcp_defer_accept_opts) rescue nil
135: listen_sockets[t_socket.fileno] = { :socket => t_socket,:block => block,:module => t_module }
136: @read_ios << t_socket
137: end
[ show source ]
# File framework/core.rb, line 166
166: def terminate_me
167: # FIXME: close the open sockets
168: exit
169: end
[ show source ]
# File framework/core.rb, line 162
162: def user_thread_window
163: run_user_threads if respond_to?(:run_user_threads)
164: end