PageRenderTime 61ms CodeModel.GetById 37ms RepoModel.GetById 1ms app.codeStats 0ms

/src/PeerDeviceNet_Core/src/com/xconns/peerdevicenet/core/DiscoveryMulticastThread.java

https://bitbucket.org/yigongliu/peerdevicenet
Java | 236 lines | 173 code | 22 blank | 41 comment | 21 complexity | f75f24b89c29661e0c31a8eaa0001cf9 MD5 | raw file
  1. /*
  2. * Copyright (C) 2013 Yigong Liu, XCONNS, LLC
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.xconns.peerdevicenet.core;
  17. import java.io.IOException;
  18. import java.net.DatagramPacket;
  19. import java.net.InetAddress;
  20. import java.net.MulticastSocket;
  21. import java.net.SocketTimeoutException;
  22. import java.net.UnknownHostException;
  23. import java.util.concurrent.RejectedExecutionException;
  24. import java.util.concurrent.ScheduledFuture;
  25. import java.util.concurrent.TimeUnit;
  26. import android.net.wifi.WifiManager;
  27. import android.net.wifi.WifiManager.MulticastLock;
  28. import android.util.Log;
  29. import android.util.Pair;
  30. import com.xconns.peerdevicenet.DeviceInfo;
  31. import com.xconns.peerdevicenet.NetInfo;
  32. import com.xconns.peerdevicenet.utils.Utils;
  33. public class DiscoveryMulticastThread extends Thread {
  34. public static final String TAG = "MulticastScanThread";
  35. RouterService context = null;
  36. WifiManager wifi = null;
  37. Transport.SearchHandler handler = null;
  38. final byte[] MCAST_GROUP_ADDR = new byte[] { (byte) 224, (byte) 0,
  39. (byte) 121, (byte) 121 };
  40. final int MCAST_GROUP_PORT = 7383;
  41. final int BUFFER_SIZE = 1024;
  42. int timeout = 10000; // 10 seonds
  43. private ScheduledFuture<?> timerTask = null;
  44. private boolean canceled = false;
  45. private NetInfo netInfo = null;
  46. private DeviceInfo mDeviceInfo = null;
  47. //private HashMap<String, DeviceInfo> foundDevices = new HashMap<String, DeviceInfo>();
  48. private InetAddress groupAddress;
  49. private MulticastSocket bSocket;
  50. public DiscoveryMulticastThread(RouterService c, WifiManager w, NetInfo n,
  51. DeviceInfo dev, int t, Transport.SearchHandler h) {
  52. context = c;
  53. wifi = w;
  54. netInfo = n;
  55. mDeviceInfo = dev;
  56. timeout = t;
  57. handler = h;
  58. }
  59. public void stop_scan() {
  60. synchronized (this) {
  61. canceled = true;
  62. if (timerTask != null)
  63. timerTask.cancel(true);
  64. }
  65. if (bSocket != null)
  66. bSocket.close();
  67. }
  68. private MyTimerTask scanTask = null;
  69. class MyTimerTask implements Runnable {
  70. int count;
  71. int maxCount;
  72. byte[] addrInfo;
  73. public MyTimerTask(int c) {
  74. maxCount = c;
  75. count = 0;
  76. addrInfo = Utils.marshallDeviceInfoSSL(mDeviceInfo, context.useSSL);
  77. }
  78. @Override
  79. public void run() {
  80. Log.d(TAG, "mscan Timer task starts");
  81. try {
  82. // multicast my addr info
  83. DatagramPacket request = new DatagramPacket(addrInfo,
  84. addrInfo.length, groupAddress, MCAST_GROUP_PORT);
  85. bSocket.send(request);
  86. } catch (IOException e) {
  87. Log.e(TAG,
  88. "failed during multicast addr info: " + e.getMessage());
  89. stop_scan();
  90. } catch (Throwable t) {
  91. Log.e(TAG, "general exception inside mscan timer task", t);
  92. stop_scan();
  93. }
  94. count++;
  95. if (count >= maxCount) {
  96. Log.d(TAG, "10 sec passed, stop scanning");
  97. stop_scan();
  98. }
  99. }
  100. };
  101. public void run() {
  102. Log.d(TAG, "start_multicast_scan");
  103. boolean done = false;
  104. synchronized (this) {
  105. done = canceled;
  106. }
  107. if (!done) {
  108. try {
  109. groupAddress = InetAddress.getByAddress(MCAST_GROUP_ADDR);
  110. } catch (UnknownHostException e) {
  111. Log.d(TAG, "cannot resolve multicast addr: " + e.getMessage());
  112. return;
  113. }
  114. /*
  115. * WifiManager wifi = (WifiManager) activity
  116. * .getSystemService(Context.WIFI_SERVICE);
  117. */
  118. MulticastLock multicastLock = wifi
  119. .createMulticastLock("MulticastScan");
  120. multicastLock.acquire();
  121. Log.d(TAG, "--1");
  122. try {
  123. bSocket = new MulticastSocket(MCAST_GROUP_PORT);
  124. // bSocket.setTimeToLive(2);
  125. bSocket.setSoTimeout(timeout);
  126. bSocket.setReuseAddress(true);
  127. bSocket.joinGroup(groupAddress);
  128. synchronized (this) {
  129. done = canceled;
  130. // start timer to multicast addr info
  131. if (!done) {
  132. scanTask = new MyTimerTask(timeout / 1000);
  133. try {
  134. timerTask = context.timer.schedule(scanTask, 1000L,
  135. TimeUnit.MILLISECONDS);
  136. }
  137. catch(RejectedExecutionException re) {
  138. Log.d(TAG, "failed to start scan timer2: "+re.getMessage());
  139. done = true;
  140. }
  141. catch(NullPointerException ne) {
  142. Log.d(TAG, "failed to start scan timer2: "+ne.getMessage());
  143. done = true;
  144. }
  145. }
  146. }
  147. if (!done) {
  148. // recv peer addresses
  149. byte[] buf = new byte[BUFFER_SIZE];
  150. DatagramPacket packet = new DatagramPacket(buf, buf.length);
  151. // Loop and try to receive responses until the timeout
  152. // elapses.
  153. // We'll get
  154. // back the packet we just sent out, which will be
  155. // discarded.
  156. try {
  157. while (true) {
  158. // zero the incoming buffer for good measure.
  159. java.util.Arrays.fill(buf, (byte) 0); // clear
  160. // buffer
  161. bSocket.receive(packet);
  162. if (packet.getData() != null
  163. && packet.getLength() > 0) {
  164. // Log.d(TAG, "raw_data="+new
  165. // String(packet.getData(), 0,
  166. // packet.getLength()));
  167. Pair<DeviceInfo, Boolean> pair = Utils.unmarshallDeviceInfoSSL(
  168. packet.getData(), packet.getLength());
  169. DeviceInfo dev = pair.first;
  170. boolean useSSL = pair.second;
  171. if (dev != null && dev.addr != null
  172. && dev.port != null) {
  173. Log.d(TAG, "recv multicast from "
  174. + dev.addr);
  175. if (!mDeviceInfo.addr.equals(dev.addr)) {
  176. /*
  177. if (foundDevices.size() > 0
  178. && foundDevices
  179. .containsKey(dev.addr))
  180. continue;
  181. */
  182. Log.d(TAG, "found new device: "
  183. + dev.name + " : " + dev.addr
  184. + " : " + dev.port);
  185. //foundDevices.put(dev.addr, dev);
  186. handler.onSearchFoundDevice(dev, useSSL);
  187. }
  188. } else {
  189. Log.e(TAG,
  190. "Multicast scan receive null device: "
  191. + dev.name + "," + dev.addr
  192. + "," + dev.port);
  193. }
  194. } else {
  195. Log.e(TAG, "Multicast scan receive null packet");
  196. }
  197. }
  198. } catch (SocketTimeoutException e) {
  199. Log.e(TAG, "Multicast scan receive timed out");
  200. }
  201. }
  202. } catch (IOException e) {
  203. Log.e(TAG,
  204. "socketc closed for multicast scan: " + e.getMessage());
  205. } finally {
  206. stop_scan();
  207. multicastLock.release();
  208. }
  209. }
  210. handler.onSearchComplete();
  211. Log.e(TAG, "multicast scan finished");
  212. return;
  213. }
  214. }