• Welcome to Valhalla Legends Archive.
 

[C++] Need help interpreting stuff and questions answered.

Started by Sorc_Polgara, May 17, 2004, 06:23 PM

Previous topic - Next topic

Sorc_Polgara

I'm trying to use C++ with BNLS.  BNLSProtocolSpec.txt looks like a great resource, but I can't make anything of it atm.  I need to know a few things.
Quote
#define BNLS_NULL                       (0x00)
#define BNLS_CDKEY                      (0x01)
#define BNLS_LOGONCHALLENGE             (0x02)
#define BNLS_LOGONPROOF                 (0x03)
#define BNLS_CREATEACCOUNT              (0x04)
#define BNLS_CHANGECHALLENGE            (0x05)
#define BNLS_CHANGEPROOF                (0x06)
#define BNLS_UPGRADECHALLENGE           (0x07)
#define BNLS_UPGRADEPROOF               (0x08)
#define BNLS_VERSIONCHECK               (0x09)
#define BNLS_CONFIRMLOGON               (0x0a)
#define BNLS_HASHDATA                   (0x0b)
#define BNLS_CDKEY_EX                   (0x0c)
#define BNLS_CHOOSENLSREVISION          (0x0d)
#define BNLS_AUTHORIZE                  (0x0e)
#define BNLS_AUTHORIZEPROOF             (0x0f)
#define BNLS_REQUESTVERSIONBYTE         (0x10)
#define BNLS_VERIFYSERVER               (0x11)
#define BNLS_RESERVESERVERSLOTS         (0x12)
#define BNLS_SERVERLOGONCHALLENGE       (0x13)
#define BNLS_SERVERLOGONPROOF           (0x14)

1)  The BNLSProtocolSpec sheet has the above.  Do I need to put this into my program?  If so, do I put it into a header file or can I just put it at the top of my program?

Quote
BYTE: 8-bit unsigned integer.
CHAR: 8-bit signed integer.
WORD: 16-bit unsigned integer in Intel (little-endian) byte order.
SHORT: 16-bit signed integer in Intel (little-endian) byte order.
DWORD: 32-bit unsigned integer in Intel (little-endian) byte order.*
LONG: 32-bit signed integer in Intel (little-endian) byte order.
String: Null-terminated ANSI (multi-byte) string.
BOOL: Same as DWORD, but has only two valid values: TRUE (1), and FALSE (0).

2)  Sure... How do I use these though?  Are these data types?  

Quote(16 DWORDs) Data from SID_AUTH_ACCOUNTLOGON (0x53).

I'm thinking that "(16 DWORDs)" is telling me that I need 16 DWORD's, literally.  If this is what it means, how do I initialize 16 DWORDs?

Quote
The BNLS server listens on TCP/IP port 9367.
The official BNLS server is bnls.valhallalegends.com.

3)  I think I know how to set the TCP/IP port to 9367 for the BNLS server to listen, but I have no clue on what to do for the second line.

I think the code fpr setting the winsock port looks something like: "server.sin_port = hton ((unsigned short) 7654);"?

I need to know how to connect to "bnls.valhallalegends.com" using winsock?  Any C++ code for it?

Quote
BNLS_CDKEY (0x01)
-----------------
This message will encrypt your CD-key, and will reply with the properly encoded CD-key as it is supposed to

be sent in the message SID_AUTH_CHECK (0x51). It now works with CD-keys of all products.

(DWORD) Session key from Battle.net. This is the second DWORD in SID_AUTH_INFO (0x50).
(String) CD-key. No dashes or spaces.

Response:
---------
(BOOL) Success (TRUE if successful, FALSE otherwise). If this is FALSE, there is no more data in this

message.
(DWORD) Client session key.
(9 DWORDs) CD-key data.

4)  Here's the biggy questions.  Ok so, using winsock how the hell do you use this information 0o?

Quote
(DWORD) Session key from Battle.net. This is the second DWORD in SID_AUTH_INFO (0x50).
(String) CD-key. No dashes or spaces.

This tells me what it does in words, but I have no clue how to actually send this information to BNLS in code using winsock.  Can I get an example of some C++ code that shows how this information is being sent to BNLS through winsock?  The references to "SID_AUTH_INFO (0x50)" I recognize from bnetdocs.

Quote
(BOOL) Success (TRUE if successful, FALSE otherwise). If this is FALSE, there is no more data in this message.
(DWORD) Client session key.
(9 DWORDs) CD-key data.

This is what is sent back from BNLS?  If so, I understand why BNLS is sending first line "(BOOL)", but the other 2 lines have me kind of lost.  If BNLS is sending this information back then how do I store this stuff and use it with winsock?  Can I get a example of this in C++ code please?



Sorry for so many questions and being noob.  I just am frustrated a bit because I can't seem to find any existing source code that can answer my questions in simple terms.

Maddox

1) You can do either one, I like the put them in a seperate header file.

2) These are the definitions for data types. Most of these are defined in <windows.h> (if you're using windows).
typedef unsigned char BYTE;
typedef char CHAR;
typedef unsigned short WORD;
typedef short SHORT;
typedef unsigned long DWORD;
typedef long LONG;
typedef DWORD BOOL;

If you want 16 DWORDs then do DWORD Foo[16];

4) You might want to download some client software from pscode.com to look at socket stuff.

5) Most people use a buffer class to insert data and then send the contents to battle.net.

6) A client sessionkey is used as the salt to hash your password.
asdf.

MyndFyre

Quote from: Sorc_Polgara on May 17, 2004, 06:23 PM
I'm trying to use C++ with BNLS.  BNLSProtocolSpec.txt looks like a great resource, but I can't make anything of it atm.  I need to know a few things.
Okay.

Quote from: Sorc_Polgara on May 17, 2004, 06:23 PM


#define BNLS_NULL                       (0x00)
#define BNLS_CDKEY                      (0x01)
#define BNLS_LOGONCHALLENGE             (0x02)
#define BNLS_LOGONPROOF                 (0x03)
#define BNLS_CREATEACCOUNT              (0x04)
#define BNLS_CHANGECHALLENGE            (0x05)
#define BNLS_CHANGEPROOF                (0x06)
#define BNLS_UPGRADECHALLENGE           (0x07)
#define BNLS_UPGRADEPROOF               (0x08)
#define BNLS_VERSIONCHECK               (0x09)
#define BNLS_CONFIRMLOGON               (0x0a)
#define BNLS_HASHDATA                   (0x0b)
#define BNLS_CDKEY_EX                   (0x0c)
#define BNLS_CHOOSENLSREVISION          (0x0d)
#define BNLS_AUTHORIZE                  (0x0e)
#define BNLS_AUTHORIZEPROOF             (0x0f)
#define BNLS_REQUESTVERSIONBYTE         (0x10)
#define BNLS_VERIFYSERVER               (0x11)
#define BNLS_RESERVESERVERSLOTS         (0x12)
#define BNLS_SERVERLOGONCHALLENGE       (0x13)
#define BNLS_SERVERLOGONPROOF           (0x14)


1)  The BNLSProtocolSpec sheet has the above.  Do I need to put this into my program?  If so, do I put it into a header file or can I just put it at the top of my program?
If you don't put it into your program then having the definitions won't do you too much good, will it?  You don't *HAVE* to put them in there, but it might just help. ^_^

Quote from: Sorc_Polgara on May 17, 2004, 06:23 PM
Quote
BYTE: 8-bit unsigned integer.
CHAR: 8-bit signed integer.
WORD: 16-bit unsigned integer in Intel (little-endian) byte order.
SHORT: 16-bit signed integer in Intel (little-endian) byte order.
DWORD: 32-bit unsigned integer in Intel (little-endian) byte order.*
LONG: 32-bit signed integer in Intel (little-endian) byte order.
String: Null-terminated ANSI (multi-byte) string.
BOOL: Same as DWORD, but has only two valid values: TRUE (1), and FALSE (0).
2)  Sure... How do I use these though?  Are these data types?  
You might just be onto something.

typedef unsigned char BYTE;
typedef unsigned short int WORD;
typedef short int SHORT;
typedef unsigned long int DWORD
typedef long int LONG;
typedef char* NTSTRING;
typedef DWORD BOOL;


Quote from: Sorc_Polgara on May 17, 2004, 06:23 PM
Quote(16 DWORDs) Data from SID_AUTH_ACCOUNTLOGON (0x53).
I'm thinking that "(16 DWORDs)" is telling me that I need 16 DWORD's, literally.  If this is what it means, how do I initialize 16 DWORDs?
You're really a genius.  I don't even program in C++.

DWORD dwords[16] = malloc(sizeof(DWORD) * 16);


Quote from: Sorc_Polgara on May 17, 2004, 06:23 PM

Quote
BNLS_CDKEY (0x01)
-----------------
This message will encrypt your CD-key, and will reply with the properly encoded CD-key as it is supposed to

be sent in the message SID_AUTH_CHECK (0x51). It now works with CD-keys of all products.

(DWORD) Session key from Battle.net. This is the second DWORD in SID_AUTH_INFO (0x50).
(String) CD-key. No dashes or spaces.

Response:
---------
(BOOL) Success (TRUE if successful, FALSE otherwise). If this is FALSE, there is no more data in this

message.
(DWORD) Client session key.
(9 DWORDs) CD-key data.

3)  Here's the biggy questions.  Ok so, using winsock how the hell do you use this information 0o?


typedef struct bnls_cdkey_send {
 DWORD bnls_product_id,
 NTSTRING cd_key
} BNLS_CDKEY_SEND, *LP_BNLS_CDKEY_SEND;
typedef struct bnls_cdkey_recv {
 BOOL success,
 DWORD client_session_key,
 DWORD encrypted_cd_key[9]
} BNLS_CDKEY_RECV, *LP_BNLS_CDKEY_RECV;

It occurs to me that if you wanted to be fancy, you might be able to do something like this:


typedef struct bnls_cdkey_recv {
union {
 struct bnls_cdkey_recv_success {
   BOOL success,
   DWORD client_session_key,
   DWORD[9] encrypted_cd_key
 },
 struct bnls_cdkey_recv_failure {
   BOOL success
 }
}
} BNLS_CDKEY_RECV, *LP_BNLS_CDKEY_RECV;

but I'm not entirely certain about the semantic differences between structs within unions.

OK, I'm done flaming you.  Here are some helpful things to know or to learn:

1.) Understand how data is stored in memory and how it is subsequently transmitted over the network wire.  With that, understand what a data type is (for example, a DWORD is simply a 32-bit integer -- 4 bytes -- with a special characteristic: it is unsigned (it is not interpreted as negative).  32-bit compilers tend to indicate this as just an unsigned int, or older compilers use unsigned long int.  That's what's in the typedefs that I gave you.
2.) Understand that BNLS is simply a service to perform the encryption used to authenticate to Battle.net.  It isn't a Battle.net Chat Server or anything of the like.
3.) Understand the appropriate usage of headers and #defines in C/C++.  You can define those BNLS message constants at the top of each of your source code files, or you can create another file, such as BnlsMsgs.h, and #include that file into the rest of your files that reference it.

[edit]Lmao, Maddox.  I was summoned away for about an hour after I finished all but the last couple things I said in this post.  I think it's funny we posted nearly the exact same thing.  ;)
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.

Sorc_Polgara

Great.  Thanks for the info.

I still don't know how to send a packet or w/e to BNLS using winsock.  Myndfyres example I don't think shows an example of sending it to BNLS through winsock.


Quote
The BNLS server listens on TCP/IP port 9367.
The official BNLS server is bnls.valhallalegends.com.

I think I know how to set the TCP/IP port to 9367 for the BNLS server to listen, but I have no clue on what to do for the second line.

I think the code fpr setting the winsock port looks something like: "server.sin_port = hton ((unsigned short) 9367);"?

I need to know how to connect to "bnls.valhallalegends.com" using winsock?  Any C++ code for it?

Eibro

I'm going to type a bunch of code in the forum textbox. God help me if I make a mistake.
// Connecting to BNLS (or any other address...)

const char* kBNLSAddress = "bnls.valhallalegends.com";
const u_short kBNLSPort = 9367;

// Create our socket
SOCKET sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );

// Resolve hostname & fill remote addr structure
HOSTENT* lpHost = gethostbyname( kBNLSAddress );
sockaddr_in inAddr;
inAddr.sin_family = AF_INET;
inAddr.sin_port = htons( kBNLSPort );
inAddr.sin_addr.S_un.S_addr = *(ULONG*)lpHost->h_addr_list[0];
ZeroMemory( inAddr.sin_zero, sizeof( inAddr.sin_zero ) );

if ( connect( sock, (sockaddr*)&inAddr, sizeof( sockaddr_in ) ) == 0 )
   printf( "Connected to BNLS\n!" );

Eibro of Yeti Lovers.

MyndFyre

Make sure you include the appropriate headers and link approrpiate libraries (Winsock2.h and Ws2_32.lib come to mind).
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.

Sorc_Polgara

#6
Wow, thanks alot Eibro[yL].


One last thing (I hope), then I will shutup (perhaps).

Quote
BNLS message format:

(WORD) Message size, including this 3-byte header
(BYTE) Message ID
(....) Message-dependant data

A message and its response have the same ID. (The response to BNLS_CDKEY is BNLS_CDKEY, etc)

Quote
BNLS_AUTHORIZE (0x0e)
---------------------
This message logs on to the BNLS server.

(String) Bot ID.

Response:
---------
If the bot ID isn't recognized by the server, the connection is terminated.
Otherwise, a response is sent:

(DWORD) Server code.



How would I send the "(String) Bot ID." to BNLS server using that BNLS message format?  When I recieve the response "(DWORD) Server code." from the BNLS server, how would I handle it?  Some C++ code please.


Thanks

Zakath

Are you familiar with socket handling basics? You send it by creating a buffer containing the proper BNLS packet header, followed by that string. Then you use the send() function to transmit it.

The server code can be obtained by calling recv() when the reply arrives, and then changing the data from a char * to a DWORD.
Quote from: iago on February 02, 2005, 03:07 PM
Yes, you can't have everybody...contributing to the main source repository.  That would be stupid and create chaos.

Opensource projects...would be dumb.