Jump to content


Photo

Net39 DLL


  • Please log in to reply
248 replies to this topic

#1 sabriath

sabriath

    12013

  • GMC Member
  • 3197 posts

Posted 15 October 2010 - 11:50 AM

**BETA** v0.1.3
http://www.host-a.ne...h/net39_lic.zip

**BETA** v0.1.4 (not compatible with v0.1.3)
http://www.host-a.ne...riath/net39.zip

Mods: If this is in the wrong place, my apologies. I am currently in the middle of making hopefully the best network library. Although this is in a non-working order, it is a work-in-progress and would like help from the community if they are able. I have asked the mods to move this to the DLL extension forum section, as this has reached a stage where it mostly works, but still needs thorough testing and I am still adding more and more features. Thank you

Written in Code::Blocks targetting vsc++2008

{2011:1-1}
http://www.host-a.ne...h/net39_lic.zip

A new year, and a new plan for the format of this topic. I will begin striking out old "journal" type updates and deleting them over time, no need looking to the past anymore. I will however keep 3 lists inside spoiler tags, 1 will contain a revision log (with as little description of changes for each build) and the others will contain the full list of functions and constants. There is no point in explaining each function, I will write a tutorial specifically designed for that purpose, I don't want to bog down this topic with it. The package contains the license, revision log, source code, dll (debug build), gex extension file, and an example gmk file. Eventually even this journal log will be absorbed into the new order of things, and only important items will be left....


Please feel free to post comments, suggestions, questions, help, bugs, etc. Thank you!

Last File Push: 2011-01-19
Revision:
Spoiler


Constants v0.1.4 (note: not all are actually used):
Spoiler


Constants v0.1.3:
Spoiler


Functions v0.1.4:
Spoiler


Functions v0.1.3:
Spoiler

Edited by sabriath, 19 January 2011 - 11:26 PM.

  • 9

Tutorials of Interest:
* Multiplayer: mine or True Valhalla's

Projects:
* Net39
* My 39dll scripts
* My 39dll lib
* Multiplayer Engine
* Artificial Chemistry

Posted Image

#2 NYS

NYS

    GMC Member

  • GMC Member
  • 453 posts
  • Version:GM:Studio

Posted 15 October 2010 - 11:58 AM

Great your taking your time to do this :)

I would use it, but I have already used many 39dll scripts so renaming isn't so fun, if I want to keep the old scripts too.
  • 0

#3 slayer 64

slayer 64

    Slayer of gingers

  • GMC Member
  • 4301 posts
  • Version:GM:Studio

Posted 16 October 2010 - 08:19 PM

i'm not sure what all the changes are going to do for me. looks like 39dll is pretty much the same, but more efficient internally i guess?
you must be pretty good at c++.
if you're going to re work 39dll, maybe you should use GMAPI and have objects automatically keep track of themselves on all machines connected to each other a server.

the end user would use scripts like this:
objControl create event
init(0,"www.aGameServer.com")//1=server 0=client
objControl
if lostConnection() game_end()
if machinesConnected()>10 removeLastMachine()
objPlayer create event
keepVariableUpToDate("x")
keepVariableUpToDate("y")
keepVariableUpToDate("z")
the scripts and dll would automatically trade messages to keep variables and objects in sync.
ideally the end user wouldn't need sockets.

obviously there's a lot of details and i'm not an expert on 39dll. lol
  • 2

5y5rs3d.pngfg0UQNL.png


#4 2DLuis

2DLuis

    Graphic Designer

  • GMC Member
  • 2527 posts
  • Version:GM8

Posted 16 October 2010 - 11:54 PM

A quick question,

Did you fix the 39DLL glitch where in C++ if you received more than 1 string in a message, the data turned all screwy? And therefore you had to receive the data in one variable char array, and then pass it on to another normal char* variable. I could not quite determine from your post if you had addressed this.

Looks good,
-Luis
  • 0

#5 ash47

ash47

    O_o

  • GMC Member
  • 1347 posts

Posted 17 October 2010 - 12:35 AM

perhaps a different title / description?

otherwise, awesome :P
  • 0
Posted Image

Rate this topic: 0 | 1 | 2 | 3 | 4 | 5

PRESS IT
\/


#6 Revel

Revel

    ɹǝqɯǝɯ ɔɯƃ

  • GMC Member
  • 4935 posts
  • Version:GM8

Posted 17 October 2010 - 12:46 AM

Nice, it's about time someone provided a 39dll alternative. I've been using RakNet, and I've noticed on thing that might be good for your DLL. A high resolution timer built into the DLL. It's great for quick timestamping of messages and that way you don't need to use another DLL like Yourself's DLL.
  • 0

#7 sabriath

sabriath

    12013

  • GMC Member
  • 3197 posts

Posted 17 October 2010 - 09:06 AM

@NYS: most of the functions will offer the same abilities as 39dll, so renaming would merely be for the scripts themselves. Your main code should not be effected unless you did a lot of extra work (and I may provide other scripts for crossover maintenance).

looks like 39dll is pretty much the same, but more efficient internally i guess?

Well the primary #1 reason for me doing this is because:
a = createbuffer();
b = createbuffer();
c = createbuffer();

freebuffer(b);

'c' now points to a NULL indexed address as far as 39dll is concerned, and whatever you "wrote" in 'c' buffer, will now be in addressed by 'b' even though it was freed.

have objects automatically keep track of themselves on all machines connected to each other a server.

Those are later plans I had in mind, but I want to just get all the direct internals done first. The thought had crossed my mind to make a network dll that did 99% of the work for you (even dead reckoning), but that's going to take me awhile...baby steps.

Did you fix the 39DLL glitch where in C++ if you received more than 1 string in a message, the data turned all screwy? And therefore you had to receive the data in one variable char array, and then pass it on to another normal char* variable. I could not quite determine from your post if you had addressed this.

I did not know this was a problem, can you explain in more detail about this?

If you mean something like:
writestring("this"+ chr(0) + "and this");
That's because c++ "strlen" automatically returns the 'size' of the string ending with the chr(0) command, so instead you would do this:
writestring("this"); //automatically adds '\0'
writestring("and this");

chr(0) is finnicky in C-type languages because they don't store the size of the string as a 2 byte short like other languages do, and as you know, it takes up 1 of the 256 ascii code designations. This sucks, but you cannot do anything about it directly. However, what I can offer is a "size" argument optional (already somewhat implemented), which would allow you to override 'strlen' check (a size=0 will cause a 'strlen' check). So you would do this (as an example):
writestring("this" + chr(0) + "and this" + chr(0), 14);

If this isn't what you mean, let me know so I can see if I can fix whatever it is.

perhaps a different title / description?

Suggestions?

Nice, it's about time someone provided a 39dll alternative. I've been using RakNet, and I've noticed on thing that might be good for your DLL. A high resolution timer built into the DLL. It's great for quick timestamping of messages and that way you don't need to use another DLL like Yourself's DLL.

I will be adding in that ability once I've fleshed out all of the direct access areas first.

Thanks everyone for the support, hopefully I'll have a demo out this week or the following (my anniversary was a couple days ago, so I wasn't able to program). Keep those ideas comin'!!
  • 0

Tutorials of Interest:
* Multiplayer: mine or True Valhalla's

Projects:
* Net39
* My 39dll scripts
* My 39dll lib
* Multiplayer Engine
* Artificial Chemistry

Posted Image

#8 csscom

csscom

    GMC Member

  • New Member
  • 74 posts

Posted 17 October 2010 - 05:19 PM

Cool stuff, I always assumed everything in 39dll was in perfect working order since it was on version 2.5.

I see your upgrading somethings and one sections says 39dll can cause disjointing with gm.
what does this mean? and can you provide and example of how it can causes problems for a GMMMO.
  • 0

#9 Revel

Revel

    ɹǝqɯǝɯ ɔɯƃ

  • GMC Member
  • 4935 posts
  • Version:GM8

Posted 17 October 2010 - 06:04 PM

I see your upgrading somethings and one sections says 39dll can cause disjointing with gm.
what does this mean? and can you provide and example of how it can causes problems for a GMMMO.


Well the primary #1 reason for me doing this is because:

a = createbuffer();
b = createbuffer();
c = createbuffer();

freebuffer(b);

'c' now points to a NULL indexed address as far as 39dll is concerned, and whatever you "wrote" in 'c' buffer, will now be in addressed by 'b' even though it was freed.


  • 0

#10 sabriath

sabriath

    12013

  • GMC Member
  • 3197 posts

Posted 18 October 2010 - 02:30 PM

@TV: thank you for your overview, however I had already thought of doing backward compatibility, so no need to rename/rework any of your game's code (you would just take out 39sters version and plug mine right in). But mine will have added features obviously, if you need/want to use them.

Finally, I am naturally skeptical that there may be bugs with this DLL.

Quite disheartening to see, but that's ok, my c++ is rusty. I'm hoping the community can help squash the bugs when I put this in beta stage.

39dll has some flaws, perhaps, but none that have directly or noticeably caused any problems.

Not many people use the buffer system, they just write/read the default buffer and clear it when done, so they wouldn't notice the problem at all. However, I do use the buffers greatly, so not only is my library broken from it, but some of my personal scripts are as well....and everyone who relies on them are screwed. It's no biggy though, the extensions I have planned alone will hopefully put this at the top :)

@All: I have updated my original post, as well as the dll. I somewhat finished the socket class, but I have to get to bed. I still hope to have a demo within a week or 2...fingers crossed!
  • 0

Tutorials of Interest:
* Multiplayer: mine or True Valhalla's

Projects:
* Net39
* My 39dll scripts
* My 39dll lib
* Multiplayer Engine
* Artificial Chemistry

Posted Image

#11 Marchal_Mig12

Marchal_Mig12

    The Rhouan

  • GMC Member
  • 1182 posts
  • Version:GM:Studio

Posted 18 October 2010 - 05:06 PM

I am glad someone is finally taking over 39ster work :). Could you add up some more distinct benefits on top of the features you're adding to 39dll. Also, as someone suggested before, it is no so funny to add mp_ before each script. If you could get rid of those, it would be perfect.

Finally, I believe this topic belongs to the DLL one instead ;).

Mig
  • 0

#12 2DLuis

2DLuis

    Graphic Designer

  • GMC Member
  • 2527 posts
  • Version:GM8

Posted 18 October 2010 - 07:50 PM

I did not know this was a problem, can you explain in more detail about this?


Sure. Say in your GM client, you structure a message like so:
clearbuffer();
writebyte(MSG_ID);
writestring(global.user);
writestring(global.pass);
sendmessage(global._tcpsock);

When you receive said message in a c++ server, you have to do something like below:
                            sbuffer = readstring(0);  
                            strcpy(Players[i].Username, sbuffer);
                            sbuffer = readstring(0); 
                            strcpy(Players[i].Password, sbuffer); 

That is assuming you initialized your variables as follows:
// Though this is not too pertinent to the problem
// Player class
class Player
{
    public:
        double Sock;
        char Username[255];
        char Password[255];
        char* FileName;
        short AccID;
        short PlayerID;
        char* IPAddress;
        bool InUse;
};

And initializing the buffer variable as follows:
//39DLL Fix (global variable)
char* sbuffer;

And if you were to not do this, you would receive the first string just fine, yet the second one would become enmeshed with random data.

That is just cut paste from my c++ engine, so it may be somewhat sloppy,

Edited by 2DLuis, 18 October 2010 - 07:54 PM.

  • 0

#13 sabriath

sabriath

    12013

  • GMC Member
  • 3197 posts

Posted 18 October 2010 - 11:10 PM

When you receive said message in a c++ server, you have to do something like below:

That looks like how it is suppose to be done, so I'm not sure I follow. What have you tried to do and it failed to work?

In my opinion, here is an easier way, but bypasses the buffer class altogether:
char* buff = new char[5000];
int len;

size = recv(s->sockid, buff, 5000, 0);
if (size > 0)
{
  len = strlen(buff) + 1; //get location of second string
  strcpy(Players[i].Username, buff);
  strcpy(Players[i].Password, buff + len);
}
delete(buff);

"buff" can be pre-initialized in a more public manner so that it doesn't have to keep being allocated and freed for each call.

The other issue, but is not a 39dll problem, is that TCP is a stream protocol, which means that you may very well receive the first string but not the second one....so the "strcpy" of the buffer at the second string's position will be garbled RAM data rather than from the buffer.

You can circumvent this by sending a 1 or 2 byte integer denoting the size of the total message being sent (or use 39dll's currently built-in feature using format=0). When you start receiving information, just append it to the buffer until the size of the buffer correlates with this value, then call your function, shift the buffer down, and you're ready to continue with the next message.

As it looks right now, my upgrades to 39dll will help both GM and c++ programmers, while the original was intended primarily for GM use...although it will be nothing like RakNet.
  • 0

Tutorials of Interest:
* Multiplayer: mine or True Valhalla's

Projects:
* Net39
* My 39dll scripts
* My 39dll lib
* Multiplayer Engine
* Artificial Chemistry

Posted Image

#14 LoopStan

LoopStan

    North-See Developer

  • GMC Member
  • 1398 posts

Posted 18 October 2010 - 11:58 PM

Yes 2Dluis, you have to have a buffer variable. I am really to lazy to post the stuff I used on here, but you shouldn't be using 39dll in a c++ app anyway, you should be making it so you can use it on linux and get super fast server speeds and more up time :)
  • 0

Posted Image


#15 Revel

Revel

    ɹǝqɯǝɯ ɔɯƃ

  • GMC Member
  • 4935 posts
  • Version:GM8

Posted 19 October 2010 - 12:44 AM

you should be making it so you can use it on linux and get super fast server speeds and more up time

RakNet *cough* :chikin
  • 0

#16 lasttea999

lasttea999

    GMC Member

  • GMC Member
  • 290 posts

Posted 19 October 2010 - 01:42 AM

This all sounds great... but only vaguely! I think that there are many GM users who, like myself, are using 39dll with only the bare minimum of required knowledge. I wish I could comprehend all that goes on within the DLL, but, alas, I am as yet unfamiliar with C++... You could argue that this demonstrates some degree of irresponsibility, but on the other hand 39dll seems to have opened up many new possibilities among GM users, and besides, how useful can an extension be if you have to know how to make it to use it?

Would it be possible, then, to provide a tutorial on this upgrade at some point, detailing, in particular, the changes between this and the original and the improvements it has incorporated?

Thank you to all of you diligent programmers for your efforts!

Edited by lasttea999, 19 October 2010 - 01:45 AM.

  • 0
Posted ImagePosted Image

#17 Revel

Revel

    ɹǝqɯǝɯ ɔɯƃ

  • GMC Member
  • 4935 posts
  • Version:GM8

Posted 19 October 2010 - 03:55 AM

Would it be possible, then, to provide a tutorial on this upgrade at some point, detailing, in particular, the changes between this and the original and the improvements it has incorporated?


It will be basically identical to 39dll, but more efficient back-end, some bugs fixed, and will have some more features which you don't necessarily have to learn.

Edited by Revel, 19 October 2010 - 03:55 AM.

  • 0

#18 sabriath

sabriath

    12013

  • GMC Member
  • 3197 posts

Posted 19 October 2010 - 08:56 AM

Would it be possible, then, to provide a tutorial on this upgrade at some point, detailing, in particular, the changes between this and the original and the improvements it has incorporated?


It will be basically identical to 39dll, but more efficient back-end, some bugs fixed, and will have some more features which you don't necessarily have to learn.

And I will also be writing a new tutorial for all aspects of networking when I'm finished. I only ask for patience while I juggle work/life/hobby.


Edit: Didn't want to double post, although most will probably oversee this considering it's not going to bump the topic, but I figured I'd put it here just in case.

I have updated the file, it now contains the main.h/main.cpp files situated with a backbone structure. I decided to clean up a few things and redid DList class since creating/freeing memory just for an integer seemed a bit overkill, instead it uses a loop to search for a NULL in the list and assigns it (which the original 39dll did the same thing, but mine doesn't push the list down).

After cleaning up as much as I could, I accidentally hit the build key and the error list hit me like a ton of bricks. I knocked all of them out of the park except for 3 (which is actually 1, just done 3 times). I will be asking a few friends, but I'll post it here too just in case someone can help...

sprintf(&Digest + i * 2, "%02X", (char*)(&Ret[i]));

That kicks back an error saying:

"Ret: cannot change 'char (*_w64)[65]' to 'char*'" or something

I have tried every means possible, turning the pointers inside and out and I just cannot get the darn program to understand that I want to pass a UINT32[8] array byte for byte to get the hex digits. The "Ret[i]" code is wrong already because it needs to be casted as a "char*" so that it can go 1 byte increments, but somehow this doesn't work either (which I originally had):

(char*)Ret[i]

I figured since Ret[] was a static member of the class, it didn't have a pointer association, so that's why I switched to &Ret...then I thought:

((char*)&Ret) + i

But that doesn't work either....or did I try that? I'm tired now, I'll hit this up tomorrow after work.

Edited by sabriath, 19 October 2010 - 01:49 PM.

  • 0

Tutorials of Interest:
* Multiplayer: mine or True Valhalla's

Projects:
* Net39
* My 39dll scripts
* My 39dll lib
* Multiplayer Engine
* Artificial Chemistry

Posted Image

#19 Marchal_Mig12

Marchal_Mig12

    The Rhouan

  • GMC Member
  • 1182 posts
  • Version:GM:Studio

Posted 19 October 2010 - 04:09 PM

Hi everyone, I thought it could be very useful to share this with you. http://www.brynosaur...pub/net/p2pnat/

It talks about every side of online concepts (tcp hole punching, udp hole punching, tcp hairpin and udp hairpin). It also includes an interesting section to determine the NAT type of certain routers and the success of routers to be hole punched, etc. All in all, VERY useful informations.
  • 0

#20 39ster

39ster

    GMC Member

  • GMC Member
  • 898 posts

Posted 20 October 2010 - 06:32 AM

It's good someone has finally started working on it. My code is actually quite embarrassing, and i've been meaning to re-program it for the sole purpose of having better looking source code (i started the first version of the DLL shortly after learning C). Although, if it were me re-programming it, i wouldn't of even bothered trying to make the API look like the original. It would be very different and completely incompatible with current scripts that use the DLL.
  • 0

#21 jon sploder

jon sploder

    GMC Member

  • GMC Member
  • 919 posts

Posted 20 October 2010 - 09:17 AM

I would definitely use this as long as it is not too different to 39dll itself.
  • 0

#22 sabriath

sabriath

    12013

  • GMC Member
  • 3197 posts

Posted 20 October 2010 - 03:06 PM

@Marchal: Thanks for the link to share with everyone, I might add that stuff in my next tutorial.

@39ster: I had planned on making it very different, but a lot of people have already invested in your scheme, so I didn't want to deter them. The extensions will far-outweigh the original design and hopefully people will stop using those so that I can start deprecating them. Not saying that your program is garbage, but I read awhile ago that you had no plans on upgrading it further, so I figured I'd give you a break :)

@jon: I will be releasing a set of scripts for GM that EXACTLY match (by name) the ones you get with the original 39dll. Any work that you have already done using those scripts will still accomplish roughly the same thing (so you simply delete those, and add mine). The plans I have for extending this will hopefully make everyone's life easier when it comes to network programming....heck, the grouping system and filtering system alone are quite needed.


@all: I have edited the original post, another update has been uploaded. I have now reached alpha-stage with the material, I am tired and I'm not sure what else to say, so good night guys....and let me know what you think!

Please give suggestions if you got them...would love to read them!
  • 0

Tutorials of Interest:
* Multiplayer: mine or True Valhalla's

Projects:
* Net39
* My 39dll scripts
* My 39dll lib
* Multiplayer Engine
* Artificial Chemistry

Posted Image

#23 TheMagicNumber

TheMagicNumber

    GMC Member

  • GMC Member
  • 5247 posts
  • Version:Unknown

Posted 21 October 2010 - 12:59 PM

When you receive said message in a c++ server, you have to do something like below:

That looks like how it is suppose to be done, so I'm not sure I follow. What have you tried to do and it failed to work?

The "problem" is that in GM, readstring() copies the string from the returned char* in the runner, but in C/C++, it doesn't. readstring() always returns the same value (except in this DLL where it may change when resized), the data stored at that location changes. Hopefully everybody can understand what's going on.
  • 1

#24 sabriath

sabriath

    12013

  • GMC Member
  • 3197 posts

Posted 21 October 2010 - 01:53 PM

The "problem" is that in GM, readstring() copies the string from the returned char* in the runner, but in C/C++, it doesn't. readstring() always returns the same value (except in this DLL where it may change when resized), the data stored at that location changes. Hopefully everybody can understand what's going on.

Oh, I see what you're saying now. Yes, GM will not properly free the char* pointer, instead it strcpy's it and expects the dll to take care of the memory management on the pointer...this is why it uses the same memory location for the pointer. The best thing you can do is either strcpy the return value into a new string, or simply call the "read" function directly (instead of the "read***" functions, which all call the "read" parent-type function).

void Buffer::read(void* dst, int size)
{
	if ((readpos + size) > count)
		size = count - readpos;
	if (size <= 0)
		return;
	memcpy(dst, data + readpos, size);
	readpos += size;
}

That's the code for 'read'....so if you want to read a string off the buffer using c++ tacked into these functions, do this instead:

int len = 1 + (int)strlen(mybuffer->data);
char* mystring = new char[len];
mybuffer->read(mystring, len);

Now "mystring" contains what you want, and you can pass the pointer around all day and not have to worry about the Buffer class destroying the data. You will be responsible for the memory management of that pointer though, just as a heads up.

If you are planning to use this AS a dll rather than link directly into the open-source files themselves, then you will need to unfortunately strcpy the return in order to preserve the data....I will not be doing a DLLEXPORT for functions outside the realm of GM possibility of use, sorry.
  • 0

Tutorials of Interest:
* Multiplayer: mine or True Valhalla's

Projects:
* Net39
* My 39dll scripts
* My 39dll lib
* Multiplayer Engine
* Artificial Chemistry

Posted Image

#25 TheMagicNumber

TheMagicNumber

    GMC Member

  • GMC Member
  • 5247 posts
  • Version:Unknown

Posted 21 October 2010 - 07:46 PM

GM isn't supposed to free the char* pointer. The location is the same because the value returned by readchars and readstring is always the same, the static buffer of 20000 chars.

Edited by TheMagicNumber, 21 October 2010 - 07:54 PM.

  • 1

#26 sabriath

sabriath

    12013

  • GMC Member
  • 3197 posts

Posted 22 October 2010 - 12:35 AM

GM isn't supposed to free the char* pointer. The location is the same because the value returned by readchars and readstring is always the same, the static buffer of 20000 chars.

Why wouldn't GM be responsible? Last time I checked, when you call a function that returns a pointer, then you should call a function with that pointer to free it....whether that function is in the dll, or just the memory manager itself, _you_ are responsible for the pointers on the caller side. GM just uses the pointer to copy data, then chucks it, this is (imo) irresponsible -- which also requires us dll programmers to use this stupid workaround of static memory.

I have given the code for the c++ bypass to GM's workaround...all good now :)
  • 0

Tutorials of Interest:
* Multiplayer: mine or True Valhalla's

Projects:
* Net39
* My 39dll scripts
* My 39dll lib
* Multiplayer Engine
* Artificial Chemistry

Posted Image

#27 TheMagicNumber

TheMagicNumber

    GMC Member

  • GMC Member
  • 5247 posts
  • Version:Unknown

Posted 22 October 2010 - 11:43 AM

So, if we want to keep this data, we should make a copy of it since GM needs to free one? :) You are also saying nobody should use stack allocated strings, it's not bad.

Whatever allocated it should free it, it makes the most sense.
  • 1

#28 sabriath

sabriath

    12013

  • GMC Member
  • 3197 posts

Posted 22 October 2010 - 12:19 PM

So, if we want to keep this data, we should make a copy of it since GM needs to free one?

The point is GM _doesn't_ free the pointer, it does a strcpy of the return and ignores the pointer (so if the DLL doesn't take care of the memory management of the string, the string will dangle in memory for the lifetime of the program....imagine a GM server reading 10 strings per second...the memory will max out pretty quickly). This is a flaw (imo) in GM, so if you want to use the functions provided as-is, you will need to use strcpy as well.

You are also saying nobody should use stack allocated strings, it's not bad.

The stack has a smaller boundary than the heap, it will run out far sooner than regular memory allocation. I could have used a "hack" to return the pointer in the stack for the string as a return to GM....but that's extremely bad programming because that space is considered frame_unknown the moment the DLL returns to GM...for all I know, GM could do several recursive calls in order to "read" this so-called string, at which point the string will be overwritten with new stack data. Cannot be trusted to use the stack in this way.

Whatever allocated it should free it, it makes the most sense.

Not quite....if that were the case, then "alloc" function should free it's own memory, since it's the function that actually "creates" the space of memory for your program to use. If you go *IN* to a function knowing that it returns a memory location, then that calling function _IS_ responsible for that pointer to be dealt with. Normally you would have a matching "free" function for every "alloc" type function, but GM doesn't pass anything by-reference, so I can't do that either. This is, for now, the best case for GM.


@All: I am almost complete with the GM scripts file, I should be finished today and can start getting to work on testing, thank you all for support/comments...please let me know your thoughts in the meantime!
  • 0

Tutorials of Interest:
* Multiplayer: mine or True Valhalla's

Projects:
* Net39
* My 39dll scripts
* My 39dll lib
* Multiplayer Engine
* Artificial Chemistry

Posted Image

#29 sabriath

sabriath

    12013

  • GMC Member
  • 3197 posts

Posted 22 October 2010 - 09:24 PM

Updated the main post, along with a new upload, which contains a GMK of all the original 39dll scripts (with exact same names).

*NOTE* This is still in Alpha, please take caution in use of this product, it has yet to be tested by myself, let alone anyone I know of. Feel free to browse through and see the inside of the project and comment/thoughts/ideas/etc. are welcome.
  • 0

Tutorials of Interest:
* Multiplayer: mine or True Valhalla's

Projects:
* Net39
* My 39dll scripts
* My 39dll lib
* Multiplayer Engine
* Artificial Chemistry

Posted Image

#30 Revel

Revel

    ɹǝqɯǝɯ ɔɯƃ

  • GMC Member
  • 4935 posts
  • Version:GM8

Posted 22 October 2010 - 09:55 PM

I took a glance at your socket code, and I've already found a massive problem.

From line 200:
size = recv(id, dbuff, 65536, 0);

Your receiving 65536 bytes of data. What happens if two "32768 byte" messages were stored on the sockets data queue? You would essentially be "receiving" them all as one packet which could be very bad for a game.

Your method also requires a constant 65536 byte buffer allocated.

I didn't really look at your sending/buffer set up, but the best way would be to have a 2 byte header at the beginning of every packet containing the size of the packet. When you receive a packet, you would read the 2 byte header, then read the rest of the data. That way sending multiple messages won't all be received as one giant message. With this method, you don't have to keep a 65536 buffer allocated, you simply allocate enough space for the packet. You could also implement a system where it expands/directly writes to the buffer without creating a second buffer.

Edited by Revel, 22 October 2010 - 09:56 PM.

  • 0

#31 sabriath

sabriath

    12013

  • GMC Member
  • 3197 posts

Posted 22 October 2010 - 10:48 PM

I took a glance at your socket code, and I've already found a massive problem.

From line 200:

size = recv(id, dbuff, 65536, 0);

Your receiving 65536 bytes of data.

I had 2 choices to go with...either read 1 byte at a time until I got a WSAEWOULDBLOCK error, or attempt to grab as much as I could in 1 shot and deal with whatever size returns. Reading 1 byte at a time (or even XXX byte-blocks at a time) in succession until a WSAEWOULDBLOCK _could_ possibly cause a stall (constantly reallocating memory for each new block on top of the successive reads and calling WSAGetLast each roll). I opted the choice to read in 64k (the maximum packet size) in 1 shot and be done. This is not set in stone, I can easily reduce the limits, or even make the dllInit function use an argument for the size of the backbuffer.

What happens if two "32768 byte" messages were stored on the sockets data queue?

Depends on what protocol it is...for UDP, each packet is separate entities and each "receive" of 64k will only grab the 32k each. TCP is a stream protocol, you are not guaranteed to receive the same size you sent...which means you could get 16k followed by 48k, or 32k/32k, or 64k/0k...this was the other _slight_ error that 39ster had not accounted for in his original.

What you see in the send/receive functions are the _raw_ options format, which buffers the data without caring about size of actual messages. I have plans for other formats, including filtering which I have gone over.

You would essentially be "receiving" them all as one packet which could be very bad for a game.

Your game is _suppose_ to be programmed as a continued read of data ANYWAY...something like:
while(bytesleft())
{
  switch(readbyte())
  {
    case whatever:
  }
}
Why else do you think 39ster put that function in there for? What do you think nagle does? These are no coincidences.

Your method also requires a constant 65536 byte buffer allocated.

Again, this can be reduced....figured 64k was no biggy, but I'll keep this on the front of my mind to change in the next update, 16k should be a fair size.

I didn't really look at your sending/buffer set up, but the best way would be to have a 2 byte header at the beginning of every packet containing the size of the packet.

39ster tried this as well, which was the problem I had with his TCP scheme. Let me show you a hypothetical example:

Johnny decides to send a message, "hello brian", to brian
This message is packaged as .25. (the byte code for "sending message to someone"), .31881. (the int code for _brian_s ID from the server), and "hello brian\0" (the text)
You "send" this to the 39dll, which you think it will just send it.....nooooo

1. it allocates space for the size of the buffer + 2 bytes (takes some time)
2. it writes 2 bytes to this new buffer denoting it's payload size
3. it memcopies the sent buffer to it (takes some time)
4. then it sends it

That's not that bad right? What if, for some reason (because in hypotheticals, things happen), the connection between 2 points of the cloud that Johnny and Brian both "communicate" over, can only take 48 byte payloads. This becomes a problem because our package is:

.17.25.31881."hello brian\0" + 40 bytes IP header
59 bytes total

IP is fragmentable, so guess what happens when this reaches our dead zone? In order for IP to fragment, it must add it's IP header to every piece of data in the split (along with some other things, but I'll keep it simple for now). This means our package has just turned into 3 packages:

40 bytes IP header + .17.25.31881."h"
40 bytes IP header + "ello bri"
40 bytes IP header + "an\0"

Let us now reach even further and say that these packages get to Brian's computer in this fashion, and GM "reads" them like so:

1. read in 2 bytes (at this point, it only has the first message) = .17.
2. read in 17 bytes of data = .25.31881."h" (recv function returns 6, because only those 6 bytes are currently in the window)
3. GM is given this message, which is not even finished
4. next call to "receivemessage" will read 2 bytes (which is the next message "el" is a pretty big number of bytes to read)
5. read in "el" bytes of data = "lo bri" (only 6 were available at this moment in the window)

etc. etc.

Obviously the internet doesn't have a 48 byte MTU anywhere...but there are places that do have a 1k MTU, and UDP is sometimes limited to even 572 bytes MTU (which is truncated, not fragmented in most cases). This might not be a problem in a tiny game with a few updates...but the server might send 4k data chunks per second per person just to update what OTHER people are doing, it adds up. When IP starts to fragment these huge chunks, your clients will start destroying data without even knowing, and GM will get back junk code messages.

I _do_ have plans to have a size format of "wait to receive" which will send back a "do not have a message yet" (0) until the 'bin' buffer for that socket has reached the amount given by its 2-byte header, then it will memmove up to the next position and read the next 2-byte header. This would severely dampen the speed of your communications, so it should only be used on things like chat channels and other not-time-crucial things, but it would be MUCH better than the current system.

Edited by sabriath, 22 October 2010 - 10:53 PM.

  • 1

Tutorials of Interest:
* Multiplayer: mine or True Valhalla's

Projects:
* Net39
* My 39dll scripts
* My 39dll lib
* Multiplayer Engine
* Artificial Chemistry

Posted Image

#32 Revel

Revel

    ɹǝqɯǝɯ ɔɯƃ

  • GMC Member
  • 4935 posts
  • Version:GM8

Posted 22 October 2010 - 11:10 PM

Depends on what protocol it is...for UDP, each packet is separate entities and each "receive" of 64k will only grab the 32k each. TCP is a stream protocol, you are not guaranteed to receive the same size you sent...which means you could get 16k followed by 48k, or 32k/32k, or 64k/0k...this was the other _slight_ error that 39ster had not accounted for in his original.

Any packet being sent over the Internet Protocol can be fragmented. All fragmentation is done "behind the scenes" by Winsock. Any fragmentation is done transparently and is only passed to the sockets data buffer after the full packet has been reassembled on the receiving end. You shouldn't be worrying about fragmentation since it's all handled automatically. So yes, when you send a TCP packet, after the receiving end is done its "back end" processing, the packet will be identical to what was sent, same size and everything.

1. read in 2 bytes (at this point, it only has the first message) = .17.
2. read in 17 bytes of data = .25.31881. (recv function returns 6, because only those 6 bytes are currently in the window)
3. GM is given this message, which is not even finished
4. next call to "receivemessage" will read 2 bytes (which is the next message "he" is a pretty big number of bytes to read)
5. read in "he" bytes of data = "llo br" (only 6 were available at this moment in the window)

The fragmented data won't be added to the sockets data buffer until the whole message has been received and reassembled. This means your entire message will be on the data buffer regardless of how much fragmentation was done to the packet.

1. it allocates space for the size of the buffer + 2 bytes (takes some time)
2. it writes 2 bytes to this new buffer denoting it's payload size
3. it memcopies the sent buffer to it (takes some time)
4. then it sends it


Yes, 39dll does it terribly.
The best way to do it would be to have the 2 byte header allocated in the buffer the entire time, so you don't have to go prepend it when you go to send the message. The easiest way would be to write everything at writepos+2, so you keep a "blank" 2 bytes at the beginning.



But now I understand that your receive method was just for the "Raw" method and you haven't added the packet header yet.


Also, are you planning on adding IPv6 support?

Edited by Revel, 22 October 2010 - 11:14 PM.

  • 0

#33 sabriath

sabriath

    12013

  • GMC Member
  • 3197 posts

Posted 23 October 2010 - 12:13 AM

So yes, when you send a TCP packet, after the receiving end is done its "back end" processing, the packet will be identical to what was sent, same size and everything.

http://www.rhyshaden.com/tcp.htm *check sliding window*
http://www.osischool...indow/index.php *nice little demo of the sliding window*

http://en.wikipedia....gle's_algorithm

Sooooo...not exactly. Unless there is another message band signal that I don't know about other than SYN, ACK, and FIN....is there a MSG_BLOCK_END signal?

The fragmented data won't be added to the sockets data buffer until the whole message has been received and reassembled. This means your entire message will be on the data buffer regardless of how much fragmentation was done to the packet.

I don't see how you figure this....messages have only 1 thing associated with them, and that's the sliding window SEQ value which is usually modded to some value based on the total size of the window buffer. When you "receive", you are grabbing what is on the left side of the MSS that has been flagged as "acknowledged," after which it will then be flagged as "sent to application."

When you "send" XXX bytes using the function, it appends that data into the buffer directly behind the last byte that was sent (and wrapping around back to the front, if you reach the LAR pointer, the rest of the message is truncated)...."send" function returns how many bytes actually made it onto this buffer. The throttle/congestion module will take care of sending the next set, flagging them as sent but not ACKed, and also resizing the window.

By the way, SEQ is a byte pointer indexed from the start of the buffer in memory...not the actual packets themselves, they are just appended to the end as I mentioned. Have a look at that java thing and imagine that each of those numbers are MTU sized blocks.

Yes, 39dll does it terribly.
The best way to do it would be to have the 2 byte header allocated in the buffer the entire time, so you don't have to go prepend it when you go to send the message. The easiest way would be to write everything at writepos+2, so you keep a "blank" 2 bytes at the beginning.

That does seem the best method on _sending_ the packets....and the method I roughly stated above is best for _receiving_ them, at least for reliability issues.

But now I understand that your receive method was just for the "Raw" method and you haven't added the packet header yet.

Exactly....the options could be endless..."options" of a socket currently is assigned these:

bit 0 = whether it is a listening socket, quick check for send/recv on these, quick returns an error
bits 1-3 = receiving options, giving 8 possibilities
bits 4-7 = sending options, giving 8 possibilities
bits 8-32 = unused for now

The options check is in a switch statement:
switch(options & 112) <-- located in 'Socket::Send'
switch(options & 14)  <-- located in 'Socket::Recv'
In each of those, you can find the "case 0:" for RAW formatting of the buffer data.

Also, are you planning on adding IPv6 support?

I am not a very good IPv6 guy, but I _do_ want to support it...it will have to go on the backburner though. There is really no point right now in using it because IPv6 is STILL being encapsulated in IPv4 headers for transmission, it's slow, and cumbersome. I would gladly switch....if I knew more about it lol. Going from 4 byte address to a 16 byte address _might_ be a little overkill? The header is HUGE as well, and they keep putting bandaids on a system that should be overhauled completely....but hey, no one owns the internets right lol
  • 1

Tutorials of Interest:
* Multiplayer: mine or True Valhalla's

Projects:
* Net39
* My 39dll scripts
* My 39dll lib
* Multiplayer Engine
* Artificial Chemistry

Posted Image

#34 Revel

Revel

    ɹǝqɯǝɯ ɔɯƃ

  • GMC Member
  • 4935 posts
  • Version:GM8

Posted 23 October 2010 - 01:19 AM

I think your thinking about it too deeply. Unless your using RAW (SOCK_RAW) sockets, you shouldn't be worrying about the details you are describing. Winsock takes care of all of that stuff for you. No matter what happens, the data will end up on the sockets data queue either one packet at a time, or multiple packets in the data queue as one block of data.

My original question was how you were going to separate the packets from eachother because you were simply reading 65k bytes off the data queue which provided no way of separating the packets. You have since mentioned that you have not yet added any method to do so, which has cleared some things up. I also missed the option checking code you had in the Send/Recv.
  • 0

#35 sabriath

sabriath

    12013

  • GMC Member
  • 3197 posts

Posted 23 October 2010 - 07:05 AM

@Revel: Currently the format is a raw read and raw write....which in TCP is a full stream. Data will continue to waterfall across the connection without boundary with this mode, which is exactly how it works in the real world anyway, but I'm not going to argue with you over that....moving on...

The next method I have in mind is exactly how you describe it. There is a 'Buffer*' (bin) already assigned to a socket when it is created (although this won't happen normally, it'll be created when the right option is set). When GM calls "receivemessage", it will check your options and see that you want perdetermined sized datablocks...so it will expand the size of 'bin' 16k (or whatever the default will be) from it's 'writepos', and attempt a 'recv' from the socket to this location. It will then update the 'writepos' based on how many bytes actually got read. If the size header has not been read yet, and the buffer is at least 2 bytes, grab the 2 bytes off and store in the size header. It will then check the 2 byte size header against the count of the buffer, if the buffer is not big enough, it will return with a "no message on queue" signal. If it is big enough, it will:

1. memcpy the size of the block to the targetted buffer
2. take the data following that block and memmove it up to the front '0' position
3. reduce the count by the size of the block, along with the readpos and writepos
4. return the size of the block to GM to let it know it has a full message block ready to read


When sending data, it's easier...whenever clearing the buffer in this mode, it will automatically start the offset at byte 2, the count will still show 0, and any attempts to setpos the pointers to it will not work. When "sendmessage" is called, it writes the size of the buffer in that 2 byte space and sends it.


There are plenty of other options to cover, this is just the second one that will be in the works when I'm finished testing all the functions and fixing the bugs. I start my real world job again tomorrow, so I won't have much time to spend on it as much, but if anyone would like to help, I would greatly appreciate it.
  • 0

Tutorials of Interest:
* Multiplayer: mine or True Valhalla's

Projects:
* Net39
* My 39dll scripts
* My 39dll lib
* Multiplayer Engine
* Artificial Chemistry

Posted Image

#36 safwat1995

safwat1995

    GMC Member

  • New Member
  • 394 posts
  • Version:Unknown

Posted 23 October 2010 - 07:25 AM

looks like 39dll is pretty much the same, but more efficient internally i guess?

Well the primary #1 reason for me doing this is because:
a = createbuffer();
b = createbuffer();
c = createbuffer();

freebuffer(b);

'c' now points to a NULL indexed address as far as 39dll is concerned, and whatever you "wrote" in 'c' buffer, will now be in addressed by 'b' even though it was freed.


could you please explain that further?
  • 0

#37 sabriath

sabriath

    12013

  • GMC Member
  • 3197 posts

Posted 23 October 2010 - 08:06 AM

could you please explain that further?

Had 39ster used the CList "Remove" functions, it would have done what I explained, but I retracted my argument because 39ster bypassed those functions altogether. The 39dll does not do what I stated, sorry for the panic.

The CList "Remove" function would compact the list of pointers, that's why I stated what I did. It's like when you "createbuffer" it puts a book on your desk, and do it again and another book goes on top, and this continues on and on. When you "freebuffer" I _thought_ he called the 'remove' function, which would remove your book from the table, but all the other books would fall down 1 slot. So when the guy goes looking for his book in the 10th position, it's not there.

Again, 39ster bypassed this, create/free buffer do what they are suppose to.
  • 0

Tutorials of Interest:
* Multiplayer: mine or True Valhalla's

Projects:
* Net39
* My 39dll scripts
* My 39dll lib
* Multiplayer Engine
* Artificial Chemistry

Posted Image

#38 39ster

39ster

    GMC Member

  • GMC Member
  • 898 posts

Posted 23 October 2010 - 08:31 AM

Here's an idea. Remove setformat(). Instead have separate functions to send and receive in different formats.

Example:

SendMessage(sockID, buffID); //Send a data message (two bytes at the front of the packet with is the length over TCP)
SendText(sockID, string); //Send a string (no formatting)
SendBytes(sockID, buffID); //Send a buffer(no formatting)

ReceiveMessage(sockID, buffID); //Receives a data message (using the two bytes for the length over TCP)
ReceiveText(sockID, delimiter); //Receives a string. Use delimiter to determine end of string (same as format mode 1)
ReceiveBytes(sockID, buffID, count); //Receives count amount of bytes from the socket

Easier than always having to switch format modes. You could also leave in the original scripts for compatibility.

Although the only problem i see is with ReceiveText() as it would return a string, it would be more difficult to check for socket errors.

Edited by 39ster, 23 October 2010 - 08:32 AM.

  • 0

#39 safwat1995

safwat1995

    GMC Member

  • New Member
  • 394 posts
  • Version:Unknown

Posted 23 October 2010 - 09:45 AM

SendMessage(sockID, buffID); //Send a data message (two bytes at the front of the packet with is the length over TCP)

I have always wondered, what are the two header bytes for?
  • 0

#40 -Tyler-

-Tyler-

    Online Programmer

  • GMC Member
  • 198 posts

Posted 23 October 2010 - 12:33 PM

SendMessage(sockID, buffID); //Send a data message (two bytes at the front of the packet with is the length over TCP)

I have always wondered, what are the two header bytes for?


Someone correct me if I'm wrong, but I believe they let 39dll know how many data bytes it should receive and copy to the buffer because the 2 bytes written are the buffer size. When you send the string "text\0" the packet is 47 bytes: 40 bytes for the TCP header, 2 bytes for the amount of data to receive (5 in the case), and 5 bytes for the message ("text" plus the one byte "\0" null to indicate the end of the string).
  • 0
Armageddon Online is in development...
This time, the everything will be in C++. And yes, it is still alive, even in October 2011.

#41 sabriath

sabriath

    12013

  • GMC Member
  • 3197 posts

Posted 23 October 2010 - 09:37 PM

@39ster: sounds like a good idea, but then the tutorial I'll write will get all complicated with "well which function should I use" questions *foreseeing the future* lol. I was planning on making the "choose your format" at the socket creation level, so "listen", "accept", and "connect" would all have an extra argument for format, but I'm not sure yet.

@safwat1995, -Tyler-: yes, the 2 bytes at the front of the message let 39dll know how many bytes to grab off the sliding window...which is a small problem with a streaming protocol, but it's ok. Not many applications use this method (websites don't for example), so this format is normally 39dll-only design.
  • 0

Tutorials of Interest:
* Multiplayer: mine or True Valhalla's

Projects:
* Net39
* My 39dll scripts
* My 39dll lib
* Multiplayer Engine
* Artificial Chemistry

Posted Image

#42 jon sploder

jon sploder

    GMC Member

  • GMC Member
  • 919 posts

Posted 23 October 2010 - 11:21 PM

@39ster: sounds like a good idea, but then the tutorial I'll write will get all complicated with "well which function should I use" questions *foreseeing the future* lol. I was planning on making the "choose your format" at the socket creation level, so "listen", "accept", and "connect" would all have an extra argument for format, but I'm not sure yet.


Surely you shouldn't decide what methods to used based on the questions that will be asked later on? :lol:
I for one are happy with having to program more for more efficiency.
I'm being left behind in understanding what you are technically talking about, but as for suggestions could you add in by default the crush scripts made by safwat1995; http://gmc.yoyogames...howtopic=484730 or something similar?
  • 0

#43 TheMagicNumber

TheMagicNumber

    GMC Member

  • GMC Member
  • 5247 posts
  • Version:Unknown

Posted 24 October 2010 - 12:43 AM

Whatever allocated it should free it, it makes the most sense.

Not quite....if that were the case, then "alloc" function should free it's own memory, since it's the function that actually "creates" the space of memory for your program to use. If you go *IN* to a function knowing that it returns a memory location, then that calling function _IS_ responsible for that pointer to be dealt with. Normally you would have a matching "free" function for every "alloc" type function, but GM doesn't pass anything by-reference, so I can't do that either. This is, for now, the best case for GM.

GM should never expect a heap-allocated string that it needs to free. It's perfectly fine the way it is. Now, if GML and how GM uses DLLs changed, maybe this would change.
  • 1

#44 sabriath

sabriath

    12013

  • GMC Member
  • 3197 posts

Posted 24 October 2010 - 10:15 AM

Surely you shouldn't decide what methods to used based on the questions that will be asked later on? :lol:
I for one are happy with having to program more for more efficiency.
I'm being left behind in understanding what you are technically talking about, but as for suggestions could you add in by default the crush scripts made by safwat1995; http://gmc.yoyogames...howtopic=484730 or something similar?

I will send him a message and ask if he'd be ok with me writing in his functions. Although I wouldn't need his help for such a simple task, I don't want to offend anyone's work.

GM should never expect a heap-allocated string that it needs to free. It's perfectly fine the way it is. Now, if GML and how GM uses DLLs changed, maybe this would change.

Well considering GM _knows_ that a 'char*' is a string, and the only way to get that string is to allocate for it...then it would make sense that GM should take responsibility of it. Just like if you were to ask your mom for some spaghetti, you should expect it to be on a plate, and when you get a plate, you should take care and put it in the sink when you're finished with it. What GM does is move the spaghetti onto its own plate (strcpy), and then leaves the other one on the table. I honestly don't understand why it just doesn't use the pointer AS it's own string, I mean you know very well that the data structure of the GM runner ends the string tag with a 'char*' to it (the spaghetti already comes with a plate....why move it to another plate?).

Look, I really don't want to argue with you about this, let's just agree to disagree about it. :)



@all: I tested some of the functions so far, and the following I have gotten to work (but the adjustments I've made have not been pushed to my host-a account yet, so be patient)....

dllinit
dllfree
iptouint
uinttoip
netconnected
getmacaddress
createbuffer
freebuffer
bufferexists
writebyte
readbyte
readshort
readushort

**md5string not working

That's all I've tested right now...I cannot get md5string to work properly, for some reason I keep getting the _address_ of the Ret pointer instead of the actual data inside...but when I deref the pointer, it tells me "cannot convert (char) into (char*)", it's pissing me off. If someone can look at that stuff, I would appreciate it.
  • 0

Tutorials of Interest:
* Multiplayer: mine or True Valhalla's

Projects:
* Net39
* My 39dll scripts
* My 39dll lib
* Multiplayer Engine
* Artificial Chemistry

Posted Image

#45 safwat1995

safwat1995

    GMC Member

  • New Member
  • 394 posts
  • Version:Unknown

Posted 24 October 2010 - 03:55 PM

...I will send him a message and ask if he'd be ok with me writing in his functions. Although I wouldn't need his help for such a simple task, I don't want to offend anyone's work.

39dll has given me the ability to create things I once considered impossible, I have to give something in return.
You may use crush freely :)

Edited by safwat1995, 24 October 2010 - 03:55 PM.

  • 1

#46 sabriath

sabriath

    12013

  • GMC Member
  • 3197 posts

Posted 24 October 2010 - 10:59 PM

39dll has given me the ability to create things I once considered impossible, I have to give something in return.
You may use crush freely :)


Alrighty then...the file has been updated along with other fixes I did. It now contains in Buffer class:

writebits(val, bitsize)
val = readbits(bitsize)

I can write the crush/uncrush scripts to adjust numbers based on a range and give these functions a proper bitsize. I have to get to work, but I will work on the rest a little later, I still am in the process of testing all the functions.

Thanks safwat1995 for letting me implement it.
  • 0

Tutorials of Interest:
* Multiplayer: mine or True Valhalla's

Projects:
* Net39
* My 39dll scripts
* My 39dll lib
* Multiplayer Engine
* Artificial Chemistry

Posted Image

#47 TheMagicNumber

TheMagicNumber

    GMC Member

  • GMC Member
  • 5247 posts
  • Version:Unknown

Posted 25 October 2010 - 12:20 AM

why move it to another plate.

39dll would want its memory back, having GM free the string automatically forces 39dll to allocate another string. It's simply not how it should be done. If it were your way, there will be cases where the DLL programmer will need to make a copy.
  • 1

#48 Ace

Ace

    GMC Member

  • GMC Member
  • 372 posts

Posted 25 October 2010 - 12:48 AM

@Sabriath:

We need some file sending functions (preferably p2p) that work without serious effort or understanding for the programmer. That's one of the things I had a hard time understanding (and still do to some extent) with 39dll is how to send a file quickly and efficiently (preferably with UDP) to other people connected to my game. Any chance at getting something like this in there? D:
  • 0
Posted Image Posted Image Online Fighting & Roleplay Game

ZERO ENGINE
Posted Image

#49 safwat1995

safwat1995

    GMC Member

  • New Member
  • 394 posts
  • Version:Unknown

Posted 25 October 2010 - 04:47 AM

what are the benefits of using this version instead of v2.5?

Edited by safwat1995, 25 October 2010 - 04:48 AM.

  • 0

#50 sabriath

sabriath

    12013

  • GMC Member
  • 3197 posts

Posted 25 October 2010 - 09:05 AM

39dll would want its memory back, having GM free the string automatically forces 39dll to allocate another string. It's simply not how it should be done. If it were your way, there will be cases where the DLL programmer will need to make a copy.

Why must you argue with me...I honestly don't get it. I have been doing this for 20+ years, maybe I mess up now-and-then, but I'm 100% positive on this. There is only 1 "good" programming practices when it comes to memory management:

make 2 functions, 1 to create the thing you want, and 1 to free it when you are done. Both these functions are part of the same library/cpp/code/whatever. For example, malloc/free, new/delete, open/closehandle, etc. etc.

The GM runner however does not do this, it never stores the pointer to the string at all...it copies the data and you lose the pointer. The runner NOR the programmer has no way of calling the "free" function to clean up the mess GM has left. This forces the responsibility for the pointer onto the dll.

Look at the malloc/free example. When a programmer considers using 'malloc' in his code, he is given a pointer to memory he can use....the "malloc" function assumes NO control over that area of memory anymore. He has also taken responsibility to call 'free' when finished to give the pointer back to 'malloc' for reassignment.

In this same way, GM runner calls a DLL function and gets a pointer...it also must assume control of that pointer, and allow a call to a type of "free" functionality to give the control back to the DLL when finished. The GM runner does not do this, it junks the pointer without caring at all about the memory. This forces dll programmers to write stupid "RetVal" wrapping code to make sure the memory doesn't leak like a sieve because GM disregards all pointers returned by it.

Also, it isn't about 39dll wanting it's memory back....remember, GM is loading 39dll in ITS space, not the other way around. GM is ASKING for a 'char*' return, therefore whatever memory 39dll allocates for it, GM is _suppose_ to be responsible. I do not understand how you cannot see this, but I'm not trying to make an enemy out of you.

We need some file sending functions (preferably p2p) that work without serious effort or understanding for the programmer. That's one of the things I had a hard time understanding (and still do to some extent) with 39dll is how to send a file quickly and efficiently (preferably with UDP) to other people connected to my game. Any chance at getting something like this in there? D:

Will do

what are the benefits of using this version instead of v2.5?

At this moment, organization, speed, and functionality. When all finished, it will be at LEAST 2x better than the original 39dll (hopefully I'm under-exaggerating that estimate). As I mentioned already, 39ster has stated that he had NO plans on continuing updating 39dll, and I am willing to work with the GMC members and add as many of their suggestions as I can.



edit:
@all - another file push along with editing of main post...nasty purple are the changes, I'm just picking colors at random to use for highlighting new material, sorry.

Edited by sabriath, 25 October 2010 - 10:36 AM.

  • 0

Tutorials of Interest:
* Multiplayer: mine or True Valhalla's

Projects:
* Net39
* My 39dll scripts
* My 39dll lib
* Multiplayer Engine
* Artificial Chemistry

Posted Image