/* ----- BEGIN LICENSE BLOCK -----
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the DataShare server.
*
* The Initial Developer of the Original Code is
* Ball Aerospace & Technologies Corp, Fairborn, Ohio
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Charles Wood <cwood@ball.com>
*
* ----- END LICENSE BLOCK ----- */
/* RCS $Id: TcpSocket.java,v 1.3 2002/01/29 20:50:17 lizellaman Exp $
* $Log: TcpSocket.java,v $
* Revision 1.3 2002/01/29 20:50:17 lizellaman
* Added LoggingInterface, modified the PropertiesInterface implementation
*
* Revision 1.2 2002/01/20 23:26:29 lizellaman
* add command line parameter that causes an plain DataShareObject to be sent to 'inactive' TCP connections after X milliseconds on inactivity
*
* Revision 1.1.1.1 2001/10/23 13:37:18 lizellaman
* initial sourceforge release
*
*/
package org.datashare;
import java.net.Socket;
import java.net.SocketException;
import java.io.EOFException;
import java.io.InterruptedIOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.InvalidClassException;
import org.datashare.objects.ChannelDescription;
import org.datashare.objects.DataShareObject;
/**
* @date March 01, 2001
*/
public class TcpSocket extends SocketAdapter implements Runnable
{
private Socket socket;
private int priority;
boolean running = true;
private ObjectInputStream ois = null;
private ObjectOutputStream oos = null;
private String myThreadName = "";
private Thread myThread = null;
private TransmitDataThread tdt = null;
public TcpSocket(Socket socket, DataReceiverInterface dri, int priority)
{
this.socket = socket;
try{
this.socket.setSoTimeout(SessionUtilities.getTCPSocketReadTimeout()); // we may want reads to timeout
}
catch(SocketException se)
{
se.printStackTrace();
}
this.dri = dri;
this.priority = priority;
this.localIP = socket.getLocalAddress();
this.localPort = socket.getLocalPort();
this.remoteIP = socket.getInetAddress();
this.remotePort = socket.getPort();
this.keyValue = "Socket-TCP-" + localIP.getHostAddress() + ":" + localPort +
"-" + remoteIP.getHostAddress() + ":" + remotePort;
try{
ois = new ObjectInputStream(socket.getInputStream());
oos = new ObjectOutputStream(socket.getOutputStream());
}
catch(Exception e)
{
e.printStackTrace();
stopThreadAndCloseSocket();
}
SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().DEBUG,
SessionUtilities.getLoggingInterface().NETWORK,
"New connection: " + keyValue + " with active set to " + (this.getActive()?"true":"false"));
// create our thread for buffering and transmiting data
tdt = new TransmitDataThread(this);
tdt.setName("XmitThread for " + keyValue);
try{
tdt.setPriority(Thread.currentThread().getPriority() + SessionUtilities.SocketXmtRelativePriority); // make transmitting lower priority, since it has buffering
}
catch(Exception e)
{
SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().ERROR,
SessionUtilities.getLoggingInterface().NETWORK,
"Problems setting Xmt Thread priority:");
e.printStackTrace();
}
tdt.start();
}
/**
* returns the type socket for this instance
*/
int getType()
{
return ChannelDescription.TCP;
}
/**
* call this method when data is to be sent over this connection, puts it into a queue
* so it can be sent from a xmit thread
*/
void sendData(DataShareObject dsObject)
{
SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().DEBUG,
SessionUtilities.getLoggingInterface().NETWORK,
"3-Adding "+ dsObject.sendingClientKey +"'s object to "+this.getClientKey() +"'s xmt buffer");
tdt.addData(dsObject);
}
/**
* this is the method that actually sends the data
*/
protected void xmitData(DataShareObject dsObject)
{
try{
if(running)
{
oos.writeObject(dsObject);
oos.flush();
}
}
catch(Exception e)
{
SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().ERROR,
SessionUtilities.getLoggingInterface().NETWORK,
"Problem in Socket " + this.keyValue + ":");
// e.printStackTrace();
stopThreadAndCloseSocket();
}
}
/**
* our thread loops while receiving data from Client
*/
public void run()
{
myThreadName = Thread.currentThread().getName();
myThread = Thread.currentThread();
SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().DEBUG,
SessionUtilities.getLoggingInterface().NETWORK,
"Setting TCP socket " + this.keyValue + " to priority " + priority);
try{
Thread.currentThread().setPriority(priority);
while(running)
{
try{
Object object = ois.readObject(); // blocks until an object is received
try{
DataShareObject dso = (DataShareObject)object;
dri.clientDataReceived(dso,this); // send it to whoever registered for these objects
Thread.currentThread().yield();
}
catch(ClassCastException cce)
{
SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().WARNING,
SessionUtilities.getLoggingInterface().NETWORK,
"Problem-TcpSocket "+this.keyValue + " received unknown object");
}
}
catch(ClassNotFoundException cnfe)
{
SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().WARNING,
SessionUtilities.getLoggingInterface().NETWORK,
"Problem reading Tcp Stream: "+cnfe.getMessage());
}
catch(InvalidClassException ice)
{
SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().WARNING,
SessionUtilities.getLoggingInterface().NETWORK,
"Problem reading Tcp Stream: "+ice.getMessage());
}
catch(InterruptedIOException iioe)
{
SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().DEBUG,
SessionUtilities.getLoggingInterface().NETWORK,
"Tcp socket " + this.keyValue + " timedOut");
this.xmitData(new DataShareObject()); // send a packet to keep the connection alive (idle too long!)
}
}
SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().DEBUG,
SessionUtilities.getLoggingInterface().NETWORK,
"Thread " + Thread.currentThread().getName() + " is stopping (scheduled)");
}
catch(SocketException se)
{
SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().DEBUG,
SessionUtilities.getLoggingInterface().NETWORK,
"Lost connection: " + keyValue);
stopThreadAndCloseSocket();
}
catch(EOFException eofe)
{
SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().DEBUG,
SessionUtilities.getLoggingInterface().NETWORK,
"Lost connection: " + keyValue);
stopThreadAndCloseSocket();
}
catch(Exception e)
{
SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().DEBUG,
SessionUtilities.getLoggingInterface().NETWORK,
"Problems reading Tcp data:");
e.printStackTrace();
stopThreadAndCloseSocket();
}
SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().DEBUG,
SessionUtilities.getLoggingInterface().NETWORK,
"Thread " + Thread.currentThread().getName() + " has stopped");
}
/**
* closes socket and stops this thread
*/
void stopThreadAndCloseSocket()
{
if(running == true)
{
SessionUtilities.getLoggingInterface().debugMsg(SessionUtilities.getLoggingInterface().DEBUG,
SessionUtilities.getLoggingInterface().NETWORK,
"removing/closing socket " + this.keyValue);
running = false;
myThread.setName("Stopped--"+myThreadName);
try{
if(socket != null)
socket.close();
}
catch(Exception e){}
try{
if(oos != null)
oos.close();
}
catch(Exception e){}
try{
if(ois != null)
ois.close();
}
catch(Exception e){}
finally
{
tdt.stopThread();
dri.connectionLost(this);
}
}
}
/**
* close socket, stop thread, and notify server
*/
public void close()
{
stopThreadAndCloseSocket();
}
} //// end of class
|