1
/***************************************************************************
2
* Copyright (C) 2009 by The qGo Project *
4
* This file is part of qGo. *
6
* qGo is free software: you can redistribute it and/or modify *
7
* it under the terms of the GNU General Public License as published by *
8
* the Free Software Foundation; either version 2 of the License, or *
9
* (at your option) any later version. *
11
* This program is distributed in the hope that it will be useful, *
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14
* GNU General Public License for more details. *
16
* You should have received a copy of the GNU General Public License *
17
* along with this program; if not, see <http://www.gnu.org/licenses/> *
18
* or write to the Free Software Foundation, Inc., *
19
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
20
***************************************************************************/
23
#include "tomconnection.h"
25
#include "playergamelistings.h"
27
#include "serverlistdialog.h"
28
#include "serverliststorage.h"
29
#include "codecwarndialog.h"
30
/* Note that Tom either has additional checks on this or simply that one cannot play against
31
* the same username meaning that sendMatchOffers may not be received. */
34
TomConnection::TomConnection(const QString & user, const QString & pass)
35
: TygemConnection(user, pass, TypeTOM)
37
serverCodec = QTextCodec::codecForName(getCodecString());
40
new CodecWarnDialog(getCodecString());
41
serverCodec = QTextCodec::codecForLocale();
43
if(!getServerListStorage().restoreServerList(TypeTOM, serverList))
47
if(reconnectToServer() < 0)
49
qDebug("User canceled");
50
connectionState = CANCELED;
56
const char * TomConnection::getCodecString(void)
61
QString TomConnection::getPlaceString(void)
63
return "Tom: " + serverList[current_server_index]->name;
66
int TomConnection::requestServerInfo(void)
68
qDebug("Requesting Tom Server Info");
69
if(!openConnection("61.135.158.147", 80, NOT_MAIN_CONNECTION))
71
qDebug("Can't get server info");
74
unsigned int length = 0x94;
75
unsigned char * packet = new unsigned char[length]; //term 0x00
76
snprintf((char *)packet, length,
77
"GET /service/files/livebaduk3.cfg HTTP/1.1\r\n" \
78
"User-Agent: Tygem HTTP\r\n" \
79
"Host: duiyi.sports.tom.com\r\n" \
80
"Connection: Keep-Alive\r\n" \
81
"Cache-Control: no-cache\r\n\r\n");
83
for(int i = 0; i < length; i++)
84
printf("%02x", packet[i]);
87
if(write((const char *)packet, length) < 0)
89
qWarning("*** failed sending server info request");
94
connectionState = INFO;
98
/* We need to write a tygem parser that doesn't need to be different for tom FIXME */
99
void TomConnection::handleServerInfo(unsigned char * msg, unsigned int length)
101
char * p = (char *)msg;
106
for(i = 0; i < length; i++)
111
while(p < ((char *)msg + length))
113
while(p < ((char *)msg + length - 1) && p[0] != '\n')
116
//FIXME, check for size
117
if(strncmp(p, "/LIVE ", 6) == 0)
119
//same as for /SERVER but with only 2 [], name and ip
121
else if(strncmp(p, "/LECTURE ", 9) == 0)
123
//same as for /SERVER but with only 2 [], name and ip
125
else if(strncmp(p, "/SERVER ", 8) == 0 ||
126
strncmp(p, "/_SERVER ", 9) == 0) //whats the "_" FIXME
128
//TOM has only 2 [], name and ip
132
unsigned char ipaddr[16];
133
unsigned char name[20];
135
while(i < 2 && p < ((char *)msg + length))
139
qDebug("Server info parse error");
144
si = new ServerItem();
145
unsigned char * dest;
151
while(*p != ']' && p < ((char *)msg + length))
153
if((i == 1 && j < 15) || (i == 0 && j < 19))
164
strncpy(si->ipaddress, (const char *)ipaddr, 16);
165
si->name = serverCodec->toUnicode((char *)name, strlen((char *)name));
166
qDebug("Server: %s", ipaddr);
167
serverList.push_back(si);
174
else if(strncmp(p, "/ENCRYPT ", 9) == 0)
180
/* We close here because this first time, its going to close
181
* anyway, and if we don't close here, we'll get an error
182
* and lose the object */
183
connectionState = RECONNECTING;
184
closeConnection(false);
186
if(reconnectToServer() < 0)
188
qDebug("User canceled");
189
closeConnection(false);
190
connectionState = CANCELED;
192
// dispatch->onError(); //not great... FIXME
198
QByteArray TomConnection::getTygemGameRecordQByteArray(GameData * game)
200
Room * room = getDefaultRoom();
201
const PlayerListing * black, * white;
202
int black_ordinal, white_ordinal;
203
char black_qualifier, white_qualifier;
204
QByteArray white_qualifier_string, black_qualifier_string;
205
unsigned char black_level, white_level;
207
unsigned char month, day, hour, minute, second;
208
secondsToDate(year, month, day, hour, minute, second);
212
black = room->getPlayerListing(game->black_name);
215
qDebug("Can't get player listing for black: \"%s\"", game->black_name.toLatin1().constData());
218
white = room->getPlayerListing(game->white_name);
221
qDebug("Can't get player listing for white: \"%s\"", game->white_name.toLatin1().constData());
224
sscanf(black->rank.toLatin1().constData(), "%d%c", &black_ordinal, &black_qualifier);
225
if(black_qualifier == 'k')
227
black_level = 0x12 - black_ordinal;
228
black_qualifier_string.append("\xbc\xb6");
230
else if(black_qualifier == 'p')
231
black_level = black_ordinal + 0x1a;
234
black_level = black_ordinal + 0x11;
235
//double check that this isn't the pro tag?
236
black_qualifier_string.append("\xb6\xce");
238
sscanf(white->rank.toLatin1().constData(), "%d%c", &white_ordinal, &white_qualifier);
239
if(white_qualifier == 'k')
241
white_level = 0x12 - white_ordinal;
242
white_qualifier_string.append("\xbc\xb6");
244
else if(white_qualifier == 'p')
245
white_level = white_ordinal + 0x1a;
248
white_level = white_ordinal + 0x11;
249
white_qualifier_string.append("\xb6\xce");
253
/* GIBOKIND and GAMELECNAME and maybe some others are missing
254
* from Tom record, so there's a question of whether that's only
255
* in the 0672s and is left out of the records or whether that's
256
* just not part of Tom. I do get the feeling that, except for
257
* a few particular entries, we can be pretty easy going with
259
//string += "\\[GIBOKIND=China\\]\r\n"; //I don't see this in file, necessary?
260
string += "\\[TYPE=0\\]\r\n";
261
string += "\\[GAMECONDITION=";
262
string.append("\xc8\xce\xcf\xc8");
263
//c8c3cfc8 seems suffient for a finished
265
//I think cbc0bbee313ab7d6 is possibly
266
//some unfinished game or something
268
string += "\\[GAMETIME=";
270
string += "\\[GAMERESULT="; //3f3332353f3f //w + 325 margin ONLY, no color
271
//badac6e5cab1bce4caa4 B + T
272
//b0d7c6e5d6d0c5cccaa4 W + R
273
//bada38d4d6332f34d7d3caa4 B + margin?
274
switch(game->fullresult->result)
276
case GameResult::DRAW:
277
//string += QString(0xb9ab) + QString(0xbdc2) + QString(0xbace);
279
case GameResult::FORFEIT:
280
//c8e6 20 bdc3 b0a3 20 c3ca b0fa bdc2
283
case GameResult::TIME:
285
case GameResult::RESIGN:
286
if(game->fullresult->winner_color == stoneWhite)
288
//string += QString(0xb9e9);
292
//string += QString(0xc8e6);
294
//string += " " + QString(0xbad2) + QString(0xb0e8) + QString(0xbdc2);
296
case GameResult::SCORE:
298
float fmargin = game->fullresult->winner_score = game->fullresult->loser_score;
299
margin = (int)fmargin;
300
if(fmargin > (float)margin)
301
margin = (margin * 10) + 5;
304
qDebug("FIXME margin: %d\n", margin);
305
string += QByteArray::number(margin);
306
//string += QString(0x3f) + " " + QByteArray::number(margin) +
307
// QString(0x3f3f) + " " + QString(0x3f);
314
string += "\\[GAMEZIPSU=" + QByteArray::number(margin) + "\\]\r\n";
315
string += "\\[GAMEDUM=0\\]\r\n";
316
string += "\\[GAMEGONGJE=0\\]\r\n";
317
string += "\\[GAMETOTALNUM="; //0xd7dc: 3335cafd" 35?
318
string += " " + QByteArray::number(game->moves);
320
string += "\\[SZAUDIO=0\\]\r\n";
321
string += "\\[GAMENAME=";
322
string.append("\xd3\xd1\xd2\xea\xb6\xd4\xbe\xd6\\]\r\n");
323
//cdfd bdb5 bcb6 b6d4 bed6 5c5d //a broadcast game I saw
324
/* Be careful here also, no idea what this says, we should
325
* probably leave it blank */
326
string += "\\[GAMEDATE=" + QByteArray::number(year) + "-";
327
string.append("\xc4\xea");
328
string += QByteArray::number(month) +
329
string.append("xd4\xc2");
330
string += QByteArray::number(day);
331
string.append("\xc8\xd5");
332
string += " "; /*+ QString(0xcfc2) +
334
string += " " + QByteArray::number(hour % 12) +
335
(minute < 10 ? ":0" : ":") + QByteArray::number(minute) + "\\]\r\n";
336
/* Note that its very likely that one of the above strings contains a PM versus
338
const char tom_game_place_array[] = {0x54, 0x6f, 0x6d, 0xb6, 0xd4, 0xde, 0xc4};
339
QByteArray tom_game_place(tom_game_place_array, 7);
340
string += "\\[GAMEPLACE=" + tom_game_place + "\\]\r\n";
341
string += "\\[GAMELECNAME=\\]\r\n";
342
/* FIXME, note that this is very likely going to be different on the korean
343
* server. This is for eweiqi really */
344
string += "\\[GAMEWHITENAME=" + serverCodec->fromUnicode(white->notnickname) + "("
345
+ QByteArray::number(white_ordinal)
346
+ white_qualifier_string + ")\\]\r\n";
347
string += "\\[GAMEWHITELEVEL=" + QByteArray::number(white_level)
348
+ white_qualifier_string + "\\]\r\n";
349
string += "\\[GAMEWHITENICK=" + serverCodec->fromUnicode(white->name) + "\\]\r\n";
350
string += "\\[GAMEWHITECOUNTRY=" + QByteArray::number(white->country_id) + "\\]\r\n";
351
string += "\\[GAMEWAVATA=1\\]\r\n";
352
string += "\\[GAMEWIMAGE=\\]\r\n";
353
string += "\\[GAMEBLACKNAME=" + serverCodec->fromUnicode(black->notnickname) + "("
354
+ QByteArray::number(black_ordinal)
355
+ black_qualifier_string + ")\\]\r\n";
356
string += "\\[GAMEBLACKLEVEL=" + QByteArray::number(black_level)
357
+ black_qualifier_string + "\\]\r\n";
358
string += "\\[GAMEBLACKNICK=" + serverCodec->fromUnicode(black->name) + "\\]\r\n";
359
string += "\\[GAMEBLACKCOUNTRY=" + QByteArray::number(black->country_id) + "\\]\r\n";
360
string += "\\[GAMEBAVATA=1\\]\r\n";
361
string += "\\[GAMEBIMAGE=\\]\r\n";
362
string += "\\[GAMECOMMENT=\\]\r\n";
363
//country = 2 = gbkind = gibokind
364
string += "\\[GAMEINFOMAIN=GBKIND:2,GTYPE:0,GCDT:1,GTIME:" +
365
QByteArray::number(game->maintime) + "-" +
366
QByteArray::number(game->periodtime) + "-" +
367
QByteArray::number(game->stones_periods) + ",GRLT:0";
368
string += ",ZIPSU:" + QByteArray::number(margin) +
369
",DUM:0,GONGJE:0,TCNT:" +
370
QByteArray::number(game->moves);
371
string += ",AUSZ:0\\]\r\n";
372
string += "\\[GAMEINFOSUB=GNAMEF:0,GPLCF:0,GNAME:";
373
string += "GDATE:" + QByteArray::number(year) + "- " + QByteArray::number(month)
374
+ "- " + QByteArray::number(day) + "-" + QByteArray::number(hour)
375
+ "-" + QByteArray::number(minute) + "-" + QByteArray::number(second);
377
string += ",GCMT:\\]\r\n";
378
string += "\\[WUSERINFO=WID:" + serverCodec->fromUnicode(white->notnickname) + ",WLV:" + QByteArray::number(white_level) +
379
",WNICK:" + serverCodec->fromUnicode(white->name) + ",WNCD:" + QByteArray::number(white->country_id) +
380
",WAID:60001,WIMG:\\]\r\n";
381
string += "\\[BUSERINFO=BID:" + serverCodec->fromUnicode(black->notnickname) + ",BLV:" + QByteArray::number(black_level) +
382
",BNICK:" + serverCodec->fromUnicode(black->name) + ",BNCD:" + QByteArray::number(black->country_id) +
383
",BAID:60001,BIMG:\\]\r\n";
384
/* Here, I'm thinking S0 is black wins, S1 is white wins
385
* then again, there's also W1 indicating white win with W0 as white loss */
386
/* I've also seen W4 as indicating W + R */
387
/* I've also seen S1 W7 as B + T also with Z0 indicating that's time remaining
389
/* T is likely time settings, 30 seconds, 3 periods, 1200 total time maybe (20min)*/
390
string += getTygemGameTagQByteArray(game, white_level, black_level, margin);
391
//tag is simple of earlier info