1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package com.intel.bluetooth.emu;
27
28 import java.io.IOException;
29 import java.io.InterruptedIOException;
30
31 import javax.bluetooth.BluetoothConnectionException;
32
33 import com.intel.bluetooth.DebugLog;
34 import com.intel.bluetooth.RemoteDeviceHelper;
35 import com.intel.bluetooth.Utils;
36
37
38
39
40 class ServiceListener {
41
42 private static final String RFCOMM_PREFIX = "rfcomm-";
43
44 private static final String L2CAP_PREFIX = "l2cap-";
45
46 private final String portID;
47
48 private boolean rfcomm;
49
50 private Object lock = new Object();
51
52 private Device serverDevice;
53
54 private static long connectionCount = 0;
55
56 private boolean connected = false;
57
58 private boolean closed = false;
59
60 private boolean interrupted = false;
61
62 private long connectionId = 0;
63
64 private int serverSecurityOpt;
65
66 private int serverReceiveMTU;
67
68 static String rfPrefix(int channel) {
69 return RFCOMM_PREFIX + channel;
70 }
71
72 static String l2Prefix(int pcm) {
73 return L2CAP_PREFIX + Integer.toHexString(pcm);
74 }
75
76 ServiceListener(String portID) {
77 this.portID = portID;
78 this.rfcomm = this.portID.startsWith(RFCOMM_PREFIX);
79 }
80
81 String getPortID() {
82 return this.portID;
83 }
84
85 long accept(Device serverDevice, boolean authenticate, boolean encrypt, int serverReceiveMTU) throws IOException {
86 this.serverDevice = serverDevice;
87 this.serverReceiveMTU = serverReceiveMTU;
88 this.serverSecurityOpt = Utils.securityOpt(authenticate, encrypt);
89
90 serverDevice.serviceListenerAccepting(getPortID());
91 while ((!closed) && (!interrupted) && (!connected)) {
92 synchronized (lock) {
93 try {
94 lock.wait();
95 } catch (InterruptedException e) {
96 throw new InterruptedIOException("accept interrupted");
97 }
98 }
99 }
100 if (closed || interrupted || !connected) {
101 throw new InterruptedIOException("accept closed");
102 }
103 return connectionId;
104 }
105
106 long connect(Device clientDevice, boolean authenticate, boolean encrypt, int cilentReceiveMTU, long timeout)
107 throws IOException {
108 ConnectionBuffer cb = null;
109 boolean clientConnected = false;
110 try {
111 int securityOpt = Utils.securityOpt(authenticate, encrypt);
112 if (this.serverSecurityOpt > securityOpt) {
113 securityOpt = this.serverSecurityOpt;
114 }
115
116 int bsize = DeviceManagerServiceImpl.configuration.getConnectionBufferSize();
117 boolean senderFlushBlock = DeviceManagerServiceImpl.configuration.isSenderFlushBlock();
118 ConnectedInputStream cis = new ConnectedInputStream(bsize, senderFlushBlock);
119 ConnectedOutputStream sos = new ConnectedOutputStream(cis);
120
121 ConnectedInputStream sis = new ConnectedInputStream(bsize, senderFlushBlock);
122 ConnectedOutputStream cos = new ConnectedOutputStream(sis);
123
124 ConnectionBuffer sb;
125 if (this.rfcomm) {
126 cb = new ConnectionBufferRFCOMM(serverDevice.getDescriptor().getAddress(), getPortID(), cis, cos);
127 sb = new ConnectionBufferRFCOMM(clientDevice.getDescriptor().getAddress(), getPortID(), sis, sos);
128 } else {
129 cb = new ConnectionBufferL2CAP(serverDevice.getDescriptor().getAddress(), getPortID(), cis, cos,
130 this.serverReceiveMTU);
131 sb = new ConnectionBufferL2CAP(clientDevice.getDescriptor().getAddress(), getPortID(), sis, sos,
132 cilentReceiveMTU);
133 }
134 cb.connect(sb);
135 cb.setSecurityOpt(securityOpt);
136 sb.setSecurityOpt(securityOpt);
137
138 sb.setServerSide(true);
139
140 long id;
141 synchronized (ServiceListener.class) {
142 connectionCount++;
143 id = connectionCount;
144 }
145 MonitorConnection monitor = new MonitorConnection(clientDevice.getDescriptor().getAddress(), serverDevice
146 .getDescriptor().getAddress(), getPortID(), id);
147 cb.setMonitor(monitor.getClientBuffer());
148 sb.setMonitor(monitor.getServerBuffer());
149
150 serverDevice.addConnectionBuffer(id, sb);
151 connectionId = id;
152 connected = true;
153 synchronized (lock) {
154 lock.notifyAll();
155 }
156 long endOfDellay = System.currentTimeMillis() + timeout;
157 while ((!sb.isServerAccepted()) && (!sb.isClosed())) {
158 long timeleft = endOfDellay - System.currentTimeMillis();
159 if (timeleft <= 0) {
160 throw new BluetoothConnectionException(BluetoothConnectionException.TIMEOUT, "Service "
161 + getPortID() + " not ready");
162 }
163 synchronized (sb) {
164 try {
165 sb.wait(timeleft);
166 } catch (InterruptedException e) {
167 throw new InterruptedIOException();
168 }
169 }
170 }
171 if (!sb.isServerAccepted()) {
172 throw new BluetoothConnectionException(BluetoothConnectionException.FAILED_NOINFO,
173 "Connection rejected");
174 }
175
176 MonitoringServiceImpl.registerConnection(monitor);
177 clientDevice.addConnectionBuffer(id, cb);
178 clientConnected = true;
179
180 StringBuffer logMsg = new StringBuffer();
181 logMsg.append(RemoteDeviceHelper.getBluetoothAddress(clientDevice.getDescriptor().getAddress()));
182 logMsg.append(" connected to ");
183 logMsg.append(RemoteDeviceHelper.getBluetoothAddress(serverDevice.getDescriptor().getAddress()));
184 logMsg.append(" ").append(this.getPortID());
185 DebugLog.debug(logMsg.toString());
186
187 return id;
188 } finally {
189 if (!connected) {
190 interrupted = true;
191 }
192 if (!clientConnected) {
193 cb.close();
194 }
195 synchronized (lock) {
196 lock.notifyAll();
197 }
198 }
199 }
200
201 void close() {
202 closed = true;
203 synchronized (lock) {
204 lock.notifyAll();
205 }
206 }
207 }