package de.desy.tine.headers;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.util.LinkedList;
import de.desy.tine.client.TLinkFactory;
import de.desy.tine.client.TLink;
import de.desy.tine.dataUtils.TDataType;
import de.desy.tine.definitions.TErrorList;
import de.desy.tine.definitions.TFormat;
import de.desy.tine.definitions.TStrings;
import de.desy.tine.definitions.TTransport;
import de.desy.tine.endianUtils.Swap;
import de.desy.tine.server.logger.DbgLog;
import de.desy.tine.server.logger.MsgLog;
public class TGlobalsHdr
{
short msgSizeInBytes;
short mtu;
int debugLevel = 0;
byte[] globalsNameAsByteArray = new byte[TStrings.KEYWORD_NAME_SIZE]; // 64 chars
short dArrayLength;
short dFormat;
short status;
short dTimestampUSec;
int dStamp;
int sysStamp;
int dTimestamp;
int dTimestampMSec;
static final int maxPayloadSizeInBytes = TTransport.UDP_BUFFER_SIZE;
static final int glbhdrSizeInBytes = (TStrings.KEYWORD_NAME_SIZE + 4*2 + 4*4);
static final int glbhdrSizeInBytesLegacy = (TStrings.KEYWORD_NAME_SHORTSIZE + 2*2 + 1*4);
static ByteArrayInputStream dBuffer;
byte[] usernameAsByteArray = new byte[TStrings.USERNAME_SIZE];
private short protocol;
private short numInPacket;
static final short hdrSizeInBytes = 2 + TStrings.USERNAME_SIZE + 2 + 2; // network header size
private short totalSizeInBytes;
TLinkFactory tf;
/**
* Attach a GlobalsData object to the factory
* Creation date: (8/21/01 6:33:36 PM)
*/
public TGlobalsHdr(TLinkFactory tfactory)
{
tf = tfactory;
}
private LinkedList<TLink> lnks = new LinkedList<TLink>();
private byte[] dBytes = new byte[maxPayloadSizeInBytes];
public TLink[] toStruct(InetAddress gaddr, byte[] data, int length)
{
TLink glb;
boolean isLegacy = false;
int bytesread = 0;
int ghdrsize = glbhdrSizeInBytes;
int nlen = TStrings.KEYWORD_NAME_SIZE;
TLinkFactory.GlobalInfo gi = tf.getGlobalsInfo(gaddr);
try
{
lnks.clear();
dBuffer = new ByteArrayInputStream(data);
DataInputStream ds = new DataInputStream(dBuffer);
// overall message length:
totalSizeInBytes = Swap.Short(ds.readShort());
if (totalSizeInBytes < hdrSizeInBytes + glbhdrSizeInBytesLegacy)
{
String msg = "recv: " + totalSizeInBytes + " bytes : hdr " + hdrSizeInBytes + glbhdrSizeInBytesLegacy;
DbgLog.log("TGlobalsHdr",msg);
return null;
}
ds.read(usernameAsByteArray,0,TStrings.USERNAME_SIZE);
protocol = Swap.Short(ds.readShort());
numInPacket = Swap.Short(ds.readShort());
bytesread = 22;
switch (protocol)
{
case 3: // legacy
isLegacy = true;
ghdrsize = glbhdrSizeInBytesLegacy;
nlen = TStrings.KEYWORD_NAME_SHORTSIZE;
break;
case 4: // modern
break;
default: // is not a globals packet!
return null;
}
String key, ctx;
int dts, dtsUSEC;
for (int i=0; i<numInPacket && bytesread < totalSizeInBytes; i++)
{
ds.read(globalsNameAsByteArray,0,nlen);
dArrayLength = Swap.Short(ds.readShort());
dFormat = (short)(Swap.Short(ds.readShort()) % 256);
if (isLegacy)
{
dTimestamp = Swap.Long(ds.readInt());
status = 0;
dStamp = sysStamp = dTimestampMSec = 0;
dTimestampUSec = 0;
}
else
{
status = Swap.Short(ds.readShort());
dTimestampUSec = Swap.Short(ds.readShort());
dStamp = Swap.Long(ds.readInt());
sysStamp = Swap.Long(ds.readInt());
dTimestamp = Swap.Long(ds.readInt());
dTimestampMSec = Swap.Long(ds.readInt());
}
bytesread += ghdrsize;
ctx = null;
key = new String(globalsNameAsByteArray).trim();
String[] parts = key.split("/");
if (parts.length > 2)
{
ctx = parts[1]; key = parts[2];
}
if (ctx != null) gi = tf.getGlobalsInfo(ctx, gaddr);
//dts = (long) dTimestamp * 1000 + (long) dTimestampMSec;
dts = dTimestamp;
dtsUSEC = dTimestampMSec * 1000 + (dTimestampUSec % 1000);
glb = tf.findTLink(gaddr, ctx, key);
int dataSizeInBytes = dArrayLength * TFormat.formatSizeOf(dFormat);
byte[] d = dBytes; //new byte[dataSizeInBytes];
ds.read(d,0,dataSizeInBytes); //ds.read(d,0,d.length);
bytesread += dataSizeInBytes;
if (gi != null)
{
gi.updateDataElement(key.trim(), d, dArrayLength, dFormat, dts, dtsUSEC, sysStamp, status);
gi.hasUpdated = true;
}
// push this data set into the corresponding TDataType object
if (glb != null && glb.dOutput != null)
{
postOutputData(glb, d, dFormat, dArrayLength, dts, dtsUSEC, sysStamp, dStamp, status, TLink.STATUS_REMOTE);
lnks.add(glb);
}
}
ds.close();
dBuffer.close();
}
catch (IOException e)
{
e.printStackTrace();
MsgLog.log("TGlobalsHdr.toStruct",e.toString(),TErrorList.code_failure,e,0);
return null;
}
return lnks.toArray(new TLink[0]);
}
public static void postOutputData(TLink lnk,byte[] d,short fmt,int len,int ts,int tsUSEC,int sds,int ds,int sts,int stsrc)
{
lnk.dOutput.resetBuffersReady();
if (lnk.dOutput.getFormat() == TFormat.CF_DEFAULT)
{
lnk.dOutput.dFormat = fmt;
lnk.dOutput.dArrayLength = len;
lnk.dOutput.numblks = 1;
if (fmt != TFormat.CF_STRUCT && lnk.dOutput.getDataObject() == null)
{
lnk.dOutput.setDataObject(lnk.dOutput.dArrayLength,lnk.dOutput.dFormat);
}
}
lnk.linkStatus = sts;
lnk.linkStatusSource = stsrc;
lnk.dOutput.sysDataStamp = sds;
lnk.dOutput.usrDataStamp = ds;
lnk.dOutput.timestamp = ts;
lnk.dOutput.timestampUSEC = tsUSEC;
lnk.dOutput.dTimestamp = ts + tsUSEC/1000;
if (fmt == lnk.dOutput.getFormat())
{
lnk.dOutput.update(d,1,0);
lnk.dOutput.blksin = lnk.dOutput.bytesin = 0;
lnk.dOutput.resetBuffersReady();
lnk.dOutput.isDataObjectInSync = false;
TLinkFactory.getInstance().fillinIncomingData(lnk);
}
else
{ // try to re-format (what came in to what the caller wants ...)
TDataType dt = new TDataType(len,fmt);
dt.update(d,1,0);
lnk.dOutput.blksin = lnk.dOutput.bytesin = 0;
dt.resetBuffersReady();
Object srcData = dt.getDataObject();
dt.getData(srcData);
lnk.dOutput.putData(srcData);
lnk.dOutput.hasBeenUpdated = dt.hasBeenUpdated = true;
lnk.dOutput.dCompletionLength = len;
}
}
}