The online racing simulator
Java experiment.
(11 posts, started )
Java experiment.
Hello. I am that kind of guy that has to try everything. I usually solve my problems but in this case I need a push in the right direction.

From insim.txt
struct InSimInit // UDP packet to initialise the InSim system
{
char Id [4]; // ISI + zero
word Port; // Port for UDP replies from LFS (0...65535)
byte Flags; // Bit flags for options - see below
byte NodeSecs; // Number of seconds between NLP or MCI packets (0=none)
char Admin [16]; // Admin password (required if set in LFS host options)
};

So. How hard can it be to try this in java? Well. I quickly wrote a sampleprogram but realized that UDP is something I'm not too familiar with.
Especially not in Java. illepall
package lfs.udp;

import java.io.*;
import java.net.*;

public class UDPSend
{

protected static final int TIMEOUT = 5000;

public static void main(String args[])
{
try
{
String host = "localhost";
InetAddress address = InetAddress.getByName(host);

byte[] message = "ISI00000password".getBytes();

DatagramPacket packet = new DatagramPacket(message, message.length, address, 15567);
DatagramSocket dsocket = new DatagramSocket();
dsocket.setSoTimeout(TIMEOUT);
dsocket.send(packet);

// Wait for a answer.. Hopefully.
byte[] buffer = new byte[2048];
DatagramPacket answerpacket = new DatagramPacket(buffer, buffer.length);
dsocket.receive(answerpacket);

String msg = new String(buffer, 0, answerpacket.getLength());
System.out.println("recevied: "+msg);

dsocket.close();
}
catch (Exception e)
{
System.err.println(e);
}
}
}

See that string? "ISI00000password".. Am I totally out in the bush here or do I have something going with this code?
I think you will have to make sure the total packet size is 24. Dunno to be honest. I am also using java for insim, but I dont use the getBytes() function. I do it like this:


byte[] temp = new byte[24];
//ISI + zero
temp[0] = 0x49;
temp[1] = 0x53;
temp[2] = 0x49;
temp[3] = 0x00;

//Port
temp[4] = 0x00;
temp[5] = 0x00;

//Flags
temp[6] = (byte)41;

//Nodesecs
temp[7] = 0x01;

//Password
temp[8] = 0x00;
temp[9] = 0x00;
temp[10] = 0x00;
temp[11] = 0x00;
temp[12] = 0x00;
temp[13] = 0x00;
temp[14] = 0x00;
temp[15] = 0x00;
temp[16] = 0x00;
temp[17] = 0x00;
temp[18] = 0x00;
temp[19] = 0x00;
temp[20] = 0x00;
temp[21] = 0x00;
temp[22] = 0x00;
temp[23] = 0x00;


I know it is a bit sloppy, but on the other hand, it is easy to make sure you put the data in the correct place, which is nice for a starting java coder

EDIT: I am also not sure about the way you make a connection to lfs, it is a bit different from how I do it.
#3 - -wes-
Ok I can see your logic but your not quite there yet.

Lfs is expecting a packet of data that is 24 bytes long.
so you need an array of 24 bytes.

How about a class for each of the packets you can send to lfs?

setup the members ie port flags etc with correct types. Then convert each one in to bytes and stick them into your byte array.
Then you send the whole 24 bytes to lfs and hope it does something..
lfs will say uknown packet if it has any thing at all or will flash up the connecting port number.

I would like to help further but I went for a c++ winsock app, my code cant help you.

You need a java expert.
Frankmd beet me too it!
Well. I didn't realize that the packet HAD to be 24 bytes. :doh:
This codesnippet works just fine if someone wanna experiment.
Now let's see what this leads to. I probably won't stop until I have completed something useful. :rolleyes:
package lfs.udp;

import java.io.*;
import java.net.*;

public class InsimInit
{
protected static final int TIMEOUT = 60000;
private String returnmsg;

public InsimInit(String password, int port)
{
try
{
// Prepare the 24 byte array and zerofill it.
byte[] message = new byte[24];
for(int i=0; i<message.length; i++) message[i] = 0x00;

// Fill it with initvalues
message[6] = (byte)41; // Flags
message[7] = (byte)1; // NodeSecs
System.arraycopy("ISI".getBytes(), 0, message, 0, 3);
System.arraycopy(password.getBytes(), 0, message, 8, password.length());

// Connect and send
String host = "localhost";
InetAddress address = InetAddress.getByName(host);
DatagramPacket packet = new DatagramPacket(message, message.length, address, port);
DatagramSocket dsocket = new DatagramSocket();
dsocket.setSoTimeout(TIMEOUT);
dsocket.send(packet);

// Wait for answer
byte[] buffer = new byte[2048];
while(true)
{
DatagramPacket answerpacket = new DatagramPacket(buffer, buffer.length);
dsocket.receive(answerpacket);

System.out.println("Receiving: " +
new String(buffer, 0, answerpacket.getLength()));

// Reset the length of the packet before reusing it.
answerpacket.setLength(buffer.length);
}

//dsocket.close();

}
catch (Exception e)
{
System.err.println(e);
}
}

public static void main(String args[])
{
new InsimInit("lepper", 3333);
}
}

you dont need to zerofill the byte array, because it is filled with zeros by default...

and i recommend that you dont use one try - catch block.. there is a lot of things that can go wrong and throw an exception but from some exceptions you can recover without the need to restart the program..
for example:
public InsimInit(String password, int port) throws SomeException
{
DatagramSocket dsocket = null;

// Prepare the 24 byte array and zerofill it.
byte[] message = new byte[24];
for(int i=0; i<message.length; i++) message[i] = 0x00;

// Fill it with initvalues
message[6] = (byte)41; // Flags
message[7] = (byte)1; // NodeSecs
System.arraycopy("ISI".getBytes(), 0, message, 0, 3);
System.arraycopy(password.getBytes(), 0, message, 8, password.length());

// Connect and send
String host = "localhost";
try{
InetAddress address = InetAddress.getByName(host);
DatagramPacket packet = new DatagramPacket(message, message.length, address, port);
dsocket = new DatagramSocket();
dsocket.setSoTimeout(TIMEOUT);
try{
dsocket.send(packet);
}catch(IOException e){
e.printStackTrace();
//maybe some code to try to send the packet again a few times...
//if it still fails throw exception
throw new SomeException();
}

// Wait for answer
byte[] buffer = new byte[2048];
while(true)
{
DatagramPacket answerpacket = new DatagramPacket(buffer, buffer.length);
try{
dsocket.receive(answerpacket);
System.out.println("Receiving: " +
new String(buffer, 0, answerpacket.getLength()));

// Reset the length of the packet before reusing it.
answerpacket.setLength(buffer.length);
}catch(IOException e){
e.printStackTrace();
//again, try to do something with it..
}
}
}catch(UnknownHostException e){
e.printStackTrace(); //bad address? ask for a different one...
}catch(SocketException e){
e.printStackTrace();
}finally{
if(dsocket != null)
dsocket.close();
}

}

and i recommend that you use an object for each packet, that way it will be more transparent and universal.....
something like this..
interface InSimPacket
{
public byte[] getBytes();
}

....

class InitPacket implements InSimPacket
{
private final byte[] ID = new byte[]{0x49, 0x53, 0x49, 0x00}; //ISI0
private short port;
private Flags flags;
private byte nodeSecs;
private String admin;

public InitPacket(short port, Flags flags, byte nodeSecs, String admin)
{
//set up class properties...
}

public byte[] getBytes()
{
//convert all properties to byte[] and return
}
}

...

private void sendPacket(InSimPacket packet)
{
...
byte[] message = packet.getBytes();
DatagramPacket packet = new DatagramPacket(message, message.length, address, port);
...
}

...

sendPacket(new InitPacket(port, flafs, nodeSecs, admin))

i haven't tryed to make an insim app yet, so i can't help you with particular details, but as soon as i finish my tourney system, i will try to write something too...
#6 - -wes-
Quote from Nitemare :you dont need to zerofill the byte array, because it is filled with zeros by default...

(snip)

true for java but not for c++ structures. You do need to zero fill them.


InSimPack data,data2;
memset(&data, 0, sizeof(data));


If you use the new keyword I think it zero's them.


InSimPack* data= new InSimPack();

If you havn't done networking before you might want to write a basic client server system first. Just to get used to the idea.
Well. frankmd pushed me in the direction I needed really.
I have written numerous client/server stuff in my days. Both in C and pascal but TCP.
So far I have a working insimlistener. Events are thrown from a threaded baseclass.
I've decided to continue using this method. Example:

import net.liveforspeed.insim.*;
public class test implements InSimListener
{
public test()
{
InSim is = new InSim("localhost", 29999, "password");
is.addListener(this);
is.connect();
}

public void inSimVersionReply(InSimEvent e) {
VersionPacket vp = (VersionPacket)e.getObject();
System.out.println(vp.getProduct());
}

public void inSimStateChanged(InSimEvent e) {;;}
}

Ofcourse you have to write all eventmethods at this point. Even if you don't use them. Just like ItemListener.
Atleast until I have written adapters. This was fun.

Some problems was ofcourse this thing with Java and unsigned bytes. yeah. They don't exist. :-)
So at the moment I am writing some wrappers. Short s = unsigned(aByte);
Also this thing with converting 2 bytes (byte[2]) to an integer. Still working on that one.¨
My project has grown to about 15 classes/interfaces. Real eventhandling. Real threading.
I'll be back.
Quote from tehSnaile :
Also this thing with converting 2 bytes (byte[2]) to an integer. Still working on that one.¨

I use this one:


var = ((p[n+1]&0xff) << 8) | (p[n]&0xff);

Quote from Frankmd :I use this one:

var = ((p[n+1]&0xff) << 8) | (p[n]&0xff);


Thanks. I haven't tried it yet but I'm sure it works. I guess that "var" was an int right? How about turning it back to a bytearray? :rolleyes:

public int bytesToInt(byte[] b) {
int i = ((p[n+1]&0xff) << 8) | (p[n]&0xff);
return i;
}
public byte[] intToBytes(int i) {
// ????
}

yes, var was an int.


import java.nio.ByteBuffer;
import java.nio.ByteOrder;


int value;

ByteBuffer temp = ByteBuffer.wrap(new byte[4]);
temp.putInt(0, value).order( ByteOrder.BIG_ENDIAN );

#11 - abz1
Im going to create some of my own simple programs in java and this is exactly the thread i needed to start me off. Cheers guys.

Java experiment.
(11 posts, started )
FGED GREDG RDFGDR GSFDG