/*
* festivoice
*
* Copyright 2009 FURUHASHI Sadayuki, KASHIHARA Shuzo, SHIBATA Yasuharu
*
* 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 net.festivoice;
import java.lang.*;
import java.util.*;
import java.net.*;
import java.util.concurrent.*;
class UDPDataWithAddress
{
private InetSocketAddress address;
private UDPData data;
public UDPDataWithAddress(DatagramPacket received) throws Exception
{
address = new InetSocketAddress(received.getAddress(), received.getPort());
data = UDPData.deserialize(received.getData());
}
public InetSocketAddress getInetSocketAddress()
{
return address;
}
public UDPData getData()
{
return data;
}
}
class Worker extends Thread
{
private DatagramSocket socket;
private IChannelManager channelServer;
private BlockingQueue<UDPDataWithAddress> queue;
private boolean endFlag = false;
public Worker(DatagramSocket socket, IChannelManager channelServer, BlockingQueue<UDPDataWithAddress> queue)
{
this.socket = socket;
this.channelServer = channelServer;
this.queue = queue;
}
public void run()
{
while(!endFlag) {
try {
UDPDataWithAddress dataWithAddress = queue.take();
InetSocketAddress fromAddress = dataWithAddress.getInetSocketAddress();
UDPData data = dataWithAddress.getData();
IChannelInfo channel = channelServer.channelData(data.getChannelName(),
data.getUserName(), fromAddress);
short userIndex = 0;
for(IUserInfo user : channel.getUsers()) {
if(user.getInetSocketAddress().equals(fromAddress)) {
break;
} else {
++userIndex;
}
}
for(IUserInfo user : channel.getUsers()) {
if(!user.getInetSocketAddress().equals(fromAddress)) {
byte[] send_data = UDPData.serialize(data.getUserName(),data.getChannelName(),data.getVoiceData(),
data.getSequenceNumber(),userIndex);
DatagramPacket send = new DatagramPacket(send_data, send_data.length, user.getInetSocketAddress());
socket.send(send);
}
}
} catch (Exception e) {
//System.out.println("send error: "+e);
//e.printStackTrace();
}
}
}
public void end()
{
endFlag = true;
}
}
public class UDPStreamServer extends AbstractStreamServer {
private static int DEFAULT_QUEUE_MAX = 2048;
private DatagramSocket socket;
private Worker[] workers;
private BlockingQueue<UDPDataWithAddress> queue;
UDPStreamServer(InetSocketAddress addr, IChannelManager channelServer) throws SocketException
{
socket = new DatagramSocket(addr);
queue = new LinkedBlockingQueue<UDPDataWithAddress>(DEFAULT_QUEUE_MAX);
workers = new Worker[1];
for(int i=0; i < workers.length; ++i) {
workers[i] = new Worker(socket, channelServer, queue);
}
}
public void run()
{
for(Worker w : workers) {
w.start();
}
byte[] buf = new byte[1024 * 35];
DatagramPacket received = new DatagramPacket(buf, buf.length);
received.setLength(buf.length);
while (true) {
try {
socket.receive(received);
UDPDataWithAddress data = new UDPDataWithAddress(received);
queue.put(data);
} catch (Exception e) {
}
}
}
private void changeQueueItems(int itemNumber)
{
BlockingQueue new_queue = new LinkedBlockingQueue<UDPDataWithAddress>(itemNumber);
queue.drainTo(new_queue);
queue = new_queue;
}
}