inter.cpp 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457
  1. // Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
  2. // For more information, see LICENCE in the main folder
  3. #include "inter.hpp"
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <string>
  7. #include <sys/stat.h> // for stat/lstat/fstat - [Dekamaster/Ultimate GM Tool]
  8. #include <vector>
  9. #include <yaml-cpp/yaml.h>
  10. #include "../common/cbasetypes.hpp"
  11. #include "../common/database.hpp"
  12. #include "../common/malloc.hpp"
  13. #include "../common/showmsg.hpp"
  14. #include "../common/socket.hpp"
  15. #include "../common/strlib.hpp"
  16. #include "../common/timer.hpp"
  17. #include "char.hpp"
  18. #include "char_logif.hpp"
  19. #include "char_mapif.hpp"
  20. #include "inter.hpp"
  21. #include "int_achievement.hpp"
  22. #include "int_auction.hpp"
  23. #include "int_clan.hpp"
  24. #include "int_elemental.hpp"
  25. #include "int_guild.hpp"
  26. #include "int_homun.hpp"
  27. #include "int_mail.hpp"
  28. #include "int_mercenary.hpp"
  29. #include "int_party.hpp"
  30. #include "int_pet.hpp"
  31. #include "int_quest.hpp"
  32. #include "int_storage.hpp"
  33. std::string cfgFile = "inter_server.yml"; ///< Inter-Config file
  34. InterServerDatabase interServerDb;
  35. #define WISDATA_TTL (60*1000) //Wis data Time To Live (60 seconds)
  36. #define WISDELLIST_MAX 256 // Number of elements in the list Delete data Wis
  37. Sql* sql_handle = NULL; ///Link to mysql db, connection FD
  38. struct Inter_Config inter_config;
  39. static void inter_config_init(void);
  40. /// Received packet Lengths from map-server
  41. int inter_recv_packet_length[] = {
  42. -1,-1, 7,-1, -1,13,36, (2+4+4+4+1+NAME_LENGTH), 0,-1, 0, 0, 0, 0, 0, 0, // 3000-
  43. 6,-1, 0, 0, 0, 0, 0, 0, 10,-1, 0, 0, 0, 0, 0, 0, // 3010-
  44. -1,10,-1,14, 15+NAME_LENGTH,19, 6,-1, 14,14, 6, 0, 0, 0, 0, 0, // 3020- Party
  45. -1, 6,-1,-1, 55,19, 6,-1, 14,-1,-1,-1, 18,19,186,-1, // 3030-
  46. -1, 9, 0, 0, 0, 0, 0, 0, 8, 6,11,10, 10,-1,6+NAME_LENGTH, 0, // 3040-
  47. -1,-1,10,10, 0,-1,12, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3050- Auction System [Zephyrus]
  48. 6,-1, 6,-1, 16+NAME_LENGTH+ACHIEVEMENT_NAME_LENGTH, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3060- Quest system [Kevin] [Inkfish] / Achievements [Aleos]
  49. -1,10, 6,-1, 0, 0, 0, 0, 0, 0, 0, 0, -1,10, 6,-1, // 3070- Mercenary packets [Zephyrus], Elemental packets [pakpil]
  50. 48,14,-1, 6, 0, 0, 0, 0, 0, 0,13,-1, 0, 0, 0, 0, // 3080- Pet System, Storage
  51. -1,10,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3090- Homunculus packets [albator]
  52. 2,-1, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 30A0- Clan packets
  53. };
  54. struct WisData {
  55. int id, fd, count, len, gmlvl;
  56. t_tick tick;
  57. char src[NAME_LENGTH], dst[NAME_LENGTH], msg[512];
  58. };
  59. static DBMap* wis_db = NULL; // int wis_id -> struct WisData*
  60. static int wis_dellist[WISDELLIST_MAX], wis_delnum;
  61. /* from pc.cpp due to @accinfo. any ideas to replace this crap are more than welcome. */
  62. const char* job_name(int class_) {
  63. switch (class_) {
  64. case JOB_NOVICE:
  65. case JOB_SWORDMAN:
  66. case JOB_MAGE:
  67. case JOB_ARCHER:
  68. case JOB_ACOLYTE:
  69. case JOB_MERCHANT:
  70. case JOB_THIEF:
  71. return msg_txt(JOB_NOVICE+class_);
  72. case JOB_KNIGHT:
  73. case JOB_PRIEST:
  74. case JOB_WIZARD:
  75. case JOB_BLACKSMITH:
  76. case JOB_HUNTER:
  77. case JOB_ASSASSIN:
  78. return msg_txt(7 - JOB_KNIGHT+class_);
  79. case JOB_KNIGHT2:
  80. return msg_txt(7);
  81. case JOB_CRUSADER:
  82. case JOB_MONK:
  83. case JOB_SAGE:
  84. case JOB_ROGUE:
  85. case JOB_ALCHEMIST:
  86. case JOB_BARD:
  87. case JOB_DANCER:
  88. return msg_txt(13 - JOB_CRUSADER+class_);
  89. case JOB_CRUSADER2:
  90. return msg_txt(13);
  91. case JOB_WEDDING:
  92. case JOB_SUPER_NOVICE:
  93. case JOB_GUNSLINGER:
  94. case JOB_NINJA:
  95. case JOB_XMAS:
  96. return msg_txt(20 - JOB_WEDDING+class_);
  97. case JOB_SUMMER:
  98. case JOB_SUMMER2:
  99. return msg_txt(71);
  100. case JOB_HANBOK:
  101. case JOB_OKTOBERFEST:
  102. return msg_txt(105 - JOB_HANBOK+class_);
  103. case JOB_NOVICE_HIGH:
  104. case JOB_SWORDMAN_HIGH:
  105. case JOB_MAGE_HIGH:
  106. case JOB_ARCHER_HIGH:
  107. case JOB_ACOLYTE_HIGH:
  108. case JOB_MERCHANT_HIGH:
  109. case JOB_THIEF_HIGH:
  110. return msg_txt(25 - JOB_NOVICE_HIGH+class_);
  111. case JOB_LORD_KNIGHT:
  112. case JOB_HIGH_PRIEST:
  113. case JOB_HIGH_WIZARD:
  114. case JOB_WHITESMITH:
  115. case JOB_SNIPER:
  116. case JOB_ASSASSIN_CROSS:
  117. return msg_txt(32 - JOB_LORD_KNIGHT+class_);
  118. case JOB_LORD_KNIGHT2:
  119. return msg_txt(32);
  120. case JOB_PALADIN:
  121. case JOB_CHAMPION:
  122. case JOB_PROFESSOR:
  123. case JOB_STALKER:
  124. case JOB_CREATOR:
  125. case JOB_CLOWN:
  126. case JOB_GYPSY:
  127. return msg_txt(38 - JOB_PALADIN + class_);
  128. case JOB_PALADIN2:
  129. return msg_txt(38);
  130. case JOB_BABY:
  131. case JOB_BABY_SWORDMAN:
  132. case JOB_BABY_MAGE:
  133. case JOB_BABY_ARCHER:
  134. case JOB_BABY_ACOLYTE:
  135. case JOB_BABY_MERCHANT:
  136. case JOB_BABY_THIEF:
  137. return msg_txt(45 - JOB_BABY + class_);
  138. case JOB_BABY_KNIGHT:
  139. case JOB_BABY_PRIEST:
  140. case JOB_BABY_WIZARD:
  141. case JOB_BABY_BLACKSMITH:
  142. case JOB_BABY_HUNTER:
  143. case JOB_BABY_ASSASSIN:
  144. return msg_txt(52 - JOB_BABY_KNIGHT + class_);
  145. case JOB_BABY_KNIGHT2:
  146. return msg_txt(52);
  147. case JOB_BABY_CRUSADER:
  148. case JOB_BABY_MONK:
  149. case JOB_BABY_SAGE:
  150. case JOB_BABY_ROGUE:
  151. case JOB_BABY_ALCHEMIST:
  152. case JOB_BABY_BARD:
  153. case JOB_BABY_DANCER:
  154. return msg_txt(58 - JOB_BABY_CRUSADER + class_);
  155. case JOB_BABY_CRUSADER2:
  156. return msg_txt(58);
  157. case JOB_SUPER_BABY:
  158. return msg_txt(65);
  159. case JOB_TAEKWON:
  160. return msg_txt(66);
  161. case JOB_STAR_GLADIATOR:
  162. case JOB_STAR_GLADIATOR2:
  163. return msg_txt(67);
  164. case JOB_SOUL_LINKER:
  165. return msg_txt(68);
  166. case JOB_GANGSI:
  167. case JOB_DEATH_KNIGHT:
  168. case JOB_DARK_COLLECTOR:
  169. return msg_txt(72 - JOB_GANGSI+class_);
  170. case JOB_RUNE_KNIGHT:
  171. case JOB_WARLOCK:
  172. case JOB_RANGER:
  173. case JOB_ARCH_BISHOP:
  174. case JOB_MECHANIC:
  175. case JOB_GUILLOTINE_CROSS:
  176. return msg_txt(75 - JOB_RUNE_KNIGHT+class_);
  177. case JOB_RUNE_KNIGHT_T:
  178. case JOB_WARLOCK_T:
  179. case JOB_RANGER_T:
  180. case JOB_ARCH_BISHOP_T:
  181. case JOB_MECHANIC_T:
  182. case JOB_GUILLOTINE_CROSS_T:
  183. return msg_txt(75 - JOB_RUNE_KNIGHT_T+class_);
  184. case JOB_ROYAL_GUARD:
  185. case JOB_SORCERER:
  186. case JOB_MINSTREL:
  187. case JOB_WANDERER:
  188. case JOB_SURA:
  189. case JOB_GENETIC:
  190. case JOB_SHADOW_CHASER:
  191. return msg_txt(81 - JOB_ROYAL_GUARD+class_);
  192. case JOB_ROYAL_GUARD_T:
  193. case JOB_SORCERER_T:
  194. case JOB_MINSTREL_T:
  195. case JOB_WANDERER_T:
  196. case JOB_SURA_T:
  197. case JOB_GENETIC_T:
  198. case JOB_SHADOW_CHASER_T:
  199. return msg_txt(81 - JOB_ROYAL_GUARD_T+class_);
  200. case JOB_RUNE_KNIGHT2:
  201. case JOB_RUNE_KNIGHT_T2:
  202. return msg_txt(75);
  203. case JOB_ROYAL_GUARD2:
  204. case JOB_ROYAL_GUARD_T2:
  205. return msg_txt(81);
  206. case JOB_RANGER2:
  207. case JOB_RANGER_T2:
  208. return msg_txt(77);
  209. case JOB_MECHANIC2:
  210. case JOB_MECHANIC_T2:
  211. return msg_txt(79);
  212. case JOB_BABY_RUNE:
  213. case JOB_BABY_WARLOCK:
  214. case JOB_BABY_RANGER:
  215. case JOB_BABY_BISHOP:
  216. case JOB_BABY_MECHANIC:
  217. case JOB_BABY_CROSS:
  218. case JOB_BABY_GUARD:
  219. case JOB_BABY_SORCERER:
  220. case JOB_BABY_MINSTREL:
  221. case JOB_BABY_WANDERER:
  222. case JOB_BABY_SURA:
  223. case JOB_BABY_GENETIC:
  224. case JOB_BABY_CHASER:
  225. return msg_txt(88 - JOB_BABY_RUNE+class_);
  226. case JOB_BABY_RUNE2:
  227. return msg_txt(88);
  228. case JOB_BABY_GUARD2:
  229. return msg_txt(94);
  230. case JOB_BABY_RANGER2:
  231. return msg_txt(90);
  232. case JOB_BABY_MECHANIC2:
  233. return msg_txt(92);
  234. case JOB_SUPER_NOVICE_E:
  235. case JOB_SUPER_BABY_E:
  236. return msg_txt(101 - JOB_SUPER_NOVICE_E+class_);
  237. case JOB_KAGEROU:
  238. case JOB_OBORO:
  239. return msg_txt(103 - JOB_KAGEROU+class_);
  240. case JOB_REBELLION:
  241. return msg_txt(106);
  242. case JOB_SUMMONER:
  243. return msg_txt(108);
  244. case JOB_BABY_SUMMONER:
  245. return msg_txt(109);
  246. case JOB_BABY_NINJA:
  247. case JOB_BABY_KAGEROU:
  248. case JOB_BABY_OBORO:
  249. case JOB_BABY_TAEKWON:
  250. case JOB_BABY_STAR_GLADIATOR:
  251. case JOB_BABY_SOUL_LINKER:
  252. case JOB_BABY_GUNSLINGER:
  253. case JOB_BABY_REBELLION:
  254. return msg_txt(110 - JOB_BABY_NINJA+class_);
  255. case JOB_BABY_STAR_GLADIATOR2:
  256. case JOB_STAR_EMPEROR:
  257. case JOB_SOUL_REAPER:
  258. case JOB_BABY_STAR_EMPEROR:
  259. case JOB_BABY_SOUL_REAPER:
  260. return msg_txt(114 - JOB_BABY_STAR_GLADIATOR2 + class_);
  261. case JOB_STAR_EMPEROR2:
  262. return msg_txt(118);
  263. case JOB_BABY_STAR_EMPEROR2:
  264. return msg_txt(120);
  265. default:
  266. return msg_txt(199);
  267. }
  268. }
  269. /**
  270. * [Dekamaster/Nightroad]
  271. **/
  272. const char * geoip_countryname[253] = {"Unknown","Asia/Pacific Region","Europe","Andorra","United Arab Emirates","Afghanistan","Antigua and Barbuda","Anguilla","Albania","Armenia","Netherlands Antilles",
  273. "Angola","Antarctica","Argentina","American Samoa","Austria","Australia","Aruba","Azerbaijan","Bosnia and Herzegovina","Barbados",
  274. "Bangladesh","Belgium","Burkina Faso","Bulgaria","Bahrain","Burundi","Benin","Bermuda","Brunei Darussalam","Bolivia",
  275. "Brazil","Bahamas","Bhutan","Bouvet Island","Botswana","Belarus","Belize","Canada","Cocos (Keeling) Islands","Congo, The Democratic Republic of the",
  276. "Central African Republic","Congo","Switzerland","Cote D'Ivoire","Cook Islands","Chile","Cameroon","China","Colombia","Costa Rica",
  277. "Cuba","Cape Verde","Christmas Island","Cyprus","Czech Republic","Germany","Djibouti","Denmark","Dominica","Dominican Republic",
  278. "Algeria","Ecuador","Estonia","Egypt","Western Sahara","Eritrea","Spain","Ethiopia","Finland","Fiji",
  279. "Falkland Islands (Malvinas)","Micronesia, Federated States of","Faroe Islands","France","France, Metropolitan","Gabon","United Kingdom","Grenada","Georgia","French Guiana",
  280. "Ghana","Gibraltar","Greenland","Gambia","Guinea","Guadeloupe","Equatorial Guinea","Greece","South Georgia and the South Sandwich Islands","Guatemala",
  281. "Guam","Guinea-Bissau","Guyana","Hong Kong","Heard Island and McDonald Islands","Honduras","Croatia","Haiti","Hungary","Indonesia",
  282. "Ireland","Israel","India","British Indian Ocean Territory","Iraq","Iran, Islamic Republic of","Iceland","Italy","Jamaica","Jordan",
  283. "Japan","Kenya","Kyrgyzstan","Cambodia","Kiribati","Comoros","Saint Kitts and Nevis","Korea, Democratic People's Republic of","Korea, Republic of","Kuwait",
  284. "Cayman Islands","Kazakhstan","Lao People's Democratic Republic","Lebanon","Saint Lucia","Liechtenstein","Sri Lanka","Liberia","Lesotho","Lithuania",
  285. "Luxembourg","Latvia","Libyan Arab Jamahiriya","Morocco","Monaco","Moldova, Republic of","Madagascar","Marshall Islands","Macedonia","Mali",
  286. "Myanmar","Mongolia","Macau","Northern Mariana Islands","Martinique","Mauritania","Montserrat","Malta","Mauritius","Maldives",
  287. "Malawi","Mexico","Malaysia","Mozambique","Namibia","New Caledonia","Niger","Norfolk Island","Nigeria","Nicaragua",
  288. "Netherlands","Norway","Nepal","Nauru","Niue","New Zealand","Oman","Panama","Peru","French Polynesia",
  289. "Papua New Guinea","Philippines","Pakistan","Poland","Saint Pierre and Miquelon","Pitcairn Islands","Puerto Rico","Palestinian Territory","Portugal","Palau",
  290. "Paraguay","Qatar","Reunion","Romania","Russian Federation","Rwanda","Saudi Arabia","Solomon Islands","Seychelles","Sudan",
  291. "Sweden","Singapore","Saint Helena","Slovenia","Svalbard and Jan Mayen","Slovakia","Sierra Leone","San Marino","Senegal","Somalia","Suriname",
  292. "Sao Tome and Principe","El Salvador","Syrian Arab Republic","Swaziland","Turks and Caicos Islands","Chad","French Southern Territories","Togo","Thailand",
  293. "Tajikistan","Tokelau","Turkmenistan","Tunisia","Tonga","Timor-Leste","Turkey","Trinidad and Tobago","Tuvalu","Taiwan",
  294. "Tanzania, United Republic of","Ukraine","Uganda","United States Minor Outlying Islands","United States","Uruguay","Uzbekistan","Holy See (Vatican City State)","Saint Vincent and the Grenadines","Venezuela",
  295. "Virgin Islands, British","Virgin Islands, U.S.","Vietnam","Vanuatu","Wallis and Futuna","Samoa","Yemen","Mayotte","Serbia","South Africa",
  296. "Zambia","Montenegro","Zimbabwe","Anonymous Proxy","Satellite Provider","Other","Aland Islands","Guernsey","Isle of Man","Jersey",
  297. "Saint Barthelemy","Saint Martin"};
  298. unsigned char *geoip_cache;
  299. void geoip_readdb(void){
  300. struct stat bufa;
  301. FILE *db=fopen("./db/GeoIP.dat","rb");
  302. fstat(fileno(db), &bufa);
  303. geoip_cache = (unsigned char *) aMalloc(sizeof(unsigned char) * bufa.st_size);
  304. if(fread(geoip_cache, sizeof(unsigned char), bufa.st_size, db) != bufa.st_size) { ShowError("geoip_cache reading didn't read all elements \n"); }
  305. fclose(db);
  306. ShowStatus("Finished Reading " CL_GREEN "GeoIP" CL_RESET " Database.\n");
  307. }
  308. /* [Dekamaster/Nightroad] */
  309. /* WHY NOT A DBMAP: There are millions of entries in GeoIP and it has its own algorithm to go quickly through them, a DBMap wouldn't be efficient */
  310. const char* geoip_getcountry(uint32 ipnum){
  311. int depth;
  312. unsigned int x;
  313. unsigned int offset = 0;
  314. for (depth = 31; depth >= 0; depth--) {
  315. const unsigned char *buf;
  316. buf = geoip_cache + (long)6 *offset;
  317. if (ipnum & (1 << depth)) {
  318. /* Take the right-hand branch */
  319. x = (buf[3*1 + 0] << (0*8))
  320. + (buf[3*1 + 1] << (1*8))
  321. + (buf[3*1 + 2] << (2*8));
  322. } else {
  323. /* Take the left-hand branch */
  324. x = (buf[3*0 + 0] << (0*8))
  325. + (buf[3*0 + 1] << (1*8))
  326. + (buf[3*0 + 2] << (2*8));
  327. }
  328. if (x >= 16776960) {
  329. x=x-16776960;
  330. return geoip_countryname[x];
  331. }
  332. offset = x;
  333. }
  334. return geoip_countryname[0];
  335. }
  336. /* sends a mesasge to map server (fd) to a user (u_fd) although we use fd we keep aid for safe-check */
  337. /* extremely handy I believe it will serve other uses in the near future */
  338. void inter_to_fd(int fd, int u_fd, int aid, char* msg, ...) {
  339. char msg_out[512];
  340. va_list ap;
  341. int len = 1;/* yes we start at 1 */
  342. va_start(ap,msg);
  343. len += vsnprintf(msg_out, 512, msg, ap);
  344. va_end(ap);
  345. WFIFOHEAD(fd,12 + len);
  346. WFIFOW(fd,0) = 0x3807;
  347. WFIFOW(fd,2) = 12 + (unsigned short)len;
  348. WFIFOL(fd,4) = u_fd;
  349. WFIFOL(fd,8) = aid;
  350. safestrncpy(WFIFOCP(fd,12), msg_out, len);
  351. WFIFOSET(fd,12 + len);
  352. return;
  353. }
  354. /**
  355. * Transmit the result of a account_information request from map-serv, with type 1
  356. * @param fd : map-serv link
  357. * @param u_fd : player fd to send info to
  358. * @param acc_id : id of player found
  359. * @param acc_name : name of player found
  360. */
  361. void mapif_acc_info_ack(int fd, int u_fd, int acc_id, const char* acc_name){
  362. WFIFOHEAD(fd,10 + NAME_LENGTH);
  363. WFIFOW(fd,0) = 0x3808;
  364. WFIFOL(fd,2) = u_fd;
  365. WFIFOL(fd,6) = acc_id;
  366. safestrncpy(WFIFOCP(fd,10),acc_name,NAME_LENGTH);
  367. WFIFOSET(fd,10 + NAME_LENGTH);
  368. }
  369. /**
  370. * Receive a account_info request from map-serv
  371. * @author : [Dekamaster/Nightroad]
  372. * @param fd : map-serv link
  373. */
  374. void mapif_parse_accinfo(int fd) {
  375. int u_fd = RFIFOL(fd,2), u_aid = RFIFOL(fd,6), u_group = RFIFOL(fd,10);
  376. char type= RFIFOB(fd,14);
  377. char query[NAME_LENGTH], query_esq[NAME_LENGTH*2+1];
  378. uint32 account_id = 0;
  379. char *data;
  380. safestrncpy(query, RFIFOCP(fd,15), NAME_LENGTH);
  381. Sql_EscapeString(sql_handle, query_esq, query);
  382. account_id = atoi(query);
  383. if (account_id < START_ACCOUNT_NUM) { // is string
  384. if ( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name`,`class`,`base_level`,`job_level`,`online` FROM `%s` WHERE `name` LIKE '%s' LIMIT 10", charserv_table(char_table), query_esq)
  385. || Sql_NumRows(sql_handle) == 0 ) {
  386. if( Sql_NumRows(sql_handle) == 0 ) {
  387. inter_to_fd(fd, u_fd, u_aid, (char *)msg_txt(212) ,query);
  388. } else {
  389. Sql_ShowDebug(sql_handle);
  390. inter_to_fd(fd, u_fd, u_aid, (char *)msg_txt(213));
  391. }
  392. Sql_FreeResult(sql_handle);
  393. return;
  394. } else {
  395. if( Sql_NumRows(sql_handle) == 1 ) {//we found a perfect match
  396. Sql_NextRow(sql_handle);
  397. Sql_GetData(sql_handle, 0, &data, NULL); account_id = atoi(data);
  398. Sql_FreeResult(sql_handle);
  399. } else {// more than one, listing... [Dekamaster/Nightroad]
  400. inter_to_fd(fd, u_fd, u_aid, (char *)msg_txt(214),(int)Sql_NumRows(sql_handle));
  401. while ( SQL_SUCCESS == Sql_NextRow(sql_handle) ) {
  402. int class_;
  403. short base_level, job_level, online;
  404. char name[NAME_LENGTH];
  405. Sql_GetData(sql_handle, 0, &data, NULL); account_id = atoi(data);
  406. Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(name, data, sizeof(name));
  407. Sql_GetData(sql_handle, 2, &data, NULL); class_ = atoi(data);
  408. Sql_GetData(sql_handle, 3, &data, NULL); base_level = atoi(data);
  409. Sql_GetData(sql_handle, 4, &data, NULL); job_level = atoi(data);
  410. Sql_GetData(sql_handle, 5, &data, NULL); online = atoi(data);
  411. inter_to_fd(fd, u_fd, u_aid, (char *)msg_txt(215), account_id, name, job_name(class_), base_level, job_level, online?"Online":"Offline");
  412. }
  413. Sql_FreeResult(sql_handle);
  414. return;
  415. }
  416. }
  417. }
  418. /* it will only get here if we have a single match then ask login-server to fetch the `login` record */
  419. if (!account_id || chlogif_req_accinfo(fd, u_fd, u_aid, account_id, type) != 1) {
  420. inter_to_fd(fd, u_fd, u_aid, (char *)msg_txt(213));
  421. }
  422. return;
  423. }
  424. /**
  425. * Show account info from login-server to user
  426. */
  427. void mapif_accinfo_ack(bool success, int map_fd, int u_fd, int u_aid, int account_id, int8 type,
  428. int group_id, int logincount, int state, const char *email, const char *last_ip, const char *lastlogin,
  429. const char *birthdate, const char *userid)
  430. {
  431. if (map_fd <= 0 || !session_isActive(map_fd))
  432. return; // check if we have a valid fd
  433. if (!success) {
  434. inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(216), account_id);
  435. return;
  436. }
  437. if (type == 1) { //type 1 we don't want all the info [lighta] @CHECKME
  438. mapif_acc_info_ack(map_fd, u_fd, account_id, userid);
  439. return;
  440. }
  441. inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(217), account_id);
  442. inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(218), userid, group_id, state);
  443. inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(221), email, birthdate);
  444. inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(222), last_ip, geoip_getcountry(str2ip(last_ip)));
  445. inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(223), logincount, lastlogin);
  446. inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(224));
  447. if ( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`, `name`, `char_num`, `class`, `base_level`, `job_level`, `online` FROM `%s` WHERE `account_id` = '%d' ORDER BY `char_num` LIMIT %d", charserv_table(char_table), account_id, MAX_CHARS)
  448. || Sql_NumRows(sql_handle) == 0 )
  449. {
  450. if( Sql_NumRows(sql_handle) == 0 )
  451. inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(226));
  452. else {
  453. inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(213));
  454. Sql_ShowDebug(sql_handle);
  455. }
  456. } else {
  457. while ( SQL_SUCCESS == Sql_NextRow(sql_handle) ) {
  458. uint32 char_id, class_;
  459. short char_num, base_level, job_level, online;
  460. char name[NAME_LENGTH];
  461. char *data;
  462. Sql_GetData(sql_handle, 0, &data, NULL); char_id = atoi(data);
  463. Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(name, data, sizeof(name));
  464. Sql_GetData(sql_handle, 2, &data, NULL); char_num = atoi(data);
  465. Sql_GetData(sql_handle, 3, &data, NULL); class_ = atoi(data);
  466. Sql_GetData(sql_handle, 4, &data, NULL); base_level = atoi(data);
  467. Sql_GetData(sql_handle, 5, &data, NULL); job_level = atoi(data);
  468. Sql_GetData(sql_handle, 6, &data, NULL); online = atoi(data);
  469. inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(225), char_num, char_id, name, job_name(class_), base_level, job_level, online?"Online":"Offline");
  470. }
  471. }
  472. Sql_FreeResult(sql_handle);
  473. }
  474. /**
  475. * Handles save reg data from map server and distributes accordingly.
  476. *
  477. * @param val either str or int, depending on type
  478. * @param type false when int, true otherwise
  479. **/
  480. void inter_savereg(uint32 account_id, uint32 char_id, const char *key, unsigned int index, intptr_t val, bool is_string)
  481. {
  482. char esc_val[254*2+1];
  483. char esc_key[32*2+1];
  484. Sql_EscapeString(sql_handle, esc_key, key);
  485. if( is_string && val ) {
  486. Sql_EscapeString(sql_handle, esc_val, (char*)val);
  487. }
  488. if( key[0] == '#' && key[1] == '#' ) { // global account reg
  489. if( session_isValid(login_fd) )
  490. chlogif_send_global_accreg(key,index,val,is_string);
  491. else {
  492. ShowError("Login server unavailable, can't perform update on '%s' variable for AID:%d CID:%d\n",key,account_id,char_id);
  493. }
  494. } else if ( key[0] == '#' ) { // local account reg
  495. if( is_string ) {
  496. if( val ) {
  497. if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`account_id`,`key`,`index`,`value`) VALUES ('%d','%s','%u','%s')", schema_config.acc_reg_str_table, account_id, esc_key, index, esc_val) )
  498. Sql_ShowDebug(sql_handle);
  499. } else {
  500. if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `key` = '%s' AND `index` = '%u' LIMIT 1", schema_config.acc_reg_str_table, account_id, esc_key, index) )
  501. Sql_ShowDebug(sql_handle);
  502. }
  503. } else {
  504. if( val ) {
  505. if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`account_id`,`key`,`index`,`value`) VALUES ('%d','%s','%u','%d')", schema_config.acc_reg_num_table, account_id, esc_key, index, (int)val) )
  506. Sql_ShowDebug(sql_handle);
  507. } else {
  508. if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `key` = '%s' AND `index` = '%u' LIMIT 1", schema_config.acc_reg_num_table, account_id, esc_key, index) )
  509. Sql_ShowDebug(sql_handle);
  510. }
  511. }
  512. } else { /* char reg */
  513. if( is_string ) {
  514. if( val ) {
  515. if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`char_id`,`key`,`index`,`value`) VALUES ('%d','%s','%u','%s')", schema_config.char_reg_str_table, char_id, esc_key, index, esc_val) )
  516. Sql_ShowDebug(sql_handle);
  517. } else {
  518. if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d' AND `key` = '%s' AND `index` = '%u' LIMIT 1", schema_config.char_reg_str_table, char_id, esc_key, index) )
  519. Sql_ShowDebug(sql_handle);
  520. }
  521. } else {
  522. if( val ) {
  523. if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`char_id`,`key`,`index`,`value`) VALUES ('%d','%s','%u','%d')", schema_config.char_reg_num_table, char_id, esc_key, index, (int)val) )
  524. Sql_ShowDebug(sql_handle);
  525. } else {
  526. if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d' AND `key` = '%s' AND `index` = '%u' LIMIT 1", schema_config.char_reg_num_table, char_id, esc_key, index) )
  527. Sql_ShowDebug(sql_handle);
  528. }
  529. }
  530. }
  531. }
  532. // Load account_reg from sql (type=2)
  533. int inter_accreg_fromsql(uint32 account_id, uint32 char_id, int fd, int type)
  534. {
  535. char* data;
  536. size_t len;
  537. unsigned int plen = 0;
  538. switch( type ) {
  539. case 3: //char reg
  540. if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `key`, `index`, `value` FROM `%s` WHERE `char_id`='%d'", charserv_table(char_reg_str_table), char_id) )
  541. Sql_ShowDebug(sql_handle);
  542. break;
  543. case 2: //account reg
  544. if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `key`, `index`, `value` FROM `%s` WHERE `account_id`='%d'", charserv_table(acc_reg_str_table), account_id) )
  545. Sql_ShowDebug(sql_handle);
  546. break;
  547. case 1: //account2 reg
  548. ShowError("inter_accreg_fromsql: Char server shouldn't handle type 1 registry values (##). That is the login server's job!\n");
  549. return 0;
  550. default:
  551. ShowError("inter_accreg_fromsql: Invalid type %d\n", type);
  552. return 0;
  553. }
  554. WFIFOHEAD(fd, 60000 + 300);
  555. WFIFOW(fd, 0) = 0x3804;
  556. // 0x2 = length, set prior to being sent
  557. WFIFOL(fd, 4) = account_id;
  558. WFIFOL(fd, 8) = char_id;
  559. WFIFOB(fd, 12) = 0; // var type (only set when all vars have been sent, regardless of type)
  560. WFIFOB(fd, 13) = 1; // is string type
  561. WFIFOW(fd, 14) = 0; // count
  562. plen = 16;
  563. /**
  564. * Vessel!
  565. *
  566. * str type
  567. * { keyLength(B), key(<keyLength>), index(L), valLength(B), val(<valLength>) }
  568. **/
  569. while ( SQL_SUCCESS == Sql_NextRow(sql_handle) ) {
  570. Sql_GetData(sql_handle, 0, &data, NULL);
  571. len = strlen(data)+1;
  572. WFIFOB(fd, plen) = (unsigned char)len; // won't be higher; the column size is 32
  573. plen += 1;
  574. safestrncpy(WFIFOCP(fd,plen), data, len);
  575. plen += len;
  576. Sql_GetData(sql_handle, 1, &data, NULL);
  577. WFIFOL(fd, plen) = (unsigned int)atol(data);
  578. plen += 4;
  579. Sql_GetData(sql_handle, 2, &data, NULL);
  580. len = strlen(data)+1;
  581. WFIFOB(fd, plen) = (unsigned char)len; // won't be higher; the column size is 254
  582. plen += 1;
  583. safestrncpy(WFIFOCP(fd,plen), data, len);
  584. plen += len;
  585. WFIFOW(fd, 14) += 1;
  586. if( plen > 60000 ) {
  587. WFIFOW(fd, 2) = plen;
  588. WFIFOSET(fd, plen);
  589. // prepare follow up
  590. WFIFOHEAD(fd, 60000 + 300);
  591. WFIFOW(fd, 0) = 0x3804;
  592. // 0x2 = length, set prior to being sent
  593. WFIFOL(fd, 4) = account_id;
  594. WFIFOL(fd, 8) = char_id;
  595. WFIFOB(fd, 12) = 0; // var type (only set when all vars have been sent, regardless of type)
  596. WFIFOB(fd, 13) = 1; // is string type
  597. WFIFOW(fd, 14) = 0; // count
  598. plen = 16;
  599. }
  600. }
  601. WFIFOW(fd, 2) = plen;
  602. WFIFOSET(fd, plen);
  603. Sql_FreeResult(sql_handle);
  604. switch( type ) {
  605. case 3: //char reg
  606. if (SQL_ERROR == Sql_Query(sql_handle, "SELECT `key`, `index`, `value` FROM `%s` WHERE `char_id`='%d'", charserv_table(char_reg_num_table), char_id))
  607. Sql_ShowDebug(sql_handle);
  608. break;
  609. case 2: //account reg
  610. if (SQL_ERROR == Sql_Query(sql_handle, "SELECT `key`, `index`, `value` FROM `%s` WHERE `account_id`='%d'", charserv_table(acc_reg_num_table), account_id))
  611. Sql_ShowDebug(sql_handle);
  612. break;
  613. #if 0 // This is already checked above.
  614. case 1: //account2 reg
  615. ShowError("inter_accreg_fromsql: Char server shouldn't handle type 1 registry values (##). That is the login server's work!\n");
  616. return 0;
  617. #endif // 0
  618. }
  619. WFIFOHEAD(fd, 60000 + 300);
  620. WFIFOW(fd, 0) = 0x3804;
  621. // 0x2 = length, set prior to being sent
  622. WFIFOL(fd, 4) = account_id;
  623. WFIFOL(fd, 8) = char_id;
  624. WFIFOB(fd, 12) = 0; // var type (only set when all vars have been sent, regardless of type)
  625. WFIFOB(fd, 13) = 0; // is int type
  626. WFIFOW(fd, 14) = 0; // count
  627. plen = 16;
  628. /**
  629. * Vessel!
  630. *
  631. * int type
  632. * { keyLength(B), key(<keyLength>), index(L), value(L) }
  633. **/
  634. while ( SQL_SUCCESS == Sql_NextRow(sql_handle) ) {
  635. Sql_GetData(sql_handle, 0, &data, NULL);
  636. len = strlen(data)+1;
  637. WFIFOB(fd, plen) = (unsigned char)len;/* won't be higher; the column size is 32 */
  638. plen += 1;
  639. safestrncpy(WFIFOCP(fd,plen), data, len);
  640. plen += len;
  641. Sql_GetData(sql_handle, 1, &data, NULL);
  642. WFIFOL(fd, plen) = (unsigned int)atol(data);
  643. plen += 4;
  644. Sql_GetData(sql_handle, 2, &data, NULL);
  645. WFIFOL(fd, plen) = atoi(data);
  646. plen += 4;
  647. WFIFOW(fd, 14) += 1;
  648. if( plen > 60000 ) {
  649. WFIFOW(fd, 2) = plen;
  650. WFIFOSET(fd, plen);
  651. /* prepare follow up */
  652. WFIFOHEAD(fd, 60000 + 300);
  653. WFIFOW(fd, 0) = 0x3804;
  654. /* 0x2 = length, set prior to being sent */
  655. WFIFOL(fd, 4) = account_id;
  656. WFIFOL(fd, 8) = char_id;
  657. WFIFOB(fd, 12) = 0;/* var type (only set when all vars have been sent, regardless of type) */
  658. WFIFOB(fd, 13) = 0;/* is int type */
  659. WFIFOW(fd, 14) = 0;/* count */
  660. plen = 16;
  661. }
  662. }
  663. WFIFOB(fd, 12) = type;
  664. WFIFOW(fd, 2) = plen;
  665. WFIFOSET(fd, plen);
  666. Sql_FreeResult(sql_handle);
  667. return 1;
  668. }
  669. /**
  670. * Set default hardcoded Inter-serv configurations
  671. **/
  672. static void inter_config_init(void) {
  673. inter_config.party_share_level = 10;
  674. inter_config.char_server_port = 3306;
  675. inter_config.char_server_ip = "127.0.0.1";
  676. inter_config.char_server_id = "ragnarok";
  677. inter_config.char_server_pw = "";
  678. inter_config.char_server_db = "ragnarok";
  679. inter_config.default_codepage = "";
  680. }
  681. /*==========================================
  682. * read config file
  683. *------------------------------------------*/
  684. int inter_config_read(const char* cfgName)
  685. {
  686. char line[1024];
  687. FILE* fp;
  688. fp = fopen(cfgName, "r");
  689. if(fp == NULL) {
  690. ShowError("File not found: %s\n", cfgName);
  691. return 1;
  692. }
  693. while(fgets(line, sizeof(line), fp)) {
  694. char w1[24], w2[1024];
  695. if (line[0] == '/' && line[1] == '/')
  696. continue;
  697. if (sscanf(line, "%23[^:]: %1023[^\r\n]", w1, w2) != 2)
  698. continue;
  699. if(!strcmpi(w1,"char_server_ip"))
  700. inter_config.char_server_ip = w2;
  701. else if(!strcmpi(w1,"char_server_port"))
  702. inter_config.char_server_port = atoi(w2);
  703. else if(!strcmpi(w1,"char_server_id"))
  704. inter_config.char_server_id = w2;
  705. else if(!strcmpi(w1,"char_server_pw"))
  706. inter_config.char_server_pw = w2;
  707. else if(!strcmpi(w1,"char_server_db"))
  708. inter_config.char_server_db = w2;
  709. else if(!strcmpi(w1,"default_codepage"))
  710. inter_config.default_codepage = w2;
  711. else if(!strcmpi(w1,"party_share_level"))
  712. inter_config.party_share_level = (unsigned short)atof(w2);
  713. else if(!strcmpi(w1,"log_inter"))
  714. charserv_config.log_inter = atoi(w2);
  715. else if(!strcmpi(w1,"inter_server_conf"))
  716. cfgFile = w2;
  717. else if(!strcmpi(w1,"import"))
  718. inter_config_read(w2);
  719. }
  720. fclose(fp);
  721. ShowInfo ("Done reading %s.\n", cfgName);
  722. return 0;
  723. }
  724. // Save interlog into sql
  725. int inter_log(const char* fmt, ...)
  726. {
  727. char str[255];
  728. char esc_str[sizeof(str)*2+1];// escaped str
  729. va_list ap;
  730. va_start(ap,fmt);
  731. vsnprintf(str, sizeof(str), fmt, ap);
  732. va_end(ap);
  733. Sql_EscapeStringLen(sql_handle, esc_str, str, strnlen(str, sizeof(str)));
  734. if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`time`, `log`) VALUES (NOW(), '%s')", charserv_table(interlog_table), esc_str) )
  735. Sql_ShowDebug(sql_handle);
  736. return 0;
  737. }
  738. const std::string InterServerDatabase::getDefaultLocation(){
  739. return std::string(conf_path) + "/" + cfgFile;
  740. }
  741. /**
  742. * Reads and parses an entry from the inter_server.
  743. * @param node: YAML node containing the entry.
  744. * @return count of successfully parsed rows
  745. */
  746. uint64 InterServerDatabase::parseBodyNode( const YAML::Node& node ){
  747. uint32 id;
  748. if( !this->asUInt32( node, "ID", id ) ){
  749. return 0;
  750. }
  751. auto storage_table = this->find( id );
  752. bool existing = storage_table != nullptr;
  753. if( !existing ){
  754. if( !this->nodeExists( node, "Name" ) ){
  755. this->invalidWarning( node, "Node \"Name\" is missing.\n" );
  756. return 0;
  757. }
  758. if( !this->nodeExists( node, "Table" ) ){
  759. this->invalidWarning( node, "Node \"Table\" is missing.\n" );
  760. return 0;
  761. }
  762. storage_table = std::make_shared<s_storage_table>();
  763. storage_table->id = (uint8)id;
  764. }
  765. if( this->nodeExists( node, "Name" ) ){
  766. std::string name;
  767. if( !this->asString( node, "Name", name ) ){
  768. return 0;
  769. }
  770. safestrncpy( storage_table->name, name.c_str(), NAME_LENGTH );
  771. }
  772. if( this->nodeExists( node, "Table" ) ){
  773. std::string table;
  774. if( !this->asString( node, "Table", table ) ){
  775. return 0;
  776. }
  777. safestrncpy( storage_table->table, table.c_str(), DB_NAME_LEN );
  778. }
  779. if( this->nodeExists( node, "Max" ) ){
  780. uint16 max;
  781. if( !this->asUInt16( node, "Max", max ) ){
  782. return 0;
  783. }
  784. storage_table->max_num = max;
  785. }else{
  786. if( !existing ){
  787. storage_table->max_num = MAX_STORAGE;
  788. }
  789. }
  790. if( !existing ){
  791. this->put( storage_table->id, storage_table );
  792. }
  793. return 1;
  794. }
  795. // initialize
  796. int inter_init_sql(const char *file)
  797. {
  798. inter_config_init();
  799. inter_config_read(file);
  800. //DB connection initialized
  801. sql_handle = Sql_Malloc();
  802. ShowInfo("Connect Character DB server.... (Character Server)\n");
  803. if( SQL_ERROR == Sql_Connect(sql_handle, inter_config.char_server_id.c_str(), inter_config.char_server_pw.c_str(), inter_config.char_server_ip.c_str(), inter_config.char_server_port, inter_config.char_server_db.c_str()) )
  804. {
  805. ShowError("Couldn't connect with username = '%s', password = '%s', host = '%s', port = '%d', database = '%s'\n",
  806. inter_config.char_server_id.c_str(), inter_config.char_server_pw.c_str(), inter_config.char_server_ip.c_str(), inter_config.char_server_port, inter_config.char_server_db.c_str());
  807. Sql_ShowDebug(sql_handle);
  808. Sql_Free(sql_handle);
  809. exit(EXIT_FAILURE);
  810. }
  811. if( !inter_config.default_codepage.empty() ) {
  812. if( SQL_ERROR == Sql_SetEncoding(sql_handle, inter_config.default_codepage.c_str()) )
  813. Sql_ShowDebug(sql_handle);
  814. }
  815. ShowStatus("Character server connection: Database '" CL_WHITE "%s" CL_RESET "' at '" CL_WHITE "%s" CL_RESET "'\n", inter_config.char_server_db.c_str(), inter_config.char_server_ip.c_str());
  816. wis_db = idb_alloc(DB_OPT_RELEASE_DATA);
  817. interServerDb.load();
  818. inter_guild_sql_init();
  819. inter_storage_sql_init();
  820. inter_party_sql_init();
  821. inter_pet_sql_init();
  822. inter_homunculus_sql_init();
  823. inter_mercenary_sql_init();
  824. inter_elemental_sql_init();
  825. inter_mail_sql_init();
  826. inter_auction_sql_init();
  827. inter_clan_init();
  828. geoip_readdb();
  829. return 0;
  830. }
  831. // finalize
  832. void inter_final(void)
  833. {
  834. wis_db->destroy(wis_db, NULL);
  835. inter_guild_sql_final();
  836. inter_storage_sql_final();
  837. inter_party_sql_final();
  838. inter_pet_sql_final();
  839. inter_homunculus_sql_final();
  840. inter_mercenary_sql_final();
  841. inter_elemental_sql_final();
  842. inter_mail_sql_final();
  843. inter_auction_sql_final();
  844. inter_clan_final();
  845. if(geoip_cache) aFree(geoip_cache);
  846. return;
  847. }
  848. /**
  849. * IZ 0x388c <len>.W { <storage_table>.? }*?
  850. * Sends storage information to map-server
  851. * @param fd
  852. **/
  853. void inter_Storage_sendInfo(int fd) {
  854. int size = sizeof(struct s_storage_table), len = 4 + interServerDb.size() * size, offset;
  855. // Send storage table information
  856. WFIFOHEAD(fd, len);
  857. WFIFOW(fd, 0) = 0x388c;
  858. WFIFOW(fd, 2) = len;
  859. offset = 4;
  860. for( auto storage : interServerDb ){
  861. memcpy(WFIFOP(fd, offset), storage.second.get(), size);
  862. offset += size;
  863. }
  864. WFIFOSET(fd, len);
  865. }
  866. int inter_mapif_init(int fd)
  867. {
  868. inter_Storage_sendInfo(fd);
  869. return 0;
  870. }
  871. //--------------------------------------------------------
  872. // broadcast sending
  873. int mapif_broadcast(unsigned char *mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY, int sfd)
  874. {
  875. unsigned char *buf = (unsigned char*)aMalloc((len)*sizeof(unsigned char));
  876. WBUFW(buf,0) = 0x3800;
  877. WBUFW(buf,2) = len;
  878. WBUFL(buf,4) = fontColor;
  879. WBUFW(buf,8) = fontType;
  880. WBUFW(buf,10) = fontSize;
  881. WBUFW(buf,12) = fontAlign;
  882. WBUFW(buf,14) = fontY;
  883. memcpy(WBUFP(buf,16), mes, len - 16);
  884. chmapif_sendallwos(sfd, buf, len);
  885. aFree(buf);
  886. return 0;
  887. }
  888. // Wis sending
  889. int mapif_wis_message(struct WisData *wd)
  890. {
  891. unsigned char buf[2048];
  892. int headersize = 12 + 2 * NAME_LENGTH;
  893. if (wd->len > 2047-headersize) wd->len = 2047-headersize; //Force it to fit to avoid crashes. [Skotlex]
  894. WBUFW(buf, 0) = 0x3801;
  895. WBUFW(buf, 2) = headersize+wd->len;
  896. WBUFL(buf, 4) = wd->id;
  897. WBUFL(buf, 8) = wd->gmlvl;
  898. safestrncpy(WBUFCP(buf,12), wd->src, NAME_LENGTH);
  899. safestrncpy(WBUFCP(buf,12 + NAME_LENGTH), wd->dst, NAME_LENGTH);
  900. safestrncpy(WBUFCP(buf,12 + 2*NAME_LENGTH), wd->msg, wd->len);
  901. wd->count = chmapif_sendall(buf,WBUFW(buf,2));
  902. return 0;
  903. }
  904. // Send the requested account_reg
  905. int mapif_account_reg_reply(int fd, uint32 account_id, uint32 char_id, int type)
  906. {
  907. inter_accreg_fromsql(account_id,char_id,fd,type);
  908. return 0;
  909. }
  910. //Request to kick char from a certain map server. [Skotlex]
  911. int mapif_disconnectplayer(int fd, uint32 account_id, uint32 char_id, int reason)
  912. {
  913. if (fd >= 0)
  914. {
  915. WFIFOHEAD(fd,7);
  916. WFIFOW(fd,0) = 0x2b1f;
  917. WFIFOL(fd,2) = account_id;
  918. WFIFOB(fd,6) = reason;
  919. WFIFOSET(fd,7);
  920. return 0;
  921. }
  922. return -1;
  923. }
  924. //--------------------------------------------------------
  925. /**
  926. * Existence check of WISP data
  927. * @see DBApply
  928. */
  929. int check_ttl_wisdata_sub(DBKey key, DBData *data, va_list ap)
  930. {
  931. t_tick tick;
  932. struct WisData *wd = (struct WisData *)db_data2ptr(data);
  933. tick = va_arg(ap, t_tick);
  934. if (DIFF_TICK(tick, wd->tick) > WISDATA_TTL && wis_delnum < WISDELLIST_MAX)
  935. wis_dellist[wis_delnum++] = wd->id;
  936. return 0;
  937. }
  938. int check_ttl_wisdata(void)
  939. {
  940. t_tick tick = gettick();
  941. int i;
  942. do {
  943. wis_delnum = 0;
  944. wis_db->foreach(wis_db, check_ttl_wisdata_sub, tick);
  945. for(i = 0; i < wis_delnum; i++) {
  946. struct WisData *wd = (struct WisData*)idb_get(wis_db, wis_dellist[i]);
  947. ShowWarning("inter: wis data id=%d time out : from %s to %s\n", wd->id, wd->src, wd->dst);
  948. // removed. not send information after a timeout. Just no answer for the player
  949. //mapif_wis_reply(wd->fd, wd->src, 1); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
  950. idb_remove(wis_db, wd->id);
  951. }
  952. } while(wis_delnum >= WISDELLIST_MAX);
  953. return 0;
  954. }
  955. //--------------------------------------------------------
  956. // broadcast sending
  957. int mapif_parse_broadcast(int fd)
  958. {
  959. mapif_broadcast(RFIFOP(fd,16), RFIFOW(fd,2), RFIFOL(fd,4), RFIFOW(fd,8), RFIFOW(fd,10), RFIFOW(fd,12), RFIFOW(fd,14), fd);
  960. return 0;
  961. }
  962. /**
  963. * Parse received item broadcast and sends it to all connected map-serves
  964. * ZI 3009 <cmd>.W <len>.W <nameid>.W <source>.W <type>.B <name>.24B <srcname>.24B
  965. * IZ 3809 <cmd>.W <len>.W <nameid>.W <source>.W <type>.B <name>.24B <srcname>.24B
  966. * @param fd
  967. * @return
  968. **/
  969. int mapif_parse_broadcast_item(int fd) {
  970. unsigned char buf[9 + NAME_LENGTH*2];
  971. memcpy(WBUFP(buf, 0), RFIFOP(fd, 0), RFIFOW(fd,2));
  972. WBUFW(buf, 0) = 0x3809;
  973. chmapif_sendallwos(fd, buf, RFIFOW(fd,2));
  974. return 0;
  975. }
  976. // Wis sending result
  977. // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
  978. int mapif_wis_reply( int mapserver_fd, char* target, uint8 flag ){
  979. unsigned char buf[27];
  980. WBUFW(buf, 0) = 0x3802;
  981. safestrncpy(WBUFCP(buf, 2), target, NAME_LENGTH);
  982. WBUFB(buf,26) = flag;
  983. return chmapif_send(mapserver_fd, buf, 27);
  984. }
  985. // Wisp/page request to send
  986. int mapif_parse_WisRequest(int fd)
  987. {
  988. struct WisData* wd;
  989. char name[NAME_LENGTH];
  990. char esc_name[NAME_LENGTH*2+1];// escaped name
  991. char* data;
  992. size_t len;
  993. int headersize = 8+2*NAME_LENGTH;
  994. if ( fd <= 0 ) {return 0;} // check if we have a valid fd
  995. if (RFIFOW(fd,2)-headersize >= sizeof(wd->msg)) {
  996. ShowWarning("inter: Wis message size too long.\n");
  997. return 0;
  998. } else if (RFIFOW(fd,2)-headersize <= 0) { // normaly, impossible, but who knows...
  999. ShowError("inter: Wis message doesn't exist.\n");
  1000. return 0;
  1001. }
  1002. safestrncpy(name, RFIFOCP(fd,8+NAME_LENGTH), NAME_LENGTH); //Received name may be too large and not contain \0! [Skotlex]
  1003. Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH));
  1004. if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `name` FROM `%s` WHERE `name`='%s'", charserv_table(char_table), esc_name) )
  1005. Sql_ShowDebug(sql_handle);
  1006. // search if character exists before to ask all map-servers
  1007. if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
  1008. {
  1009. mapif_wis_reply(fd, RFIFOCP(fd, 8), 1);
  1010. }
  1011. else
  1012. {// Character exists. So, ask all map-servers
  1013. // to be sure of the correct name, rewrite it
  1014. Sql_GetData(sql_handle, 0, &data, &len);
  1015. memset(name, 0, NAME_LENGTH);
  1016. memcpy(name, data, zmin(len, NAME_LENGTH));
  1017. // if source is destination, don't ask other servers.
  1018. if( strncmp(RFIFOCP(fd,8), name, NAME_LENGTH) == 0 )
  1019. {
  1020. mapif_wis_reply(fd, RFIFOCP(fd, 8), 1);
  1021. }
  1022. else
  1023. {
  1024. static int wisid = 0;
  1025. CREATE(wd, struct WisData, 1);
  1026. // Whether the failure of previous wisp/page transmission (timeout)
  1027. check_ttl_wisdata();
  1028. wd->id = ++wisid;
  1029. wd->fd = fd;
  1030. wd->len= RFIFOW(fd,2)-headersize;
  1031. wd->gmlvl = RFIFOL(fd,4);
  1032. safestrncpy(wd->src, RFIFOCP(fd,8), NAME_LENGTH);
  1033. safestrncpy(wd->dst, RFIFOCP(fd,8+NAME_LENGTH), NAME_LENGTH);
  1034. safestrncpy(wd->msg, RFIFOCP(fd,8+2*NAME_LENGTH), wd->len);
  1035. wd->tick = gettick();
  1036. idb_put(wis_db, wd->id, wd);
  1037. mapif_wis_message(wd);
  1038. }
  1039. }
  1040. Sql_FreeResult(sql_handle);
  1041. return 0;
  1042. }
  1043. // Wisp/page transmission result
  1044. int mapif_parse_WisReply(int fd)
  1045. {
  1046. int id;
  1047. uint8 flag;
  1048. struct WisData *wd;
  1049. id = RFIFOL(fd,2);
  1050. flag = RFIFOB(fd,6);
  1051. wd = (struct WisData*)idb_get(wis_db, id);
  1052. if (wd == NULL)
  1053. return 0; // This wisp was probably suppress before, because it was timeout of because of target was found on another map-server
  1054. if ((--wd->count) <= 0 || flag != 1) {
  1055. mapif_wis_reply(wd->fd, wd->src, flag); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
  1056. idb_remove(wis_db, id);
  1057. }
  1058. return 0;
  1059. }
  1060. // Received wisp message from map-server for ALL gm (just copy the message and resends it to ALL map-servers)
  1061. int mapif_parse_WisToGM(int fd)
  1062. {
  1063. unsigned char buf[2048]; // 0x3003/0x3803 <packet_len>.w <wispname>.24B <permission>.L <message>.?B
  1064. memcpy(WBUFP(buf,0), RFIFOP(fd,0), RFIFOW(fd,2));
  1065. WBUFW(buf, 0) = 0x3803;
  1066. chmapif_sendall(buf, RFIFOW(fd,2));
  1067. return 0;
  1068. }
  1069. // Save account_reg into sql (type=2)
  1070. int mapif_parse_Registry(int fd)
  1071. {
  1072. int account_id = RFIFOL(fd, 4), char_id = RFIFOL(fd, 8), count = RFIFOW(fd, 12);
  1073. if( count ) {
  1074. int cursor = 14, i;
  1075. bool isLoginActive = session_isActive(login_fd);
  1076. if( isLoginActive )
  1077. chlogif_upd_global_accreg(account_id,char_id);
  1078. for(i = 0; i < count; i++) {
  1079. size_t lenkey = RFIFOB( fd, cursor );
  1080. const char* src_key= RFIFOCP(fd, cursor + 1);
  1081. std::string key( src_key, lenkey );
  1082. cursor += lenkey + 1;
  1083. unsigned int index = RFIFOL(fd, cursor);
  1084. cursor += 4;
  1085. switch (RFIFOB(fd, cursor++)) {
  1086. // int
  1087. case 0:
  1088. {
  1089. intptr_t lVal = RFIFOL( fd, cursor );
  1090. inter_savereg( account_id, char_id, key.c_str(), index, lVal, false );
  1091. cursor += 4;
  1092. break;
  1093. }
  1094. case 1:
  1095. inter_savereg(account_id,char_id,key.c_str(),index,0,false);
  1096. break;
  1097. // str
  1098. case 2:
  1099. {
  1100. size_t len_val = RFIFOB( fd, cursor );
  1101. const char* src_val= RFIFOCP(fd, cursor + 1);
  1102. std::string sval( src_val, len_val );
  1103. cursor += len_val + 1;
  1104. inter_savereg( account_id, char_id, key.c_str(), index, (intptr_t)sval.c_str(), true );
  1105. break;
  1106. }
  1107. case 3:
  1108. inter_savereg(account_id,char_id,key.c_str(),index,0,true);
  1109. break;
  1110. default:
  1111. ShowError("mapif_parse_Registry: unknown type %d\n",RFIFOB(fd, cursor - 1));
  1112. return 1;
  1113. }
  1114. }
  1115. if (isLoginActive)
  1116. chlogif_prepsend_global_accreg();
  1117. }
  1118. return 0;
  1119. }
  1120. // Request the value of all registries.
  1121. int mapif_parse_RegistryRequest(int fd)
  1122. {
  1123. //Load Char Registry
  1124. if (RFIFOB(fd,12)) mapif_account_reg_reply(fd,RFIFOL(fd,2),RFIFOL(fd,6),3);
  1125. //Load Account Registry
  1126. if (RFIFOB(fd,11)) mapif_account_reg_reply(fd,RFIFOL(fd,2),RFIFOL(fd,6),2);
  1127. //Ask Login Server for Account2 values.
  1128. if (RFIFOB(fd,10)) chlogif_request_accreg2(RFIFOL(fd,2),RFIFOL(fd,6));
  1129. return 1;
  1130. }
  1131. void mapif_namechange_ack(int fd, uint32 account_id, uint32 char_id, int type, int flag, char *name)
  1132. {
  1133. WFIFOHEAD(fd, NAME_LENGTH+13);
  1134. WFIFOW(fd, 0) = 0x3806;
  1135. WFIFOL(fd, 2) = account_id;
  1136. WFIFOL(fd, 6) = char_id;
  1137. WFIFOB(fd,10) = type;
  1138. WFIFOB(fd,11) = flag;
  1139. memcpy(WFIFOP(fd, 12), name, NAME_LENGTH);
  1140. WFIFOSET(fd, NAME_LENGTH+13);
  1141. }
  1142. int mapif_parse_NameChangeRequest(int fd)
  1143. {
  1144. uint32 account_id, char_id;
  1145. int type;
  1146. char* name;
  1147. int i;
  1148. account_id = RFIFOL(fd,2);
  1149. char_id = RFIFOL(fd,6);
  1150. type = RFIFOB(fd,10);
  1151. name = RFIFOCP(fd,11);
  1152. // Check Authorised letters/symbols in the name
  1153. if (charserv_config.char_config.char_name_option == 1) { // only letters/symbols in char_name_letters are authorised
  1154. for (i = 0; i < NAME_LENGTH && name[i]; i++)
  1155. if (strchr(charserv_config.char_config.char_name_letters, name[i]) == NULL) {
  1156. mapif_namechange_ack(fd, account_id, char_id, type, 0, name);
  1157. return 0;
  1158. }
  1159. } else if (charserv_config.char_config.char_name_option == 2) { // letters/symbols in char_name_letters are forbidden
  1160. for (i = 0; i < NAME_LENGTH && name[i]; i++)
  1161. if (strchr(charserv_config.char_config.char_name_letters, name[i]) != NULL) {
  1162. mapif_namechange_ack(fd, account_id, char_id, type, 0, name);
  1163. return 0;
  1164. }
  1165. }
  1166. //TODO: type holds the type of object to rename.
  1167. //If it were a player, it needs to have the guild information and db information
  1168. //updated here, because changing it on the map won't make it be saved [Skotlex]
  1169. //name allowed.
  1170. mapif_namechange_ack(fd, account_id, char_id, type, 1, name);
  1171. return 0;
  1172. }
  1173. //--------------------------------------------------------
  1174. /// Returns the length of the next complete packet to process,
  1175. /// or 0 if no complete packet exists in the queue.
  1176. ///
  1177. /// @param length The minimum allowed length, or -1 for dynamic lookup
  1178. int inter_check_length(int fd, int length)
  1179. {
  1180. if( length == -1 )
  1181. {// variable-length packet
  1182. if( RFIFOREST(fd) < 4 )
  1183. return 0;
  1184. length = RFIFOW(fd,2);
  1185. }
  1186. if( (int)RFIFOREST(fd) < length )
  1187. return 0;
  1188. return length;
  1189. }
  1190. int inter_parse_frommap(int fd)
  1191. {
  1192. int cmd;
  1193. int len = 0;
  1194. cmd = RFIFOW(fd,0);
  1195. // Check is valid packet entry
  1196. if(cmd < 0x3000 || cmd >= 0x3000 + ARRAYLENGTH(inter_recv_packet_length) || inter_recv_packet_length[cmd - 0x3000] == 0)
  1197. return 0;
  1198. // Check packet length
  1199. if((len = inter_check_length(fd, inter_recv_packet_length[cmd - 0x3000])) == 0)
  1200. return 2;
  1201. switch(cmd) {
  1202. case 0x3000: mapif_parse_broadcast(fd); break;
  1203. case 0x3001: mapif_parse_WisRequest(fd); break;
  1204. case 0x3002: mapif_parse_WisReply(fd); break;
  1205. case 0x3003: mapif_parse_WisToGM(fd); break;
  1206. case 0x3004: mapif_parse_Registry(fd); break;
  1207. case 0x3005: mapif_parse_RegistryRequest(fd); break;
  1208. case 0x3006: mapif_parse_NameChangeRequest(fd); break;
  1209. case 0x3007: mapif_parse_accinfo(fd); break;
  1210. /* 0x3008 unused */
  1211. case 0x3009: mapif_parse_broadcast_item(fd); break;
  1212. default:
  1213. if( inter_party_parse_frommap(fd)
  1214. || inter_guild_parse_frommap(fd)
  1215. || inter_storage_parse_frommap(fd)
  1216. || inter_pet_parse_frommap(fd)
  1217. || inter_homunculus_parse_frommap(fd)
  1218. || inter_mercenary_parse_frommap(fd)
  1219. || inter_elemental_parse_frommap(fd)
  1220. || inter_mail_parse_frommap(fd)
  1221. || inter_auction_parse_frommap(fd)
  1222. || inter_quest_parse_frommap(fd)
  1223. || inter_clan_parse_frommap(fd)
  1224. || inter_achievement_parse_frommap(fd)
  1225. )
  1226. break;
  1227. else
  1228. return 0;
  1229. }
  1230. RFIFOSKIP(fd, len);
  1231. return 1;
  1232. }