/*
* Copyright 2012 The Stanford MobiSocial Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package mobisocial.musubi.nearby.broadcast;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.nio.ByteBuffer;
import mobisocial.musubi.model.helpers.IdentitiesManager;
import mobisocial.musubi.nearby.scanner.MulticastScannerTask;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
public class MulticastBroadcastTask extends AsyncTask<Void, Void, Void> {
private static final String TAG = "MulticastBroadcast";
private static MulticastBroadcastTask sInstance;
public static final int SEVEN_SECONDS = 7000;
public static final int THIRTY_SECONDS = 30000;
public static final int NO_RETRY = -1;
private InetAddress mNearbyGroup;
private MulticastSocket mSocket;
private final byte[] mBroadcastMsg;
private boolean mRunning;
private boolean mDone;
private final int mDuration;
private final int mWaitRetry;
/**
*
* @param context
* @param duration The number of ms to wait between broadcasts
* @param waitRetry After a failure, the number of ms to wait before retrying
*/
public MulticastBroadcastTask(Context context, int duration, int waitRetry) {
String requestStr = IdentitiesManager.uriForMyIBHashedIdentity().toString();
mBroadcastMsg = new byte[4 + requestStr.length()];
ByteBuffer buf = ByteBuffer.wrap(mBroadcastMsg);
buf.putInt(MulticastScannerTask.PROTOCOL_BROADCAST_URI);
buf.put(requestStr.getBytes());
mWaitRetry = waitRetry;
mDuration = duration;
}
public static MulticastBroadcastTask getInstance(Context context) {
if (sInstance == null || sInstance.mDone) {
sInstance = new MulticastBroadcastTask(context, SEVEN_SECONDS, NO_RETRY);
}
return sInstance;
}
@Override
protected void onPreExecute() {
try {
mRunning = true;
mDone = false;
mNearbyGroup = InetAddress.getByName(MulticastScannerTask.NEARBY_GROUP);
mSocket = new MulticastSocket(MulticastScannerTask.NEARBY_PORT);
} catch (IOException e) {
Log.w(TAG, "error multicasting", e);
mSocket = null;
}
}
@Override
protected Void doInBackground(Void... params) {
try {
mSocket.joinGroup(mNearbyGroup);
} catch (IOException e) {
Log.w(TAG, "Failed to connect to multicast", e);
}
while (mSocket != null) {
if (isCancelled()) {
mSocket.disconnect();
break;
}
try {
DatagramPacket profile = new DatagramPacket(mBroadcastMsg,
mBroadcastMsg.length, mNearbyGroup, MulticastScannerTask.NEARBY_PORT);
// if (DBG) Log.d(TAG, "sending multicast packet");
mSocket.send(profile);
try {
Thread.sleep(mDuration);
} catch (InterruptedException e) {}
} catch (IOException e) {
if (mWaitRetry > 0) {
try {
Thread.sleep(mWaitRetry);
} catch (InterruptedException e2) {}
} else {
mSocket = null;
}
}
}
mRunning = false;
mDone = true;
return null;
}
public boolean isRunning() {
return mRunning;
}
}