• Welcome to Valhalla Legends Archive.
 

C++ Basic Connection

Started by Trunning, March 27, 2010, 03:25 AM

Previous topic - Next topic

Trunning

Basically I'm stuck at receiving, I'm not sure if I have to put the pingval in a struct with the header, msgid and length. Or if I'm even receiving correctly, but if I'm doing anything wrong help is appreciated.

So if you can steer me in the right direction, I'd appreciated that.

#pragma comment(lib, "Ws2_32.lib")
#include <windows.h>
#include <winsock.h>
#include <string>
#include <iostream>
using namespace std;

int main(){
  WSADATA wsaData;

  WSAStartup(MAKEWORD(2,0), &wsaData);

  LPHOSTENT host;

  host = gethostbyname("asia.battle.net");

  if (!host)
  {
     MessageBox(NULL, "Host error", "", MB_OK);
     WSACleanup();
     return 0;
  }

  SOCKET theSocket;
  SOCKET theBnet;

  theSocket = socket(AF_INET,
                 SOCK_STREAM,
                 IPPROTO_TCP);

  theBnet = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

  if (theSocket == INVALID_SOCKET)
  {
     MessageBox(NULL, "theSocket bad...", "", MB_OK);
     WSACleanup();
     return 0;
  }

  if (theBnet == INVALID_SOCKET)
  {
  MessageBox(NULL, "Bnet socket bad...", "", MB_OK);
  WSACleanup();
  return 0;
  }

  SOCKADDR_IN info;

  info.sin_family = AF_INET;
  info.sin_addr = *((LPIN_ADDR)*host->h_addr_list);
  info.sin_port = htons(6112);

  int con;
  con = connect(theSocket, (LPSOCKADDR)&info, sizeof(info));

  if (con == SOCKET_ERROR)
  {
     MessageBox(NULL, (LPCSTR)WSAGetLastError(), "", MB_OK);
     WSACleanup();
     return 0;
  }

  struct SID_AUTH_INFO {
     BYTE   Header;
     BYTE   MsgID;
     WORD   wLen;
     DWORD   ProtocolID;
     DWORD   PlatformID;
     DWORD   ProductID;
     DWORD   VerByte;
     DWORD   ProductLang;
     DWORD   LocalIP;
     DWORD   TimeZone;
     DWORD   LocaleID;
     DWORD   LangID;
     char   CountryAbr[4];
     char   Country[10];
  } Packet;
 
  Packet.Header      = 0xFF;
  Packet.MsgID      = 0x50;
  Packet.wLen         = sizeof(SID_AUTH_INFO);
  Packet.ProtocolID   = 0x0;
  Packet.PlatformID   = '68XI';
  Packet.ProductID   = 'DV2D';
  Packet.VerByte      = 0x0D;
  Packet.ProductLang   = 0;
  Packet.LocalIP      = inet_addr("192.168.1.100");
  Packet.TimeZone      = 600;
  Packet.LocaleID      = 0;
  Packet.LangID      = (DWORD)GetUserDefaultLangID();
  strcpy(Packet.CountryAbr, "Aus");
  strcpy(Packet.Country, "Australia");

  DWORD PingVal;

  bind(theBnet, (LPSOCKADDR)&info, sizeof(info));

  cout << "Sending 0x50... " << send(theSocket, (const char*)&Packet, sizeof(SID_AUTH_INFO), NULL) << " bytes sent\n\n";

  recv(theBnet, (char *)&PingVal, sizeof(PingVal), NULL);

  cout << PingVal;

  // for testing purposes
  char n;
  cin >> n;
  closesocket(theBnet);
  closesocket(theSocket);
  return 0;
}

brew

#1
Quote from: Trunning on March 27, 2010, 03:25 AM
Basically I'm stuck at receiving, I'm not sure if I have to put the pingval in a struct with the header, msgid and length. Or if I'm even receiving correctly, but if I'm doing anything wrong help is appreciated.

So if you can steer me in the right direction, I'd appreciated that.

#pragma comment(lib, "Ws2_32.lib")
#include <windows.h>
#include <winsock.h>
#include <string>
#include <iostream>
using namespace std;

int main(){
  WSADATA wsaData;

  WSAStartup(MAKEWORD(2,0), &wsaData);

  LPHOSTENT host;

  host = gethostbyname("asia.battle.net");

  if (!host)
  {
     MessageBox(NULL, "Host error", "", MB_OK);
     WSACleanup();
     return 0;
  }

  SOCKET theSocket;
  SOCKET theBnet;

  theSocket = socket(AF_INET,
                 SOCK_STREAM,
                 IPPROTO_TCP);

  theBnet = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

  if (theSocket == INVALID_SOCKET)
  {
     MessageBox(NULL, "theSocket bad...", "", MB_OK);
     WSACleanup();
     return 0;
  }

  if (theBnet == INVALID_SOCKET)
  {
  MessageBox(NULL, "Bnet socket bad...", "", MB_OK);
  WSACleanup();
  return 0;
  }

  SOCKADDR_IN info;

  info.sin_family = AF_INET;
  info.sin_addr = *((LPIN_ADDR)*host->h_addr_list);
  info.sin_port = htons(6112);

  int con;
  con = connect(theSocket, (LPSOCKADDR)&info, sizeof(info));

  if (con == SOCKET_ERROR)
  {
     MessageBox(NULL, (LPCSTR)WSAGetLastError(), "", MB_OK);
     WSACleanup();
     return 0;
  }

  struct SID_AUTH_INFO {
     BYTE   Header;
     BYTE   MsgID;
     WORD   wLen;
     DWORD   ProtocolID;
     DWORD   PlatformID;
     DWORD   ProductID;
     DWORD   VerByte;
     DWORD   ProductLang;
     DWORD   LocalIP;
     DWORD   TimeZone;
     DWORD   LocaleID;
     DWORD   LangID;
     char   CountryAbr[4];
     char   Country[10];
  } Packet;
 
  Packet.Header      = 0xFF;
  Packet.MsgID      = 0x50;
  Packet.wLen         = sizeof(SID_AUTH_INFO);
  Packet.ProtocolID   = 0x0;
  Packet.PlatformID   = '68XI';
  Packet.ProductID   = 'DV2D';
  Packet.VerByte      = 0x0D;
  Packet.ProductLang   = 0;
  Packet.LocalIP      = inet_addr("192.168.1.100");
  Packet.TimeZone      = 600;
  Packet.LocaleID      = 0;
  Packet.LangID      = (DWORD)GetUserDefaultLangID();
  strcpy(Packet.CountryAbr, "Aus");
  strcpy(Packet.Country, "Australia");

  DWORD PingVal;

  bind(theBnet, (LPSOCKADDR)&info, sizeof(info));

  cout << "Sending 0x50... " << send(theSocket, (const char*)&Packet, sizeof(SID_AUTH_INFO), NULL) << " bytes sent\n\n";

  recv(theBnet, (char *)&PingVal, sizeof(PingVal), NULL);

  cout << PingVal;

  // for testing purposes
  char n;
  cin >> n;
  closesocket(theBnet);
  closesocket(theSocket);
  return 0;
}


Lots of problems here.
The first thing that jumped out at me was the fact that your packet IDs are backwards... why? 'VD2D', '68XI', etc. The ill-gotten advice to write IDs backwards originated from the fact that nearly all bot 'developers' used VB6, and inserted that data as a binary string. You obviously don't do this since it's stored in that struct little-endian (I assume you're using a little-endian platform).
The next problem - you don't ever send the data! Before doing that, however, note that a single identification byte of 0x01 with no header of any sort must be sent after connection and before all other battle.net traffic.
Also, your size parameter is wrong. It includes the length of the header (4), and the length of the strings are not usually constant. You're just getting away with it for this packet because there's no variation from logon to logon.
Why are you recving on a different socket? theBnet is not in the connected state.



You might want to look into a basic socket tutorial.
<3 Zorm
Quote[01:08:05 AM] <@Zorm> haha, me get pussy? don't kid yourself quik
Scio te esse, sed quid sumne? :P

Trunning

Based on everything you said I changed as much as I could. I'm still not getting any data back.

#pragma comment(lib, "Ws2_32.lib")
#include <windows.h>
#include <winsock.h>
#include <string>
#include <iostream>
using namespace std;

int main(){
struct SID_AUTH_INFO {
BYTE   Header;
BYTE   MsgID;
WORD   wLen;
DWORD   ProtocolID;
DWORD   PlatformID;
DWORD   ProductID;
DWORD   VerByte;
DWORD   ProductLang;
DWORD   LocalIP;
DWORD   TimeZone;
DWORD   LocaleID;
DWORD   LangID;
char   CountryAbr[4];
char   Country[10];
} Packet;
   
Packet.Header      = 0xFF;
Packet.MsgID      = 0x50;
Packet.ProtocolID   = 0x0;
Packet.PlatformID   = 'IX86';
Packet.ProductID   = 'D2DV';
Packet.VerByte      = 0x0D;
Packet.ProductLang   = 0;
Packet.LocalIP      = inet_addr("192.168.1.100");
Packet.TimeZone      = 600;
Packet.LocaleID      = 0;
Packet.LangID      = (DWORD)GetUserDefaultLangID();
Packet.wLen         = sizeof(SID_AUTH_INFO);
strcpy(Packet.CountryAbr, "Aus");
strcpy(Packet.Country, "Australia");
int size = sizeof((Packet.MsgID) & (Packet.ProtocolID) & (Packet.PlatformID) & (Packet.ProductID) & (Packet.VerByte) & (Packet.ProductLang) & (Packet.LocalIP) & (Packet.TimeZone) & (Packet.LocaleID) & (Packet.LangID) );
DWORD Pre = 0x01;

DWORD PingVal;

int con;
WSADATA wsaData;

WSAStartup(MAKEWORD(2,0), &wsaData);

LPHOSTENT host;

host = gethostbyname("useast.battle.net");

if (!host)
{
  MessageBox(NULL, "Host error", "", MB_OK);
  WSACleanup();
  return 0;
}

SOCKET theSocket;

theSocket = socket(AF_INET,
  SOCK_STREAM,
  IPPROTO_TCP);

if (theSocket == INVALID_SOCKET)
{
  MessageBox(NULL, "theSocket bad...", "", MB_OK);
  WSACleanup();
  return 0;
}

SOCKADDR_IN info;

info.sin_family = AF_INET;
info.sin_addr = *((LPIN_ADDR)*host->h_addr_list);
info.sin_port = htons(6112);

con = connect(theSocket, (LPSOCKADDR)&info, sizeof(info));

if (con == SOCKET_ERROR)
{
  MessageBox(NULL, (LPCSTR)WSAGetLastError(), "", MB_OK);
  WSACleanup();
  return 0;
}

cout << "Sending 0x01...\n";
con = send(theSocket, (const char*)&Pre, sizeof(Pre), NULL);
if (con > 0){
cout << con << " bytes sent\n";
} else {
cout << "Nothing sent!\n";
}

cout << "Sending 0x50...\n";
con = send(theSocket, (const char*)&Packet, size, NULL);
if ( con > 0 ){
   cout << con << " bytes sent\n";
} else {
   cout << "Nothing sent!\n";
}

/*
con = bind(theSocket, (LPSOCKADDR)&info, sizeof(info));
if (con == SOCKET_ERROR){
cout << WSAGetLastError();

int n;
cin >>n;
WSACleanup();
return 0;
}*/

listen(theSocket, 2);
con = recv(theSocket, (char*)&PingVal, sizeof(PingVal), NULL);
if (con > 0){
cout << "Ping cookie: " << PingVal;
} else {
cout << "Nothing received!\n";
}

// for testing purposes
char n;
cin >> n;
closesocket(theSocket);
return 0;
}

brew

Quote from: Trunning on March 27, 2010, 09:08 PM
Based on everything you said I changed as much as I could. I'm still not getting any data back.

...
DWORD Pre = 0x01;
...



Quote from: brew on March 27, 2010, 08:40 AM
note that a single identification byte of 0x01

Also, keep in mind that the response is an 0x25 packet with the standard BNCS header, that just happens to contain a single dword of the ping value.

I strongly suggest you generalize your code more.
<3 Zorm
Quote[01:08:05 AM] <@Zorm> haha, me get pussy? don't kid yourself quik
Scio te esse, sed quid sumne? :P

Trunning

I changed Pre to a byte, still not receiving anything. And I'll organize it more when I've got working code.

Yegg

Maybe I'm not adding anything here that directly solves your issue, but this can be very helpful. I have not taken a look at your code (just briefly), but have you monitored network data being sent to and from the Bnet server while running your code?
Since it seems you're new to this area of programming (or, computers, really), you'll need a packet logger (maybe you already know this).

Install Wireshark: http://www.wireshark.org/download.html

There's nothing you need to set up in the program. Simply select your network interface you wish to monitor (it will list the network devices that are connected to your pc -- such as Ethernet). You'll want to add a filter so that it reports packets of data that are to or from the server you are connecting to ("useast.battle.net" for instance). If you dont filter it this way, you will hundreds of other packets being listed on the Wireshark window immediately and you wont be able to find your Battle.net ones.

Again, while this isn't directly solving your issue, you can't possibly know exactly what is happening on the network when your code is executed, by just looking at the console or GUI to your program. At least if you saw what a packet logger sees, it may help you out in a few areas. For all you know, certain data has been sent but your program failed to display it on the screen for one reason or another (of course, this is just a stab in the dark). In any event.. it's extremely useful to know how to effectively use a packet logger when getting into any kind of network related programming.

Try out Wireshark, do as I mentioned, and see what you may or may not be able to figure out with it.

If you need help, you can of course ask me or someone else here (I'm also sure most programmers here can or do use Wireshark).

Trunning

I'm not new to computers or C++, just combining C++ and Battle.net.

And I've got Wireshark already. I checked what the client Diablo 2 sent, and then my program, the start is different. I was hoping someone would tell me what I'm doing wrong.

brew

#7
Quote from: Trunning on March 28, 2010, 01:41 AM
I'm not new to computers or C++, just combining C++ and Battle.net.

And I've got Wireshark already. I checked what the client Diablo 2 sent, and then my program, the start is different. I was hoping someone would tell me what I'm doing wrong.

Well, in your latest rendition of your code, you seemed to have omitted the size field of the header entirely. The length is a 16 little-endian int which is equal to the length of the data you're sending, minus the size of the standard BNCS header, which is 4. In other words


Packet.wLen         = sizeof(SID_AUTH_INFO);


is wrong.

Why are you still doing that, you said you fixed it in your earlier post? You don't get any data because it's expecting 4 more bytes than you're sending it.


P.S.
You really don't that call to bind(). That socket is already 'bound' to that connection.
<3 Zorm
Quote[01:08:05 AM] <@Zorm> haha, me get pussy? don't kid yourself quik
Scio te esse, sed quid sumne? :P

Trunning

Ok this isn't working, how about you just fix my code, then I can learn from that.

#pragma comment(lib, "Ws2_32.lib")
#include <windows.h>
#include <winsock.h>
#include <string>
#include <iostream>
using namespace std;

int main(){
struct SID_AUTH_INFO {
BYTE   Header;
BYTE   MsgID;
WORD   wLen;
DWORD   ProtocolID;
DWORD   PlatformID;
DWORD   ProductID;
DWORD   VerByte;
DWORD   ProductLang;
DWORD   LocalIP;
DWORD   TimeZone;
DWORD   LocaleID;
DWORD   LangID;
char   CountryAbr[4];
char   Country[10];
} Packet;
   
Packet.Header      = 0xFF;
Packet.MsgID      = 0x50;
Packet.ProtocolID   = 0x0;
Packet.PlatformID   = 'IX86';
Packet.ProductID   = 'D2DV';
Packet.VerByte      = 0x0D;
Packet.ProductLang   = 0;
Packet.LocalIP      = inet_addr("192.168.1.100");
Packet.TimeZone      = 600;
Packet.LocaleID      = 0;
Packet.LangID      = (DWORD)GetUserDefaultLangID();
Packet.wLen         = sizeof(SID_AUTH_INFO);
strcpy(Packet.CountryAbr, "Aus");
strcpy(Packet.Country, "Australia");
int size = sizeof((Packet.MsgID) & (Packet.ProtocolID) & (Packet.PlatformID) & (Packet.ProductID) & (Packet.VerByte) & (Packet.ProductLang) & (Packet.LocalIP) & (Packet.TimeZone) & (Packet.LocaleID) & (Packet.LangID) );
DWORD Pre = 0x01;

BYTE PingVal;

int con;
WSADATA wsaData;

WSAStartup(MAKEWORD(2,0), &wsaData);

LPHOSTENT host;

host = gethostbyname("useast.battle.net");

if (!host)
{
  MessageBox(NULL, "Host error", "", MB_OK);
  WSACleanup();
  return 0;
}

SOCKET theSocket;

theSocket = socket(AF_INET,
  SOCK_STREAM,
  IPPROTO_TCP);

if (theSocket == INVALID_SOCKET)
{
  MessageBox(NULL, "theSocket bad...", "", MB_OK);
  WSACleanup();
  return 0;
}

SOCKADDR_IN info;

info.sin_family = AF_INET;
info.sin_addr = *((LPIN_ADDR)*host->h_addr_list);
info.sin_port = htons(6112);

con = connect(theSocket, (LPSOCKADDR)&info, sizeof(info));

if (con == SOCKET_ERROR)
{
  MessageBox(NULL, (LPCSTR)WSAGetLastError(), "", MB_OK);
  WSACleanup();
  return 0;
}

cout << "Sending 0x01...\n";
con = send(theSocket, (const char*)&Pre, sizeof(Pre), NULL);
if (con > 0){
cout << con << " bytes sent\n";
} else {
cout << "Nothing sent!\n";
}

cout << "Sending 0x50...\n";
con = send(theSocket, (const char*)&Packet, size, NULL);
if ( con > 0 ){
   cout << con << " bytes sent\n";
} else {
   cout << "Nothing sent!\n";
}

con = recv(theSocket, (char*)&PingVal, sizeof(PingVal), NULL);
if (con > 0){
cout << "Ping cookie: " << PingVal;
break;
}

// for testing purposes
char n;
cin >> n;
closesocket(theSocket);
return 0;
}

rabbit

I suggest you look into using a packet buffer class ("DM's packet buffer" seems to be popular).  It will allow you to construct packets in a generalized fashion and you won't have to create a struct for each packet.

Anyway, with your code, you declare and set variable size, but nowhere do I see "Packet.wLen = size", so your packet header says the packet's length is 0.
Grif: Yeah, and the people in the red states are mad because the people in the blue states are mean to them and want them to pay money for roads and schools instead of cool things like NASCAR and shotguns.  Also, there's something about ketchup in there.

brew

#10
#pragma comment(lib, "Ws2_32.lib")
#include <windows.h>
#include <winsock.h>
#include <string>
#include <iostream>
using namespace std;

int main(){
struct SID_AUTH_INFO {
BYTE   Header;
BYTE   MsgID;
WORD   wLen;
DWORD   ProtocolID;
DWORD   PlatformID;
DWORD   ProductID;
DWORD   VerByte;
DWORD   ProductLang;
DWORD   LocalIP;
DWORD   TimeZone;
DWORD   LocaleID;
DWORD   LangID;
char   CountryAbr[4];
char   Country[10];
} Packet;
 
Packet.Header      = 0xFF;
Packet.MsgID      = 0x50;
Packet.ProtocolID   = 0x0;
Packet.PlatformID   = 'IX86';
Packet.ProductID   = 'D2DV';
Packet.VerByte      = 0x0D;
Packet.ProductLang   = 0;
Packet.LocalIP      = inet_addr("192.168.1.100");
Packet.TimeZone      = 600;
Packet.LocaleID      = 0;
Packet.LangID      = (DWORD)GetUserDefaultLangID();
Packet.wLen         = sizeof(SID_AUTH_INFO) - 4;
strcpy(Packet.CountryAbr, "Aus");
strcpy(Packet.Country, "Australia");
/*int size = sizeof((Packet.MsgID) & (Packet.ProtocolID) & (Packet.PlatformID) & (Packet.ProductID) & (Packet.VerByte) & (Packet.ProductLang) & (Packet.LocalIP) & (Packet.TimeZone) & (Packet.LocaleID) & (Packet.LangID) );
DWORD Pre = 0x01;*/

BYTE PingPacket[8];

int con;
WSADATA wsaData;

WSAStartup(MAKEWORD(2,0), &wsaData);

LPHOSTENT host;

host = gethostbyname("useast.battle.net");

if (!host)
{
 MessageBox(NULL, "Host error", "", MB_OK);
 WSACleanup();
 return 0;
}

SOCKET theSocket;

theSocket = socket(AF_INET,
 SOCK_STREAM,
 IPPROTO_TCP);

if (theSocket == INVALID_SOCKET)
{
 MessageBox(NULL, "theSocket bad...", "", MB_OK);
 WSACleanup();
 return 0;
}

SOCKADDR_IN info;

info.sin_family = AF_INET;
info.sin_addr = *((LPIN_ADDR)*host->h_addr_list);
info.sin_port = htons(6112);

con = connect(theSocket, (LPSOCKADDR)&info, sizeof(info));

if (con == SOCKET_ERROR)
{
 MessageBox(NULL, (LPCSTR)WSAGetLastError(), "", MB_OK);
 WSACleanup();
 return 0;
}

cout << "Sending 0x01...\n";
con = send(theSocket, "\x01", 1, NULL); //look at this, you're sending _1_ byte. nothing more.
if (con > 0){
cout << con << " bytes sent\n";
} else {
cout << "Nothing sent!\n";
}

cout << "Sending 0x50...\n";
con = send(theSocket, (const char*)&Packet, sizeof(SID_AUTH_INFO) - 4, NULL);
if ( con > 0 ){
  cout << con << " bytes sent\n";
} else {
  cout << "Nothing sent!\n";
}

con = recv(theSocket, PingPacket, sizeof(PingPacket), NULL);
if (con > 0){
cout << "Ping cookie: " << *(unsigned __int32 *)(PingPacket + 4);
break; //what does break; do here, in an if statement?
}

// for testing purposes
char n;
cin >> n;
closesocket(theSocket);
return 0;
}


I feel that I have made myself more than perfectly clear in the previous posts. Even after observing the logon sequence for yourself via a packet capture device, it seems you've failed to grasp the concept of what is supposed to be sent and what is supposed to be received.
Are you entirely certain that you have a solid grasp on coding with C/++?

@rabbit: I don't see what's wrong with his method of packet construction. If he didn't include the header with the actual packet's struct, it would work out nicely. In fact, this is the way Blizzard coded the packet construction in their batle.snp (not with a packet buffer, *gasp*)
<3 Zorm
Quote[01:08:05 AM] <@Zorm> haha, me get pussy? don't kid yourself quik
Scio te esse, sed quid sumne? :P

rabbit

And?  I'm saying it'd be easier to get help if he used a packet buffer because more people do it that way, so more people know the pitfalls and benefits.
Grif: Yeah, and the people in the red states are mad because the people in the blue states are mean to them and want them to pay money for roads and schools instead of cool things like NASCAR and shotguns.  Also, there's something about ketchup in there.

Hdx

Alright, well when it comes to Bnet packets, Blizzard does indeed use structs themselves, but Rabbit is correct. Most people here are used to using Buffer classes. And with computer processing power so cheap it's usefull to make a Buffer class. BUT! If you're working in a language that allows you such a low level access to memory as C, then you can do a hybrid if you are fancy enough.

As for your current problem. Structure should not be an after thaught, if you do things correctly. You may never have to touch a peice of code again. And it will make your life easier to work in chunks.

The basic 'connection' function for me looks like this:
Create Socket
If (SocketConnect()){
  Send Protocol Byte
  Send First Packets
  while(SocketConnected){
    Read Header
    Read Body
    Call Packet Handeling Function
  }
}
As you can see the psudo-function is rather small, and easy to maintain. Right now seince it looks like you are realy new to sockets. I'd go this route. So for your code:

struct BNCS_HEADER{
  BYTE Sanity;
  BYTE ID;
  WORD Length;
};

struct SID_AUTH_INFO {
  BNCS_HEADER Header;
  DWORD   ProtocolID;
  DWORD   PlatformID;
  DWORD   ProductID;
  DWORD   VerByte;
  DWORD   ProductLang;
  DWORD   LocalIP;
  DWORD   TimeZone;
  DWORD   LocaleID;
  DWORD   LangID;
  char   CountryInfo[0x100]; //Allocate enough for any country info.
};


int main(){
WSADATA wsaData;                                              \
WSAStartup(MAKEWORD(2,0), &wsaData);                           |
                                                                 |
  SOCKET sockBNCS = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);   |
  if(sockBNCS == INVALID_SOCKET){                                | Create the socket
    printf("Could not create BNCS Socket\n");                    |
    WSACleanup();                                                |
    return -1;                                                   |
  }                                                             /
 
  if(socket_connect(sockBNCS, "useast.battle.net", 6112) == 0){ //Connect Socket
    int sent;
   
    printf("Sending Protocol Byte 0x01\n"); \
    sent = send(sockBNCS, '\x01', 1, NULL);  |
    if(sent > 0){                            |
      printf("Sent %d byte(s)\n", sent);     | Send Protocol Byte
    }else{                                   |
      printf("Sending Failed!\n");           |
    }                                       /
   
    send_SID_AUTH_INFO(sockBNCS); //Send First Packet

    BNCS_HEADER header; //This is the data to hold incoming packet information
    void *data = malloc(0x200); //This will hold the actual data of a packet, this is whats sent to the handler.
    int data_max = 0x200;
   
    while(true){ //While Socket Connected
      sent = recv(sockBNCS, &header, sizeof(header), NULL); \
      if(sent != sizeof(header)){                            |
        printf("Did not receive full header!\n");            |
        WSACleanup();                                        | Read the Header
        return -1;                                           |
      }                                                     /
     
      if(header.Length - 4 > data_max){  \
        free(data);                       | Reallocated space for the packet body, if necessary
        data = malloc(header.Length - 4); |
      }                                  /
     
      sent = recv(sockBNCS, &data, header.Length - 4); \
      if(sent != header.Length - 4){                    |
        printf("Could not read packet data!\n");        | Receive Body
        WSACleanup();                                   |
        return -1;                                      |
      }                                                /
     
      switch(header.ID){                                          \
        case 0x25: process_SID_PING(data, header.Length - 4);      |
        case 0x50: process_SID_AUTH_INFO(data, header.Length - 4); | Call Packet Handler Function
        ....                                                       |
      }                                                           /
    }
   
  }
  WSACleanup();
  return 0;
}

int socket_connect(SOCKET sockBNCS, const char *Server, WORD Port){
LPHOSTENT host = gethostbyname(Server);

if (!host){
    printf("Could not resolve host for %s\n", Server);
  return -1;
}

SOCKADDR_IN info;
info.sin_family = AF_INET;
info.sin_addr = *((LPIN_ADDR)*host->h_addr_list);
info.sin_port = htons(Port);

if(connect(sockBNCS, (LPSOCKADDR)&info, sizeof(info)) == SOCKET_ERROR){
    printf("Could not connect to %s:%d Error: %d\n", Server, Port, WSAGetLastError());
  return -1;
}
  return 0;
}

int send_SID_AUTH_INFO(SOCKET sockBNCS){
  SID_AUTH_INFO pkt;
  int AbbrLen, NameLen, sent;
  memset(&pkt, 0, sizeof(SID_AUTH_INFO)); //If you don't do this, the pkt could have random info.
 
  pkt.ProtocolID  = 0x00;
  pkt.PlatformID  = 'IX86';
  pkt.ProductID   = 'D2DV';
  pkt.VerByte     = 0x0D;
  pkt.ProductLang = 0x00;
  pkt.LocalIP     = inet_addr("192.168.1.100");
  pkt.TimeZone    = 600;
  pkt.LocaleID    = 0x00;
  pkt.LangID      = (DWORD)GetUserDefaultLangID();
  AbbrLen = strcpy(&pkt.CountryInfo[0], "AUS"); //I *think* strcpy() returns the number of bytes copied, can't remember
  NameLen = strcpy(&pkt.CountryInfo[AbbrLen + 1], "Australia");
 
  pkt.Header.Sanity = 0xFF;
  pkt.Header.ID     = 0x50;
  pkt.Header.Length =  4       //Header Length
                     + (4 * 9) //Number of DWORDs in the packet
                     + AbbrLen //Abbreviation Length
                     + 1       //Null Terminator
                     + NameLen //Country Name Length
                     + 1;      //Null Terminator
  printf("Sending %d bytes for 0x50 SID_AUTH_INFO\n", pkt.Header.Length);
  sent = send(sockBNCS, &pkt, pkt.Header.Length, NULL);
  if(sent > 0){
    printf("Sent %d bytes\n", sent);
  }else{
    printf("Sending failed!\n");
  }
  return 0;
}
Anyways  this code does no work obviously, but if you tweak it you can get it working

Proud host of the JBLS server www.JBLS.org.
JBLS.org Status:
JBLS/BNLS Server Status

rabbit

Shouldn't it be SOCKET &sockBNCS in those functions?
Grif: Yeah, and the people in the red states are mad because the people in the blue states are mean to them and want them to pay money for roads and schools instead of cool things like NASCAR and shotguns.  Also, there's something about ketchup in there.

Hdx

maybe, but a SOCKET is simply a ID number of the socket (AE a HANDLE) so meh. As I said the code doesnt work. It simply shows a concept of the design/layout.

Proud host of the JBLS server www.JBLS.org.
JBLS.org Status:
JBLS/BNLS Server Status