Witam, w celach naukowych chcę stworzyć prosty komunikator GG. Postanowiłem zacząć od próby wysłania i odebrania wiadomości.
Logowanie i ustawienie statusu działa, ale zatrzymałem się na nieszczęsnym wysyłaniu. Dodatkowo po zalogowaniu i wysłaniu informacji o pustej liście kontaktów dostaje pakiet z czymś nie opisanym w informacjach na temat protokołu gg na stronie http://toxygen.net/libgadu/protocol
dokładniej jest to pakiet GG_XML_ACTION o takiej treści:
<?xml version="1.0" encoding="UTF-8"?>
<app_event>
<![CDATA[[{"type": "61001","params":{"flags":1,"orginalityToken":"12057866680078094","appId":"curd"}}]]]>
</app_event>
Nie wiem czy to wina tego pakietu czy też jakiegoś błędu w moim kodzie
/* main.cpp */
#include <iostream>
#include <ctime>
#include <winsock2.h>
#include <stdio.h>
#include <openssl/sha.h>
#include "gg.h"
using namespace std;
u_long resolveHost( const string &host )
{
LPHOSTENT hostEntry = gethostbyname(host.c_str());
if ( !hostEntry )
{
unsigned int addr = inet_addr( host.c_str() );
hostEntry = gethostbyaddr((char *)&addr, 4, AF_INET);
if ( !hostEntry )
{
return 0;
}
}
return *((int*)*hostEntry->h_addr_list);
}
void init_winsock(WSADATA &wsaData, SOCKET &sock){
WSAStartup( MAKEWORD(2,2), &wsaData );
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
}
int main(int argc, char* argv[])
{
string adres;
WSADATA wsaData;
SOCKET sock;
sockaddr_in sock_Addr;
char index[1024*20] = { 0 };
int buff = 0;
adres = "91.214.237.12";
init_winsock(wsaData,sock);
sock_Addr.sin_addr.S_un.S_addr = resolveHost (adres);
sock_Addr.sin_family = AF_INET;
sock_Addr.sin_port= htons(8074);
cout << "Adres serwera: " << adres<< " port: "<< sock_Addr.sin_port <<endl;
if ( connect(sock, (sockaddr*)&sock_Addr, sizeof(sockaddr)) == SOCKET_ERROR )
{
/* polaczenie sie nie powiodlo */
sock = NULL;
return -1;
}
gg_header header;
gg_welcome gg;
gg_login80 gg_login ;
gg_new_status80 gg_status;
gg_send_msg80 gg_msg;
recv(sock,(char*)&header,sizeof(header),0);
recv(sock,(char*)&gg,sizeof(gg),0);
cout<<"Seed: "<< gg.seed<<endl;
//Przygotowanie struktury\pakietu gg_login80
char *password;
password="haslo";
gg_login.uin = numer;
sprintf(gg_login.language, "pl");
gg_login.hash_type = 0x02;
sprintf(gg_login.hash,gg_sha_hash(password, gg.seed));
cout << gg_login.hash<<endl;
for(unsigned int i = sizeof(gg_login.hash); i > strlen(gg_login.hash); i--){
gg_login.hash[i] = '\0';
}
gg_login.status = 0x0002;
gg_login.flags = 0;
gg_login.features = 0x00000367;
gg_login.local_ip = 0;
gg_login.local_port = 0;
gg_login.external_ip = 0;
gg_login.external_port = 0;
gg_login.image_size = 64;
gg_login.unknown1 = 0x64;
gg_login.version_len = 0x23;
sprintf(gg_login.version, "Gadu-Gadu Client build 10.0.0.10450");
gg_login.description_size = 0;
gg_login.description[0] = '\0';
header.type=GG_LOGIN80;
header.length=sizeof(gg_login);
send(sock,(char*)&header,sizeof(header),0);
send(sock,(char*)&gg_login,sizeof(gg_login),0);
//cout<<"\nlogowanie:\ntyp: "<<gg_login.type<<" dlugosc: "<<gg_login.length<<" zawartosc: " <<gg_login.uin<<endl;
recv(sock,(char*)&buff,sizeof(buff),0);
if(buff==GG_LOGIN80_FAILED){
cout << "Logowanie nie powiodlo sie."<<endl;
//return -2;
_sleep(500);
}
else if(buff==GG_LOGIN80_OK){
cout << "Logowanie powiodlo sie."<<endl;
}
else
return -100;
//Pusta lista
header.type=GG_LIST_EMPTY;
header.length=0;
send(sock,(char*)&header,sizeof(header),0);
//Ustaw status
sprintf(gg_status.description, '\0');
gg_status.description_size=0;
gg_status.flags = 0x00000001 | 0x00000002;
gg_status.status= 0x0002;
header.type=GG_NEW_STATUS80;
header.length=sizeof(gg_status);
send(sock,(char*)&header,sizeof(header),0);
send(sock,(char*)&gg_status,sizeof(gg_status),0);
//Tu wywalają mi się jakieś smieci
recv(sock,(char*)&header,sizeof(header),0);//Wywala mi 4 nie wiem czemu
cout<<"Header: "<<header.type<<endl;
recv(sock,(char*)&header,sizeof(header),0);//Wywala mi 0x37
cout<<"Header: "<<header.type<<endl;
recv(sock,(char*)&header,sizeof(header),0);//Wywala mi 0x44 a wiec GG_USER_DATA
cout<<"Header: "<<header.type<<endl;
if(header.type==GG_USER_DATA){
gg_user_data user_data;
recv(sock,(char*)&user_data,sizeof(user_data),0);
}
recv(sock,(char*)&header,sizeof(header),0);//Wywala mi 0x2c XML_ACTION
cout<<"Header: "<<header.type<<endl;
recv(sock,(char*)&index,168,0);
cout<<index<<endl;
/* GG_XML_ACTION
<?xml version="1.0" encoding="UTF-8"?>
<app_event>
<![CDATA[[{"type": "61001","params":{"flags":1,"orginalityToken":"12057866680078094","appId":"curd"}}]]]>
</app_event>
*/
//Wiadomość
gg_msg.attributes[0] = '2';
gg_msg.attributes[1] = '6';
gg_msg.attributes[2] = '0';
gg_msg.attributes[3] = '0';
gg_msg.attributes[4] = '0';
gg_msg.attributes[5] = '8';
gg_msg.attributes[6] = '0';
gg_msg.attributes[7] = '0';
gg_msg.attributes[8] = '0';
gg_msg.klasa=0x08;
gg_msg.recipient=3890406;
gg_msg.seq=time(NULL);
gg_msg.offset_plain = 220;//20 + sztywne 200
gg_msg.offset_attributes =420;//220+ kolejne sztywne 200
strcpy(gg_msg.html_message,"<span style=\"color:#000000; font-family:'MS Shell Dlg 2'; font-size:9pt; \">Test</span>");
strcpy(gg_msg.plain_message,"Test");
header.type=GG_SEND_MSG80;
header.length=sizeof(gg_msg);
if(send(sock,(char*)&header,sizeof(header),0)){cout<<"Header"<<endl;}
if(send(sock,(char*)&gg_msg,sizeof(gg_msg),0)){cout<<"gg_msg"<<endl;}
recv(sock,(char*)&header,sizeof(header),0);//Wywala mi 0x2d wysyłanie wiadomości?
cout<<"Header: "<<header.type<<endl;
system("pause");
closesocket(sock);
WSACleanup();
return 0;
}
/*gg.h*/
#ifndef GG_H
#define GG_H
int gg_login_hash(char *password, unsigned int seed);
char *gg_sha_hash(const char *password, unsigned int seed);
struct gg_header {
int type; /* typ pakietu */
int length; /* długość reszty pakietu */
};
#define GG_WELCOME 0x0001
struct gg_welcome {
int seed; /* ziarno */
};
#define GG_LOGIN80 0x0031
#define GG_LOGIN_HASH_GG32 0x01
#define GG_LOGIN_HASH_SHA1 0x02
#pragma pack(push,1) /* zapamiętaj bieżącą wartość wyrównania, brak wyrównania */
struct gg_login80{
int uin; /* numer Gadu-Gadu */
char language[2]; /* jêzyk: "pl" */
char hash_type; /* rodzaj funkcji skrótu has³a */
char hash[64]; /* skrót has³a dope³niony \0 */
int status; /* pocz¹tkowy status po³¹czenia */
int flags; /* pocz¹tkowe flagi po³¹czenia */
int features; /* opcje protoko³u (0x00000367)*/
int local_ip; /* lokalny adres po³¹czeñ bezpoœrednich (nieu¿ywany) */
short local_port; /* lokalny port po³¹czeñ bezpoœrednich (nieu¿ywany) */
int external_ip; /* zewnêtrzny adres (nieu¿ywany) */
short external_port; /* zewnêtrzny port (nieu¿ywany) */
char image_size; /* maksymalny rozmiar grafiki w KB */
char unknown1; /* 0x64 */
int version_len; /* d³ugoœæ ci¹gu z wersj¹ (0x23) */
char version[36]; /* "Gadu-Gadu Client build 10.0.0.10450" (bez \0) */
int description_size; /* rozmiar opisu */
char description[32]; /* opis (nie musi wyst¹piæ, bez \0) */
};
#pragma pack(pop)
#define GG_LOGIN80_OK 0x0035
#define GG_LOGIN80_FAILED 0x0043
struct gg_login80_ok {
int type, length;
int unknown1; /* 01 00 00 00 */
};
#define GG_NEW_STATUS80 0x0038
struct gg_new_status80 {
int status; /* nowy status */
int flags; /* nowe flagi */
int description_size; /* rozmiar opisu */
char description[32]; /* opis (nie musi wystąpić, bez \0) */
};
#define GG_LIST_EMPTY 0x0012
#define GG_XML_ACTION 0x002c
#define GG_SEND_MSG80 0x002d
#pragma pack(push,1)
struct gg_send_msg80 {
int recipient; /* numer odbiorcy */
int seq; /* numer sekwencyjny */
int klasa; /* klasa wiadomości */
int offset_plain; /* położenie treści czystym tekstem */
int offset_attributes; /* położenie atrybutów */
char html_message[200]; /* treść w formacie HTML (zakończona \0) */
char plain_message[200]; /* treść czystym tekstem (zakończona \0) */
char attributes[8]; /* atrybuty wiadomości */
};
#pragma pack(pop)
#define GG_USER_DATA 0x0044
struct gg_user_data {
int type; /* typ */
int num; /* liczba struktur gg_user_data_user */
};
struct gg_user_data_user {
int uin; /* numer użytkownika */
int num; /* liczba struktur gg_user_data_attr */
};
struct gg_user_data_attr {
int name_size; /* długość nazwy atrybutu */
char name[]; /* nazwa atrybutu (bez znaku \0) */
int type; /* typ atrybutu */
int value_size; /* długość wartości atrybutu */
char value[]; /* wartość atrybutu (bez znaku \0) */
};
#endif
Byłbym dozgonnie wdzięczny za jakąkolwiek wskazówkę