eventmachine 0.5.3 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/RELEASE_NOTES +14 -1
- data/TODO +10 -0
- data/ext/cmain.cpp +100 -4
- data/ext/ed.cpp +228 -44
- data/ext/ed.h +25 -2
- data/ext/em.cpp +351 -14
- data/ext/em.h +33 -8
- data/ext/emwin.h +4 -2
- data/ext/eventmachine.h +9 -1
- data/ext/files.cpp +101 -0
- data/ext/files.h +72 -0
- data/ext/project.h +3 -1
- data/ext/rubymain.cpp +113 -5
- data/lib/em/deferrable.rb +89 -0
- data/lib/em/eventable.rb +50 -0
- data/lib/eventmachine.rb +274 -9
- data/lib/eventmachine_version.rb +42 -0
- data/lib/evma/callback.rb +35 -0
- data/lib/evma/container.rb +77 -0
- data/lib/evma/factory.rb +80 -0
- data/lib/evma/protocol.rb +89 -0
- data/lib/evma/reactor.rb +50 -0
- data/lib/evma.rb +35 -0
- data/lib/pr_eventmachine.rb +714 -0
- data/lib/protocols/header_and_content.rb +134 -0
- data/lib/protocols/httpclient.rb +233 -0
- data/lib/protocols/line_and_text.rb +141 -0
- data/lib/protocols/tcptest.rb +67 -0
- data/tests/test_basic.rb +106 -0
- data/tests/test_eventables.rb +85 -0
- data/tests/test_hc.rb +207 -0
- data/tests/test_httpclient.rb +94 -0
- data/tests/test_ltp.rb +192 -0
- data/tests/test_ud.rb +52 -0
- metadata +44 -18
- data/ext/Makefile +0 -139
- data/ext/mkmf.log +0 -59
data/lib/eventmachine.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
# $Id: eventmachine.rb
|
1
|
+
# $Id: eventmachine.rb 283 2006-11-22 14:44:38Z blackhedd $
|
2
2
|
#
|
3
|
-
# Author:: blackhedd (gmail address:
|
3
|
+
# Author:: blackhedd (gmail address: garbagecat10).
|
4
4
|
# Date:: 8 Apr 2006
|
5
5
|
#
|
6
6
|
# Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
|
@@ -34,7 +34,31 @@
|
|
34
34
|
#
|
35
35
|
#
|
36
36
|
|
37
|
-
|
37
|
+
|
38
|
+
#-- Select in a library based on a global variable.
|
39
|
+
case $eventmachine_library
|
40
|
+
when :pure_ruby
|
41
|
+
require 'pr_eventmachine'
|
42
|
+
when :extension
|
43
|
+
require 'rubyeventmachine'
|
44
|
+
else
|
45
|
+
# This is the case that most user code will take.
|
46
|
+
# Prefer the extension if available.
|
47
|
+
begin
|
48
|
+
require 'rubyeventmachine'
|
49
|
+
rescue LoadError
|
50
|
+
require 'pr_eventmachine'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
require "eventmachine_version"
|
56
|
+
require 'em/deferrable'
|
57
|
+
require 'em/eventable'
|
58
|
+
#-- Additional requires are at the BOTTOM of this file, because they
|
59
|
+
#-- depend on stuff defined in here. Refactor that someday.
|
60
|
+
|
61
|
+
|
38
62
|
|
39
63
|
# == Introduction
|
40
64
|
# EventMachine provides a fast, lightweight framework for implementing
|
@@ -132,7 +156,6 @@ require 'rubyeventmachine'
|
|
132
156
|
#
|
133
157
|
module EventMachine
|
134
158
|
|
135
|
-
VERSION = "0.5.3"
|
136
159
|
|
137
160
|
# EventMachine::run initializes and runs an event loop.
|
138
161
|
# This method only returns if user-callback code calls stop_event_loop.
|
@@ -187,7 +210,7 @@ module EventMachine
|
|
187
210
|
# Ruby threads.
|
188
211
|
def EventMachine::run_without_threads &block
|
189
212
|
#EventMachine::run false, &block
|
190
|
-
EventMachine::run
|
213
|
+
EventMachine::run(&block)
|
191
214
|
end
|
192
215
|
|
193
216
|
# EventMachine#add_timer adds a one-shot timer to the event loop.
|
@@ -226,12 +249,15 @@ module EventMachine
|
|
226
249
|
# }
|
227
250
|
#
|
228
251
|
#
|
252
|
+
#--
|
253
|
+
# Changed 04Oct06: We now pass the interval as an integer number of milliseconds.
|
254
|
+
#
|
229
255
|
def EventMachine::add_timer *args, &block
|
230
256
|
interval = args.shift
|
231
257
|
code = args.shift || block
|
232
258
|
if code
|
233
259
|
# check too many timers!
|
234
|
-
s = add_oneshot_timer
|
260
|
+
s = add_oneshot_timer((interval * 1000).to_i)
|
235
261
|
@timers[s] = code
|
236
262
|
end
|
237
263
|
end
|
@@ -409,7 +435,7 @@ module EventMachine
|
|
409
435
|
# }
|
410
436
|
#
|
411
437
|
#
|
412
|
-
def EventMachine::start_server server, port, handler=nil
|
438
|
+
def EventMachine::start_server server, port, handler=nil, &block
|
413
439
|
klass = if (handler and handler.is_a?(Class))
|
414
440
|
handler
|
415
441
|
else
|
@@ -417,7 +443,19 @@ module EventMachine
|
|
417
443
|
end
|
418
444
|
|
419
445
|
s = start_tcp_server server, port
|
420
|
-
@acceptors[s] = klass
|
446
|
+
@acceptors[s] = [klass,block]
|
447
|
+
end
|
448
|
+
|
449
|
+
|
450
|
+
def EventMachine::start_unix_domain_server filename, handler=nil, &block
|
451
|
+
klass = if (handler and handler.is_a?(Class))
|
452
|
+
handler
|
453
|
+
else
|
454
|
+
Class.new( Connection ) {handler and include handler}
|
455
|
+
end
|
456
|
+
|
457
|
+
s = start_unix_server filename
|
458
|
+
@acceptors[s] = [klass,block]
|
421
459
|
end
|
422
460
|
|
423
461
|
# EventMachine#connect initiates a TCP connection to a remote
|
@@ -533,6 +571,29 @@ module EventMachine
|
|
533
571
|
end
|
534
572
|
|
535
573
|
|
574
|
+
#--
|
575
|
+
# EXPERIMENTAL. DO NOT RELY ON THIS METHOD TO BE HERE IN THIS FORM, OR AT ALL.
|
576
|
+
# (03Nov06)
|
577
|
+
# Observe, the test for already-connected FAILS if we call a reconnect inside post_init,
|
578
|
+
# because we haven't set up the connection in @conns by that point.
|
579
|
+
# RESIST THE TEMPTATION to "fix" this problem by redefining the behavior of post_init.
|
580
|
+
#
|
581
|
+
# Changed 22Nov06: if called on an already-connected handler, just return the
|
582
|
+
# handler and do nothing more. Originally this condition raised an exception.
|
583
|
+
# We may want to change it yet again and call the block, if any.
|
584
|
+
#
|
585
|
+
def EventMachine::reconnect server, port, handler
|
586
|
+
raise "invalid handler" unless handler.respond_to?(:connection_completed)
|
587
|
+
#raise "still connected" if @conns.has_key?(handler.signature)
|
588
|
+
return handler if @conns.has_key?(handler.signature)
|
589
|
+
s = connect_server server, port
|
590
|
+
handler.signature = s
|
591
|
+
@conns[s] = handler
|
592
|
+
block_given? and yield handler
|
593
|
+
handler
|
594
|
+
end
|
595
|
+
|
596
|
+
|
536
597
|
# EventMachine#open_datagram_socket is for support of UDP-based
|
537
598
|
# protocols. Its usage is similar to that of EventMachine#start_server.
|
538
599
|
# It takes three parameters: an IP address (which must be valid
|
@@ -586,6 +647,25 @@ module EventMachine
|
|
586
647
|
# necessarily ones that have sent data to which you are responding),
|
587
648
|
# then see Connection#send_datagram.
|
588
649
|
#
|
650
|
+
#--
|
651
|
+
# Replaced the implementation on 01Oct06. Thanks to Tobias Gustafsson for pointing
|
652
|
+
# out that this originally did not take a class but only a module.
|
653
|
+
#
|
654
|
+
def self::open_datagram_socket address, port, handler=nil
|
655
|
+
klass = if (handler and handler.is_a?(Class))
|
656
|
+
handler
|
657
|
+
else
|
658
|
+
Class.new( Connection ) {handler and include handler}
|
659
|
+
end
|
660
|
+
|
661
|
+
s = open_udp_socket address, port
|
662
|
+
c = klass.new s
|
663
|
+
@conns[s] = c
|
664
|
+
block_given? and yield c
|
665
|
+
c
|
666
|
+
end
|
667
|
+
=begin
|
668
|
+
(Original, replaced 01Oct06)
|
589
669
|
def self::open_datagram_socket address, port, handler=nil
|
590
670
|
s = open_udp_socket address, port
|
591
671
|
klass = Class.new( Connection ) {
|
@@ -596,6 +676,93 @@ module EventMachine
|
|
596
676
|
block_given? and yield c
|
597
677
|
c
|
598
678
|
end
|
679
|
+
=end
|
680
|
+
|
681
|
+
|
682
|
+
# For advanced users. This function sets the default timer granularity, which by default is
|
683
|
+
# slightly smaller than 100 milliseconds. Call this function to set a higher or lower granularity.
|
684
|
+
# The function affects the behavior of #add_timer and #add_periodic_timer. Most applications
|
685
|
+
# will not need to call this function.
|
686
|
+
#
|
687
|
+
# The argument is a number of milliseconds. Avoid setting the quantum to very low values because
|
688
|
+
# that may reduce performance under some extreme conditions. We recommend that you not set a quantum
|
689
|
+
# lower than 10.
|
690
|
+
#
|
691
|
+
# You MUST call this function while an EventMachine loop is running (that is, after a call to
|
692
|
+
# EventMachine#run and before a subsequent call to EventMachine#stop).
|
693
|
+
#
|
694
|
+
def self::set_quantum mills
|
695
|
+
set_timer_quantum mills.to_i
|
696
|
+
end
|
697
|
+
|
698
|
+
|
699
|
+
def self::run_deferred_callbacks # :nodoc:
|
700
|
+
until @resultqueue.empty?
|
701
|
+
result,cback = @resultqueue.pop
|
702
|
+
cback.call result if cback
|
703
|
+
end
|
704
|
+
end
|
705
|
+
|
706
|
+
# #defer is for integrating blocking operations into EventMachine's control flow.
|
707
|
+
# Call #defer with one or two blocks, as shown below (the second block is <i>optional</i>):
|
708
|
+
#
|
709
|
+
# operation = proc {
|
710
|
+
# # perform a long-running operation here, such as a database query.
|
711
|
+
# "result" # as usual, the last expression evaluated in the block will be the return value.
|
712
|
+
# }
|
713
|
+
# callback = proc {|result|
|
714
|
+
# # do something with result here, such as send it back to a network client.
|
715
|
+
# }
|
716
|
+
#
|
717
|
+
# EventMachine.defer( operation, callback )
|
718
|
+
#
|
719
|
+
# The action of #defer is to take the block specified in the first parameter (the "operation")
|
720
|
+
# and schedule it for asynchronous execution on an internal thread pool maintained by EventMachine.
|
721
|
+
# When the operation completes, it will pass the result computed by the block (if any)
|
722
|
+
# back to the EventMachine reactor. Then, EventMachine calls the block specified in the
|
723
|
+
# second parameter to #defer (the "callback"), as part of its normal, synchronous
|
724
|
+
# event handling loop. The result computed by the operation block is passed as a parameter
|
725
|
+
# to the callback. You may omit the callback parameter if you don't need to execute any code
|
726
|
+
# after the operation completes.
|
727
|
+
#
|
728
|
+
# <i>Caveats:</i>
|
729
|
+
# This is a <b>provisional</b> implementation and is subject to change.
|
730
|
+
# Note carefully that the code in your deferred operation will be executed on a separate
|
731
|
+
# thread from the main EventMachine processing and all other Ruby threads that may exist in
|
732
|
+
# your program. Also, multiple deferred operations may be running at once! Therefore, you
|
733
|
+
# are responsible for ensuring that your operation code is threadsafe. [Need more explanation
|
734
|
+
# and examples.]
|
735
|
+
# Don't write a deferred operation that will block forever. If so, the current implementation will
|
736
|
+
# not detect the problem, and the thread will never be returned to the pool. EventMachine limits
|
737
|
+
# the number of threads in its pool, so if you do this enough times, your subsequent deferred
|
738
|
+
# operations won't get a chance to run. [We might put in a timer to detect this problem.]
|
739
|
+
#
|
740
|
+
def self::defer op, callback = nil
|
741
|
+
unless @threadqueue
|
742
|
+
|
743
|
+
#start_server "127.0.0.1", 29999, DeferredTrigger
|
744
|
+
#@deferred_trigger = connect "127.0.0.1", 29999
|
745
|
+
|
746
|
+
require 'thread'
|
747
|
+
@threadqueue = Queue.new
|
748
|
+
@resultqueue = Queue.new
|
749
|
+
20.times {|ix|
|
750
|
+
Thread.new {
|
751
|
+
my_ix = ix
|
752
|
+
loop {
|
753
|
+
op,cback = @threadqueue.pop
|
754
|
+
result = op.call
|
755
|
+
@resultqueue << [result, cback]
|
756
|
+
EventMachine.signal_loopbreak
|
757
|
+
#@deferred_trigger.send_data "."
|
758
|
+
}
|
759
|
+
}
|
760
|
+
}
|
761
|
+
end
|
762
|
+
|
763
|
+
@threadqueue << [op,callback]
|
764
|
+
end
|
765
|
+
|
599
766
|
|
600
767
|
|
601
768
|
private
|
@@ -613,16 +780,44 @@ module EventMachine
|
|
613
780
|
raise ConnectionNotBound
|
614
781
|
end
|
615
782
|
when ConnectionAccepted
|
616
|
-
accep = @acceptors[conn_binding]
|
783
|
+
accep,blk = @acceptors[conn_binding]
|
784
|
+
raise NoHandlerForAcceptedConnection unless accep
|
617
785
|
c = accep.new data
|
618
786
|
@conns[data] = c
|
787
|
+
blk and blk.call(c)
|
788
|
+
c # (needed?)
|
619
789
|
when TimerFired
|
620
790
|
t = @timers.delete( data ) or raise UnknownTimerFired
|
621
791
|
t.call
|
792
|
+
when ConnectionCompleted
|
793
|
+
c = @conns[conn_binding] or raise ConnectionNotBound
|
794
|
+
c.connection_completed
|
795
|
+
when LoopbreakSignalled
|
796
|
+
run_deferred_callbacks
|
622
797
|
end
|
623
798
|
end
|
624
799
|
|
625
800
|
|
801
|
+
# Documentation stub
|
802
|
+
#--
|
803
|
+
# This is a provisional implementation of a stream-oriented file access object.
|
804
|
+
# We also experiment with wrapping up some better exception reporting.
|
805
|
+
class << self
|
806
|
+
def _open_file_for_writing filename, handler=nil
|
807
|
+
klass = if (handler and handler.is_a?(Class))
|
808
|
+
handler
|
809
|
+
else
|
810
|
+
Class.new( Connection ) {handler and include handler}
|
811
|
+
end
|
812
|
+
|
813
|
+
s = _write_file filename
|
814
|
+
c = klass.new s
|
815
|
+
@conns[s] = c
|
816
|
+
block_given? and yield c
|
817
|
+
c
|
818
|
+
end
|
819
|
+
end
|
820
|
+
|
626
821
|
|
627
822
|
# EventMachine::Connection is a class that is instantiated
|
628
823
|
# by EventMachine's processing loop whenever a new connection
|
@@ -650,6 +845,9 @@ module EventMachine
|
|
650
845
|
#
|
651
846
|
class Connection
|
652
847
|
|
848
|
+
# EXPERIMENTAL. Added the reconnect methods, which may go away.
|
849
|
+
attr_accessor :signature
|
850
|
+
|
653
851
|
def initialize sig #:nodoc:
|
654
852
|
@signature = sig
|
655
853
|
post_init
|
@@ -770,7 +968,24 @@ class Connection
|
|
770
968
|
EventMachine::send_data @signature, data, data.length
|
771
969
|
end
|
772
970
|
|
971
|
+
# #connection_completed is called by the event loop when a remote TCP connection
|
972
|
+
# attempt completes successfully. You can expect to get this notification after calls
|
973
|
+
# to EventMachine#connect. Remember that EventMachine makes remote connections
|
974
|
+
# asynchronously, just as with any other kind of network event. #connection_completed
|
975
|
+
# is intended primarily to assist with network diagnostics. For normal protocol
|
976
|
+
# handling, use #post_init to perform initial work on a new connection (such as
|
977
|
+
# send an initial set of data).
|
978
|
+
# #post_init will always be called. #connection_completed will only be called in case
|
979
|
+
# of a successful completion. A connection-attempt which fails will receive a call
|
980
|
+
# to #unbind after the failure.
|
981
|
+
def connection_completed
|
982
|
+
end
|
773
983
|
|
984
|
+
# Call #start_tls at any point to initiate TLS encryption on connected streams.
|
985
|
+
# The method is smart enough to know whether it should perform a server-side
|
986
|
+
# or a client-side handshake. An appropriate place to call #start_tls is in
|
987
|
+
# your redefined #post_init method.
|
988
|
+
#
|
774
989
|
def start_tls
|
775
990
|
EventMachine::start_tls @signature
|
776
991
|
end
|
@@ -800,8 +1015,58 @@ class Connection
|
|
800
1015
|
end
|
801
1016
|
|
802
1017
|
|
1018
|
+
# #get_peername is used with stream-connections to obtain the identity
|
1019
|
+
# of the remotely-connected peer. If a peername is available, this method
|
1020
|
+
# returns a sockaddr structure. The method returns nil if no peername is available.
|
1021
|
+
# You can use Socket#unpack_sockaddr_in and its variants to obtain the
|
1022
|
+
# values contained in the peername structure returned from #get_peername.
|
1023
|
+
def get_peername
|
1024
|
+
EventMachine::get_peername @signature
|
1025
|
+
end
|
1026
|
+
|
1027
|
+
# comm_inactivity_timeout returns the current value (in seconds) of the inactivity-timeout
|
1028
|
+
# property of network-connection and datagram-socket objects. A nonzero value
|
1029
|
+
# indicates that the connection or socket will automatically be closed if no read or write
|
1030
|
+
# activity takes place for at least that number of seconds.
|
1031
|
+
# A zero value (the default) specifies that no automatic timeout will take place.
|
1032
|
+
def comm_inactivity_timeout
|
1033
|
+
EventMachine::get_comm_inactivity_timeout @signature
|
1034
|
+
end
|
1035
|
+
|
1036
|
+
# Alias for #set_comm_inactivity_timeout.
|
1037
|
+
def comm_inactivity_timeout= value
|
1038
|
+
self.send :set_comm_inactivity_timeout, value
|
1039
|
+
end
|
1040
|
+
|
1041
|
+
# comm_inactivity_timeout= allows you to set the inactivity-timeout property for
|
1042
|
+
# a network connection or datagram socket. Specify a non-negative numeric value in seconds.
|
1043
|
+
# If the value is greater than zero, the connection or socket will automatically be closed
|
1044
|
+
# if no read or write activity takes place for at least that number of seconds.
|
1045
|
+
# Specify a value of zero to indicate that no automatic timeout should take place.
|
1046
|
+
# Zero is the default value.
|
1047
|
+
def set_comm_inactivity_timeout value
|
1048
|
+
EventMachine::set_comm_inactivity_timeout @signature, value
|
1049
|
+
end
|
1050
|
+
|
1051
|
+
#--
|
1052
|
+
# EXPERIMENTAL. DO NOT RELY ON THIS METHOD TO REMAIN SUPPORTED.
|
1053
|
+
# (03Nov06)
|
1054
|
+
def reconnect server, port
|
1055
|
+
EventMachine::reconnect server, port, self
|
1056
|
+
end
|
1057
|
+
|
803
1058
|
end
|
804
1059
|
|
805
1060
|
|
806
1061
|
end # module EventMachine
|
807
1062
|
|
1063
|
+
# At the bottom of this module, we load up protocol handlers that depend on some
|
1064
|
+
# of the classes defined here. Eventually we should refactor this out so it's
|
1065
|
+
# laid out in a more logical way.
|
1066
|
+
#
|
1067
|
+
|
1068
|
+
require 'protocols/tcptest'
|
1069
|
+
require 'protocols/httpclient'
|
1070
|
+
require 'protocols/line_and_text'
|
1071
|
+
require 'protocols/header_and_content'
|
1072
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# $Id: eventmachine_version.rb 221 2006-08-07 13:17:51Z blackhedd $
|
2
|
+
#
|
3
|
+
# Author:: blackhedd (gmail address: garbagecat10).
|
4
|
+
# Date:: 8 Apr 2006
|
5
|
+
#
|
6
|
+
# Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
|
7
|
+
#
|
8
|
+
# This program is made available under the terms of the GPL version 2.
|
9
|
+
#
|
10
|
+
# See EventMachine and EventMachine::Connection for documentation and
|
11
|
+
# usage examples.
|
12
|
+
#
|
13
|
+
#----------------------------------------------------------------------------
|
14
|
+
#
|
15
|
+
# Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
|
16
|
+
#
|
17
|
+
# Gmail: garbagecat10
|
18
|
+
#
|
19
|
+
# This program is free software; you can redistribute it and/or modify
|
20
|
+
# it under the terms of the GNU General Public License as published by
|
21
|
+
# the Free Software Foundation; either version 2 of the License, or
|
22
|
+
# (at your option) any later version.
|
23
|
+
#
|
24
|
+
# This program is distributed in the hope that it will be useful,
|
25
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
26
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
27
|
+
# GNU General Public License for more details.
|
28
|
+
#
|
29
|
+
# You should have received a copy of the GNU General Public License
|
30
|
+
# along with this program; if not, write to the Free Software
|
31
|
+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
32
|
+
#
|
33
|
+
#---------------------------------------------------------------------------
|
34
|
+
#
|
35
|
+
#
|
36
|
+
|
37
|
+
module EventMachine
|
38
|
+
|
39
|
+
VERSION = "0.7.0"
|
40
|
+
|
41
|
+
end
|
42
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# $Id: callback.rb 88 2006-05-19 03:42:54Z blackhedd $
|
2
|
+
#
|
3
|
+
# Homepage:: http://rubyeventmachine.com
|
4
|
+
# Copyright:: (C) 2006 by Francis Cianfrocca. All Rights Reserved.
|
5
|
+
# Email:: gmail address: garbagecat10
|
6
|
+
#
|
7
|
+
# Available under the GNU Lesser General Public License.
|
8
|
+
# See the file COPYING in the distribution for full licensing information.
|
9
|
+
#-------------------------------------------------------------------
|
10
|
+
# This file is part of Ruby/EventMachine.
|
11
|
+
#
|
12
|
+
# Ruby/EventMachine is free software; you can redistribute it and/or modify
|
13
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
14
|
+
# the Free Software Foundation; either version 2.1 of the License, or
|
15
|
+
# (at your option) any later version.
|
16
|
+
#
|
17
|
+
# Ruby/EventMachine is distributed in the hope that it will be useful,
|
18
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
19
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
20
|
+
# GNU Lesser General Public License for more details.
|
21
|
+
#
|
22
|
+
# You should have received a copy of the GNU Lesser General Public License
|
23
|
+
# along with Ruby/EventMachine; if not, write to the Free Software
|
24
|
+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
25
|
+
#-------------------------------------------------------------------
|
26
|
+
#
|
27
|
+
|
28
|
+
|
29
|
+
module EventMachine
|
30
|
+
|
31
|
+
def self.event_callback target, opcode, data
|
32
|
+
Evma::Container.callback target, opcode, data
|
33
|
+
end
|
34
|
+
|
35
|
+
end # module EventMachine
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# $Id: container.rb 90 2006-05-19 04:58:15Z blackhedd $
|
2
|
+
#
|
3
|
+
# Homepage:: http://rubyeventmachine.com
|
4
|
+
# Copyright:: (C) 2006 by Francis Cianfrocca. All Rights Reserved.
|
5
|
+
# Email:: gmail address: garbagecat10
|
6
|
+
#
|
7
|
+
# Available under the GNU Lesser General Public License.
|
8
|
+
# See the file COPYING in the distribution for full licensing information.
|
9
|
+
#-------------------------------------------------------------------
|
10
|
+
# This file is part of Ruby/EventMachine.
|
11
|
+
#
|
12
|
+
# Ruby/EventMachine is free software; you can redistribute it and/or modify
|
13
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
14
|
+
# the Free Software Foundation; either version 2.1 of the License, or
|
15
|
+
# (at your option) any later version.
|
16
|
+
#
|
17
|
+
# Ruby/EventMachine is distributed in the hope that it will be useful,
|
18
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
19
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
20
|
+
# GNU Lesser General Public License for more details.
|
21
|
+
#
|
22
|
+
# You should have received a copy of the GNU Lesser General Public License
|
23
|
+
# along with Ruby/EventMachine; if not, write to the Free Software
|
24
|
+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
25
|
+
#-------------------------------------------------------------------
|
26
|
+
#
|
27
|
+
|
28
|
+
|
29
|
+
require 'singleton'
|
30
|
+
|
31
|
+
module Evma
|
32
|
+
|
33
|
+
class ContainerHasObject < Exception; end
|
34
|
+
class UnsupportedCallback < Exception; end
|
35
|
+
class UnknownTarget < Exception; end
|
36
|
+
|
37
|
+
class Container
|
38
|
+
include Singleton
|
39
|
+
|
40
|
+
def initialize
|
41
|
+
@objects = {}
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.store obj
|
45
|
+
instance.store obj
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.callback target, opcode, data
|
49
|
+
instance.callback target, opcode, data
|
50
|
+
end
|
51
|
+
|
52
|
+
def store obj
|
53
|
+
sig = obj.signature
|
54
|
+
raise ContainerHasObject.new(sig) if @objects.has_key?(sig)
|
55
|
+
@objects[sig] = obj
|
56
|
+
end
|
57
|
+
|
58
|
+
def callback target, opcode, data
|
59
|
+
case opcode
|
60
|
+
when 101 # received data
|
61
|
+
obj = @objects[target] or raise UnknownTarget.new( target )
|
62
|
+
obj.receive_data data
|
63
|
+
when 102 # unbind
|
64
|
+
obj = @objects[target] or raise UnknownTarget.new( target )
|
65
|
+
obj.unbind
|
66
|
+
@objects.delete obj.signature
|
67
|
+
when 103 # accept
|
68
|
+
obj = @objects[target] or raise UnknownTarget.new( target )
|
69
|
+
obj.accept data
|
70
|
+
else
|
71
|
+
raise UnsupportedCallback.new( opcode.to_s )
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end # class Container
|
76
|
+
end # module Evma
|
77
|
+
|
data/lib/evma/factory.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
# $Id: factory.rb 90 2006-05-19 04:58:15Z blackhedd $
|
2
|
+
#
|
3
|
+
# Homepage:: http://rubyeventmachine.com
|
4
|
+
# Copyright:: (C) 2006 by Francis Cianfrocca. All Rights Reserved.
|
5
|
+
# Email:: gmail address: garbagecat10
|
6
|
+
#
|
7
|
+
# Available under the GNU Lesser General Public License.
|
8
|
+
# See the file COPYING in the distribution for full licensing information.
|
9
|
+
#-------------------------------------------------------------------
|
10
|
+
# This file is part of Ruby/EventMachine.
|
11
|
+
#
|
12
|
+
# Ruby/EventMachine is free software; you can redistribute it and/or modify
|
13
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
14
|
+
# the Free Software Foundation; either version 2.1 of the License, or
|
15
|
+
# (at your option) any later version.
|
16
|
+
#
|
17
|
+
# Ruby/EventMachine is distributed in the hope that it will be useful,
|
18
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
19
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
20
|
+
# GNU Lesser General Public License for more details.
|
21
|
+
#
|
22
|
+
# You should have received a copy of the GNU Lesser General Public License
|
23
|
+
# along with Ruby/EventMachine; if not, write to the Free Software
|
24
|
+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
25
|
+
#-------------------------------------------------------------------
|
26
|
+
#
|
27
|
+
|
28
|
+
|
29
|
+
module Evma
|
30
|
+
class ProtocolFactory < Protocol
|
31
|
+
|
32
|
+
#--
|
33
|
+
# default implementation raises an exception.
|
34
|
+
# we expect subclasses to override this.
|
35
|
+
# we can't do anything reasonable here because
|
36
|
+
def accept new_object
|
37
|
+
# don't bother calling Evma::Reactor.instance, since only Reactor can call accept
|
38
|
+
Evma::Container.store Evma::Protocol.new( new_object )
|
39
|
+
EventMachine.close_connection new_object, false
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
end # class ProtocolFactory
|
44
|
+
end # module Evma
|
45
|
+
|
46
|
+
######################################
|
47
|
+
|
48
|
+
module Evma
|
49
|
+
class TcpSocket
|
50
|
+
|
51
|
+
def self.connect server, port, protocol_handler = Evma::Protocol
|
52
|
+
Evma::Reactor.instance # ensure initialization
|
53
|
+
sig = EventMachine.connect_server server, port
|
54
|
+
Evma::Container.store protocol_handler.new( sig )
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end # module Evma
|
59
|
+
|
60
|
+
######################################
|
61
|
+
|
62
|
+
module Evma
|
63
|
+
class TcpServerFactory < Evma::ProtocolFactory
|
64
|
+
|
65
|
+
def initialize server, port, protocol_handler = Evma::Protocol
|
66
|
+
Evma::Reactor.instance # ensure initialization
|
67
|
+
sig = EventMachine.start_tcp_server server, port
|
68
|
+
super sig
|
69
|
+
@protocol_handler = protocol_handler
|
70
|
+
Evma::Container.store self
|
71
|
+
end
|
72
|
+
|
73
|
+
def accept new_obj
|
74
|
+
# don't bother calling Evma::Reactor.instance, since only Reactor can call accept
|
75
|
+
Evma::Container.store @protocol_handler.new( new_obj )
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end # module Evma
|
80
|
+
|