The online racing simulator
Did you try to do just what the compiler suggested, that is including "stdafx.h" to cinsim.h? I did the testing on my Linux box where there is no "stdafx.h"...

@MaKaKaZo: You kidding? CInSim is the best InSim lib out there, simple enough to not do anything weird behind my back, yet fully functional and easy to use.
#52 - PoVo
Quote from MadCatX :Did you try to do just what the compiler suggested, that is including "stdafx.h" to cinsim.h? I did the testing on my Linux box where there is no "stdafx.h"...

@MaKaKaZo: You kidding? CInSim is the best InSim lib out there, simple enough to not do anything weird behind my back, yet fully functional and easy to use.

It is already added
You might want do experiment a bit with it or you might just disable precompiled headers in the project settings, that should get you sorted...
#54 - PoVo
Meh, now I can't even get it to build in Code::Blocks...

If I build it, I get a file of 38kb, which crashes.

If I debug it, it runs...
That's kind of weird, do you have any idea where exactly it crashes? You can put few std::cerr's to the code to track it down. BTW, do you use pthreadGC2.lib and not pthreadVC2.lib with Code::Blocks?
#56 - PoVo
Quote from MadCatX :BTW, do you use pthreadGC2.lib and not pthreadVC2.lib with Code::Blocks?

Yes
Have you made any substantial changes to the code, or can I use the version you've already uploaded? I'll see if I encounter the same problem as you with Code::Blocks...
#58 - PoVo
Quote from MadCatX :Have you made any substantial changes to the code, or can I use the version you've already uploaded? I'll see if I encounter the same problem as you with Code::Blocks...

No, I downloaded Event Control from the start of this thread, which includes the Project file
Quote from PoVo :Meh, now I can't even get it to build in Code::Blocks...

If I build it, I get a file of 38kb, which crashes.

If I debug it, it runs...

I can help with this! This is a problem that comes from mingw compiler code optimization options. I think there were three levels of code optimization in the compiler options. If you check some of them *sometimes* it will generate an executable that crashes. This has been reported in mingw support several times, it has nothing to do with code::blocks, CInSim or my application. It works when debugging because in debug mode no optimization options are checked. You can just uncheck some of the optimization levels until you get a working executable.

This actually got me crazy some time ago when I did some minor changes to a project and suddenly it started crashing for no reason.

With you VS problem I can't help much. It's pretty clear that it's something to do with the includes, libraries and such. I'm no expert at all at that matter neither I know about VS as I have never used it.
#60 - PoVo
Quote from MaKaKaZo :I can help with this! This is a problem that comes from mingw compiler code optimization options. I think there were three levels of code optimization in the compiler options. If you check some of them *sometimes* it will generate an executable that crashes. This has been reported in mingw support several times, it has nothing to do with code::blocks, CInSim or my application. It works when debugging because in debug mode no optimization options are checked. You can just uncheck some of the optimization levels until you get a working executable.

This actually got me crazy some time ago when I did some minor changes to a project and suddenly it started crashing for no reason.

With you VS problem I can't help much. It's pretty clear that it's something to do with the includes, libraries and such. I'm no expert at all at that matter neither I know about VS as I have never used it.

I disabled all the optimisations, and still the same problem
I couldn't get the Code::Blocks project to build (MinGW linker refuses to find the pthreads lib and I don't have the nerve to solve it right now), but I got the MSVS project working. There was just one #include "stdafx.h" missing in the main.cpp
Attached files
FailUnfailed.zip - 95.9 KB - 590 views
#62 - PoVo
WOW! Nice one! Thanks very much for the great work, you made my day

To Makakazo: What exactly is the
pthread_mutex_lock (&ismutex);

and
pthread_mutex_unlock (&ismutex);

used for? I noticed it between sending buttons, does that mean, I have to use it everytime I send buttons?
Quote from PoVo :WOW! Nice one! Thanks very much for the great work, you made my day

To Makakazo: What exactly is the
pthread_mutex_lock (&ismutex);

and
pthread_mutex_unlock (&ismutex);

used for? I noticed it between sending buttons, does that mean, I have to use it everytime I send buttons?

That is used for mutual exclusion:
http://en.wikipedia.org/wiki/Mutual_exclusion

This is *only* important if you have a multi-threaded application.

As I recall, I used those functions inside the main application code in earlier versions of CInSim, but soon I realized that I could just put that code inside the library code itself, so the programmer doesn't need to control mutual exclusion.

The thing is, if you have an application where multiple threads are created, and those threads use common resources (ie. global variables), then it could happen that those resources might be used by both threads at the same time, resulting in undesirable consequences.

Please tell me which file you are viewing that code in (and CInSim version used) and I'll go into deeper detail of why I used it, but I'm pretty confident that it has to be something related with the main application algorithm, not with the library. I mean, it isn't supposed to be something that has to be used for all CInSim applications!
#64 - PoVo
It's from the X-Y-Z Positioning application
Mutex in question is handled internally in CInSim 0.6, so you don't need to explicitly lock it in your application. It's needed because there are two threads (one for receiving TCP and another for UDP packets) which both call the send_packet function. Packet sending has to be an atomic operation and the mutex is there to make sure that one thread doesn't get interrupted by the other one when sending a packet.
#66 - PoVo
So I don't have to use it while sending buttons?
You shouldn't have to, CInSim v0.6 is thread-safe in this respect. If you take a look at "send_packet" or "send_button" in CInsim.cpp, you'll see it's locking a mutex before calling the "send" method.
That's right. X-Y-Z positioning was my first attempt on an insim app using buttons and MCI packets. It's very old and uses an earlier version of CInSim. As Madcatx said, CInSim 0.6 is thread safe already so you don't need to use them.

Actually, aside from what has been already mentioned about UDP and TCP using the same method for sending packets, my main concern was using the same method frmo different threads.

For example, I usually create new threads that act as timers. They are created, wait for several seconds, and then they do something like clear a set of buttons that were created previously (this is the way I create a message that automatically disappears after X seconds). This timer thread has to use the send() method. If you have several threads like this doing different stuff, there's quite a high possibility that at some time two of them will try to use the method at the same time, and the result might lead to a unstable status or even a crash. It actually happened to me before I fixed it.

CInSim 0.6 blocks the critical methods before using them, so that only one thread can use them and calls from other threads are queued until the current one finishes. You don't need to handle that manually anymore.

If you are interested in CInSim maybe you should download the latest demo application which uses the latest CInSim version (I think... ).
in insim 5 IS_MTC was modifed and i add this code in my CInsim class


struct IS_MTC // Msg To Connection - hosts only - send to a connection / a player / all
{
byte Size; // 8 + TEXT_SIZE (TEXT_SIZE = 4, 8, 12... 128)
byte Type; // ISP_MTC
byte ReqI; // 0
byte Sound; // sound effect (see Message Sounds below)

byte UCID; // connection's unique id (0 = host / 255 = all)
byte PLID; // player's unique id (if zero, use UCID)
byte Sp2;
byte Sp3;

// char Text[TEXT_SIZE]; // up to 128 characters of text - last byte must be zero
};

function with error protection
but a have problems if strlen > 123


/**
* Send a variable sized message to connect
*/
bool CInsim::send_mtc(void* s_mst, char *errmsg)
{
struct IS_MTC *pack_mtc = (struct IS_MTC*)s_mst;

int text_len = strlen(pack_mtc->Msg);
int text2send;

if (text_len == 0)
{
strcpy(errmsg,"strlen == 0");
return false;
}
else if (text_len > 127)
{
strcpy(errmsg,"strlen > 127");
return false;
}

text2send = text_len + 4 - text_len%4; // 4, 8 ,12, ..., 128

pack_mtc->Size = 8 + text2send;

pthread_mutex_lock (&ismutex);
if (send(sock, (const char *)pack_mtc, pack_mtc->Size, 0) < 0)
{
pthread_mutex_unlock (&ismutex);
strcpy(errmsg,"can't send mtc");
return false;
}
pthread_mutex_unlock (&ismutex);
return true;
}

Shouldn't

text2send = text_len + 4 - text_len%4; // 4, 8 ,12, ..., 128

actually be?

byte remd = text_len % 4
if(remd > 0)
text2send = text_len + (4 - remd);
else
text2send = text_len;

Haven't tried it myself, but your code adds 4 to the text2send if it already is multiple of 4.
Quote from MadCatX :Shouldn't

text2send = text_len + 4 - text_len%4; // 4, 8 ,12, ..., 128

actually be?

byte remd = text_len % 4
if(remd > 0)
text2send = text_len + (4 - remd);
else
text2send = text_len;

Haven't tried it myself, but your code adds 4 to the text2send if it already is multiple of 4.

i tried it but lfs said what last byte must be zero, and i used this code
and i wrote what have problems if len > 123 chars (program is down)
Your "send_mtc" function seems to be OK, I tried it now it worked for me just fine. I hardcode the size of the Text array to 128 in insim.h and send the IS_MTC like this (msg is 127 chars long). It appears in LFS all right and my sample program doesn't crash...


char err[128];
struct IS_MTC mtc_pack;

memset(&mtc_pack, 0, sizeof(struct IS_MTC));
char* msg = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890123";

strcpy(mtc_pack.Text, msg);

mtc_pack.Size = sizeof(mtc_pack);
mtc_pack.Type = ISP_MTC;
mtc_pack.ReqI = 0;
mtc_pack.Sound = SND_MESSAGE;
mtc_pack.UCID = 255;
mtc_pack.PLID = 0;

insim.send_mtc(&mtc_pack, err);

Why don't you just copy and edit the send_button() function? It's exactly the same case and it works fine.

BTW, there's a mistake in your code because you use the field "Msg" in the IS_MTC, but now it's called "Text".

I'll change the library source code with the new insim changes when I have some time. It's a quite simple task. The good thing is that it will be backwards compatible. We will have a new send_mtc() function to send variable sized mtc packets, but the generic senc_packet() will work as well, causing a little network overhead because in that case packets sent will be the biggest possible (with 128 bytes of text).
-
(denis-takumi) DELETED by denis-takumi : I love C++

text2send = (1+((text_len-1)/4))*4;

has to be replaced with something like

text2send = (1+((text_len-1)/4))*4 + 4;

or with Denis' code to handle a situation when you have say 12 chars long string ending with zero terminator. In this case "strlen" returns 12 but you actually need to send 13 bytes where the 13th byte is '\0'. If you don't do that, LFS gives you "Last byte must be zero" error. (I found that the hard way today )

I was also thinking, wouldn't it be better to have just "send_packet" function and overload in accordingly to handle different packet types? If InSim ever gets more packets with variable size, having a different function to send each of them would get rather inconvenient...
MadCatX
(1+((126-1)/4))*4 + 4 = 132

makakazo was right

MaKaKaZo sorry my fail
btw i was copy and edit send_button function
but error protection is good idea

FGED GREDG RDFGDR GSFDG