home *** CD-ROM | disk | FTP | other *** search
Java Source | 1997-02-16 | 10.0 KB | 465 lines |
- // The Virtual Light Company 1996
- //
- // From Chapter 20: Late Night VRML 2.0 and java
- //
- // This is the Server That implements the user networking information..
- // At the moment the capabilites are very limited. The User is identified by
- // a hostname only. Thus if a user has two clients running on the one machine
- // then as soon as one closes it kills the sessions to all of the sessions
- // running on that machine. I will probably need to run a hostname/port number
- // combination.
-
- package filter;
-
- import java.net.*;
- import java.io.*;
- import java.util.*;
-
- public class UserServer extends Thread
- {
- private static final int BUFFER_LENGTH = 1024;
- private static final int MAX_UPDATE_INTERVAL = 10000; // 10 seconds
- private static final int MAX_REFRESH_PERIOD = 10000; // 10 seconds
-
- private boolean server_available = false;
- private Vector user_list;
- private Hashtable address_list;
-
- private boolean debug;
-
- public UserServer(ThreadGroup thread, boolean use_debug)
- {
- super(thread, "User Server Threadgroup");
-
- setPriority(7);
-
- System.out.println("Starting User server");
-
- user_list = new Vector(10, 2);
- address_list = new Hashtable(10, 0.8f);
-
- server_available = true;
-
- debug = use_debug;
- }
-
- public void run()
- {
- int i;
- long start_time;
- long exec_time;
- long update_diff;
- long user_start;
- User user;
-
- // if the server failed to start then exit and do nothing.
- if(!server_available)
- return;
-
- // now process the input.
- while(true)
- {
- start_time = System.currentTimeMillis();
-
- for(i = 0; i < user_list.size(); i++)
- {
- user = (User)user_list.elementAt(i);
-
- if((user.last_update - start_time) > MAX_UPDATE_INTERVAL)
- {
- synchronized (user_list)
- {
- user_list.removeElementAt(i);
- }
- synchronized (address_list)
- {
- address_list.remove(user.address.getHostName());
- }
- i--;
- }
- }
-
- // if the execution time took less that the refresh period then
- // sleep until the next 10 second bracket.
- exec_time = System.currentTimeMillis() - start_time;
- if(exec_time < MAX_REFRESH_PERIOD)
- {
- try
- {
- sleep(MAX_REFRESH_PERIOD - exec_time);
- }
- catch(InterruptedException e)
- {
- }
- }
-
- Thread.yield();
- }
- }
-
- // send the update information to the users. Since every users gets the same
- // message we create the message once and then send it to the users.
- public synchronized void send_update(String hostname,
- int timestamp,
- int seq_num,
- int src_entid,
- float[] position,
- float[] rotation,
- int region,
- float size)
- {
- int i;
- float x, y, z;
- float size_sqd = size * size;
-
- ByteArrayOutputStream bytes = new ByteArrayOutputStream(BUFFER_LENGTH);
- DataOutputStream out = new DataOutputStream(bytes);
-
- DatagramPacket packet;
- DatagramSocket socket;
- User user;
-
- // firstly let's update the user
- user = (User)address_list.get(hostname);
-
- // and check that this is a later sequence number if not discard.
- if(seq_num < user.last_seq_num)
- return;
-
- user.last_seq_num = seq_num;
- user.entid = src_entid;
- user.last_update = System.currentTimeMillis();
- user.current_region = region;
- user.size = size_sqd;
- user.position = position;
- user.rotation = rotation;
-
- if(debug)
- System.out.println("Sending update");
-
- try
- {
- socket = new DatagramSocket();
- }
- catch(IOException e)
- {
- // ARGH, barf!
- System.out.println("UserServer: unable to create outgoing update socket");
- return;
- }
-
- // create the output buffer once
- try
- {
- // The RTP header octet 1 = 0x80, octet 2 = 79d
- out.writeByte(0x80);
- out.writeByte(79);
-
- // sequence number, timestamp, SSRC
- out.writeShort(seq_num);
- out.writeInt(timestamp);
- out.writeInt(src_entid);
-
- // the position
- out.writeFloat(position[0]);
- out.writeFloat(position[1]);
- out.writeFloat(position[2]);
-
- // the position
- out.writeFloat(rotation[0]);
- out.writeFloat(rotation[1]);
- out.writeFloat(rotation[2]);
- out.writeFloat(rotation[3]);
-
- // region, acuity, flags
- out.writeInt(region);
- out.writeFloat(size);
- out.writeInt(0);
- // when sending an update out it is 0
- }
- catch(IOException e)
- {
- System.out.println("User server: error writing update");
- return;
- }
-
- // all done for the message, now send it to the clients
-
- synchronized(user_list)
- {
- for(i = 0; i < user_list.size(); i++)
- {
- user = (User)user_list.elementAt(i);
- x = user.position[0] - position[0];
- y = user.position[1] - position[1];
- z = user.position[2] - position[2];
-
- // if the acuity is too small reject and try next client.
- if((size_sqd / (x*x + y*y + z*z)) < user.acuity)
- continue;
-
- for(j = 0; j < user.regions.size; j++)
- if(user.regions[j] == region)
- {
- found = true;
- break;
- }
-
- if(!found)
- continue;
-
- packet = new DatagramPacket(bytes.toByteArray(),
- bytes.size(),
- user.address,
- user.update_port);
- try
- {
- socket.send(packet);
- }
- catch(IOException e)
- {
- System.out.println("User server: " +
- "error sending update packet");
- }
- }
- }
-
- socket.close();
- }
-
- public void set_filter(String hostname,
- int update_port,
- float acuity,
- int horizon,
- int[] regions,
- int[] ports)
- {
- User user = (User)address_list.get(hostname);
-
- // if the hostname does not exist then add this to set the updates
- if(user == null)
- {
- if(debug)
- System.out.println("Adding a new user");
-
- user = new User(update_port, acuity, horizon, regions, ports);
- try
- {
- user.address = InetAddress.getByName(hostname);
- }
- catch(UnknownHostException e)
- {
- System.err.println("Unable to dereference host");
- return;
- }
- synchronized (address_list)
- {
- address_list.put(hostname, user);
- }
- synchronized (user_list)
- {
- user_list.addElement(user);
- }
- }
- else
- {
- synchronized (user)
- {
- user.update_port = update_port;
- user.acuity = acuity * acuity;
- user.horizon = horizon;
- user.regions = regions;
- user.ports = ports;
- user.last_update = System.currentTimeMillis();
- }
- }
- }
-
- public void suspend(String hostname)
- {
- User user = (User)address_list.get(hostname);
-
- if(user == null)
- return;
-
- synchronized (user_list)
- {
- user_list.removeElement(user);
- }
- synchronized (address_list)
- {
- address_list.remove(hostname);
- }
- }
-
- public void refresh(String address)
- {
- int i;
- ByteArrayOutputStream bytes = new ByteArrayOutputStream(BUFFER_LENGTH);
- DataOutputStream out = new DataOutputStream(bytes);
-
- DatagramPacket packet;
- DatagramSocket socket;
-
- User user;
- User me = (User)address_list.get(address);
-
- if(debug)
- System.out.println("Sending refresh");
-
- try
- {
- socket = new DatagramSocket();
- }
- catch(IOException e)
- {
- // ARGH, barf!
- System.out.println("UserServer: unable to create outgoing refresh socket");
- return;
- }
-
- for(i = 0; i < user_list.size(); i++)
- {
- user = (User)user_list.elementAt(i);
-
- // reset the stream to start from the beginning of the packet
- bytes.reset();
-
- try
- {
- // The RTP header octet 1 = 0x80, octet 2 = 79d
- out.writeByte(0x80);
- out.writeByte(80);
-
- // sequence number, timestamp, SSRC
- out.writeShort(user.last_seq_num);
- out.writeInt((int)user.last_update);
- out.writeInt(user.entid);
-
- // the position
- out.writeFloat(user.position[0]);
- out.writeFloat(user.position[1]);
- out.writeFloat(user.position[2]);
-
- // the position
- out.writeFloat(user.rotation[0]);
- out.writeFloat(user.rotation[1]);
- out.writeFloat(user.rotation[2]);
- out.writeFloat(user.rotation[3]);
-
- // region, acuity, flags
- out.writeInt(user.current_region);
- out.writeFloat(user.size);
- out.writeInt(0);
- // the flags are 0 for an update refresh
- }
- catch(IOException e)
- {
- System.out.println("User server: error writing update");
- return;
- }
-
- // all done for the message, now send it to the clients
- packet = new DatagramPacket(bytes.toByteArray(),
- bytes.size(),
- me.address,
- me.update_port);
- try
- {
- socket.send(packet);
- }
- catch(IOException e)
- {
- System.out.println("User server: error sending update packet");
- }
- }
- }
-
- public synchronized void remove(String hostname)
- {
- User user = (User)address_list.get(hostname);
-
- synchronized(address_list)
- {
- address_list.remove(hostname);
- }
- synchronized(user_list)
- {
- user_list.removeElement(user);
- }
- }
-
- public synchronized void send_chat(int seq_num,
- int mesg_type,
- int text_id,
- String msg_text)
- {
- int i;
- ByteArrayOutputStream bytes = new ByteArrayOutputStream(BUFFER_LENGTH);
- DataOutputStream out = new DataOutputStream(bytes);
-
- DatagramPacket packet;
- DatagramSocket socket;
-
- User user;
-
- if(debug)
- System.out.println("Sending chat message");
-
- try
- {
- socket = new DatagramSocket();
- }
- catch(IOException e)
- {
- // ARGH, barf!
- System.out.println("UserServer: unable to create outgoing update socket");
- return;
- }
-
-
- // create the output buffer once
- try
- {
- // The RTP header octet 1 = 0x80, octet 2 = 79d
- out.writeByte(0x80);
- out.writeByte(80);
-
- // sequence number, timestamp, SSRC
- out.writeShort(seq_num);
- out.writeInt(0); // txt msg has timestamp 0
- out.writeInt(text_id);
-
- // the position
- out.writeShort(mesg_type);
- out.writeShort(msg_text.length());
-
- // now write the message
- out.writeBytes(msg_text);
-
- }
- catch(IOException e)
- {
- System.out.println("User server: error writing update");
- return;
- }
-
- for(i = 0; i < user_list.size(); i++)
- {
- user = (User)user_list.elementAt(i);
- packet = new DatagramPacket(bytes.toByteArray(),
- bytes.size(),
- user.address,
- user.update_port);
- try
- {
- socket.send(packet);
- }
- catch(IOException e)
- {
- System.out.println("User server: error sending text packet");
- }
- }
- }
- }
-