datawire_mdk 2.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b898e0f72fd506802a43a6ad9972043b933c2092
4
+ data.tar.gz: 126e7d6be42af520468d4477cca660a0a11d4160
5
+ SHA512:
6
+ metadata.gz: 8f29db7b0ab84f7c5b02d3e827b9c1a752a9870d082d1fe93360d9205e43fa82152a5e8d0641e8eabf44999c935c9d661dbd74b2807a8feafb11d775c07ab3fb
7
+ data.tar.gz: cba352b068fdb7558d57ef6f40b43c49abf443e305dc40dae8a10b9fdbb3216e614bb252ee4ba558f81c0ba67106643920e74e4c3578fe1dc8c30ceb4e4e9901
@@ -0,0 +1,1213 @@
1
+ module DatawireQuarkCore
2
+ require 'net/http'
3
+ require 'uri'
4
+ require 'json'
5
+ require 'thread'
6
+
7
+ require 'concurrent'
8
+ require 'celluloid/current'
9
+ require 'reel'
10
+ require 'logging'
11
+ require 'event_emitter'
12
+ require 'securerandom'
13
+
14
+ module GettersSetters
15
+ # Generate Java/Quark-style getters and setters for
16
+ # instance variables.
17
+ #
18
+ # Example:
19
+ #
20
+ # class Foo
21
+ # extend GettersSetters
22
+ #
23
+ # getters :fooBar, :bazQux
24
+ # setters :fooBar
25
+ # end
26
+ #
27
+ # The above equivalent to:
28
+ #
29
+ # class Foo
30
+ # extend GettersAndSetters
31
+ #
32
+ # def getFooBar
33
+ # @fooBar
34
+ # end
35
+ #
36
+ # def getBazQux
37
+ # @bazQux
38
+ # end
39
+ #
40
+ # def setFooBar(value)
41
+ # @fooBar = value
42
+ #
43
+ # nil
44
+ # end
45
+ # end
46
+
47
+ def getters(*names)
48
+ names.each do |name|
49
+ define_method('get' + capitalize(name)) do
50
+ instance_variable_get("@#{name}")
51
+ end
52
+ end
53
+ end
54
+
55
+ def setters(*names)
56
+ names.each do |name|
57
+ define_method('set' + capitalize(name)) do |value|
58
+ instance_variable_set("@#{name}", value)
59
+
60
+ nil
61
+ end
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ def capitalize(string)
68
+ string[0].upcase + string[1..-1]
69
+ end
70
+ end
71
+
72
+ module Static
73
+ Unassigned = Class.new
74
+
75
+ def unlazy_statics
76
+ names = _lazy_statics
77
+ # puts "unlazying #{self.name} fields #{names}"
78
+ names.each do |name|
79
+ self.send(name)
80
+ end
81
+ end
82
+ def _lazy_statics
83
+ lazy = :@_lazy_statics
84
+ if not self.instance_variable_defined? lazy
85
+ # puts "Bootstrap #{self.name}"
86
+ l = self.instance_variable_set(lazy, {:__owner__ => self.name})
87
+ else
88
+ l = self.instance_variable_get(lazy)
89
+ end
90
+ if not l.has_key? self.name
91
+ o = l[:__owner__]
92
+ # puts "Adding slot for #{self.name} to lazy of #{o}"
93
+ l[self.name] = []
94
+ end
95
+ l[self.name]
96
+ end
97
+ def static(pairs)
98
+ pairs.each do |name, default|
99
+ _lazy_statics << name
100
+ self.instance_variable_set("@#{name}", Unassigned)
101
+
102
+ define_singleton_method(name) do
103
+ value = self.instance_variable_get("@#{name}")
104
+
105
+ if value == Unassigned
106
+ value = default.call
107
+ self.instance_variable_set("@#{name}", value)
108
+ end
109
+
110
+ value
111
+ end
112
+
113
+ define_singleton_method("#{name}=") do |value|
114
+ self.instance_variable_set("@#{name}", value)
115
+ end
116
+
117
+ define_method(name) do
118
+ self.class.send(name)
119
+ end
120
+
121
+ define_method("#{name}=") do |value|
122
+ self.class.send("#{name}=", value)
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ def self.print(message)
129
+ Kernel.print message == nil ? 'null' : message, "\n"
130
+ end
131
+
132
+ def self.urlencode(hash)
133
+ URI.encode_www_form hash
134
+ end
135
+
136
+ def self.split(string, separator)
137
+ return ['', ''] if string == separator
138
+ result = string.split(separator)
139
+ result = result + [''] if string.end_with? separator
140
+
141
+ result
142
+ end
143
+
144
+ def self.getFileContents(path, result)
145
+ begin
146
+ result.value = File.read(path, {"encoding": "UTF-8"})
147
+ result.finish(nil)
148
+ rescue => ex
149
+ result.finish(::Quark.quark.os.OSError.new(ex.message))
150
+ end
151
+ end
152
+
153
+ def self._getClass obj
154
+ clz = __getClass obj
155
+ # puts "runtime _getClass for #{obj} is #{clz}"
156
+ clz
157
+ end
158
+ def self.__getClass obj
159
+ return nil if obj.nil?
160
+ return "quark.bool" if (obj == true) or (obj == false)
161
+ return "quark.String" if obj.is_a? String
162
+ return "quark.int" if obj.is_a? Fixnum
163
+ return "quark.float" if obj.is_a? Float
164
+ return "quark.List<quark.Object>" if obj.is_a? Array
165
+ return "quark.Map<quark.Object,quark.Object>" if obj.is_a? Hash
166
+ if obj.respond_to? "_getClass" then
167
+ return obj._getClass
168
+ else
169
+ return "quark.Object"
170
+ end
171
+ end
172
+
173
+ class QuarkObject
174
+
175
+ def to_s
176
+ return self.toString() if self.respond_to? :toString
177
+ return super()
178
+ end
179
+
180
+ end
181
+
182
+ class List < Array
183
+ def to_s
184
+ '[' + map(&:to_s).join(', ') + ']'
185
+ end
186
+ end
187
+
188
+ class JSONObject
189
+ attr_accessor :value
190
+
191
+ def initialize(value=nil)
192
+ @value = value
193
+ end
194
+
195
+ def self.parse(json)
196
+ new JSON.parse("[#{json}]")[0]
197
+ end
198
+
199
+ def ==(other)
200
+ not other.nil? and value == other.value
201
+ end
202
+
203
+ def toString
204
+ value.to_json
205
+ end
206
+
207
+ def size
208
+ isList || isObject ? value.size : 1
209
+ end
210
+
211
+ def getType
212
+ case @value
213
+ when Hash
214
+ 'object'
215
+ when Array
216
+ 'list'
217
+ when String
218
+ 'string'
219
+ when Numeric
220
+ 'number'
221
+ when true, false
222
+ 'bool'
223
+ when nil
224
+ 'null'
225
+ else
226
+ raise RuntimeError, "Unknown JSONObject type #{@value.inspect}"
227
+ end
228
+ end
229
+
230
+ def set(value)
231
+ @value = value
232
+
233
+ self
234
+ end
235
+
236
+ # Object
237
+
238
+ def isObject
239
+ value.is_a? Hash
240
+ end
241
+
242
+ def setObject
243
+ @value = {}
244
+
245
+ self
246
+ end
247
+
248
+ def getObjectItem(key)
249
+ return undefined unless isObject and value.key? key
250
+
251
+ self.class.new value[key]
252
+ end
253
+
254
+ def setObjectItem(key, item)
255
+ setObject unless isObject
256
+ value[key] = item.value
257
+
258
+ self
259
+ end
260
+
261
+ def keys
262
+ return undefined unless isObject
263
+
264
+ List.new value.keys
265
+ end
266
+
267
+ # List
268
+
269
+ def isList
270
+ value.is_a? Array
271
+ end
272
+
273
+ def setList
274
+ @value = List.new
275
+
276
+ self
277
+ end
278
+
279
+ def getListItem(index)
280
+ return undefined unless isList and (0...size).include? index
281
+
282
+ self.class.new value[index]
283
+ end
284
+
285
+ def setListItem(index, item)
286
+ setList unless isList
287
+ value[index] = item.value
288
+
289
+ self
290
+ end
291
+
292
+ # String
293
+
294
+ def isString
295
+ value.is_a? String
296
+ end
297
+
298
+ def getString
299
+ return nil unless isString
300
+
301
+ value
302
+ end
303
+
304
+ alias_method :setString, :set
305
+
306
+ # Number
307
+
308
+ def isNumber
309
+ value.is_a? Numeric
310
+ end
311
+
312
+ def getNumber
313
+ return nil unless isNumber
314
+
315
+ value
316
+ end
317
+
318
+ alias_method :setNumber, :set
319
+
320
+ # Bool
321
+
322
+ def getBool
323
+ return nil unless isBool
324
+
325
+ value
326
+ end
327
+
328
+ def isBool
329
+ [true, false].include? value
330
+ end
331
+
332
+ alias_method :setBool, :set
333
+
334
+ # Null
335
+
336
+ def isNull
337
+ value == nil
338
+ end
339
+
340
+ def setNull
341
+ @value = nil
342
+
343
+ self
344
+ end
345
+
346
+ # Undefined
347
+
348
+ UNDEFINED = Class.new
349
+
350
+ def isUndefined
351
+ UNDEFINED.equal? value
352
+ end
353
+
354
+ def isDefined
355
+ not isUndefined
356
+ end
357
+
358
+ def undefined
359
+ self.class.new UNDEFINED
360
+ end
361
+ end
362
+
363
+ module HTTP
364
+ class Base
365
+ def setHeader(key, value)
366
+ @headers[key.downcase] = value
367
+
368
+ nil
369
+ end
370
+
371
+ def getHeader(key)
372
+ @headers[key.downcase]
373
+ end
374
+
375
+ def getHeaders
376
+ @headers.keys
377
+ end
378
+ end
379
+
380
+ class Request < Base
381
+ extend GettersSetters
382
+
383
+ getters :body, :method, :url
384
+ setters :body, :method
385
+
386
+ def initialize(url)
387
+ @url = url
388
+ @method = 'GET'
389
+ @body = nil
390
+ @headers = {}
391
+ end
392
+ end
393
+
394
+ class Response < Base
395
+ extend GettersSetters
396
+
397
+ getters :code, :body
398
+ setters :code, :body
399
+
400
+ def initialize
401
+ @code = 500
402
+ @body = ''
403
+ @headers = {}
404
+ @responded = false
405
+ end
406
+ end
407
+ end
408
+
409
+ class Sources
410
+ def initialize()
411
+ @sources = Concurrent::Map.new
412
+ @seq = Concurrent::AtomicFixnum.new
413
+ @log = Logger.new "quark.runtime.sources"
414
+ end
415
+
416
+ def add (topic)
417
+ key = "%s-%s" % [ @seq.increment, topic ]
418
+ @sources.put_if_absent(key, Time.new)
419
+ key
420
+ end
421
+
422
+ def remove (key)
423
+ @sources.delete(key)
424
+ end
425
+
426
+ def empty?
427
+ @sources.empty?
428
+ end
429
+
430
+ def explain
431
+ @sources.each_key { |k|
432
+ @log.trace "Waiting for %s from %s" % [k, @sources[k]]
433
+ }
434
+ end
435
+ end
436
+
437
+
438
+ if not Logging.initialized?
439
+ Logging.init %w(trace debug info warn error fatal)
440
+ end
441
+ class QuarkLayout < ::Logging::Layout
442
+ def initialize
443
+ @namecache = {}
444
+ end
445
+ def format( event )
446
+ level = ::Logging::LNAMES[event.level].upcase
447
+ topic = topic_of(event)
448
+ obj = format_obj(event.data)
449
+ sprintf("%s %s %s\n", level, topic, obj)
450
+ end
451
+ def topic_of(event)
452
+ name = event.logger
453
+ topic = @namecache[name]
454
+ if topic.nil?
455
+ @namecache[name] = topic = name.gsub("::",".")
456
+ end
457
+ topic
458
+ end
459
+ end
460
+
461
+ def self.configureLogging(appender, level)
462
+ root = Logging.logger["quark"]
463
+ if appender.name == ":STDOUT"
464
+ app = Logging.appenders.stdout
465
+ elsif appender.name == ":STDERR"
466
+ app = Logging.appenders.stderr
467
+ else
468
+ app = Logging.appenders.file(appender.name)
469
+ end
470
+ app.layout = QuarkLayout.new
471
+ root.appenders = app
472
+ root.level = level
473
+ end
474
+
475
+ class Logger
476
+ extend Forwardable
477
+ @@init = false
478
+ def initialize(topic)
479
+ @log = Logging.logger["quark::" + topic.gsub(".","::")]
480
+ end
481
+ if Logging.level_num(:trace).nil?
482
+ def_delegator :@log, :debug, :trace
483
+ else
484
+ def_delegator :@log, :trace, :trace
485
+ end
486
+ def_delegators :@log, :debug, :info, :warn, :error
487
+ end
488
+
489
+ class Eventor
490
+ def initialize(runtime)
491
+ @executor = Concurrent::SingleThreadExecutor.new
492
+ @timers = Concurrent::TimerSet.new(:executor => @executor)
493
+ @sources = Sources.new
494
+ @runtime = runtime
495
+ at_exit { wait_for_sources }
496
+ @log = Logger.new "quark.runtime"
497
+ end
498
+
499
+ attr_reader :runtime
500
+
501
+ def add(source)
502
+ @sources.add source
503
+ end
504
+
505
+ def event(final:nil, &block)
506
+ @executor.post { execute(final, block) }
507
+ end
508
+
509
+ def execute(final, block)
510
+ begin
511
+ block.call()
512
+ rescue => ex
513
+ puts "aieee", ex, ex.backtrace
514
+ @log.error ex
515
+ ensure
516
+ @sources.remove final if final
517
+ end
518
+ end
519
+
520
+ def schedule(delay, &block)
521
+ @timers.post(delay, &block)
522
+ end
523
+
524
+ def wait_for_sources
525
+ last = Time.new - 10
526
+ delta = 1
527
+ while not @sources.empty?
528
+ now = Time.new
529
+ if now - last > delta
530
+ @sources.explain
531
+ last = now
532
+ if delta < 60
533
+ delta = delta * 1.41
534
+ end
535
+ end
536
+ sleep 0.1
537
+ end
538
+ rescue Interrupt
539
+ #@log.warn "Interrupted"
540
+ end
541
+
542
+ end
543
+
544
+ class Runtime
545
+ def initialize()
546
+ @events = Eventor.new self
547
+ @log = Logger.new "quark.runtime"
548
+ @servers = Servers.new(@events)
549
+ end
550
+ def schedule(task, delay)
551
+ src = @events.add "timer"
552
+ @events.schedule(delay) { @events.event(final:src) { task.onExecute self } }
553
+ end
554
+ def request(request, handler)
555
+ src = @events.add "http request"
556
+ t = Thread.new do
557
+ begin
558
+ url = request.getUrl
559
+ @events.event { handler.onHTTPInit url }
560
+ headers = {}
561
+ request.getHeaders.each { |k| headers[k] = request.getHeader k }
562
+ uri = URI(url)
563
+ req = Net::HTTPGenericRequest.new(request.getMethod.upcase, 1, 1, uri, headers)
564
+ req.body = request.getBody
565
+ res = Net::HTTP.start(uri.host, uri.port,
566
+ :use_ssl => uri.scheme == 'https') do | http |
567
+ http.request(req)
568
+ end
569
+ response = HTTP::Response.new
570
+ response.setCode(res.code.to_i)
571
+ response.setBody(res.body)
572
+ @events.event { handler.onHTTPResponse request, response }
573
+ rescue Exception => e
574
+ #@log.warn "EXCEPTION: #{e.inspect}"
575
+ #@log.warn "MESSAGE: #{e.message}"
576
+ @events.event { handler.onHTTPError request, ::Quark.quark.HTTPError.new(e.message) }
577
+ ensure
578
+ @events.event(final:src) { handler.onHTTPFinal request }
579
+ end
580
+ end
581
+ end
582
+
583
+ def serveHTTP(url, servlet)
584
+ @servers.add(HTTPAdapter.new(url, servlet, @events))
585
+ end
586
+
587
+ def serveWS(url, servlet)
588
+ @servers.add(WSAdapter.new(url, servlet, @events))
589
+ end
590
+
591
+ def respond(request, response)
592
+ if request.rs == response
593
+ request.respond :http_response
594
+ else
595
+ request.fail! 500, "servlet failed to pair up request and response\r\n"
596
+ end
597
+ end
598
+
599
+ def open(url, handler)
600
+ begin
601
+ src = @events.add "ws client"
602
+ client = WebsocketClient.new(url)
603
+ sock = WebsocketAdapter.new(client)
604
+ events = @events
605
+ events.event { handler.onWSInit(sock) }
606
+ client.on_client(:open) do |wsevt|
607
+ # puts "open"
608
+ sock.opened = true
609
+ events.event { handler.onWSConnected(sock) }
610
+ end
611
+ client.on_client(:message) do |wsevt|
612
+ # puts "message"
613
+ case wsevt.data
614
+ when Array then
615
+ buffer = Buffer.new(wsevt.data.pack("C*"))
616
+ events.event { handler.onWSBinary(sock, buffer) }
617
+ when String then
618
+ events.event { handler.onWSMessage(sock, wsevt.data) }
619
+ end
620
+ end
621
+ client.on_client(:close) do |wsevt|
622
+ # puts "close"
623
+ if sock.opened
624
+ events.event { handler.onWSClosed(sock) }
625
+ end
626
+ events.event(final:src) { handler.onWSFinal(sock) }
627
+ end
628
+ client.on_client(:error) do |wsevt|
629
+ # puts self
630
+ events.event { handler.onWSError(sock, ::Quark.quark.WSError.new(wsevt.message)) }
631
+ end
632
+ client.issues.on(:start_failed) do |err|
633
+ events.event { handler.onWSError(sock, ::Quark.quark.WSError.new(err.to_s)) }
634
+ events.event(final:src) { handler.onWSFinal(sock) }
635
+ end
636
+ Thread.new { client.run }
637
+ rescue ::Exception => err
638
+ puts "AIEEE", err, err.backtrace
639
+ end
640
+ end
641
+
642
+ def fail(message)
643
+ @log.error message
644
+ exit! 1
645
+ end
646
+
647
+ def logger(topic)
648
+ return Logger.new topic
649
+ end
650
+
651
+ def codec
652
+ return Codec.new
653
+ end
654
+
655
+ def now
656
+ (Time.now.to_f * 1000).round
657
+ end
658
+
659
+ def sleep(seconds)
660
+ Kernel.sleep seconds
661
+ end
662
+
663
+ def uuid
664
+ SecureRandom.uuid
665
+ end
666
+
667
+ def callSafely(unary_callable, default)
668
+ begin
669
+ ::Quark.quark.callUnaryCallable(unary_callable, nil)
670
+ rescue
671
+ @log.error("Exception while calling safely: #{$!}")
672
+ default
673
+ end
674
+ end
675
+ end
676
+
677
+ class WebsocketAdapter
678
+ attr_accessor :opened
679
+ def initialize(client)
680
+ @client = client
681
+ @opened = false
682
+ end
683
+
684
+ def send (message)
685
+ @client.text message
686
+ end
687
+
688
+ def sendBinary (message)
689
+ @client.binary message.data
690
+ end
691
+
692
+ def close
693
+ @client.close
694
+ end
695
+ end
696
+
697
+ class WebscketIssues
698
+ include EventEmitter
699
+ end
700
+ class WebsocketClient
701
+ extend Forwardable
702
+ def initialize(url)
703
+ @url = url
704
+ @client = ::WebSocket::Driver.client(self)
705
+ @issues = WebscketIssues.new
706
+ end
707
+ attr_reader :url
708
+
709
+
710
+ def issues
711
+ @issues
712
+ end
713
+
714
+ def run
715
+ begin
716
+ uri = URI(url)
717
+ port = uri.port || (uri.scheme == "ws" ? 80 : 443)
718
+ tcp = Celluloid::IO::TCPSocket.new(uri.host, port)
719
+ if uri.scheme == "wss"
720
+ @socket = Celluloid::IO::SSLSocket.new(tcp)
721
+ @socket.connect
722
+ else
723
+ @socket = tcp
724
+ end
725
+ @client.start
726
+ rescue ::Exception => err
727
+ @issues.emit(:start_failed, err)
728
+ else
729
+ loop do
730
+ begin
731
+ @client.parse(@socket.readpartial(1024))
732
+ rescue EOFError
733
+ break
734
+ end
735
+ end
736
+ end
737
+ end
738
+
739
+ def_delegators :@client, :text, :binary, :ping, :close, :protocol
740
+ def_delegator :@client, :on, :on_client
741
+
742
+ def write(buffer)
743
+ @socket.write buffer
744
+ end
745
+
746
+ end
747
+
748
+ class IncomingRequest < HTTP::Request
749
+ attr_accessor :rs
750
+ attr_accessor :fut
751
+ attr_accessor :request
752
+ attr_accessor :svr
753
+ attr_accessor :action
754
+ attr_accessor :ws_handler
755
+
756
+ def fail! (code, body)
757
+ @rs.setCode(code)
758
+ @rs.setBody(body)
759
+ respond :http_response
760
+ end
761
+
762
+ def respond(action)
763
+ @svr.respond(self, action)
764
+ end
765
+ end
766
+
767
+ class Servers
768
+ include Celluloid
769
+ def initialize(events)
770
+ @servers = {}
771
+ @events= events
772
+ end
773
+ def add(adapter)
774
+ if not adapter.scheme_supported?
775
+ error = "${adapter.uri.scheme} is not supported"
776
+ @events.event { adapter.servlet.onServletError(adapter.url, ::Quark.quark.ServletError.new(error)) }
777
+ return
778
+ end
779
+ if adapter.secure?
780
+ error = "${adapter.uri.scheme} is not yet supported"
781
+ @events.event { adapter.servlet.onServletError(adapter.url, ::Quark.quark.ServletError.new(error)) }
782
+ return
783
+ end
784
+ server = @servers[adapter.key]
785
+ if server.nil?
786
+ if adapter.secure?
787
+ server = HTTPSServer.new(adapter.uri.hostname, adapter.uri.port, @events)
788
+ else
789
+ server = HTTPServer.new(adapter.uri.hostname, adapter.uri.port, @events)
790
+ end
791
+ # in case the port was 0 this will mutate the #effective_url, and #key of adapter
792
+ adapter.uri.port = server.local_address.ip_port
793
+ @servers[adapter.key] = server
794
+ end
795
+ server.add(adapter)
796
+ end
797
+ end
798
+
799
+ class Adapter
800
+ def initialize(url, servlet, events)
801
+ @url = url
802
+ @uri = URI(url)
803
+ @servlet = servlet
804
+ @events = events
805
+ end
806
+ attr_reader :servlet, :uri, :url
807
+ attr_accessor :source
808
+
809
+ def scheme_supported?
810
+ self.schemes.values.include? @uri.scheme
811
+ end
812
+
813
+ def secure?
814
+ self.schemes[:secure] == @uri.scheme
815
+ end
816
+
817
+ def key
818
+ "#{@uri.host}:#{@uri.port}"
819
+ end
820
+
821
+ def effective_url
822
+ @uri.to_s
823
+ end
824
+
825
+ end
826
+
827
+ class HTTPAdapter < Adapter
828
+ def schemes
829
+ {plain: "http", secure: "https"}
830
+ end
831
+
832
+ def process_request(rq)
833
+ if rq.request.websocket?
834
+ rq.fail! 400, "http here, move along\r\n"
835
+ else
836
+ @events.event { servlet.onHTTPRequest(rq, rq.rs) }
837
+ end
838
+ end
839
+
840
+ def process_response(rq)
841
+ end
842
+ end
843
+
844
+ class ServerWebsocketAdapter
845
+ def initialize(sock)
846
+ @sock = sock
847
+ end
848
+ def send (message)
849
+ @sock.write message
850
+ end
851
+
852
+ def sendBinary (message)
853
+ @sock.write message.data.unpack("C*")
854
+ end
855
+
856
+ def close
857
+ @sock.close
858
+ end
859
+ end
860
+
861
+ class WSAdapter < Adapter
862
+ def schemes
863
+ {plain: "ws", secure: "wss"}
864
+ end
865
+
866
+ def process_request(rq)
867
+ if rq.request.websocket?
868
+ @events.event { rq.ws_handler = servlet.onWSConnect(rq); rq.respond :detach }
869
+ else
870
+ rq.fail! 400, "websockets here, move along\r\n"
871
+ end
872
+ end
873
+ def process_response(rq)
874
+ if rq.ws_handler.nil?
875
+ rq.fail 403, "Forbidden\r\n"
876
+ else
877
+ websocket = rq.request.websocket
878
+ sock = ServerWebsocketAdapter.new(websocket)
879
+ handler = rq.ws_handler
880
+ src = @events.add ("server websocket")
881
+ events = @events
882
+ @events.event { handler.onWSInit(sock) }
883
+ @events.event { handler.onWSConnected(sock) }
884
+ websocket.on_close do |wsevent|
885
+ events.event { handler.onWSClosed(sock) }
886
+ events.event(final:src) { handler.onWSFinal(sock) }
887
+ end
888
+ websocket.on_error do |wsevt|
889
+ events.event { handler.onWSError(sock, ::Quark.quark.WSError.new(wsevt.message)) }
890
+ end
891
+ Thread.new do
892
+ while not websocket.closed?
893
+ data = websocket.read
894
+ case data
895
+ when Array then
896
+ buffer = Buffer.new(data.pack("C*"))
897
+ events.event { handler.onWSBinary(sock, buffer) }
898
+ when String then
899
+ events.event { handler.onWSMessage(sock, data) }
900
+ end
901
+ end
902
+ end
903
+ end
904
+ rescue => ex
905
+ puts "aieieie", ex
906
+ end
907
+ end
908
+
909
+ module MyServer
910
+ def initialize(host = "127.0.0.1", port = 3000, events)
911
+ super(host, port, &method(:on_connection))
912
+ @events = events
913
+ @paths = {}
914
+ @log = Logger.new "quark.runtime.server"
915
+ end
916
+
917
+
918
+ def local_address
919
+ Addrinfo.new(@server.getsockname)
920
+ end
921
+
922
+ def add(adapter)
923
+ old = @paths[adapter.uri.path]
924
+ if not adapter.nil?
925
+ @paths[adapter.uri.path] = adapter
926
+ adapter.source = @events.add(adapter.effective_url)
927
+ @events.event { adapter.servlet.onServletInit(adapter.effective_url, @events.runtime) }
928
+ end
929
+ if not old.nil?
930
+ # XXX: servlet is not quiesced
931
+ @events.event(final: adapter.source) { adapter.servlet.onServletFinal(adapter.effective_url) }
932
+ end
933
+ end
934
+
935
+ def on_connection(connection)
936
+ connection.each_request do |request|
937
+ begin
938
+ rq = IncomingRequest.new(request.url)
939
+ rq.setBody(request.body)
940
+ request.headers.each {|key, value| rq.setHeader(key, value)}
941
+ rq.setMethod(request.method)
942
+ rq.request = request
943
+ rq.rs = HTTP::Response.new
944
+ rq.fut = Celluloid::Condition.new
945
+ rq.svr = self
946
+ rq.action = :wait
947
+ adapter = @paths[request.uri.path]
948
+ if adapter.nil?
949
+ rq.fail! 404, "not found\r\n"
950
+ else
951
+ adapter.process_request(rq)
952
+ end
953
+ if rq.action == :wait
954
+ rq.fut.wait
955
+ end
956
+ adapter.process_response(rq)
957
+ case rq.action
958
+ when :http_response
959
+ http_response(rq)
960
+ when :detach
961
+ connection.detach
962
+ else
963
+ @log.error "Unknown action #{rq.action} for HTTP request"
964
+ rq.fail! 500, "quark runtime is confused, unknown http request action\r\n"
965
+ http_response(rq)
966
+ end
967
+ rescue => ex
968
+ @log.error ex
969
+ end
970
+ end
971
+ end
972
+
973
+ def http_response(rq)
974
+ rs = rq.rs
975
+ headers = {}
976
+ rs.getHeaders.each { |k| headers[k] = rs.getHeader k }
977
+ response = Reel::Response::new(rs.getCode, headers, rs.getBody)
978
+ rq.request.respond response
979
+ end
980
+
981
+ def respond(rq, action)
982
+ waiting = rq.action == :wait
983
+ rq.action = action
984
+ if waiting
985
+ # condition is race-free only in the context of the originating actor
986
+ rq.fut.signal
987
+ end
988
+ end
989
+ end
990
+
991
+ class HTTPServer < Reel::Server::HTTP
992
+ include MyServer
993
+ end
994
+
995
+ class HTTPSServer < Reel::Server::HTTPS
996
+ include MyServer
997
+ end
998
+
999
+
1000
+ HTTPRequest = HTTP::Request
1001
+
1002
+ class Servlet
1003
+ def onServletInit(url, rt)
1004
+ end
1005
+ def onServletError(url, error)
1006
+ end
1007
+ def onServletEnd(url)
1008
+ end
1009
+ end
1010
+
1011
+ class HTTPServlet < Servlet
1012
+ def onHTTPRequest(request, response)
1013
+ end
1014
+ end
1015
+
1016
+ class WSServlet < Servlet
1017
+ def onWSConnect(request)
1018
+ end
1019
+ end
1020
+
1021
+ def self.url_get(url)
1022
+ Net::HTTP.get(URI(url))
1023
+ end
1024
+
1025
+ def self.default_codec
1026
+ Codec.new
1027
+ end
1028
+
1029
+ def self.cast(value, &block)
1030
+ # For now there is no easy way to check in Ruby that Quark class C is
1031
+ # subclass of of Quark class B, so don't check anything until that's fixed.
1032
+ # The correct way to do so would be via reflect.Class.hasInstance, probably,
1033
+ # but that doesn't support interfaces yet.
1034
+ value
1035
+ end
1036
+
1037
+ class Mutex
1038
+ end
1039
+
1040
+ class Lock < Mutex
1041
+ def initialize
1042
+ @lock = ::Thread::Mutex.new
1043
+ end
1044
+
1045
+ def acquire
1046
+ if @lock.owned?
1047
+ fail "Illegal re-acquisition of a quark lock"
1048
+ end
1049
+ @lock.lock
1050
+ end
1051
+
1052
+ def release
1053
+ if !@lock.owned?
1054
+ fail "Illegal release of a not-acquired quark lock"
1055
+ end
1056
+ @lock.unlock
1057
+ end
1058
+
1059
+ private
1060
+
1061
+ def fail(reason)
1062
+ @log.fatal reason
1063
+ exit! 1 # XXX: we should go via Quark runtime, but need to develop a method to query it, Context is not yet exposed to the native code...
1064
+ end
1065
+ end
1066
+
1067
+ class Condition < Lock
1068
+ def initialize
1069
+ super
1070
+ @condition = ::Thread::ConditionVariable.new
1071
+ end
1072
+ def waitWakeup(timeout)
1073
+ if !@lock.owned?
1074
+ fail "Illegal waitWakeup of a not-acquired quark Condition"
1075
+ end
1076
+ @condition.wait(@lock, timeout / 1000.0)
1077
+ end
1078
+
1079
+ def wakeup
1080
+ if !@lock.owned?
1081
+ fail "Illegal wakeup of a not-acquired quark Condition"
1082
+ end
1083
+ @condition.signal
1084
+ end
1085
+ end
1086
+
1087
+ class TLS
1088
+ UNINITIALIZED = []
1089
+ private_constant :UNINITIALIZED
1090
+ def initialize(initializer)
1091
+ @initializer = initializer
1092
+ @var = Concurrent::ThreadLocalVar.new UNINITIALIZED
1093
+ end
1094
+
1095
+ def getValue
1096
+ value = @var.value
1097
+ if UNINITIALIZED.equal?(value)
1098
+ @var.value = value = @initializer.getValue
1099
+ end
1100
+ value
1101
+ end
1102
+
1103
+ def setValue(value)
1104
+ @var.value = value
1105
+ end
1106
+ end
1107
+
1108
+ class Codec
1109
+ ZERO = "\0".encode Encoding::ASCII_8BIT
1110
+ def buffer(size)
1111
+ Buffer.new ZERO * size
1112
+ end
1113
+
1114
+ def toHexdump(buffer, index, size, spaceScale)
1115
+ hex = buffer.data[index...index+size].unpack("H*")[0]
1116
+ (0...hex.size).each_slice(2**(spaceScale+1)).map {|i|
1117
+ hex[i[0]..i[-1]]
1118
+ }.join " "
1119
+ end
1120
+
1121
+ def toBase64(buffer, index, size)
1122
+ Base64.encode64(buffer.data[index...index+size]).strip
1123
+ end
1124
+
1125
+ def fromHexdump(value)
1126
+ value = value.split(" ").join
1127
+ if value[0...2].downcase == "0x"
1128
+ value[0...2] = ""
1129
+ end
1130
+ Buffer.new ((0...value.length).each_slice(2).map { |i|
1131
+ value[i[0]..i[1]].to_i(16)
1132
+ }.pack("C*"))
1133
+ end
1134
+
1135
+ def fromBase64(value)
1136
+ Buffer.new Base64.decode64 value
1137
+ end
1138
+ end
1139
+
1140
+ class Buffer
1141
+ BIN = Encoding::ASCII_8BIT
1142
+ UTF8 = Encoding::UTF_8
1143
+ module BE
1144
+ SHORT = "s>"
1145
+ INT = "l>"
1146
+ LONG = "q>"
1147
+ FLOAT = "G"
1148
+ end
1149
+ module LE
1150
+ SHORT = "s<"
1151
+ INT = "l<"
1152
+ LONG = "q<"
1153
+ FLOAT = "E"
1154
+ end
1155
+ attr_reader :data
1156
+ def initialize(data)
1157
+ @data = data.dup.force_encoding BIN
1158
+ @ord = BE
1159
+ end
1160
+ def capacity
1161
+ @data.length
1162
+ end
1163
+ def putStringUTF8(index, value)
1164
+ value = value.dup.force_encoding BIN
1165
+ len = value.length
1166
+ @data[index...index+len] = value
1167
+ len
1168
+ end
1169
+ def getStringUTF8(index, length)
1170
+ @data[index...index+length].force_encoding UTF8
1171
+ end
1172
+ def getByte(index)
1173
+ @data[index].bytes[0]
1174
+ end
1175
+ def putByte(index, value)
1176
+ @data[index] = [value].pack("C")
1177
+ end
1178
+ def littleEndian
1179
+ @ord = LE
1180
+ self
1181
+ end
1182
+ def getShort(index)
1183
+ @data[index..-1].unpack(@ord::SHORT)[0]
1184
+ end
1185
+ def putShort(index, value)
1186
+ @data[index...index+2] = [value].pack(@ord::SHORT)
1187
+ end
1188
+ def getInt(index)
1189
+ @data[index..-1].unpack(@ord::INT)[0]
1190
+ end
1191
+ def putInt(index, value)
1192
+ @data[index...index+4] = [value].pack(@ord::INT)
1193
+ end
1194
+ def getLong(index)
1195
+ @data[index..-1].unpack(@ord::LONG)[0]
1196
+ end
1197
+ def putLong(index, value)
1198
+ @data[index...index+8] = [value].pack(@ord::LONG)
1199
+ end
1200
+ def getFloat(index)
1201
+ @data[index..-1].unpack(@ord::FLOAT)[0]
1202
+ end
1203
+ def putFloat(index, value)
1204
+ @data[index...index+8] = [value].pack(@ord::FLOAT)
1205
+ end
1206
+ def getSlice(index, length)
1207
+ return Buffer.new(@data[index...index+length])
1208
+ end
1209
+ def inspect
1210
+ "Buffer(%s)" % Codec.new.toHexdump(self, 0, @data.length, 3)
1211
+ end
1212
+ end
1213
+ end