1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.transport.vmpipe;
21
22 import java.io.IOException;
23 import java.net.SocketAddress;
24 import java.util.HashSet;
25 import java.util.Set;
26
27 import org.apache.mina.common.AbstractIoConnector;
28 import org.apache.mina.common.ConnectFuture;
29 import org.apache.mina.common.DefaultConnectFuture;
30 import org.apache.mina.common.ExceptionMonitor;
31 import org.apache.mina.common.IdleStatusChecker;
32 import org.apache.mina.common.IoFilterChain;
33 import org.apache.mina.common.IoFuture;
34 import org.apache.mina.common.IoFutureListener;
35 import org.apache.mina.common.IoHandler;
36 import org.apache.mina.common.IoSessionInitializer;
37 import org.apache.mina.common.TransportMetadata;
38
39
40
41
42
43
44
45
46 public final class VmPipeConnector extends AbstractIoConnector {
47
48
49
50
51 public VmPipeConnector() {
52 super(new DefaultVmPipeSessionConfig());
53 }
54
55 public TransportMetadata getTransportMetadata() {
56 return VmPipeSessionImpl.METADATA;
57 }
58
59 @Override
60 public VmPipeSessionConfig getSessionConfig() {
61 return (VmPipeSessionConfig) super.getSessionConfig();
62 }
63
64 @Override
65 protected ConnectFuture connect0(SocketAddress remoteAddress,
66 SocketAddress localAddress,
67 IoSessionInitializer<? extends ConnectFuture> sessionInitializer) {
68 VmPipe entry = VmPipeAcceptor.boundHandlers.get(remoteAddress);
69 if (entry == null) {
70 return DefaultConnectFuture.newFailedFuture(new IOException(
71 "Endpoint unavailable: " + remoteAddress));
72 }
73
74 DefaultConnectFuture future = new DefaultConnectFuture();
75
76
77 VmPipeAddress actualLocalAddress;
78 try {
79 actualLocalAddress = nextLocalAddress();
80 } catch (IOException e) {
81 return DefaultConnectFuture.newFailedFuture(e);
82 }
83
84 VmPipeSessionImpl localSession = new VmPipeSessionImpl(this,
85 getListeners(), actualLocalAddress, getHandler(), entry);
86
87 finishSessionInitialization(localSession, future, sessionInitializer);
88
89
90 localSession.getCloseFuture().addListener(LOCAL_ADDRESS_RECLAIMER);
91
92
93 try {
94 IoFilterChain filterChain = localSession.getFilterChain();
95 this.getFilterChainBuilder().buildFilterChain(filterChain);
96
97
98 getListeners().fireSessionCreated(localSession);
99 IdleStatusChecker.getInstance().addSession(localSession);
100 } catch (Throwable t) {
101 future.setException(t);
102 return future;
103 }
104
105
106 VmPipeSessionImpl remoteSession = localSession.getRemoteSession();
107 ((VmPipeAcceptor) remoteSession.getService()).doFinishSessionInitialization(remoteSession, null);
108 try {
109 IoFilterChain filterChain = remoteSession.getFilterChain();
110 entry.getAcceptor().getFilterChainBuilder().buildFilterChain(
111 filterChain);
112
113
114 entry.getListeners().fireSessionCreated(remoteSession);
115 IdleStatusChecker.getInstance().addSession(remoteSession);
116 } catch (Throwable t) {
117 ExceptionMonitor.getInstance().exceptionCaught(t);
118 remoteSession.close();
119 }
120
121
122
123 ((VmPipeFilterChain) localSession.getFilterChain()).start();
124 ((VmPipeFilterChain) remoteSession.getFilterChain()).start();
125
126 return future;
127 }
128
129 @Override
130 protected IoFuture dispose0() throws Exception {
131 return null;
132 }
133
134 private static final Set<VmPipeAddress> TAKEN_LOCAL_ADDRESSES = new HashSet<VmPipeAddress>();
135
136 private static int nextLocalPort = -1;
137
138 private static final IoFutureListener<IoFuture> LOCAL_ADDRESS_RECLAIMER = new LocalAddressReclaimer();
139
140 private static VmPipeAddress nextLocalAddress() throws IOException {
141 synchronized (TAKEN_LOCAL_ADDRESSES) {
142 if (nextLocalPort >= 0) {
143 nextLocalPort = -1;
144 }
145 for (int i = 0; i < Integer.MAX_VALUE; i++) {
146 VmPipeAddress answer = new VmPipeAddress(nextLocalPort--);
147 if (!TAKEN_LOCAL_ADDRESSES.contains(answer)) {
148 TAKEN_LOCAL_ADDRESSES.add(answer);
149 return answer;
150 }
151 }
152 }
153
154 throw new IOException("Can't assign a local VM pipe port.");
155 }
156
157 private static class LocalAddressReclaimer implements IoFutureListener<IoFuture> {
158 public void operationComplete(IoFuture future) {
159 synchronized (TAKEN_LOCAL_ADDRESSES) {
160 TAKEN_LOCAL_ADDRESSES.remove(future.getSession()
161 .getLocalAddress());
162 }
163 }
164 }
165 }