summaryrefslogtreecommitdiff
path: root/vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java
diff options
context:
space:
mode:
authorBenjamin Sanders <ben@Benjamins-MacBook-Pro.local>2025-10-11 10:34:24 -0400
committerBenjamin Sanders <ben@Benjamins-MacBook-Pro.local>2025-10-11 10:34:24 -0400
commit5571dc766e2143e39762ff0b47c41d1c2e154f4c (patch)
treef4f124d314a7e76c04484515aa0fd1f2e271a601 /vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java
parent359f3309c97fc894b63e0a295c76ab298504d635 (diff)
Vendor bundled gems for deployment
Diffstat (limited to 'vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java')
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java/.classpath8
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java/.project17
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java/src/com/rubyeventmachine/EmReactor.java613
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java/src/com/rubyeventmachine/EmReactorException.java40
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java/src/com/rubyeventmachine/EventableChannel.java72
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java/src/com/rubyeventmachine/EventableDatagramChannel.java201
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java/src/com/rubyeventmachine/EventableSocketChannel.java415
7 files changed, 1366 insertions, 0 deletions
diff --git a/vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java/.classpath b/vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java/.classpath
new file mode 100644
index 0000000..11672dd
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry excluding="src/" kind="src" path=""/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
+ <classpathentry kind="output" path="src"/>
+</classpath>
diff --git a/vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java/.project b/vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java/.project
new file mode 100644
index 0000000..c7766db
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>em_reactor</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java/src/com/rubyeventmachine/EmReactor.java b/vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java/src/com/rubyeventmachine/EmReactor.java
new file mode 100644
index 0000000..31642f3
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java/src/com/rubyeventmachine/EmReactor.java
@@ -0,0 +1,613 @@
+/**
+ * $Id$
+ *
+ * Author:: Francis Cianfrocca (gmail: blackhedd)
+ * Homepage:: http://rubyeventmachine.com
+ * Date:: 15 Jul 2007
+ *
+ * See EventMachine and EventMachine::Connection for documentation and
+ * usage examples.
+ *
+ *
+ *----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
+ * Gmail: blackhedd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of either: 1) the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version; or 2) Ruby's License.
+ *
+ * See the file COPYING for complete licensing information.
+ *
+ *---------------------------------------------------------------------------
+ *
+ *
+ */
+
+package com.rubyeventmachine;
+
+import java.io.*;
+import java.nio.channels.*;
+import java.util.*;
+import java.nio.*;
+import java.net.*;
+import java.util.concurrent.atomic.*;
+import java.security.*;
+
+public class EmReactor {
+ public final int EM_TIMER_FIRED = 100;
+ public final int EM_CONNECTION_READ = 101;
+ public final int EM_CONNECTION_UNBOUND = 102;
+ public final int EM_CONNECTION_ACCEPTED = 103;
+ public final int EM_CONNECTION_COMPLETED = 104;
+ public final int EM_LOOPBREAK_SIGNAL = 105;
+ public final int EM_CONNECTION_NOTIFY_READABLE = 106;
+ public final int EM_CONNECTION_NOTIFY_WRITABLE = 107;
+ public final int EM_SSL_HANDSHAKE_COMPLETED = 108;
+ public final int EM_SSL_VERIFY = 109;
+ public final int EM_PROXY_TARGET_UNBOUND = 110;
+ public final int EM_PROXY_COMPLETED = 111;
+
+ public final int EM_PROTO_SSLv2 = 2;
+ public final int EM_PROTO_SSLv3 = 4;
+ public final int EM_PROTO_TLSv1 = 8;
+ public final int EM_PROTO_TLSv1_1 = 16;
+ public final int EM_PROTO_TLSv1_2 = 32;
+
+ private Selector mySelector;
+ private TreeMap<Long, ArrayList<Long>> Timers;
+ private HashMap<Long, EventableChannel> Connections;
+ private HashMap<Long, ServerSocketChannel> Acceptors;
+ private ArrayList<Long> NewConnections;
+ private ArrayList<Long> UnboundConnections;
+ private ArrayList<EventableSocketChannel> DetachedConnections;
+
+ private boolean bRunReactor;
+ private long BindingIndex;
+ private AtomicBoolean loopBreaker;
+ private ByteBuffer myReadBuffer;
+ private int timerQuantum;
+
+ public EmReactor() {
+ Timers = new TreeMap<Long, ArrayList<Long>>();
+ Connections = new HashMap<Long, EventableChannel>();
+ Acceptors = new HashMap<Long, ServerSocketChannel>();
+ NewConnections = new ArrayList<Long>();
+ UnboundConnections = new ArrayList<Long>();
+ DetachedConnections = new ArrayList<EventableSocketChannel>();
+
+ BindingIndex = 0;
+ loopBreaker = new AtomicBoolean();
+ loopBreaker.set(false);
+ myReadBuffer = ByteBuffer.allocate(32*1024); // don't use a direct buffer. Ruby doesn't seem to like them.
+ timerQuantum = 98;
+ }
+
+ /**
+ * This is a no-op stub, intended to be overridden in user code.
+ */
+ public void eventCallback (long sig, int eventType, ByteBuffer data, long data2) {
+ System.out.println ("Default callback: "+sig+" "+eventType+" "+data+" "+data2);
+ }
+ public void eventCallback (long sig, int eventType, ByteBuffer data) {
+ eventCallback (sig, eventType, data, 0);
+ }
+
+
+ public void run() {
+ try {
+ mySelector = Selector.open();
+ bRunReactor = true;
+ } catch (IOException e) {
+ throw new RuntimeException ("Could not open selector", e);
+ }
+
+ while (bRunReactor) {
+ runLoopbreaks();
+ if (!bRunReactor) break;
+
+ runTimers();
+ if (!bRunReactor) break;
+
+ removeUnboundConnections();
+ checkIO();
+ addNewConnections();
+ processIO();
+ }
+
+ close();
+ }
+
+ void addNewConnections() {
+ ListIterator<EventableSocketChannel> iter = DetachedConnections.listIterator(0);
+ while (iter.hasNext()) {
+ EventableSocketChannel ec = iter.next();
+ ec.cleanup();
+ }
+ DetachedConnections.clear();
+
+ ListIterator<Long> iter2 = NewConnections.listIterator(0);
+ while (iter2.hasNext()) {
+ long b = iter2.next();
+
+ EventableChannel ec = Connections.get(b);
+ if (ec != null) {
+ try {
+ ec.register();
+ } catch (ClosedChannelException e) {
+ UnboundConnections.add (ec.getBinding());
+ }
+ }
+ }
+ NewConnections.clear();
+ }
+
+ void removeUnboundConnections() {
+ ListIterator<Long> iter = UnboundConnections.listIterator(0);
+ while (iter.hasNext()) {
+ long b = iter.next();
+
+ EventableChannel ec = Connections.remove(b);
+ if (ec != null) {
+ eventCallback (b, EM_CONNECTION_UNBOUND, null);
+ ec.close();
+
+ EventableSocketChannel sc = (EventableSocketChannel) ec;
+ if (sc != null && sc.isAttached())
+ DetachedConnections.add (sc);
+ }
+ }
+ UnboundConnections.clear();
+ }
+
+ void checkIO() {
+ long timeout;
+
+ if (NewConnections.size() > 0) {
+ timeout = -1;
+ } else if (!Timers.isEmpty()) {
+ long now = new Date().getTime();
+ long k = Timers.firstKey();
+ long diff = k-now;
+
+ if (diff <= 0)
+ timeout = -1; // don't wait, just poll once
+ else
+ timeout = diff;
+ } else {
+ timeout = 0; // wait indefinitely
+ }
+
+ try {
+ if (timeout == -1)
+ mySelector.selectNow();
+ else
+ mySelector.select(timeout);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ void processIO() {
+ Iterator<SelectionKey> it = mySelector.selectedKeys().iterator();
+ while (it.hasNext()) {
+ SelectionKey k = it.next();
+ it.remove();
+
+ if (k.isConnectable())
+ isConnectable(k);
+
+ else if (k.isAcceptable())
+ isAcceptable(k);
+
+ else {
+ if (k.isWritable())
+ isWritable(k);
+
+ if (k.isReadable())
+ isReadable(k);
+ }
+ }
+ }
+
+ void isAcceptable (SelectionKey k) {
+ ServerSocketChannel ss = (ServerSocketChannel) k.channel();
+ SocketChannel sn;
+ long b;
+
+ for (int n = 0; n < 10; n++) {
+ try {
+ sn = ss.accept();
+ if (sn == null)
+ break;
+ } catch (IOException e) {
+ e.printStackTrace();
+ k.cancel();
+
+ ServerSocketChannel server = Acceptors.remove(k.attachment());
+ if (server != null)
+ try{ server.close(); } catch (IOException ex) {};
+ break;
+ }
+
+ try {
+ sn.configureBlocking(false);
+ } catch (IOException e) {
+ e.printStackTrace();
+ continue;
+ }
+
+ b = createBinding();
+ EventableSocketChannel ec = new EventableSocketChannel (sn, b, mySelector);
+ Connections.put (b, ec);
+ NewConnections.add (b);
+
+ eventCallback (((Long)k.attachment()).longValue(), EM_CONNECTION_ACCEPTED, null, b);
+ }
+ }
+
+ void isReadable (SelectionKey k) {
+ EventableChannel ec = (EventableChannel) k.attachment();
+ long b = ec.getBinding();
+
+ if (ec.isWatchOnly()) {
+ if (ec.isNotifyReadable())
+ eventCallback (b, EM_CONNECTION_NOTIFY_READABLE, null);
+ } else {
+ myReadBuffer.clear();
+
+ try {
+ ec.readInboundData (myReadBuffer);
+ myReadBuffer.flip();
+ if (myReadBuffer.limit() > 0)
+ eventCallback (b, EM_CONNECTION_READ, myReadBuffer);
+ } catch (IOException e) {
+ UnboundConnections.add (b);
+ }
+ }
+ }
+
+ void isWritable (SelectionKey k) {
+ EventableChannel ec = (EventableChannel) k.attachment();
+ long b = ec.getBinding();
+
+ if (ec.isWatchOnly()) {
+ if (ec.isNotifyWritable())
+ eventCallback (b, EM_CONNECTION_NOTIFY_WRITABLE, null);
+ }
+ else {
+ try {
+ if (!ec.writeOutboundData())
+ UnboundConnections.add (b);
+ } catch (IOException e) {
+ UnboundConnections.add (b);
+ }
+ }
+ }
+
+ void isConnectable (SelectionKey k) {
+ EventableSocketChannel ec = (EventableSocketChannel) k.attachment();
+ long b = ec.getBinding();
+
+ try {
+ if (ec.finishConnecting())
+ eventCallback (b, EM_CONNECTION_COMPLETED, null);
+ else
+ UnboundConnections.add (b);
+ } catch (IOException e) {
+ UnboundConnections.add (b);
+ }
+ }
+
+ void close() {
+ try {
+ if (mySelector != null)
+ mySelector.close();
+ } catch (IOException e) {}
+ mySelector = null;
+
+ // run down open connections and sockets.
+ Iterator<ServerSocketChannel> i = Acceptors.values().iterator();
+ while (i.hasNext()) {
+ try {
+ i.next().close();
+ } catch (IOException e) {}
+ }
+
+ // 29Sep09: We create an ArrayList of the existing connections, then iterate over
+ // that to call unbind on them. This is because an unbind can trigger a reconnect,
+ // which will add to the Connections HashMap, causing a ConcurrentModificationException.
+ // XXX: The correct behavior here would be to latch the various reactor methods to return
+ // immediately if the reactor is shutting down.
+ ArrayList<EventableChannel> conns = new ArrayList<EventableChannel>();
+ Iterator<EventableChannel> i2 = Connections.values().iterator();
+ while (i2.hasNext()) {
+ EventableChannel ec = i2.next();
+ if (ec != null) {
+ conns.add (ec);
+ }
+ }
+ Connections.clear();
+
+ ListIterator<EventableChannel> i3 = conns.listIterator(0);
+ while (i3.hasNext()) {
+ EventableChannel ec = i3.next();
+ eventCallback (ec.getBinding(), EM_CONNECTION_UNBOUND, null);
+ ec.close();
+
+ EventableSocketChannel sc = (EventableSocketChannel) ec;
+ if (sc != null && sc.isAttached())
+ DetachedConnections.add (sc);
+ }
+
+ ListIterator<EventableSocketChannel> i4 = DetachedConnections.listIterator(0);
+ while (i4.hasNext()) {
+ EventableSocketChannel ec = i4.next();
+ ec.cleanup();
+ }
+ DetachedConnections.clear();
+ }
+
+ void runLoopbreaks() {
+ if (loopBreaker.getAndSet(false)) {
+ eventCallback (0, EM_LOOPBREAK_SIGNAL, null);
+ }
+ }
+
+ public void stop() {
+ bRunReactor = false;
+ signalLoopbreak();
+ }
+
+ void runTimers() {
+ long now = new Date().getTime();
+ while (!Timers.isEmpty()) {
+ long k = Timers.firstKey();
+ if (k > now)
+ break;
+
+ ArrayList<Long> callbacks = Timers.get(k);
+ Timers.remove(k);
+
+ // Fire all timers at this timestamp
+ ListIterator<Long> iter = callbacks.listIterator(0);
+ while (iter.hasNext()) {
+ eventCallback (0, EM_TIMER_FIRED, null, iter.next().longValue());
+ }
+ }
+ }
+
+ public long installOneshotTimer (long milliseconds) {
+ long s = createBinding();
+ long deadline = new Date().getTime() + milliseconds;
+
+ if (Timers.containsKey(deadline)) {
+ Timers.get(deadline).add(s);
+ } else {
+ ArrayList<Long> callbacks = new ArrayList<Long>();
+ callbacks.add(s);
+ Timers.put(deadline, callbacks);
+ }
+
+ return s;
+ }
+
+ public long startTcpServer (SocketAddress sa) throws EmReactorException {
+ try {
+ ServerSocketChannel server = ServerSocketChannel.open();
+ server.configureBlocking(false);
+ server.socket().bind (sa);
+ long s = createBinding();
+ Acceptors.put(s, server);
+ server.register(mySelector, SelectionKey.OP_ACCEPT, s);
+ return s;
+ } catch (IOException e) {
+ throw new EmReactorException ("unable to open socket acceptor: " + e.toString());
+ }
+ }
+
+ public long startTcpServer (String address, int port) throws EmReactorException {
+ return startTcpServer (new InetSocketAddress (address, port));
+ }
+
+ public void stopTcpServer (long signature) throws IOException {
+ ServerSocketChannel server = Acceptors.remove(signature);
+ if (server != null)
+ server.close();
+ else
+ throw new RuntimeException ("failed to close unknown acceptor");
+ }
+
+ public long openUdpSocket (InetSocketAddress address) throws IOException {
+ // TODO, don't throw an exception out of here.
+ DatagramChannel dg = DatagramChannel.open();
+ dg.configureBlocking(false);
+ dg.socket().bind(address);
+ long b = createBinding();
+ EventableChannel ec = new EventableDatagramChannel (dg, b, mySelector);
+ dg.register(mySelector, SelectionKey.OP_READ, ec);
+ Connections.put(b, ec);
+ return b;
+ }
+
+ public long openUdpSocket (String address, int port) throws IOException {
+ return openUdpSocket (new InetSocketAddress (address, port));
+ }
+
+ public void sendData (long sig, ByteBuffer bb) throws IOException {
+ Connections.get(sig).scheduleOutboundData( bb );
+ }
+
+ public void sendData (long sig, byte[] data) throws IOException {
+ sendData (sig, ByteBuffer.wrap(data));
+ }
+
+ public void setCommInactivityTimeout (long sig, long mills) {
+ Connections.get(sig).setCommInactivityTimeout (mills);
+ }
+
+ public void sendDatagram (long sig, byte[] data, int length, String recipAddress, int recipPort) {
+ sendDatagram (sig, ByteBuffer.wrap(data), recipAddress, recipPort);
+ }
+
+ public void sendDatagram (long sig, ByteBuffer bb, String recipAddress, int recipPort) {
+ (Connections.get(sig)).scheduleOutboundDatagram( bb, recipAddress, recipPort);
+ }
+
+ public long connectTcpServer (String address, int port) {
+ return connectTcpServer(null, 0, address, port);
+ }
+
+ public long connectTcpServer (String bindAddr, int bindPort, String address, int port) {
+ long b = createBinding();
+
+ try {
+ SocketChannel sc = SocketChannel.open();
+ sc.configureBlocking(false);
+ if (bindAddr != null)
+ sc.socket().bind(new InetSocketAddress (bindAddr, bindPort));
+
+ EventableSocketChannel ec = new EventableSocketChannel (sc, b, mySelector);
+
+ if (sc.connect (new InetSocketAddress (address, port))) {
+ // Connection returned immediately. Can happen with localhost connections.
+ // WARNING, this code is untested due to lack of available test conditions.
+ // Ought to be be able to come here from a localhost connection, but that
+ // doesn't happen on Linux. (Maybe on FreeBSD?)
+ // The reason for not handling this until we can test it is that we
+ // really need to return from this function WITHOUT triggering any EM events.
+ // That's because until the user code has seen the signature we generated here,
+ // it won't be able to properly dispatch them. The C++ EM deals with this
+ // by setting pending mode as a flag in ALL eventable descriptors and making
+ // the descriptor select for writable. Then, it can send UNBOUND and
+ // CONNECTION_COMPLETED on the next pass through the loop, because writable will
+ // fire.
+ throw new RuntimeException ("immediate-connect unimplemented");
+ }
+ else {
+ ec.setConnectPending();
+ Connections.put (b, ec);
+ NewConnections.add (b);
+ }
+ } catch (IOException e) {
+ // Can theoretically come here if a connect failure can be determined immediately.
+ // I don't know how to make that happen for testing purposes.
+ throw new RuntimeException ("immediate-connect unimplemented: " + e.toString());
+ }
+ return b;
+ }
+
+ public void closeConnection (long sig, boolean afterWriting) {
+ EventableChannel ec = Connections.get(sig);
+ if (ec != null)
+ if (ec.scheduleClose (afterWriting))
+ UnboundConnections.add (sig);
+ }
+
+ long createBinding() {
+ return ++BindingIndex;
+ }
+
+ public void signalLoopbreak() {
+ loopBreaker.set(true);
+ if (mySelector != null)
+ mySelector.wakeup();
+ }
+
+ public void startTls (long sig) throws NoSuchAlgorithmException, KeyManagementException {
+ Connections.get(sig).startTls();
+ }
+
+ public void setTimerQuantum (int mills) {
+ if (mills < 5 || mills > 2500)
+ throw new RuntimeException ("attempt to set invalid timer-quantum value: "+mills);
+ timerQuantum = mills;
+ }
+
+ public Object[] getPeerName (long sig) {
+ EventableChannel channel = Connections.get(sig);
+ if (channel != null) {
+ return Connections.get(sig).getPeerName();
+ }
+ else {
+ ServerSocketChannel acceptor = Acceptors.get(sig);
+ return new Object[] { acceptor.socket().getLocalPort(),
+ acceptor.socket().getInetAddress().getHostAddress() };
+ }
+ }
+
+ public Object[] getSockName (long sig) {
+ EventableChannel channel = Connections.get(sig);
+ if (channel != null) {
+ return Connections.get(sig).getSockName();
+ }
+ else {
+ ServerSocketChannel acceptor = Acceptors.get(sig);
+ return new Object[] { acceptor.socket().getLocalPort(),
+ acceptor.socket().getInetAddress().getHostAddress() };
+ }
+ }
+
+ public long attachChannel (SocketChannel sc, boolean watch_mode) {
+ long b = createBinding();
+
+ EventableSocketChannel ec = new EventableSocketChannel (sc, b, mySelector);
+
+ ec.setAttached();
+ if (watch_mode)
+ ec.setWatchOnly();
+
+ Connections.put (b, ec);
+ NewConnections.add (b);
+
+ return b;
+ }
+
+ public SocketChannel detachChannel (long sig) {
+ EventableSocketChannel ec = (EventableSocketChannel) Connections.get (sig);
+ if (ec != null) {
+ UnboundConnections.add (sig);
+ return ec.getChannel();
+ } else {
+ return null;
+ }
+ }
+
+ public void setNotifyReadable (long sig, boolean mode) {
+ ((EventableSocketChannel) Connections.get(sig)).setNotifyReadable(mode);
+ }
+
+ public void setNotifyWritable (long sig, boolean mode) {
+ ((EventableSocketChannel) Connections.get(sig)).setNotifyWritable(mode);
+ }
+
+ public boolean isNotifyReadable (long sig) {
+ return Connections.get(sig).isNotifyReadable();
+ }
+
+ public boolean isNotifyWritable (long sig) {
+ return Connections.get(sig).isNotifyWritable();
+ }
+
+ public boolean pauseConnection (long sig) {
+ return ((EventableSocketChannel) Connections.get(sig)).pause();
+ }
+
+ public boolean resumeConnection (long sig) {
+ return ((EventableSocketChannel) Connections.get(sig)).resume();
+ }
+
+ public boolean isConnectionPaused (long sig) {
+ return ((EventableSocketChannel) Connections.get(sig)).isPaused();
+ }
+
+ public long getOutboundDataSize (long sig) {
+ return Connections.get(sig).getOutboundDataSize();
+ }
+
+ public int getConnectionCount() {
+ return Connections.size() + Acceptors.size();
+ }
+}
diff --git a/vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java/src/com/rubyeventmachine/EmReactorException.java b/vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java/src/com/rubyeventmachine/EmReactorException.java
new file mode 100644
index 0000000..69efaa3
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java/src/com/rubyeventmachine/EmReactorException.java
@@ -0,0 +1,40 @@
+/**
+ * $Id$
+ *
+ * Author:: Francis Cianfrocca (gmail: blackhedd)
+ * Homepage:: http://rubyeventmachine.com
+ * Date:: 15 Jul 2007
+ *
+ * See EventMachine and EventMachine::Connection for documentation and
+ * usage examples.
+ *
+ *
+ *----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
+ * Gmail: blackhedd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of either: 1) the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version; or 2) Ruby's License.
+ *
+ * See the file COPYING for complete licensing information.
+ *
+ *---------------------------------------------------------------------------
+ *
+ *
+ */
+
+package com.rubyeventmachine;
+
+/**
+ * @author francis
+ *
+ */
+public class EmReactorException extends Exception {
+ static final long serialVersionUID = 0;
+ public EmReactorException (String msg) {
+ super (msg);
+ }
+}
diff --git a/vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java/src/com/rubyeventmachine/EventableChannel.java b/vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java/src/com/rubyeventmachine/EventableChannel.java
new file mode 100644
index 0000000..3d4f5fd
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java/src/com/rubyeventmachine/EventableChannel.java
@@ -0,0 +1,72 @@
+/**
+ * $Id$
+ *
+ * Author:: Francis Cianfrocca (gmail: blackhedd)
+ * Homepage:: http://rubyeventmachine.com
+ * Date:: 15 Jul 2007
+ *
+ * See EventMachine and EventMachine::Connection for documentation and
+ * usage examples.
+ *
+ *
+ *----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
+ * Gmail: blackhedd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of either: 1) the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version; or 2) Ruby's License.
+ *
+ * See the file COPYING for complete licensing information.
+ *
+ *---------------------------------------------------------------------------
+ *
+ *
+ */
+
+
+package com.rubyeventmachine;
+
+import java.nio.ByteBuffer;
+import java.io.IOException;
+import java.nio.channels.ClosedChannelException;
+
+public interface EventableChannel {
+
+ public void scheduleOutboundData (ByteBuffer bb);
+
+ public void scheduleOutboundDatagram (ByteBuffer bb, String recipAddress, int recipPort);
+
+ public boolean scheduleClose (boolean afterWriting);
+
+ public void startTls();
+
+ public long getBinding();
+
+ public void readInboundData (ByteBuffer dst) throws IOException;
+
+ public void register() throws ClosedChannelException;
+
+ /**
+ * This is called by the reactor after it finishes running.
+ * The idea is to free network resources.
+ */
+ public void close();
+
+ public boolean writeOutboundData() throws IOException;
+
+ public long getOutboundDataSize();
+
+ public void setCommInactivityTimeout (long seconds);
+
+ public Object[] getPeerName();
+ public Object[] getSockName();
+
+ public boolean isWatchOnly();
+
+ public boolean isNotifyReadable();
+ public boolean isNotifyWritable();
+
+}
diff --git a/vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java/src/com/rubyeventmachine/EventableDatagramChannel.java b/vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java/src/com/rubyeventmachine/EventableDatagramChannel.java
new file mode 100644
index 0000000..df1c9fd
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java/src/com/rubyeventmachine/EventableDatagramChannel.java
@@ -0,0 +1,201 @@
+/**
+ * $Id$
+ *
+ * Author:: Francis Cianfrocca (gmail: blackhedd)
+ * Homepage:: http://rubyeventmachine.com
+ * Date:: 15 Jul 2007
+ *
+ * See EventMachine and EventMachine::Connection for documentation and
+ * usage examples.
+ *
+ *
+ *----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
+ * Gmail: blackhedd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of either: 1) the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version; or 2) Ruby's License.
+ *
+ * See the file COPYING for complete licensing information.
+ *
+ *---------------------------------------------------------------------------
+ *
+ *
+ */
+
+
+package com.rubyeventmachine;
+
+import java.nio.ByteBuffer;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.DatagramChannel;
+import java.util.LinkedList;
+import java.io.*;
+import java.net.*;
+
+public class EventableDatagramChannel implements EventableChannel {
+
+ class Packet {
+ public ByteBuffer bb;
+ public SocketAddress recipient;
+ public Packet (ByteBuffer _bb, SocketAddress _recipient) {
+ bb = _bb;
+ recipient = _recipient;
+ }
+ }
+
+ DatagramChannel channel;
+ long binding;
+ Selector selector;
+ boolean bCloseScheduled;
+ LinkedList<Packet> outboundQ;
+ long outboundS;
+ SocketAddress returnAddress;
+
+
+ public EventableDatagramChannel (DatagramChannel dc, long _binding, Selector sel) throws ClosedChannelException {
+ channel = dc;
+ binding = _binding;
+ selector = sel;
+ bCloseScheduled = false;
+ outboundQ = new LinkedList<Packet>();
+ outboundS = 0;
+
+ dc.register(selector, SelectionKey.OP_READ, this);
+ }
+
+ public void scheduleOutboundData (ByteBuffer bb) {
+ try {
+ if ((!bCloseScheduled) && (bb.remaining() > 0)) {
+ outboundQ.addLast(new Packet(bb, returnAddress));
+ outboundS += bb.remaining();
+ channel.register(selector, SelectionKey.OP_WRITE | SelectionKey.OP_READ, this);
+ }
+ } catch (ClosedChannelException e) {
+ throw new RuntimeException ("no outbound data");
+ }
+ }
+
+ public void scheduleOutboundDatagram (ByteBuffer bb, String recipAddress, int recipPort) {
+ try {
+ if ((!bCloseScheduled) && (bb.remaining() > 0)) {
+ outboundQ.addLast(new Packet (bb, new InetSocketAddress (recipAddress, recipPort)));
+ outboundS += bb.remaining();
+ channel.register(selector, SelectionKey.OP_WRITE | SelectionKey.OP_READ, this);
+ }
+ } catch (ClosedChannelException e) {
+ throw new RuntimeException ("no outbound data");
+ }
+ }
+
+ public boolean scheduleClose (boolean afterWriting) {
+ System.out.println ("NOT SCHEDULING CLOSE ON DATAGRAM");
+ return false;
+ }
+
+ public void startTls() {
+ throw new RuntimeException ("TLS is unimplemented on this Channel");
+ }
+
+ public long getBinding() {
+ return binding;
+ }
+
+ public void register() throws ClosedChannelException {
+ // TODO
+ }
+
+ /**
+ * Terminate with extreme prejudice. Don't assume there will be another pass through
+ * the reactor core.
+ */
+ public void close() {
+ try {
+ channel.close();
+ } catch (IOException e) {
+ }
+ }
+
+ public void readInboundData (ByteBuffer dst) {
+ returnAddress = null;
+ try {
+ // If there is no datagram available (we're nonblocking after all),
+ // then channel.receive returns null.
+ returnAddress = channel.receive(dst);
+ } catch (IOException e) {
+ // probably a no-op. The caller will see the empty (or even partial) buffer
+ // and presumably do the right thing.
+ }
+ }
+
+ public boolean writeOutboundData() {
+ while (!outboundQ.isEmpty()) {
+ Packet p = outboundQ.getFirst();
+ int written = 0;
+ try {
+ // With a datagram socket, it's ok to send an empty buffer.
+ written = channel.send(p.bb, p.recipient);
+ outboundS -= written;
+ }
+ catch (IOException e) {
+ return false;
+ }
+
+ /* Did we consume the whole outbound buffer? If yes, pop it off and
+ * keep looping. If no, the outbound network buffers are full, so break
+ * out of here. There's a flaw that affects outbound buffers that are intentionally
+ * empty. We can tell whether they got sent or not. So we assume they were.
+ * TODO: As implemented, this ALWAYS discards packets if they were at least
+ * partially written. This matches the behavior of the C++ EM. My judgment
+ * is that this is less surprising than fragmenting the data and sending multiple
+ * packets would be. I could be wrong, so this is subject to change.
+ */
+
+ if ((written > 0) || (p.bb.remaining() == 0))
+ outboundQ.removeFirst();
+ else
+ break;
+ }
+
+ if (outboundQ.isEmpty()) {
+ try {
+ channel.register(selector, SelectionKey.OP_READ, this);
+ } catch (ClosedChannelException e) {}
+ }
+
+ // ALWAYS drain the outbound queue before triggering a connection close.
+ // If anyone wants to close immediately, they're responsible for clearing
+ // the outbound queue.
+ return (bCloseScheduled && outboundQ.isEmpty()) ? false : true;
+ }
+
+ public void setCommInactivityTimeout (long seconds) {
+ // TODO
+ System.out.println ("DATAGRAM: SET COMM INACTIVITY UNIMPLEMENTED " + seconds);
+ }
+
+ public Object[] getPeerName () {
+ if (returnAddress != null) {
+ InetSocketAddress inetAddr = (InetSocketAddress) returnAddress;
+ return new Object[]{ inetAddr.getPort(), inetAddr.getHostName() };
+ } else {
+ return null;
+ }
+ }
+
+ public Object[] getSockName () {
+ DatagramSocket socket = channel.socket();
+ return new Object[]{ socket.getLocalPort(),
+ socket.getLocalAddress().getHostAddress() };
+ }
+
+ public boolean isWatchOnly() { return false; }
+ public boolean isNotifyReadable() { return false; }
+ public boolean isNotifyWritable() { return false; }
+ public long getOutboundDataSize() { return outboundS; }
+}
diff --git a/vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java/src/com/rubyeventmachine/EventableSocketChannel.java b/vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java/src/com/rubyeventmachine/EventableSocketChannel.java
new file mode 100644
index 0000000..2905ec6
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/java/src/com/rubyeventmachine/EventableSocketChannel.java
@@ -0,0 +1,415 @@
+/**
+ * $Id$
+ *
+ * Author:: Francis Cianfrocca (gmail: blackhedd)
+ * Homepage:: http://rubyeventmachine.com
+ * Date:: 15 Jul 2007
+ *
+ * See EventMachine and EventMachine::Connection for documentation and
+ * usage examples.
+ *
+ *
+ *----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
+ * Gmail: blackhedd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of either: 1) the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version; or 2) Ruby's License.
+ *
+ * See the file COPYING for complete licensing information.
+ *
+ *---------------------------------------------------------------------------
+ *
+ *
+ */
+
+/**
+ *
+ */
+package com.rubyeventmachine;
+
+/**
+ * @author francis
+ *
+ */
+
+import java.nio.channels.*;
+import java.nio.*;
+import java.util.*;
+import java.io.*;
+import java.net.Socket;
+import javax.net.ssl.*;
+import javax.net.ssl.SSLEngineResult.*;
+import java.lang.reflect.Field;
+
+import java.security.*;
+
+public class EventableSocketChannel implements EventableChannel {
+ Selector selector;
+ SelectionKey channelKey;
+ SocketChannel channel;
+
+ long binding;
+ LinkedList<ByteBuffer> outboundQ;
+ long outboundS;
+
+ boolean bCloseScheduled;
+ boolean bConnectPending;
+ boolean bWatchOnly;
+ boolean bAttached;
+ boolean bNotifyReadable;
+ boolean bNotifyWritable;
+ boolean bPaused;
+
+ SSLEngine sslEngine;
+ SSLContext sslContext;
+
+ public EventableSocketChannel (SocketChannel sc, long _binding, Selector sel) {
+ channel = sc;
+ binding = _binding;
+ selector = sel;
+ bCloseScheduled = false;
+ bConnectPending = false;
+ bWatchOnly = false;
+ bAttached = false;
+ bNotifyReadable = false;
+ bNotifyWritable = false;
+ outboundQ = new LinkedList<ByteBuffer>();
+ outboundS = 0;
+ }
+
+ public long getBinding() {
+ return binding;
+ }
+
+ public SocketChannel getChannel() {
+ return channel;
+ }
+
+ public void register() throws ClosedChannelException {
+ if (channelKey == null) {
+ int events = currentEvents();
+ channelKey = channel.register(selector, events, this);
+ }
+ }
+
+ /**
+ * Terminate with extreme prejudice. Don't assume there will be another pass through
+ * the reactor core.
+ */
+ public void close() {
+ if (channelKey != null) {
+ channelKey.cancel();
+ channelKey = null;
+ }
+
+ if (bAttached) {
+ // attached channels are copies, so reset the file descriptor to prevent java from close()ing it
+ Field f;
+ FileDescriptor fd;
+
+ try {
+ /* do _NOT_ clobber fdVal here, it will break epoll/kqueue on jdk6!
+ * channelKey.cancel() above does not occur until the next call to select
+ * and if fdVal is gone, we will continue to get events for this fd.
+ *
+ * instead, remove fdVal in cleanup(), which is processed via DetachedConnections,
+ * after UnboundConnections but before NewConnections.
+ */
+
+ f = channel.getClass().getDeclaredField("fd");
+ f.setAccessible(true);
+ fd = (FileDescriptor) f.get(channel);
+
+ f = fd.getClass().getDeclaredField("fd");
+ f.setAccessible(true);
+ f.set(fd, -1);
+ } catch (java.lang.NoSuchFieldException e) {
+ e.printStackTrace();
+ } catch (java.lang.IllegalAccessException e) {
+ e.printStackTrace();
+ }
+
+ return;
+ }
+
+ try {
+ channel.close();
+ } catch (IOException e) {
+ }
+ }
+
+ public void cleanup() {
+ if (bAttached) {
+ Field f;
+ try {
+ f = channel.getClass().getDeclaredField("fdVal");
+ f.setAccessible(true);
+ f.set(channel, -1);
+ } catch (java.lang.NoSuchFieldException e) {
+ e.printStackTrace();
+ } catch (java.lang.IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ channel = null;
+ }
+
+ public void scheduleOutboundData (ByteBuffer bb) {
+ if (!bCloseScheduled && bb.remaining() > 0) {
+ if (sslEngine != null) {
+ try {
+ ByteBuffer b = ByteBuffer.allocate(32*1024); // TODO, preallocate this buffer.
+ sslEngine.wrap(bb, b);
+ b.flip();
+ outboundQ.addLast(b);
+ outboundS += b.remaining();
+ } catch (SSLException e) {
+ throw new RuntimeException ("ssl error");
+ }
+ }
+ else {
+ outboundQ.addLast(bb);
+ outboundS += bb.remaining();
+ }
+
+ updateEvents();
+ }
+ }
+
+ public void scheduleOutboundDatagram (ByteBuffer bb, String recipAddress, int recipPort) {
+ throw new RuntimeException ("datagram sends not supported on this channel");
+ }
+
+ /**
+ * Called by the reactor when we have selected readable.
+ */
+ public void readInboundData (ByteBuffer bb) throws IOException {
+ if (channel.read(bb) == -1)
+ throw new IOException ("eof");
+ }
+
+ public long getOutboundDataSize() { return outboundS; }
+
+ /**
+ * Called by the reactor when we have selected writable.
+ * Return false to indicate an error that should cause the connection to close.
+ * TODO, VERY IMPORTANT: we're here because we selected writable, but it's always
+ * possible to become unwritable between the poll and when we get here. The way
+ * this code is written, we're depending on a nonblocking write NOT TO CONSUME
+ * the whole outbound buffer in this case, rather than firing an exception.
+ * We should somehow verify that this is indeed Java's defined behavior.
+ * @return
+ */
+ public boolean writeOutboundData() throws IOException {
+ ByteBuffer[] bufs = new ByteBuffer[64];
+ int i;
+ long written, toWrite;
+ while (!outboundQ.isEmpty()) {
+ i = 0;
+ toWrite = 0;
+ written = 0;
+ while (i < 64 && !outboundQ.isEmpty()) {
+ bufs[i] = outboundQ.removeFirst();
+ toWrite += bufs[i].remaining();
+ i++;
+ }
+ if (toWrite > 0)
+ written = channel.write(bufs, 0, i);
+
+ outboundS -= written;
+ // Did we consume the whole outbound buffer? If yes,
+ // pop it off and keep looping. If no, the outbound network
+ // buffers are full, so break out of here.
+ if (written < toWrite) {
+ while (i > 0 && bufs[i-1].remaining() > 0) {
+ outboundQ.addFirst(bufs[i-1]);
+ i--;
+ }
+ break;
+ }
+ }
+
+ if (outboundQ.isEmpty() && !bCloseScheduled) {
+ updateEvents();
+ }
+
+ // ALWAYS drain the outbound queue before triggering a connection close.
+ // If anyone wants to close immediately, they're responsible for clearing
+ // the outbound queue.
+ return (bCloseScheduled && outboundQ.isEmpty()) ? false : true;
+ }
+
+ public void setConnectPending() {
+ bConnectPending = true;
+ updateEvents();
+ }
+
+ /**
+ * Called by the reactor when we have selected connectable.
+ * Return false to indicate an error that should cause the connection to close.
+ */
+ public boolean finishConnecting() throws IOException {
+ channel.finishConnect();
+
+ bConnectPending = false;
+ updateEvents();
+ return true;
+ }
+
+ public boolean scheduleClose (boolean afterWriting) {
+ // TODO: What the hell happens here if bConnectPending is set?
+ if (!afterWriting) {
+ outboundQ.clear();
+ outboundS = 0;
+ }
+
+ if (outboundQ.isEmpty())
+ return true;
+ else {
+ updateEvents();
+ bCloseScheduled = true;
+ return false;
+ }
+ }
+
+ public void startTls() {
+ if (sslEngine == null) {
+ try {
+ sslContext = SSLContext.getInstance("TLS");
+ sslContext.init(null, null, null); // TODO, fill in the parameters.
+ sslEngine = sslContext.createSSLEngine(); // TODO, should use the parameterized version, to get Kerb stuff and session re-use.
+ sslEngine.setUseClientMode(false);
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException ("unable to start TLS"); // TODO, get rid of this.
+ } catch (KeyManagementException e) {
+ throw new RuntimeException ("unable to start TLS"); // TODO, get rid of this.
+ }
+ }
+ System.out.println ("Starting TLS");
+ }
+
+ public ByteBuffer dispatchInboundData (ByteBuffer bb) throws SSLException {
+ if (sslEngine != null) {
+ if (true) throw new RuntimeException ("TLS currently unimplemented");
+ System.setProperty("javax.net.debug", "all");
+ ByteBuffer w = ByteBuffer.allocate(32*1024); // TODO, WRONG, preallocate this buffer.
+ SSLEngineResult res = sslEngine.unwrap(bb, w);
+ if (res.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
+ Runnable r;
+ while ((r = sslEngine.getDelegatedTask()) != null) {
+ r.run();
+ }
+ }
+ System.out.println (bb);
+ w.flip();
+ return w;
+ }
+ else
+ return bb;
+ }
+
+ public void setCommInactivityTimeout (long seconds) {
+ // TODO
+ System.out.println ("SOCKET: SET COMM INACTIVITY UNIMPLEMENTED " + seconds);
+ }
+
+ public Object[] getPeerName () {
+ Socket sock = channel.socket();
+ return new Object[]{ sock.getPort(), sock.getInetAddress().getHostAddress() };
+ }
+
+ public Object[] getSockName () {
+ Socket sock = channel.socket();
+ return new Object[]{ sock.getLocalPort(),
+ sock.getLocalAddress().getHostAddress() };
+ }
+
+ public void setWatchOnly() {
+ bWatchOnly = true;
+ updateEvents();
+ }
+ public boolean isWatchOnly() { return bWatchOnly; }
+
+ public void setAttached() {
+ bAttached = true;
+ }
+ public boolean isAttached() { return bAttached; }
+
+ public void setNotifyReadable (boolean mode) {
+ bNotifyReadable = mode;
+ updateEvents();
+ }
+ public boolean isNotifyReadable() { return bNotifyReadable; }
+
+ public void setNotifyWritable (boolean mode) {
+ bNotifyWritable = mode;
+ updateEvents();
+ }
+ public boolean isNotifyWritable() { return bNotifyWritable; }
+
+ public boolean pause() {
+ if (bWatchOnly) {
+ throw new RuntimeException ("cannot pause/resume 'watch only' connections, set notify readable/writable instead");
+ }
+ boolean old = bPaused;
+ bPaused = true;
+ updateEvents();
+ return !old;
+ }
+
+ public boolean resume() {
+ if (bWatchOnly) {
+ throw new RuntimeException ("cannot pause/resume 'watch only' connections, set notify readable/writable instead");
+ }
+ boolean old = bPaused;
+ bPaused = false;
+ updateEvents();
+ return old;
+ }
+
+ public boolean isPaused() {
+ return bPaused;
+ }
+
+ private void updateEvents() {
+ if (channelKey == null)
+ return;
+
+ int events = currentEvents();
+
+ if (channelKey.interestOps() != events) {
+ channelKey.interestOps(events);
+ }
+ }
+
+ private int currentEvents() {
+ int events = 0;
+
+ if (bWatchOnly)
+ {
+ if (bNotifyReadable)
+ events |= SelectionKey.OP_READ;
+
+ if (bNotifyWritable)
+ events |= SelectionKey.OP_WRITE;
+ }
+ else if (!bPaused)
+ {
+ if (bConnectPending)
+ events |= SelectionKey.OP_CONNECT;
+ else {
+ events |= SelectionKey.OP_READ;
+
+ if (!outboundQ.isEmpty())
+ events |= SelectionKey.OP_WRITE;
+ }
+ }
+
+ return events;
+ }
+}