Advertisement
Guest User

Untitled

a guest
Jan 24th, 2018
62
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 23.16 KB | None | 0 0
  1. package multisoft.martv;
  2.  
  3. import android.content.res.AssetManager;
  4. import android.support.annotation.Nullable;
  5. import android.text.TextUtils;
  6. import android.util.Log;
  7.  
  8. import java.io.BufferedReader;
  9. import java.io.IOException;
  10. import java.io.InputStreamReader;
  11. import java.io.PrintStream;
  12. import java.net.DatagramSocket;
  13. import java.net.DatagramPacket;
  14. import java.net.InetAddress;
  15. import java.net.MulticastSocket;
  16. import java.net.ServerSocket;
  17. import java.net.Socket;
  18. import java.net.SocketException;
  19. import java.net.SocketTimeoutException;
  20. import java.net.UnknownHostException;
  21. import java.nio.ByteBuffer;
  22. import java.nio.ByteOrder;
  23. import java.util.concurrent.TimeoutException;
  24.  
  25. /**
  26. * Created by admin on 10/4/17.
  27. */
  28.  
  29. public class HTTPThread implements Runnable {
  30. private static final String TAG = "HTTPThread";
  31.  
  32. /**
  33. * The port number we listen to
  34. */
  35. private final int mPort;
  36.  
  37.  
  38. /**
  39. * The port number we listen to
  40. */
  41. private int bufferSizePkts = 4096;
  42. private int burstLen = 64;
  43.  
  44. /**
  45. * True if the server is running.
  46. */
  47. private boolean mIsRunning;
  48.  
  49. /**
  50. * number of recovery requests running.
  51. */
  52. private int numReqRunning;
  53. private int channelGlobalID;
  54. /**
  55. * The {@link java.net.ServerSocket} that we listen to.
  56. */
  57. private ServerSocket mServerSocket;
  58.  
  59. /**
  60. * Multicast socket and group
  61. */
  62. private MulticastSocket mcastSocket;
  63. private InetAddress group;
  64. /**
  65. * WebServer constructor.
  66. */
  67. public HTTPThread(int port) {
  68. mPort = port;
  69. }
  70.  
  71. /**
  72. * receive byuffer;
  73. */
  74. public byte[] mainBuffer = new byte[bufferSizePkts * 1316];
  75.  
  76. /**
  77. * This method starts the web server listening to the specified port.
  78. */
  79. public void start() {
  80. Log.i(TAG, "Starting HTTP Thread");
  81. mIsRunning = true;
  82. MainActivity.socketThread = new Thread(this);
  83. MainActivity.socketThread.start();
  84. new Thread(this).start();
  85. }
  86.  
  87. /**
  88. * This method stops the web server
  89. */
  90. public void stop() {
  91. try {
  92. mIsRunning = false;
  93. if (null != mServerSocket) {
  94. mServerSocket.close();
  95. mServerSocket = null;
  96. }
  97. if (null != mcastSocket){
  98. mcastSocket.leaveGroup(group);
  99. mcastSocket.close();
  100. }
  101. } catch (IOException e) {
  102. Log.e(TAG, "Error closing the server socket.", e);
  103. }
  104. }
  105.  
  106. private Socket acceptSocket;
  107. @Override
  108. public void run() {
  109. try {
  110. mServerSocket = new ServerSocket(mPort);
  111. while (mIsRunning) {
  112. //Log.d(TAG, "waiting for accept");
  113. acceptSocket = mServerSocket.accept();
  114.  
  115. mainBuffer = new byte[bufferSizePkts * 1316];
  116.  
  117. handle(acceptSocket);
  118. acceptSocket.close();
  119. //Log.d(TAG, "Finished request waiting for next " + mIsRunning);
  120. }
  121. } catch (SocketException e) {
  122. Log.e(TAG, "socket error.", e);
  123. } catch (IOException e) {
  124. Log.e(TAG, "Web server error.", e);
  125. } catch (Throwable t){
  126. Log.e(TAG, "Web server error.", t);
  127. try {
  128. Thread.sleep(10);
  129. } catch (InterruptedException e) {
  130. e.printStackTrace();
  131. }
  132. }
  133. }
  134.  
  135. /**
  136. * Respond to a request from a client.
  137. *
  138. * @param socket The client socket.
  139. * @throws IOException e
  140. */
  141. private void handle(Socket socket) throws IOException {
  142. BufferedReader reader = null;
  143. PrintStream output = null;
  144. try {
  145. String route = null;
  146.  
  147. // Read HTTP headers and parse out the route.
  148. reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
  149. String line;
  150. while (!TextUtils.isEmpty(line = reader.readLine())) {
  151. if (line.startsWith("GET /")) {
  152. int start = line.indexOf('/') + 1;
  153. int end = line.indexOf(' ', start);
  154. route = line.substring(start, end);
  155. break;
  156. }
  157. }
  158.  
  159. // Output stream that we send the response to
  160. output = new PrintStream(socket.getOutputStream());
  161.  
  162. // Prepare the content to send.
  163. if (null == route) {
  164. writeServerError(output);
  165. return;
  166. }
  167.  
  168. loadBufferedStreamThread(output, route);
  169.  
  170. } finally {
  171. if (null != output) {
  172. output.close();
  173. }
  174. if (null != reader) {
  175. reader.close();
  176. }
  177. }
  178. }
  179.  
  180. /**
  181. * Writes a server error response (HTTP/1.0 500) to the given output stream.
  182. *
  183. * @param output The output stream.
  184. */
  185. private void writeServerError(PrintStream output) {
  186. output.println("HTTP/1.0 500 Internal Server Error");
  187. output.flush();
  188. }
  189.  
  190. /**
  191. * Returns pktno from byte array, numbers are assigned on retransmiting server;
  192. */
  193. private long getPktNo(byte[] buf, int off) {
  194. ByteBuffer buffer = ByteBuffer.allocate(8);
  195. buffer.put(buf, off, 8);
  196. buffer.flip();
  197. buffer.order(ByteOrder.LITTLE_ENDIAN);
  198. return buffer.getLong();
  199. }
  200.  
  201. /**
  202. * writes value to byte array chaning endianness
  203. */
  204. private byte[] byteFlipLong(long data) {
  205. byte[] byteData = new byte[8];
  206. int i;
  207. for(i = 0; i < 8; i++){
  208. byteData[i] = (byte)(data >> (i * 8));
  209. }
  210. return byteData;
  211. }
  212.  
  213. /**
  214. * writes value to byte array chaning endianness
  215. */
  216. private byte[] byteFlipInt(int data) {
  217. byte[] byteData = new byte[4];
  218. int i;
  219. for(i = 0; i < 4; i++){
  220. byteData[i] = (byte)(data >> (i * 8));
  221. }
  222. return byteData;
  223. }
  224.  
  225. /**
  226. * Loads all the content of {@code fileName}.
  227. *
  228. * @param output The output stream.
  229. * @param route route string.
  230. */
  231. private String command;
  232. private int chId;
  233. private String recoveryList;
  234. private String groupUri;
  235. private int groupPort;
  236.  
  237. private void getVariables(PrintStream output, String route){
  238. Log.i(TAG, "Got route: " + route);
  239.  
  240. int start = 0;
  241. int end = route.indexOf('?');
  242.  
  243. if(end == -1){
  244. writeServerError(output);
  245. return;
  246. }
  247.  
  248. command = route.substring(start, end);
  249.  
  250. start = route.indexOf('=') + 1;
  251. end = route.indexOf('&');
  252.  
  253. if(start == -1 || end == -1){
  254. writeServerError(output);
  255. return;
  256. }
  257.  
  258. chId = Integer.parseInt(route.substring(start, end));
  259.  
  260. start = route.indexOf('=', start + 1) + 1;
  261. end = route.indexOf('&', end + 1 );
  262.  
  263. if(start == -1 || end == -1){
  264. writeServerError(output);
  265. return;
  266. }
  267.  
  268. String uri = route.substring(start, end);
  269.  
  270. start = route.indexOf('=', start + 1) + 1;
  271. end = route.length();
  272.  
  273. if(start == -1 || end == -1){
  274. writeServerError(output);
  275. return;
  276. }
  277.  
  278. recoveryList = route.substring(start, end);
  279.  
  280. start = uri.indexOf('/') + 2;
  281. end = uri.indexOf(':', start);
  282.  
  283. groupUri = uri.substring(start, end);
  284. groupPort = Integer.parseInt(uri.substring(end + 1, uri.length()));
  285. Log.i(TAG, "Channel id: " + chId + "; Uri for said channel: " + groupUri + "; List of recovery servers: " + recoveryList);
  286. }
  287.  
  288. /**
  289. * Requests initial burst of buffer
  290. *
  291. * @param chID stream id
  292. * @param start expected sequence
  293. * @param end received sequence
  294. * @param recoveryList list of recovery servers
  295. * @return recovered pkts
  296. * @throws IOException e
  297. */
  298.  
  299. private long burstLast = 0;
  300. private int burst(int chID, long start, long end, String recoveryList) throws IOException {
  301.  
  302. String primaryRecovery = recoveryList.substring(0, recoveryList.indexOf(';', 0));
  303. InetAddress recoveryAddress = InetAddress.getByName(primaryRecovery);
  304. DatagramSocket recoverySocket = new DatagramSocket();
  305.  
  306. byte[] sendData = new byte[37];
  307. byte[] tmpb = byteFlipInt(chID);
  308. System.arraycopy(tmpb, 0, sendData, 0 ,4);
  309.  
  310. tmpb = byteFlipLong(start);
  311. System.arraycopy(tmpb, 0, sendData, 4 ,8);
  312.  
  313. tmpb = byteFlipLong(end);
  314. System.arraycopy(tmpb, 0, sendData, 12 ,8);
  315.  
  316. String mac = Utils.getMacAddress();
  317. byte yleoba[] = mac.getBytes();
  318.  
  319. for(int bi = 20, z = 0; bi < 37; bi++, z++){
  320. sendData[bi] = yleoba[z];
  321. }
  322.  
  323. //Log.d(TAG, "Sending " + Utils.bytesToHex(sendData));
  324.  
  325. DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, recoveryAddress, 16969);
  326. recoverySocket.send(sendPacket);
  327.  
  328. //Log.d(TAG, "start " + start + " end " + end);
  329.  
  330. long bytesToRecv = bufferSizePkts * 1316;
  331. if(end > 0 ){
  332. bytesToRecv = end * 1316;
  333. }
  334.  
  335. //Log.d(TAG, "Excepcting " + end + " pkts " + bytesToRecv * 1316 + " bvtes ");
  336.  
  337. byte[] receiveData = new byte[1316];
  338. DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
  339. recoverySocket.setSoTimeout(100);
  340.  
  341. int recLen = 0;
  342. while(recLen < bytesToRecv){
  343. try {
  344. recoverySocket.receive(receivePacket);
  345. recLen += receivePacket.getLength();
  346.  
  347. byte[] tmp = receivePacket.getData();
  348. long RecoveredPktNo = getPktNo(tmp, 1133);
  349. //Log.d(TAG, "Initial Burst: recovered pkt" + Utils.bytesToHex(tmp));
  350.  
  351. if(RecoveredPktNo < 0 || RecoveredPktNo >= bufferSizePkts){
  352. Log.e(TAG, "Initial Burst: Recvd damaged pkt should recover this separately " + RecoveredPktNo + Utils.bytesToHex(tmp));
  353. continue;
  354. }
  355.  
  356. int offset = (int)(1316 * RecoveredPktNo);
  357. Log.i(TAG, "Initial Burst: Writing recovered pkt no " + RecoveredPktNo + " at offset " + offset);
  358.  
  359. System.arraycopy(tmp, 0, mainBuffer, offset, 1316);
  360. burstLast = getPktNo(tmp, 1133);
  361. }catch (Throwable te) {
  362. Log.e(TAG, "Failed to recv initial burst ", te);
  363. break;
  364. }
  365. }
  366.  
  367. if(recLen == bytesToRecv){
  368. //Log.d(TAG, "Burst: recvd " + receivePacket.getLength() + " bytes");
  369. }else{
  370. //Log.d(TAG, "Burst: recvd wrong" + receivePacket.getLength());
  371. }
  372. return recLen;
  373. }
  374.  
  375. /*
  376. * recovewry thread lass
  377. */
  378. private class recoverThread implements Runnable {
  379. int chID;
  380. long startPktNo;
  381. long endPktNo;
  382. String recoveryList;
  383.  
  384. public recoverThread(int tchID, long tstart, long tend, String trecoveryList){
  385. chID = tchID;
  386. channelGlobalID = chID;
  387. startPktNo = tstart;
  388. endPktNo = tend;
  389. recoveryList = trecoveryList;
  390. }
  391.  
  392. @Override
  393. public void run() {
  394. String primaryRecovery = recoveryList.substring(0, recoveryList.indexOf(';', 0));
  395.  
  396. try {
  397. while(numReqRunning > 5){
  398. Thread.sleep(50);
  399. if(numReqRunning > 15){
  400. return;
  401. }
  402. }
  403. if(chID != channelGlobalID){
  404. Log.e(TAG, "channel changed while waiting");
  405. return;
  406. }
  407.  
  408.  
  409. InetAddress recoveryAddress = InetAddress.getByName(primaryRecovery);
  410.  
  411. DatagramSocket recoverySocket = new DatagramSocket();
  412.  
  413. byte[] sendData = new byte[37];
  414. byte[] tmpb = byteFlipInt(chID);
  415. System.arraycopy(tmpb, 0, sendData, 0 ,4);
  416.  
  417. tmpb = byteFlipLong(startPktNo);
  418. System.arraycopy(tmpb, 0, sendData, 4 ,8);
  419.  
  420. tmpb = byteFlipLong(endPktNo);
  421. System.arraycopy(tmpb, 0, sendData, 12 ,8);
  422.  
  423. String mac = Utils.getMacAddress();
  424. byte yleoba[] = mac.getBytes();
  425.  
  426. for (int bi = 20, z = 0; bi < 37; bi++, z++) {
  427. sendData[bi] = yleoba[z];
  428. }
  429.  
  430. //Log.d(TAG, "Req id: " + startPktNo + " Sending " + Utils.bytesToHex(sendData));
  431.  
  432. DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, recoveryAddress, 16969);
  433. try {
  434. recoverySocket.send(sendPacket);
  435. }catch (IOException ie){
  436. Log.e(TAG, "Req id: " + startPktNo + " IO error");
  437. return;
  438. }
  439.  
  440. //Log.d(TAG, "Req id: " + startPktNo + " start " + startPktNo + " end " + endPktNo);
  441.  
  442. long bytesToRecv;
  443. if (startPktNo > endPktNo) {
  444. bytesToRecv = ((bufferSizePkts - startPktNo) + endPktNo);
  445. } else {
  446. bytesToRecv = endPktNo - startPktNo;
  447. }
  448.  
  449. Log.i(TAG, "Req id: " + startPktNo + " Excepcting " + bytesToRecv + " pkts " + bytesToRecv * 1316 + " bvtes ");
  450.  
  451. bytesToRecv = bytesToRecv * 1316;
  452.  
  453. byte[] receiveData = new byte[1316];
  454. DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
  455. recoverySocket.setSoTimeout(50);
  456.  
  457. int recLen = 0;
  458. int retries = 0;
  459. long RecoveredPktNo = -1;
  460. while(recLen < bytesToRecv){
  461. try {
  462. recoverySocket.receive(receivePacket);
  463. recLen += receivePacket.getLength();
  464.  
  465. byte[] tmp = receivePacket.getData();
  466. RecoveredPktNo = getPktNo(tmp, 1133);
  467. //Log.d(TAG, "Req id: " + startPktNo + " recovered pkt" + Utils.bytesToHex(tmp));
  468.  
  469. if(RecoveredPktNo < 0 || RecoveredPktNo >= bufferSizePkts){
  470. Log.e(TAG, "Req id: " + startPktNo + " Recvd damaged pkt should recover this separately " + RecoveredPktNo + Utils.bytesToHex(tmp));
  471. continue;
  472. }
  473.  
  474. int offset = (int)(1316 * RecoveredPktNo);
  475. Log.i(TAG, "Req id: " + startPktNo + " Writing recovered pkt no " + RecoveredPktNo + " at offset " + offset);
  476.  
  477. System.arraycopy(tmp, 0, mainBuffer, offset, 1316);
  478. if(RecoveredPktNo == endPktNo -1){
  479. break;
  480. }
  481. }catch (Throwable te) {
  482. if(RecoveredPktNo == endPktNo){break;}
  483. if(RecoveredPktNo == -1){RecoveredPktNo = startPktNo;}
  484. retries += 1;
  485. recLen = 0;
  486. if(retries >= 4){
  487. break;
  488. }
  489. Log.e(TAG, "Req id: " + startPktNo + " Timeout retry number " + retries + " retrying from " + RecoveredPktNo);
  490. sendData = new byte[37];
  491. tmpb = byteFlipInt(chID);
  492. System.arraycopy(tmpb, 0, sendData, 0 ,4);
  493.  
  494. tmpb = byteFlipLong(RecoveredPktNo);
  495. System.arraycopy(tmpb, 0, sendData, 4 ,8);
  496.  
  497. tmpb = byteFlipLong(endPktNo);
  498. System.arraycopy(tmpb, 0, sendData, 12 ,8);
  499.  
  500. for (int bi = 20, z = 0; bi < 37; bi++, z++) {
  501. sendData[bi] = yleoba[z];
  502. }
  503.  
  504. //Log.d(TAG, "Req id: " + startPktNo + " Sending " + Utils.bytesToHex(sendData));
  505.  
  506. sendPacket = new DatagramPacket(sendData, sendData.length, recoveryAddress, 16969);
  507. try {
  508. recoverySocket.send(sendPacket);
  509. }catch (IOException ie){
  510. Log.e(TAG, "Req id: " + startPktNo + " IO error");
  511. return;
  512. }
  513. }
  514. }
  515.  
  516. if (recLen == bytesToRecv) {
  517. Log.i(TAG, "Req id: " + startPktNo + " recvd " + recLen + " bytes");
  518. } else {
  519. Log.e(TAG, "Req id: " + startPktNo + " recvd smthn wierd " + recLen);
  520. }
  521. }catch (SocketException e){
  522. Log.e(TAG, "Req id: " + startPktNo + " cannot create socket", e);
  523. }catch (UnknownHostException he){
  524. Log.e(TAG, "Req id: " + startPktNo + " what host ", he);
  525. }catch (Throwable e){
  526. Log.e(TAG, "Exception ", e);
  527. }
  528. numReqRunning -= 1;
  529. }
  530. }
  531.  
  532. /**
  533. * Loads all the content of {@code fileName}.
  534. *
  535. * @param output The output stream.
  536. * @throws IOException e
  537. */
  538. private void loadBufferedStreamThread(PrintStream output, String route) throws IOException {
  539. // Send out the content.
  540. // http://localhost:6969/live?ch=4&uri=udp://226.0.0.1:12345&recovery_list=recovery1.bintv.com;recovery2.bintv.com;
  541.  
  542. if(route.length() <= 1){
  543. writeServerError(output);
  544. return;
  545. }
  546.  
  547. getVariables(output, route);
  548.  
  549. group = InetAddress.getByName(groupUri);
  550. mcastSocket = new MulticastSocket(groupPort);
  551. mcastSocket.setSoTimeout(150);
  552.  
  553. int writeIndex = 0;
  554. int readIndex = 0;
  555. long prevPktNo = 0;
  556. long expectedPktNo;
  557. long buffPrevPktNo = 0;
  558. boolean checkDistance = true;
  559.  
  560. int recoveredLen = burst(chId, -1, 32, recoveryList);
  561. if(recoveredLen > 0){
  562. // if(acceptSocket.isConnected()){
  563. int offset = (int)(burstLast * 1316);
  564. // int start = (offset - recoveredLen);
  565. // if(start < 0){
  566. // Log.e(TAG, "No data recovered");
  567. // return;
  568. // }
  569. // output.write(mainBuffer, offset - recoveredLen, recoveredLen);
  570. // output.flush();
  571. //
  572. prevPktNo = burstLast;
  573. readIndex = offset;
  574. // }else{
  575. // //Log.d(TAG, "Not connected anymore not sending or receiving data");
  576. // return;
  577. // }
  578. }else{
  579. Log.e(TAG, "Burst failed");
  580. writeServerError(output);
  581. return;
  582. }
  583.  
  584. Log.i(TAG, "membership query start");
  585. try{
  586. mcastSocket.joinGroup(group);
  587. Log.i(TAG, "membership query end");
  588. }catch(Throwable e){
  589. writeServerError(output);
  590. Log.e(TAG, "Error joining ", e);
  591. return;
  592. }
  593.  
  594. byte[] recvBuf = new byte[1316];
  595. DatagramPacket recvPkt = new DatagramPacket(recvBuf, recvBuf.length);
  596.  
  597. output.println("HTTP/1.1 200 OK\r");
  598. output.println("Content-Type: application/octet-stream\r");
  599. output.println("\r");
  600. output.flush();
  601.  
  602. int numberOfDups = 0;
  603. while(mIsRunning){
  604.  
  605. try{
  606. mcastSocket.receive(recvPkt);
  607. }catch (SocketTimeoutException te){
  608. Log.e(TAG, "channel is dead");
  609. }catch(IOException e){
  610. writeServerError(output);
  611. Log.e(TAG, "IO exception", e);
  612. break;
  613. }
  614.  
  615. if(recvPkt.getLength() <= 0){
  616. Log.i(TAG, "No data recvd");
  617. continue;
  618. }
  619.  
  620. long pktNo = getPktNo(recvBuf, 1133);
  621. ////Log.d(TAG, "got pkt no " + pktNo + " write index " + writeIndex);
  622.  
  623. if(prevPktNo == pktNo){
  624. Log.e(TAG, "recvd duplicate");
  625. if(numberOfDups >= 10){
  626. Log.e(TAG, "too many dups could be all zeros");
  627. break;
  628. }
  629. numberOfDups += 1;
  630. continue;
  631. }
  632.  
  633. expectedPktNo = prevPktNo + 1;
  634. if(expectedPktNo == bufferSizePkts){
  635. expectedPktNo = 0;
  636. }
  637.  
  638. if(expectedPktNo != pktNo){
  639. Log.i(TAG, "Req id: " + expectedPktNo + " expected " + expectedPktNo + " got " + pktNo);
  640. new Thread(new recoverThread(chId, expectedPktNo, pktNo, recoveryList)).start();
  641. numReqRunning += 1;
  642. Log.i(TAG, "Req id: " + expectedPktNo + " created thread, number of current requests " + numReqRunning);
  643. }
  644.  
  645. prevPktNo = pktNo;
  646.  
  647. int pktLen = recvPkt.getLength();
  648. byte []pktData = recvPkt.getData();
  649.  
  650. writeIndex = (int)(1316 * pktNo);
  651.  
  652. System.arraycopy(pktData, 0, mainBuffer, writeIndex, pktLen);
  653.  
  654. if(checkDistance){
  655. readIndex = writeIndex - (burstLen * 1316);
  656. if(readIndex < 0 ){
  657. readIndex = (bufferSizePkts * 1316) + (readIndex);
  658. }
  659. checkDistance = false;
  660. }
  661.  
  662. if(acceptSocket.isConnected()){
  663. long buffPktNo = getPktNo(mainBuffer, readIndex + 1133);
  664. long buffExpectedPktNo = (buffPrevPktNo + 1);
  665. if(buffExpectedPktNo == bufferSizePkts){buffExpectedPktNo = 0;}
  666.  
  667. if(buffExpectedPktNo != buffPktNo){
  668. Log.e(TAG, "Expected " + (buffPrevPktNo + 1) + " from buffer got " + buffPktNo + " readindex " + readIndex);
  669. }else{
  670. output.write(mainBuffer, readIndex, pktLen);
  671. output.flush();
  672. //Log.d(TAG, "wrote pkt " + buffPktNo + " readindex " + readIndex);
  673. }
  674.  
  675. byte []tmp1 = new byte[1316];
  676. System.arraycopy(tmp1, 0, mainBuffer, readIndex, pktLen);
  677.  
  678. readIndex += pktLen;
  679.  
  680. if(readIndex == (bufferSizePkts * 1316)){
  681. readIndex = 0;
  682. }
  683. buffPrevPktNo = buffPktNo;
  684. }else{
  685. Log.i(TAG, "Not connected anymore not sending or receiving data");
  686. break;
  687. }
  688.  
  689. if(output.checkError()){
  690. Log.e(TAG, "Output error");
  691. break;
  692. }
  693. }
  694.  
  695. Log.i(TAG, "Leaving channel " + chId);
  696.  
  697. mcastSocket.leaveGroup(group);
  698. mcastSocket.close();
  699. mcastSocket = null;
  700. numReqRunning = 0;
  701. }
  702. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement