ServerAgent.cpp 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921
  1. /*
  2. * The contents of this file are subject to the Mozilla Public
  3. * License Version 1.1 (the "License"); you may not use this file
  4. * except in compliance with the License. You may obtain a copy of
  5. * the License at http://www.mozilla.org/MPL/
  6. *
  7. * Software distributed under the License is distributed on an "AS
  8. * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9. * implied. See the License for the specific language governing
  10. * rights and limitations under the License.
  11. *
  12. * The Original Code is Vision.
  13. *
  14. * The Initial Developer of the Original Code is The Vision Team.
  15. * Portions created by The Vision Team are
  16. * Copyright (C) 1999, 2000, 2001 The Vision Team. All Rights
  17. * Reserved.
  18. *
  19. * Contributor(s): Wade Majors <wade@ezri.org>
  20. * Rene Gollent
  21. * Todd Lair
  22. * Andrew Bazan
  23. * Jamie Wilkinson
  24. * John Robinson
  25. * Alan Ellis <alan@cgsoftware.org>
  26. * Francois Revol
  27. */
  28. #include <UTF8.h>
  29. #include <Autolock.h>
  30. #include <Directory.h>
  31. #include <Entry.h>
  32. #include <FilePanel.h>
  33. #include <MessageRunner.h>
  34. #include <Path.h>
  35. #include <String.h>
  36. #include <arpa/inet.h>
  37. #include <ctype.h>
  38. #include <netdb.h>
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <sys/socket.h>
  42. #include <sys/select.h>
  43. #include "ClientAgent.h"
  44. #include "ClientAgentLogger.h"
  45. #include "ClientWindow.h"
  46. #include "ChannelAgent.h"
  47. #include "DCCConnect.h"
  48. #include "ListAgent.h"
  49. #include "MessageAgent.h"
  50. #include "NotifyList.h"
  51. #include "ServerAgent.h"
  52. #include "StatusView.h"
  53. #include "Utilities.h"
  54. #include "Vision.h"
  55. #include "WindowList.h"
  56. class failToLock { /* exception in Establish */ };
  57. int32 ServerAgent::fServerSeed = 0;
  58. ServerAgent::ServerAgent (
  59. const char *id_,
  60. BMessage &net,
  61. BRect frame_)
  62. : ClientAgent (
  63. id_,
  64. id_,
  65. net.FindString ("nick"),
  66. frame_),
  67. fLocalip (""),
  68. fMyNick (net.FindString ("nick")),
  69. fMyLag ((net.FindBool ("lagCheck")) ? "0.000" : S_SERVER_LAG_DISABLED),
  70. fLname (net.FindString ("realname")),
  71. fLident (net.FindString ("ident")),
  72. fLocalip_private (false),
  73. fGetLocalIP (false),
  74. fIsConnected (false),
  75. fIsConnecting (true),
  76. fReconnecting (false),
  77. fIsQuitting (false),
  78. fCheckingLag (false),
  79. fReacquiredNick (true),
  80. fEstablishHasLock (false),
  81. fRetry (0),
  82. fRetryLimit (47),
  83. fLagCheck (0),
  84. fLagCount (0),
  85. fNickAttempt (0),
  86. fServerSocket (-1),
  87. fLoginThread (-1),
  88. fSenderThread (-1),
  89. fEvents (vision_app->fEvents),
  90. fServerHostName (id_),
  91. fInitialMotd (true),
  92. fCmds (net.FindString ("autoexec")),
  93. fSocket(-1),
  94. fListAgent (NULL),
  95. fNetworkData (net),
  96. fServerIndex (0),
  97. fNickIndex (0),
  98. fLogger (NULL)
  99. {
  100. fLogger = new ClientAgentLogger(fId);
  101. }
  102. ServerAgent::~ServerAgent (void)
  103. {
  104. if (fLagRunner)
  105. delete fLagRunner;
  106. while (fStartupChannels.CountItems() != 0)
  107. delete fStartupChannels.RemoveItemAt (0L);
  108. delete fLogger;
  109. delete_sem (fSendSyncSem);
  110. if (fSocket >= 0)
  111. {
  112. close (fSocket);
  113. }
  114. // wait_for_thread (fLoginThread, &result);
  115. /*
  116. while (fIgnoreNicks.CountItems() > 0)
  117. delete fIgnoreNicks.RemoveItem(0L);
  118. */
  119. while (fNotifyNicks.CountItems() > 0)
  120. delete fNotifyNicks.RemoveItemAt(0L);
  121. }
  122. void
  123. ServerAgent::AttachedToWindow(void)
  124. {
  125. Init();
  126. ClientAgent::AttachedToWindow();
  127. }
  128. void
  129. ServerAgent::AllAttached (void)
  130. {
  131. fSMsgr = BMessenger (this);
  132. ClientAgent::AllAttached ();
  133. // build notify list here since we can't send a message to ourselves sooner
  134. type_code type;
  135. int32 attrCount (0);
  136. BMessage updatemsg (M_NOTIFYLIST_ADD);
  137. BString data;
  138. fNetworkData.GetInfo ("notify", &type, &attrCount);
  139. for (int32 i = 0; i < attrCount; i++)
  140. {
  141. data += fNetworkData.FindString("notify", i);
  142. data += " ";
  143. }
  144. if (attrCount > 0)
  145. {
  146. updatemsg.AddString("cmd", data.String());
  147. fSMsgr.SendMessage(&updatemsg);
  148. }
  149. }
  150. // do nothing for now
  151. void
  152. ServerAgent::AddMenuItems(BPopUpMenu *)
  153. {
  154. }
  155. void
  156. ServerAgent::Init (void)
  157. {
  158. BString revString;
  159. Display ("Vision ");
  160. vision_app->VisionVersion (VERSION_VERSION, revString);
  161. Display (revString.String(), C_MYNICK);
  162. Display (" built on ");
  163. vision_app->VisionVersion (VERSION_DATE, revString);
  164. Display (revString.String());
  165. Display ("\nThis agent goes by the name of Smith... err ");
  166. BString temp;
  167. temp << fId << "\n";
  168. Display (temp.String(), C_NICK);
  169. Display ("Have fun!\n");
  170. fLagRunner = new BMessageRunner (
  171. this, // target ServerAgent
  172. new BMessage (M_LAG_CHECK),
  173. 10000000, // 10 seconds
  174. -1); // forever
  175. CreateSenderThread();
  176. CreateEstablishThread();
  177. }
  178. void
  179. ServerAgent::CreateSenderThread (void)
  180. {
  181. fPendingSends = new BObjectList<BString>();
  182. fSendLock = new BLocker();
  183. fSendSyncSem = create_sem (0, "VisionSendSync");
  184. BString name;
  185. name = "t>";
  186. name += (rand() %2) ? "Tima" : "Kenichi";
  187. fSenderThread = spawn_thread (
  188. Sender,
  189. name.String(),
  190. B_NORMAL_PRIORITY,
  191. this);
  192. if (fSenderThread >= B_OK)
  193. resume_thread (fSenderThread);
  194. else
  195. {
  196. printf("ERROR: could not create transmitter thread, aborting\n");
  197. delete_sem (fSendSyncSem);
  198. }
  199. }
  200. void
  201. ServerAgent::CreateEstablishThread (void)
  202. {
  203. BString name;
  204. vision_app->GetThreadName(THREAD_S, name);
  205. fLoginThread = spawn_thread (
  206. Establish,
  207. name.String(),
  208. B_NORMAL_PRIORITY,
  209. new BMessenger(this));
  210. if (fLoginThread >= B_OK)
  211. resume_thread (fLoginThread);
  212. else
  213. {
  214. printf("ERROR: could not create login/establish thread, aborting\n");
  215. }
  216. }
  217. int
  218. ServerAgent::IRCDType (void)
  219. {
  220. return fIrcdtype;
  221. }
  222. status_t
  223. ServerAgent::NewTimer (const char *, int32, int32)
  224. {
  225. // TODO: implement this once scripting is ready
  226. return B_OK;
  227. }
  228. int32
  229. ServerAgent::Timer (void *arg)
  230. {
  231. BMessage *msg (reinterpret_cast<BMessage *>(arg));
  232. ServerAgent *agent;
  233. const char *cmd;
  234. int32 sleeptimer,
  235. loops;
  236. if ((msg->FindString ("command", &cmd) != B_OK)
  237. || (msg->FindInt32 ("loops", &loops) != B_OK)
  238. || (msg->FindInt32 ("sleep", &sleeptimer) != B_OK)
  239. || (msg->FindPointer ("agent", reinterpret_cast<void **>(&agent)) != B_OK))
  240. {
  241. printf (":ERROR: couldn't find valid data in BMsg to Timer() -- bailing\n");
  242. return B_ERROR;
  243. }
  244. return B_OK;
  245. }
  246. int32
  247. ServerAgent::Sender (void *arg)
  248. {
  249. ServerAgent *agent (reinterpret_cast<ServerAgent *>(arg));
  250. BMessenger msgr (agent);
  251. sem_id sendSyncLock (-1);
  252. BLocker *sendDataLock (NULL);
  253. BObjectList<BString> *pendingSends (NULL);
  254. BMessage reply;
  255. if (msgr.IsValid() && (msgr.SendMessage(M_GET_SENDER_DATA, &reply) == B_OK))
  256. {
  257. sendSyncLock = reply.FindInt32("sendSyncLock");
  258. reply.FindPointer("sendDataLock", reinterpret_cast<void **>(&sendDataLock));
  259. reply.FindPointer("pendingSends", reinterpret_cast<void **>(&pendingSends));
  260. }
  261. else
  262. return B_ERROR;
  263. BString *data (NULL);
  264. while (acquire_sem (sendSyncLock) == B_NO_ERROR)
  265. {
  266. sendDataLock->Lock();
  267. if (!pendingSends->IsEmpty())
  268. {
  269. data = pendingSends->RemoveItemAt (0);
  270. sendDataLock->Unlock();
  271. agent->AsyncSendData (data->String());
  272. delete data;
  273. data = NULL;
  274. }
  275. else
  276. sendDataLock->Unlock();
  277. }
  278. // sender takes possession of pending sends and sendDataLock structures
  279. // allows for self-contained cleanups
  280. while (pendingSends->CountItems() > 0)
  281. delete pendingSends->RemoveItemAt (0L);
  282. delete pendingSends;
  283. delete sendDataLock;
  284. return B_OK;
  285. }
  286. int32
  287. ServerAgent::Establish (void *arg)
  288. {
  289. BMessenger *sMsgrE (reinterpret_cast<BMessenger *>(arg));
  290. AutoDestructor<BMessenger> msgrKiller(sMsgrE);
  291. BMessage getMsg;
  292. BString remoteIP;
  293. int32 serverSid;
  294. int32 serverSock (-1);
  295. if (!(sMsgrE->IsValid() && (sMsgrE->SendMessage (M_GET_ESTABLISH_DATA, &getMsg) == B_OK)))
  296. {
  297. printf (":ERROR: sMsgr not valid in Establish() -- bailing\n");
  298. return B_ERROR;
  299. }
  300. BMessage statMsg (M_DISPLAY);
  301. BString statString;
  302. try {
  303. BMessage reply;
  304. BString connectId,
  305. connectPort,
  306. ident,
  307. name,
  308. connectNick;
  309. const ServerData *serverData (NULL);
  310. ssize_t size;
  311. getMsg.FindData ("server", B_ANY_TYPE, reinterpret_cast<const void **>(&serverData), &size);
  312. // better safe than sorry, seems under certain circumstances the SendMessage can fail
  313. // "silently"
  314. if (serverData == NULL)
  315. throw failToLock();
  316. connectId = serverData->serverName;
  317. connectPort << serverData->port;
  318. getMsg.FindString ("ident", &ident);
  319. getMsg.FindString ("name", &name);
  320. getMsg.FindString ("nick", &connectNick);
  321. serverSid = getMsg.FindInt32 ("sid");
  322. if (sMsgrE->SendMessage (M_GET_RECONNECT_STATUS, &reply) == B_OK)
  323. {
  324. int retrycount (reply.FindInt32 ("retries"));
  325. if (retrycount)
  326. {
  327. statString = S_SERVER_WAITING_RETRY;
  328. statString << (retrycount * retrycount);
  329. statString += S_SERVER_WAITING_SECONDS;
  330. if (retrycount > 1)
  331. statString += S_SERVER_WAITING_PLURAL;
  332. statString += S_SERVER_WAITING_ENDING B_UTF8_ELLIPSIS "\n";
  333. ClientAgent::PackDisplay(&statMsg, statString.String(), C_ERROR);
  334. sMsgrE->SendMessage(&statMsg);
  335. snooze (1000000 * retrycount * retrycount); // wait 1, 4, 9, 16 ... seconds
  336. }
  337. if (sMsgrE->SendMessage (M_INC_RECONNECT) != B_OK)
  338. throw failToLock();
  339. statString = S_SERVER_ATTEMPT1;
  340. if (retrycount != 0)
  341. statString += S_SERVER_ATTEMPT2;
  342. statString += S_SERVER_ATTEMPT3;
  343. statString << retrycount + 1;
  344. statString += S_SERVER_ATTEMPT4;
  345. statString << reply.FindInt32 ("max_retries");
  346. statString += ")\n";
  347. ClientAgent::PackDisplay (&statMsg, statString.String(), C_ERROR);
  348. sMsgrE->SendMessage (&statMsg);
  349. }
  350. else
  351. throw failToLock();
  352. statString = S_SERVER_ATTEMPT5;
  353. statString << connectId;
  354. statString += ":";
  355. statString << connectPort;
  356. statString += B_UTF8_ELLIPSIS "\n";
  357. ClientAgent::PackDisplay (&statMsg, statString.String(), C_ERROR);
  358. sMsgrE->SendMessage (&statMsg);
  359. struct sockaddr_in remoteAddr;
  360. remoteAddr.sin_family = AF_INET;
  361. if (inet_aton (connectId.String(), &remoteAddr.sin_addr) == 0)
  362. {
  363. struct hostent *remoteInet (gethostbyname (connectId.String()));
  364. if (remoteInet)
  365. remoteAddr.sin_addr = *((in_addr *)remoteInet->h_addr_list[0]);
  366. else
  367. {
  368. ClientAgent::PackDisplay (&statMsg, S_SERVER_CONN_ERROR1 "\n", C_ERROR);
  369. sMsgrE->SendMessage (&statMsg);
  370. sMsgrE->SendMessage (M_NOT_CONNECTING);
  371. sMsgrE->SendMessage (M_SERVER_DISCONNECT);
  372. throw failToLock();
  373. }
  374. }
  375. remoteAddr.sin_port = htons(atoi (connectPort.String()));
  376. remoteIP = inet_ntoa (remoteAddr.sin_addr);
  377. vision_app->AddIdent (remoteIP.String(), ident.String());
  378. if ((serverSock = socket (AF_INET, SOCK_STREAM, 0)) < 0)
  379. {
  380. ClientAgent::PackDisplay (&statMsg, S_SERVER_CONN_ERROR1 "\n", C_ERROR);
  381. sMsgrE->SendMessage (&statMsg);
  382. sMsgrE->SendMessage (M_NOT_CONNECTING);
  383. sMsgrE->SendMessage (M_SERVER_DISCONNECT);
  384. throw failToLock();
  385. }
  386. // just see if he's still hanging around before
  387. // we got blocked for a minute
  388. ClientAgent::PackDisplay (&statMsg, S_SERVER_CONN_OPEN "\n", C_ERROR);
  389. sMsgrE->SendMessage (&statMsg);
  390. sMsgrE->SendMessage (M_LAG_CHANGED);
  391. if (connect (serverSock, (struct sockaddr *)&remoteAddr, sizeof(remoteAddr)) >= 0)
  392. {
  393. BString ip ("");
  394. struct sockaddr_in sockin;
  395. // store local ip address for future use (dcc, etc)
  396. int addrlength (sizeof (struct sockaddr_in));
  397. if (getsockname (serverSock,(struct sockaddr *)&sockin,(socklen_t *)&addrlength)) {
  398. ClientAgent::PackDisplay (&statMsg, S_SERVER_LOCALIP_ERROR "\n", C_ERROR);
  399. sMsgrE->SendMessage (&statMsg);
  400. BMessage setIP (M_SET_IP);
  401. setIP.AddString("ip", "127.0.0.1");
  402. setIP.AddBool("private", PrivateIPCheck("127.0.0.1"));
  403. sMsgrE->SendMessage(&setIP);
  404. }
  405. else
  406. {
  407. BMessage setIP (M_SET_IP);
  408. ip = inet_ntoa (sockin.sin_addr);
  409. if (vision_app->GetBool ("dccPrivateCheck"))
  410. {
  411. setIP.AddBool("private", PrivateIPCheck (ip.String()));
  412. }
  413. else
  414. {
  415. setIP.AddBool("private", false);
  416. }
  417. setIP.AddString("ip", ip.String());
  418. sMsgrE->SendMessage(&setIP);
  419. statString = S_SERVER_LOCALIP;
  420. statString += ip.String();
  421. statString += "\n";
  422. ClientAgent::PackDisplay (&statMsg, statString.String(), C_ERROR);
  423. sMsgrE->SendMessage (&statMsg);
  424. }
  425. if (vision_app->GetBool("dccPrivateCheck") && PrivateIPCheck (ip.String()))
  426. {
  427. ClientAgent::PackDisplay (&statMsg, S_SERVER_PROXY_MSG "\n", C_ERROR);
  428. sMsgrE->SendMessage (&statMsg);
  429. }
  430. ClientAgent::PackDisplay (&statMsg, S_SERVER_HANDSHAKE "\n", C_ERROR);
  431. sMsgrE->SendMessage (&statMsg);
  432. BString string;
  433. BMessage dataSend (M_SERVER_SEND);
  434. dataSend.AddString ("data", "blah");
  435. BMessage endpointMsg (M_SET_ENDPOINT);
  436. endpointMsg.AddInt32 ("socket", serverSock);
  437. if (sMsgrE->SendMessage (&endpointMsg, &reply) != B_OK)
  438. throw failToLock();
  439. if (strlen(serverData->password) > 0)
  440. {
  441. ClientAgent::PackDisplay (&statMsg, S_SERVER_PASS_MSG "\n", C_ERROR);
  442. sMsgrE->SendMessage (&statMsg);
  443. string = "PASS ";
  444. string += serverData->password;
  445. dataSend.ReplaceString ("data", string.String());
  446. sMsgrE->SendMessage (&dataSend);
  447. }
  448. string = "NICK ";
  449. string.Append (connectNick);
  450. dataSend.ReplaceString ("data", string.String());
  451. if (sMsgrE->SendMessage (&dataSend) != B_OK)
  452. throw failToLock();
  453. string = "USER ";
  454. string.Append (ident);
  455. string.Append (" localhost ");
  456. string.Append (connectId);
  457. string.Append (" :");
  458. string.Append (name);
  459. dataSend.ReplaceString ("data", string.String());
  460. if (sMsgrE->SendMessage (&dataSend) != B_OK)
  461. throw failToLock();
  462. // resume normal business matters.
  463. ClientAgent::PackDisplay (&statMsg, S_SERVER_ESTABLISH "\n", C_ERROR);
  464. sMsgrE->SendMessage (&statMsg);
  465. }
  466. else // No endpoint->connect
  467. {
  468. ClientAgent::PackDisplay (&statMsg, S_SERVER_CONN_ERROR2 "\n", C_ERROR);
  469. sMsgrE->SendMessage (&statMsg);
  470. sMsgrE->SendMessage (M_NOT_CONNECTING);
  471. sMsgrE->SendMessage (M_SERVER_DISCONNECT);
  472. throw failToLock();
  473. }
  474. } catch (failToLock)
  475. {
  476. vision_app->RemoveIdent (remoteIP.String());
  477. return B_ERROR;
  478. }
  479. struct fd_set eset, rset, wset;
  480. int selResult (0);
  481. FD_ZERO (&eset);
  482. FD_ZERO (&rset);
  483. FD_ZERO (&wset);
  484. BString buffer;
  485. FD_SET (serverSock, &eset);
  486. FD_SET (serverSock, &rset);
  487. FD_SET (serverSock, &wset);
  488. while (sMsgrE->IsValid())
  489. {
  490. char indata[1024];
  491. int32 length (0);
  492. FD_SET (serverSock, &eset);
  493. FD_SET (serverSock, &rset);
  494. FD_SET (serverSock, &wset);
  495. memset (indata, 0, 1024);
  496. struct timeval tv = { 0, 0 };
  497. if ((selResult = select (serverSock + 1, &rset, 0, &eset, &tv)) > 0
  498. && FD_ISSET (serverSock, &rset) && !FD_ISSET (serverSock, &eset))
  499. {
  500. if ((length = recv (serverSock, indata, 1023, 0)) > 0)
  501. {
  502. BString temp;
  503. int32 index;
  504. temp.SetTo (indata, strlen(indata));
  505. buffer += temp;
  506. while ((index = buffer.FindFirst ('\n')) != B_ERROR)
  507. {
  508. temp.SetTo (buffer, index);
  509. buffer.Remove (0, index + 1);
  510. temp.RemoveLast ("\r");
  511. if (vision_app->fDebugRecv)
  512. {
  513. printf ("RECEIVED: (%03" B_PRId32 ":%03" B_PRId32 ") \"", serverSid, temp.Length());
  514. for (int32 i = 0; i < temp.Length(); ++i)
  515. {
  516. if (isprint (temp[i]))
  517. printf ("%c", temp.String()[i]);
  518. else
  519. printf ("[0x%02x]", temp.String()[i]);
  520. }
  521. printf ("\"\n");
  522. }
  523. // We ship it off this way because
  524. // we want this thread to loop relatively
  525. // quickly. Let ServerWindow's main thread
  526. // handle the processing of incoming data!
  527. BMessage msg (M_PARSE_LINE);
  528. msg.AddString ("line", temp.String());
  529. sMsgrE->SendMessage (&msg);
  530. }
  531. }
  532. if (FD_ISSET (serverSock, &eset)
  533. || (FD_ISSET (serverSock, &rset) && length == 0)
  534. || !FD_ISSET (serverSock, &wset)
  535. || length < 0)
  536. {
  537. // we got disconnected :(
  538. if (vision_app->fDebugRecv)
  539. {
  540. // print interesting info
  541. printf ("Negative from endpoint receive! (%" B_PRId32 ")\n", length);
  542. printf ("eset : %s\nrset: %s\nwset: %s\n",
  543. FD_ISSET (serverSock, &eset) ? "true" : "false",
  544. FD_ISSET (serverSock, &rset) ? "true" : "false",
  545. FD_ISSET (serverSock, &wset) ? "true" : "false");
  546. }
  547. // tell the user all about it
  548. sMsgrE->SendMessage (M_NOT_CONNECTING);
  549. sMsgrE->SendMessage (M_SERVER_DISCONNECT);
  550. break;
  551. }
  552. }
  553. // select error, treat this as a disconnect as well
  554. if (selResult < 0)
  555. {
  556. sMsgrE->SendMessage (M_NOT_CONNECTING);
  557. sMsgrE->SendMessage (M_SERVER_DISCONNECT);
  558. break;
  559. }
  560. // take a nap, so the ServerAgent can do things
  561. snooze(20000);
  562. }
  563. vision_app->RemoveIdent (remoteIP.String());
  564. return B_OK;
  565. }
  566. int
  567. ServerAgent::SortNotifyItems (const NotifyListItem *item1, const NotifyListItem *item2)
  568. {
  569. if (!item1 || !item2)
  570. return 0;
  571. if (item1->GetState() && !item2->GetState())
  572. return -1;
  573. if (!item1->GetState() && item2->GetState())
  574. return 1;
  575. BString name (item1->Text());
  576. return name.ICompare(item2->Text());
  577. }
  578. void
  579. ServerAgent::AsyncSendData (const char *cData)
  580. {
  581. int32 length (0);
  582. if (!cData)
  583. return;
  584. BString data (cData);
  585. data.Append("\r\n");
  586. length = data.Length();
  587. memset(fSend_buffer, 0, sizeof(fSend_buffer));
  588. int32 dest_length (sizeof(fSend_buffer)), state (0);
  589. int32 encoding = vision_app->GetInt32("encoding");
  590. if (encoding != B_UNICODE_CONVERSION)
  591. {
  592. convert_from_utf8 (
  593. encoding,
  594. data.String(),
  595. &length,
  596. fSend_buffer,
  597. &dest_length,
  598. &state);
  599. }
  600. else
  601. {
  602. strlcpy(fSend_buffer, data.String(), dest_length);
  603. dest_length = strlen(fSend_buffer);
  604. }
  605. if (fServerSocket <= 0)
  606. {
  607. // doh, we aren't even connected.
  608. return;
  609. }
  610. struct fd_set eset, wset;
  611. FD_ZERO (&wset);
  612. FD_ZERO (&eset);
  613. FD_SET (fServerSocket, &wset);
  614. FD_SET (fServerSocket, &eset);
  615. struct timeval tv = { 5 , 0 };
  616. // do a select to prevent the writer thread from deadlocking in the send call
  617. if (select(fServerSocket + 1, NULL, &wset, &eset, &tv) <= 0 || FD_ISSET(fServerSocket, &eset)
  618. || !FD_ISSET(fServerSocket, &wset))
  619. {
  620. // if (!fReconnecting && !fIsConnecting)
  621. // fMsgr.SendMessage (M_SERVER_DISCONNECT);
  622. }
  623. else
  624. {
  625. if ((length = send (fServerSocket, fSend_buffer, dest_length, 0) < 0))
  626. {
  627. if (!fReconnecting && !fIsConnecting)
  628. fMsgr.SendMessage (M_SERVER_DISCONNECT);
  629. // doh, we aren't even connected.
  630. }
  631. }
  632. if (vision_app->fDebugSend)
  633. {
  634. data.RemoveAll ("\n");
  635. data.RemoveAll ("\r");
  636. printf(" SENT: (%03" B_PRId32 ") \"%s\"\n", length, data.String());
  637. }
  638. }
  639. void
  640. ServerAgent::SendData (const char *cData)
  641. {
  642. // this function simply queues up the data into the requests buffer, then releases
  643. // the sender thread to take care of it
  644. BString *data (new BString (cData));
  645. fSendLock->Lock();
  646. fPendingSends->AddItem (data);
  647. fSendLock->Unlock();
  648. release_sem (fSendSyncSem);
  649. }
  650. void
  651. ServerAgent::ParseLine (const char *cData)
  652. {
  653. BString data = FilterCrap (cData);
  654. int32 length (data.Length()),
  655. destLength (2048),
  656. state (0);
  657. memset (fParse_buffer, 0, sizeof (fParse_buffer));
  658. int32 encoding = vision_app->GetInt32("encoding");
  659. if (encoding != B_UNICODE_CONVERSION)
  660. {
  661. convert_to_utf8 (
  662. encoding,
  663. data.String(),
  664. &length,
  665. fParse_buffer,
  666. &destLength,
  667. &state);
  668. }
  669. else
  670. {
  671. if (IsValidUTF8(data.String(), destLength))
  672. {
  673. strlcpy(fParse_buffer, data.String(), destLength);
  674. destLength = strlen(fParse_buffer);
  675. }
  676. else
  677. {
  678. convert_to_utf8 (
  679. B_ISO1_CONVERSION,
  680. data.String(),
  681. &length,
  682. fParse_buffer,
  683. &destLength,
  684. &state);
  685. }
  686. }
  687. if (vision_app->fNumBench)
  688. {
  689. vision_app->fBench1 = system_time();
  690. if (ParseEvents (fParse_buffer))
  691. {
  692. vision_app->fBench2 = system_time();
  693. BString bencht (GetWord (data.String(), 2));
  694. vision_app->BenchOut (bencht.String());
  695. return;
  696. }
  697. }
  698. else
  699. {
  700. if (ParseEvents (fParse_buffer))
  701. return;
  702. }
  703. data.Append("\n");
  704. Display (data.String(), 0);
  705. }
  706. ClientAgent *
  707. ServerAgent::Client (const char *cName)
  708. {
  709. ClientAgent *client (0);
  710. for (int32 i = 0; i < fClients.CountItems(); ++i)
  711. {
  712. ClientAgent *item (fClients.ItemAt (i));
  713. if (strcasecmp (cName, item->Id().String()) == 0)
  714. {
  715. client = item;
  716. break;
  717. }
  718. }
  719. return client;
  720. }
  721. ClientAgent *
  722. ServerAgent::ActiveClient (void)
  723. {
  724. ClientAgent *client (NULL);
  725. // printf("finding active client\n");
  726. for (int32 i = 0; i < fClients.CountItems(); i++)
  727. {
  728. // printf("checking against client: %d, %s\n", i, fClients.ItemAt(i)->fId.String());
  729. if (!fClients.ItemAt (i)->IsHidden())
  730. {
  731. // printf("not hidden, break\n");
  732. client = fClients.ItemAt (i);
  733. break;
  734. }
  735. }
  736. return client;
  737. }
  738. void
  739. ServerAgent::Broadcast (BMessage *msg, bool sendToServer)
  740. {
  741. for (int32 i = 0; i < fClients.CountItems(); ++i)
  742. {
  743. ClientAgent *client (fClients.ItemAt (i));
  744. if (client != this)
  745. client->fMsgr.SendMessage (msg);
  746. }
  747. if (sendToServer)
  748. {
  749. fSMsgr.SendMessage(msg);
  750. }
  751. }
  752. void
  753. ServerAgent::RepliedBroadcast (BMessage *)
  754. {
  755. // TODO: implement this
  756. // BMessage cMsg (*msg);
  757. // BAutolock lock (this);
  758. //
  759. // for (int32 i = 0; i < fClients.CountItems(); ++i)
  760. // {
  761. // ClientAgent *client ((ClientAgent *)fClients.ItemAt (i));
  762. //
  763. // if (client != this)
  764. // {
  765. // BMessenger fMsgr (client);
  766. // BMessage reply;
  767. // fMsgr.SendMessage (&cMsg, &reply);
  768. // }
  769. // }
  770. }
  771. void
  772. ServerAgent::DisplayAll (
  773. const char *buffer,
  774. const uint32 fore,
  775. const uint32 back,
  776. const uint32 font)
  777. {
  778. for (int32 i = 0; i < fClients.CountItems(); ++i)
  779. {
  780. ClientAgent *client (fClients.ItemAt (i));
  781. BMessage msg (M_DISPLAY);
  782. PackDisplay (&msg, buffer, fore, back, font);
  783. client->fMsgr.SendMessage (&msg);
  784. }
  785. return;
  786. }
  787. void
  788. ServerAgent::PostActive (BMessage *msg)
  789. {
  790. BAutolock activeLock (Window());
  791. // printf("postActive\n");
  792. ClientAgent *client (ActiveClient());
  793. // printf("posting to: %p\n", client);
  794. if (client != NULL)
  795. client->fMsgr.SendMessage (msg);
  796. else
  797. fSMsgr.SendMessage (msg);
  798. }
  799. void
  800. ServerAgent::HandleReconnect (void)
  801. {
  802. /*
  803. * Function purpose: Setup the environment and attempt a new connection
  804. * to the server
  805. */
  806. if (fIsConnected)
  807. {
  808. // what's going on here?!
  809. printf (":ERROR: HandleReconnect() called when we're already connected! Whats up with that?!");
  810. return;
  811. }
  812. delete_sem(fSendSyncSem);
  813. CreateSenderThread();
  814. if (fRetry < fRetryLimit)
  815. {
  816. // we are go for main engine start
  817. fReconnecting = true;
  818. fIsConnecting = true;
  819. fNickAttempt = 0;
  820. fEstablishHasLock = false;
  821. CreateEstablishThread();
  822. }
  823. else
  824. {
  825. // we've hit our fRetry limit. throw in the towel
  826. fReconnecting = false;
  827. fRetry = 0;
  828. const char *soSorry;
  829. soSorry = S_SERVER_RETRY_LIMIT "\n";
  830. Display (soSorry, C_ERROR);
  831. ClientAgent *agent (ActiveClient());
  832. if (agent && (agent != this))
  833. agent->Display (soSorry, C_ERROR, C_BACKGROUND, F_SERVER);
  834. }
  835. }
  836. const ServerData *
  837. ServerAgent::GetNextServer ()
  838. {
  839. type_code type;
  840. int32 count;
  841. ssize_t size;
  842. fNetworkData.GetInfo ("server", &type, &count);
  843. uint32 state = (fReconnecting) ? SERVER_SECONDARY : SERVER_PRIMARY;
  844. for (;;)
  845. {
  846. if (fServerIndex >= count)
  847. {
  848. fServerIndex = 0;
  849. state = SERVER_PRIMARY;
  850. }
  851. const ServerData *server (NULL);
  852. for (; fNetworkData.FindData ("server", B_RAW_TYPE, fServerIndex,
  853. reinterpret_cast<const void **>(&server), &size) == B_OK; fServerIndex++)
  854. if (server->state == state)
  855. {
  856. memset(&fCurrentServer, 0, sizeof(ServerData));
  857. memcpy(&fCurrentServer, server, size);
  858. return &fCurrentServer;
  859. }
  860. }
  861. }
  862. const char *
  863. ServerAgent::GetNextNick ()
  864. {
  865. type_code type;
  866. int32 count;
  867. fNetworkData.GetInfo ("nick", &type, &count);
  868. if (fNickIndex < count)
  869. return fNetworkData.FindString ("nick", fNickIndex++);
  870. else
  871. {
  872. fNickIndex = 0;
  873. return "";
  874. }
  875. }
  876. bool
  877. ServerAgent::PrivateIPCheck (BString ip)
  878. {
  879. /*
  880. * Function purpose: Compare against fLocalip to see if it is a private address
  881. * if so, set fLocalip_private to true;
  882. *
  883. * Private ranges: 10.0.0.0 - 10.255.255.255
  884. * 172.16.0.0 - 172.31.255.255
  885. * 192.168.0.0 - 192.168.255.255
  886. * (as defined in RFC 1918)
  887. */
  888. if (ip == NULL || ip == "")
  889. {
  890. // it is obviously a mistake we got called.
  891. // setup some sane values and print an assertion
  892. printf (":ERROR: PrivateIPCheck() called when there is no valid data to check!\n");
  893. return true;
  894. }
  895. if (ip == "127.0.0.1")
  896. return true;
  897. // catch 10.0.0.0 - 10.255.255.255 and 192.168.0.0 - 192.168.255.255
  898. if ( (strncmp (ip, "10.", 3) == 0)
  899. || (strncmp (ip, "192.168.", 8) == 0))
  900. return true;
  901. // catch 172.16.0.0 - 172.31.255.255
  902. if (strncmp (ip, "172.", 4) == 0)
  903. {
  904. // check to see if characters 5-6 are (or are between) 16 and 31
  905. {
  906. char temp172s[3];
  907. temp172s[0] = ip[4];
  908. temp172s[1] = ip[5];
  909. temp172s[2] = '\0';
  910. int temp172n (atoi (temp172s));
  911. if (temp172n >= 16 || temp172n <= 31)
  912. return true;
  913. }
  914. return false;
  915. }
  916. // if we got this far, its a public IP address
  917. return false;
  918. }
  919. void
  920. ServerAgent::AddResumeData (BMessage *msg)
  921. {
  922. ResumeData *data;
  923. data = new ResumeData;
  924. data->expire = system_time() + 50000000LL;
  925. data->nick = msg->FindString ("vision:nick");
  926. data->file = msg->FindString ("vision:file");
  927. data->size = msg->FindString ("vision:size");
  928. data->ip = msg->FindString ("vision:ip");
  929. data->port = msg->FindString ("vision:port");
  930. data->path = msg->FindString ("path");
  931. data->pos = msg->FindInt64 ("pos");
  932. //PRINT(("%s %s %s %s %s", data->nick.String(), data->file.String(),
  933. // data->size.String(), data->ip.String(), data->port.String()));
  934. fResumes.AddItem (data);
  935. BString buffer;
  936. buffer << "PRIVMSG "
  937. << data->nick
  938. << " :\1DCC RESUME "
  939. << data->file
  940. << " "
  941. << data->port
  942. << " "
  943. << data->pos
  944. << "\1";
  945. SendData (buffer.String());
  946. }
  947. void
  948. ServerAgent::ParseAutoexecChans (const BString &origLine)
  949. {
  950. BString line (origLine);
  951. int32 chanIndex (0);
  952. if ((chanIndex = line.IFindFirst ("/JOIN")) != B_ERROR)
  953. {
  954. chanIndex += 6;
  955. line.Remove (0, chanIndex);
  956. }
  957. else if ((chanIndex = line.IFindFirst ("/J")) != B_ERROR)
  958. {
  959. chanIndex += 3;
  960. line.Remove (0, chanIndex);
  961. }
  962. else
  963. return;
  964. // parse out all autoexec channels to ensure we don't try to focus those
  965. // on join
  966. chanIndex = 0;
  967. BString *newChan (NULL);
  968. for (;;)
  969. {
  970. if ((chanIndex = line.FindFirst (',')) == B_ERROR)
  971. break;
  972. newChan = new BString();
  973. line.CopyInto (*newChan, 0, chanIndex);
  974. if ((*newChan)[0] != '#')
  975. newChan->Prepend("#");
  976. fStartupChannels.AddItem (newChan);
  977. line.Remove (0, chanIndex + 1);
  978. }
  979. newChan = new BString();
  980. // catch last channel (or only channel if no comma separations)
  981. if ((chanIndex = line.FindFirst (' ')) != B_ERROR)
  982. line.CopyInto (*newChan, 0, chanIndex);
  983. else
  984. *newChan = line;
  985. if ((*newChan)[0] != '#')
  986. newChan->Prepend("#");
  987. fStartupChannels.AddItem (newChan);
  988. }
  989. void
  990. ServerAgent::RemoveAutoexecChan (const BString &chan)
  991. {
  992. int32 chanCount (fStartupChannels.CountItems());
  993. for (int32 i = 0; i < chanCount; i++)
  994. if (fStartupChannels.ItemAt (i)->ICompare(chan) == 0)
  995. {
  996. delete fStartupChannels.RemoveItemAt (i);
  997. return;
  998. }
  999. }
  1000. void
  1001. ServerAgent::MessageReceived (BMessage *msg)
  1002. {
  1003. switch (msg->what)
  1004. {
  1005. case M_PARSE_LINE:
  1006. {
  1007. const char *buffer (NULL);
  1008. msg->FindString ("line", &buffer);
  1009. if (buffer)
  1010. ParseLine (buffer);
  1011. }
  1012. break;
  1013. case M_STATE_CHANGE:
  1014. {
  1015. Broadcast(msg);
  1016. ClientAgent::MessageReceived (msg);
  1017. }
  1018. break;
  1019. case M_SEND_RAW:
  1020. {
  1021. const char *buffer;
  1022. msg->FindString ("line", &buffer);
  1023. if (buffer)
  1024. SendData (buffer);
  1025. }
  1026. break;
  1027. case M_DISPLAY_ALL:
  1028. {
  1029. BString data;
  1030. msg->FindString ("data", &data);
  1031. DisplayAll (data.String(), msg->FindInt32 ("fore"), msg->FindInt32 ("back"), msg->FindInt32 ("font"));
  1032. }
  1033. break;
  1034. case M_GET_ESTABLISH_DATA:
  1035. {
  1036. BMessage reply (B_REPLY);
  1037. reply.AddData ("server", B_RAW_TYPE, GetNextServer(), sizeof (ServerData));
  1038. reply.AddString ("ident", fLident.String());
  1039. reply.AddString ("name", fLname.String());
  1040. reply.AddString ("nick", fMyNick.String());
  1041. msg->SendReply (&reply);
  1042. fEstablishHasLock = true;
  1043. }
  1044. break;
  1045. case M_GET_SENDER_DATA:
  1046. {
  1047. BMessage reply;
  1048. reply.AddInt32 ("sendSyncLock", fSendSyncSem);
  1049. reply.AddPointer ("sendDataLock", fSendLock);
  1050. reply.AddPointer ("pendingSends", fPendingSends);
  1051. msg->SendReply (&reply);
  1052. }
  1053. break;
  1054. case M_SET_ENDPOINT:
  1055. msg->FindInt32 ("socket", &fServerSocket);
  1056. break;
  1057. case M_NOT_CONNECTING:
  1058. fIsConnecting = false;
  1059. fReconnecting = false;
  1060. break;
  1061. case M_CONNECTED:
  1062. fIsConnected = true;
  1063. fIsConnecting = false;
  1064. break;
  1065. case M_INC_RECONNECT:
  1066. ++fRetry;
  1067. break;
  1068. case M_SET_IP:
  1069. {
  1070. static BString ip;
  1071. msg->FindString("ip", &ip);
  1072. fLocalip = ip.String();
  1073. fLocalip_private = msg->FindBool("private");
  1074. fGetLocalIP = fLocalip_private;
  1075. }
  1076. break;
  1077. case M_GET_IP:
  1078. {
  1079. BMessage reply;
  1080. reply.AddBool ("private", fLocalip_private);
  1081. reply.AddString ("ip", fLocalip);
  1082. msg->SendReply (&reply);
  1083. }
  1084. break;
  1085. case M_GET_RECONNECT_STATUS:
  1086. {
  1087. BMessage reply (B_REPLY);
  1088. reply.AddInt32 ("retries", fRetry);
  1089. reply.AddInt32 ("max_retries", fRetryLimit);
  1090. msg->SendReply(&reply);
  1091. }
  1092. break;
  1093. case M_SERVER_SEND:
  1094. {
  1095. BString buffer;
  1096. int32 i;
  1097. for (i = 0; msg->HasString ("data", i); ++i)
  1098. {
  1099. const char *str;
  1100. msg->FindString ("data", i, &str);
  1101. buffer << str;
  1102. }
  1103. SendData (buffer.String());
  1104. if (msg->IsSourceWaiting())
  1105. msg->SendReply(B_REPLY);
  1106. }
  1107. break;
  1108. case M_DCC_ACCEPT:
  1109. {
  1110. bool cont (false);
  1111. const char *nick,
  1112. *size,
  1113. *ip,
  1114. *port;
  1115. BPath path;
  1116. msg->FindString("vision:nick", &nick);
  1117. msg->FindString("vision:size", &size);
  1118. msg->FindString("vision:ip", &ip);
  1119. msg->FindString("vision:port", &port);
  1120. if (msg->HasString ("path"))
  1121. path.SetTo (msg->FindString ("path"));
  1122. else
  1123. {
  1124. const char *file;
  1125. entry_ref ref;
  1126. msg->FindRef ("directory", &ref);
  1127. msg->FindString("name", &file);
  1128. BDirectory dir (&ref);
  1129. path.SetTo (&dir, file);
  1130. }
  1131. if (msg->HasBool ("continue"))
  1132. msg->FindBool ("continue", &cont);
  1133. DCCReceive *view;
  1134. view = new DCCReceive (
  1135. nick,
  1136. path.Path(),
  1137. size,
  1138. ip,
  1139. port,
  1140. fSMsgr,
  1141. cont);
  1142. BMessage aMsg (M_DCC_FILE_WIN);
  1143. aMsg.AddPointer ("view", view);
  1144. be_app->PostMessage (&aMsg);
  1145. }
  1146. break;
  1147. case M_CHOSE_FILE: // DCC send
  1148. {
  1149. const char *nick (NULL);
  1150. entry_ref ref;
  1151. off_t size;
  1152. msg->FindString ("nick", &nick);
  1153. msg->FindRef ("refs", &ref); // get file
  1154. BEntry entry (&ref);
  1155. /* // TODO: resolve if symlink
  1156. if (entry.IsSymLink())
  1157. {
  1158. BSymLink link (&entry);
  1159. }
  1160. */
  1161. BPath path (&entry);
  1162. // PRINT(("file path: %s\n", path.Path()));
  1163. entry.GetSize (&size);
  1164. BString ssize;
  1165. ssize << size;
  1166. DCCSend *view;
  1167. view = new DCCSend (
  1168. nick,
  1169. path.Path(),
  1170. ssize.String(),
  1171. fSMsgr);
  1172. BMessage message (M_DCC_FILE_WIN);
  1173. message.AddPointer ("view", view);
  1174. vision_app->PostMessage (&message);
  1175. }
  1176. break;
  1177. case M_ADD_RESUME_DATA:
  1178. {
  1179. AddResumeData (msg);
  1180. }
  1181. break;
  1182. case B_CANCEL:
  1183. if (msg->HasPointer ("source"))
  1184. {
  1185. BFilePanel *fPanel;
  1186. msg->FindPointer ("source", reinterpret_cast<void **>(&fPanel));
  1187. delete fPanel;
  1188. }
  1189. break;
  1190. case M_CHAT_ACCEPT:
  1191. {
  1192. int32 acceptDeny;
  1193. BString theNick;
  1194. const char *theIP, *thePort;
  1195. msg->FindInt32("which", &acceptDeny);
  1196. if (acceptDeny)
  1197. return;
  1198. msg->FindString("nick", &theNick);
  1199. msg->FindString("ip", &theIP);
  1200. msg->FindString("port", &thePort);
  1201. theNick.Append (" [DCC]");
  1202. MessageAgent *newAgent (new MessageAgent (
  1203. *vision_app->pClientWin()->AgentRect(),
  1204. theNick.String(),
  1205. fId.String(),
  1206. fSMsgr,
  1207. fMyNick.String(),
  1208. "",
  1209. true,
  1210. false,
  1211. theIP,
  1212. thePort));
  1213. vision_app->pClientWin()->pWindowList()->AddAgent (newAgent,
  1214. theNick.String(),
  1215. WIN_MESSAGE_TYPE,
  1216. true);
  1217. fClients.AddItem (newAgent);
  1218. }
  1219. break;
  1220. case M_CHAT_ACTION: // dcc chat
  1221. {
  1222. ClientAgent *client;
  1223. const char *theNick;
  1224. BString thePort;
  1225. BString theId;
  1226. msg->FindString ("nick", &theNick);
  1227. msg->FindString ("port", &thePort);
  1228. theId << theNick << " [DCC]";
  1229. if ((client = Client (theId.String())) == 0)
  1230. {
  1231. MessageAgent *newAgent (new MessageAgent (
  1232. *vision_app->pClientWin()->AgentRect(),
  1233. theId.String(),
  1234. fId.String(),
  1235. fSMsgr,
  1236. fMyNick.String(),
  1237. "",
  1238. true,
  1239. true,
  1240. "",
  1241. thePort != "" ? thePort.String() : ""));
  1242. vision_app->pClientWin()->pWindowList()->AddAgent (newAgent,
  1243. theId.String(),
  1244. WIN_MESSAGE_TYPE,
  1245. true);
  1246. fClients.AddItem (newAgent);
  1247. }
  1248. }
  1249. break;
  1250. case M_SLASH_RECONNECT:
  1251. if (!fIsConnected && !fIsConnecting)
  1252. fMsgr.SendMessage (M_SERVER_DISCONNECT);
  1253. break;
  1254. case M_SERVER_DISCONNECT:
  1255. {
  1256. close (fSocket);
  1257. fSocket = -1;
  1258. if (fIsQuitting)
  1259. break;
  1260. // store current nick for reconnect use (might be an away nick, etc)
  1261. if (fReacquiredNick)
  1262. {
  1263. fReacquiredNick = false;
  1264. fReconNick = fMyNick;
  1265. }
  1266. // let the user know
  1267. if (fIsConnected)
  1268. {
  1269. fIsConnected = false;
  1270. BString sAnnounce;
  1271. sAnnounce += S_SERVER_DISCONNECT;
  1272. sAnnounce += fServerName;
  1273. sAnnounce += "\n";
  1274. Display (sAnnounce.String(), C_ERROR);
  1275. ClientAgent *agent (ActiveClient());
  1276. if (agent && (agent != this))
  1277. agent->Display (sAnnounce.String(), C_ERROR, C_BACKGROUND, F_SERVER);
  1278. }
  1279. // let other agents know about it
  1280. Broadcast(msg);
  1281. fMyLag = S_SERVER_DISCON_STATUS;
  1282. fMsgr.SendMessage (M_LAG_CHANGED);
  1283. fCheckingLag = false;
  1284. fServerSocket = -1;
  1285. // attempt a reconnect
  1286. if (!fIsConnecting)
  1287. HandleReconnect();
  1288. }
  1289. break;
  1290. case M_STATUS_ADDITEMS:
  1291. {
  1292. vision_app->pClientWin()->pStatusView()->AddItem (new StatusItem (
  1293. 0, ""),
  1294. true);
  1295. vision_app->pClientWin()->pStatusView()->AddItem (new StatusItem (
  1296. "Lag: ",
  1297. "",
  1298. STATUS_ALIGN_LEFT),
  1299. true);
  1300. vision_app->pClientWin()->pStatusView()->AddItem (new StatusItem (
  1301. 0,
  1302. "",
  1303. STATUS_ALIGN_LEFT),
  1304. true);
  1305. // The false bool for SetItemValue() tells the StatusView not to Invalidate() the view.
  1306. // We send true on the last SetItemValue().
  1307. vision_app->pClientWin()->pStatusView()->SetItemValue (STATUS_SERVER, fId.String(), false);
  1308. vision_app->pClientWin()->pStatusView()->SetItemValue (STATUS_LAG, fMyLag.String(), false);
  1309. vision_app->pClientWin()->pStatusView()->SetItemValue (STATUS_NICK, fMyNick.String(), true);
  1310. }
  1311. break;
  1312. case M_LAG_CHECK:
  1313. {
  1314. if (fIsConnected)
  1315. {
  1316. if (fNetworkData.FindBool ("lagCheck"))
  1317. {
  1318. BMessage lagSend (M_SERVER_SEND);
  1319. AddSend (&lagSend, "VISION_LAG_CHECK");
  1320. AddSend (&lagSend, endl);
  1321. if (!fCheckingLag)
  1322. {
  1323. fLagCheck = system_time();
  1324. fLagCount = 1;
  1325. fCheckingLag = true;
  1326. }
  1327. else
  1328. {
  1329. if (fLagCount > 4)
  1330. {
  1331. // we've waited 50 seconds
  1332. // connection problems?
  1333. fMyLag = S_SERVER_CONN_PROBLEM;
  1334. fMsgr.SendMessage (M_LAG_CHANGED);
  1335. }
  1336. else
  1337. {
  1338. // wait some more
  1339. char lag[15] = "";
  1340. sprintf (lag, "%" B_PRId32 "0.000+", fLagCount); // assuming a 10 second runner
  1341. fMyLag = lag;
  1342. ++fLagCount;
  1343. fMsgr.SendMessage (M_LAG_CHANGED);
  1344. }
  1345. }
  1346. }
  1347. if (fNotifyNicks.CountItems() > 0)
  1348. {
  1349. BString cmd ("ISON ");
  1350. for (int32 i = 0; i < fNotifyNicks.CountItems(); i++)
  1351. {
  1352. cmd += " ";
  1353. cmd += fNotifyNicks.ItemAt(i)->Text();
  1354. }
  1355. BMessage dataSend (M_SERVER_SEND);
  1356. dataSend.AddString ("data", cmd.String());
  1357. fSMsgr.SendMessage (&dataSend);
  1358. }
  1359. }
  1360. }
  1361. break;
  1362. case M_LAG_CHANGED:
  1363. {
  1364. if (!IsHidden())
  1365. vision_app->pClientWin()->pStatusView()->SetItemValue (STATUS_LAG, fMyLag.String(), true);
  1366. BMessage newmsg (M_LAG_CHANGED);
  1367. newmsg.AddString ("lag", fMyLag);
  1368. Broadcast (&newmsg);
  1369. }
  1370. break;
  1371. case M_REJOIN_ALL:
  1372. {
  1373. for (int32 i = 0; i < fClients.CountItems(); ++i)
  1374. {
  1375. ClientAgent *client (fClients.ItemAt (i));
  1376. if (dynamic_cast<ChannelAgent *>(client))
  1377. {
  1378. BMessage rejoinMsg (M_REJOIN);
  1379. rejoinMsg.AddString ("nickname", fMyNick.String());
  1380. client->fMsgr.SendMessage (&rejoinMsg);
  1381. }
  1382. }
  1383. }
  1384. break;
  1385. case M_OPEN_MSGAGENT:
  1386. {
  1387. ClientAgent *client;
  1388. const char *theNick;
  1389. msg->FindString ("nick", &theNick);
  1390. if (!(client = Client (theNick)))
  1391. {
  1392. MessageAgent *newAgent (new MessageAgent (
  1393. *vision_app->pClientWin()->AgentRect(),
  1394. theNick,
  1395. fId.String(),
  1396. fSMsgr,
  1397. fMyNick.String(),
  1398. ""));
  1399. vision_app->pClientWin()->pWindowList()->AddAgent (
  1400. newAgent,
  1401. theNick,
  1402. WIN_MESSAGE_TYPE,
  1403. true);
  1404. client = newAgent;
  1405. fClients.AddItem (newAgent);
  1406. }
  1407. else
  1408. client->fAgentWinItem->ActivateItem();
  1409. if (msg->HasMessage ("msg"))
  1410. {
  1411. BMessage buffer;
  1412. msg->FindMessage ("msg", &buffer);
  1413. client->fMsgr.SendMessage (&buffer);
  1414. }
  1415. }
  1416. break;
  1417. case M_CLIENT_QUIT:
  1418. {
  1419. bool shutingdown (false);
  1420. if (msg->HasBool ("vision:shutdown"))
  1421. msg->FindBool ("vision:shutdown", &shutingdown);
  1422. if (msg->HasString ("vision:quit"))
  1423. {
  1424. const char *quitstr;
  1425. msg->FindString ("vision:quit", &quitstr);
  1426. fQuitMsg = quitstr;
  1427. }
  1428. if (!fIsQuitting && fIsConnected && fServerSocket)
  1429. {
  1430. if (fQuitMsg.Length() == 0)
  1431. {
  1432. const char *expansions[1];
  1433. BString version;
  1434. vision_app->VisionVersion(VERSION_VERSION, version);
  1435. expansions[0] = version.String();
  1436. fQuitMsg << "QUIT :" << ExpandKeyed (vision_app->GetCommand (CMD_QUIT).String(), "V", expansions);
  1437. }
  1438. SendData (fQuitMsg.String());
  1439. }
  1440. fIsQuitting = true;
  1441. if (fClients.CountItems() > 0)
  1442. {
  1443. Broadcast(msg);
  1444. BMessenger listMsgr(fListAgent);
  1445. listMsgr.SendMessage(M_CLIENT_QUIT);
  1446. }
  1447. else
  1448. ClientAgent::MessageReceived(msg);
  1449. }
  1450. break;
  1451. case M_CLIENT_SHUTDOWN:
  1452. {
  1453. ClientAgent *deadagent;
  1454. if (msg->FindPointer ("agent", reinterpret_cast<void **>(&deadagent)) != B_OK)
  1455. {
  1456. printf (":ERROR: error getting valid pointer from M_CLIENT_SHUTDOWN -- bailing\n");
  1457. break;
  1458. }
  1459. fClients.RemoveItem (deadagent);
  1460. BMessage deathchant (M_OBITUARY);
  1461. deathchant.AddPointer ("agent", deadagent);
  1462. deathchant.AddPointer ("item", deadagent->fAgentWinItem);
  1463. vision_app->pClientWin()->PostMessage (&deathchant);
  1464. if (fIsQuitting && (fClients.CountItems() == 0) &&
  1465. (dynamic_cast<ServerAgent *>(deadagent) != this))
  1466. {
  1467. fSMsgr.SendMessage (M_CLIENT_QUIT);
  1468. }
  1469. }
  1470. break;
  1471. case M_LIST_COMMAND:
  1472. {
  1473. if (fListAgent)
  1474. break;
  1475. vision_app->pClientWin()->pWindowList()->AddAgent (
  1476. (fListAgent = new ListAgent (
  1477. *vision_app->pClientWin()->AgentRect(),
  1478. fServerHostName.String(), new BMessenger(this))),
  1479. "Channels",
  1480. WIN_LIST_TYPE,
  1481. true);
  1482. // kind of a hack since Agent() returns a pointer of type ClientAgent, of which
  1483. // ListAgent is not a subclass...
  1484. BMessenger listMsgr(fListAgent);
  1485. listMsgr.SendMessage(msg);
  1486. }
  1487. break;
  1488. case M_LIST_SHUTDOWN:
  1489. fListAgent = NULL;
  1490. break;
  1491. case M_REGISTER_LOGGER:
  1492. {
  1493. const char *logName;
  1494. msg->FindString ("name", &logName);
  1495. fLogger->RegisterLogger (logName);
  1496. }
  1497. break;
  1498. case M_UNREGISTER_LOGGER:
  1499. {
  1500. const char *logName;
  1501. msg->FindString ("name", &logName);
  1502. fLogger->UnregisterLogger (logName);
  1503. }
  1504. break;
  1505. case M_CLIENT_LOG:
  1506. {
  1507. const char *logName;
  1508. const char *data;
  1509. msg->FindString ("name", &logName);
  1510. msg->FindString ("data", &data);
  1511. fLogger->Log (logName, data);
  1512. }
  1513. break;
  1514. case M_IGNORE_ADD:
  1515. {
  1516. BString cmd (msg->FindString("cmd"));
  1517. BString curNick;
  1518. int32 idx (-1);
  1519. int32 i (0);
  1520. type_code type;
  1521. int32 attrCount;
  1522. // make sure this nick hasn't already been added
  1523. fNetworkData.GetInfo ("ignore", &type, &attrCount);
  1524. // TODO: print notification message to user
  1525. while ((idx = cmd.IFindFirst(" ")) > 0)
  1526. {
  1527. cmd.MoveInto(curNick, 0, cmd.IFindFirst(" "));
  1528. // remove leading space
  1529. cmd.Remove(0, 1);
  1530. for (i = 0; i < attrCount; i++)
  1531. if (curNick.ICompare(fNetworkData.FindString("ignore", i)) == 0)
  1532. break;
  1533. // no dupes found, add it
  1534. if (i == attrCount)
  1535. {
  1536. vision_app->AddIgnoreNick(fNetworkData.FindString("name"), curNick.String());
  1537. fNetworkData.AddString("ignore", curNick.String());
  1538. }
  1539. curNick = "";
  1540. }
  1541. // catch last one
  1542. if (cmd.Length() > 0)
  1543. {
  1544. for (i = 0; i < attrCount; i++)
  1545. if (cmd.ICompare(fNetworkData.FindString("ignore", i)) == 0)
  1546. break;
  1547. // no dupes found, add it
  1548. if (i == fNotifyNicks.CountItems())
  1549. {
  1550. vision_app->AddIgnoreNick(fNetworkData.FindString("name"), curNick.String());
  1551. fNetworkData.AddString("ignore", curNick.String());
  1552. }
  1553. }
  1554. }
  1555. break;
  1556. case M_IGNORE_REMOVE:
  1557. {
  1558. }
  1559. break;
  1560. case M_EXCLUDE_ADD:
  1561. {
  1562. }
  1563. break;
  1564. case M_EXCLUDE_REMOVE:
  1565. {
  1566. }
  1567. break;
  1568. case M_NOTIFYLIST_ADD:
  1569. {
  1570. BString cmd (msg->FindString("cmd"));
  1571. BString curNick;
  1572. int32 idx (-1);
  1573. int32 i (0);
  1574. // TODO: print notification message to user
  1575. while ((idx = cmd.IFindFirst(" ")) > 0)
  1576. {
  1577. cmd.MoveInto(curNick, 0, cmd.IFindFirst(" "));
  1578. // remove leading space
  1579. cmd.Remove(0, 1);
  1580. for (i = 0; i < fNotifyNicks.CountItems(); i++)
  1581. if (curNick.ICompare(fNotifyNicks.ItemAt(i)->Text()) == 0)
  1582. break;
  1583. // no dupes found, add it
  1584. if (i == fNotifyNicks.CountItems())
  1585. {
  1586. vision_app->AddNotifyNick(fNetworkData.FindString("name"), curNick.String());
  1587. NotifyListItem *item (new NotifyListItem (curNick.String(), false));
  1588. fNotifyNicks.AddItem (item);
  1589. }
  1590. curNick = "";
  1591. }
  1592. // catch last one
  1593. if (cmd.Length() > 0)
  1594. {
  1595. for (i = 0; i < fNotifyNicks.CountItems(); i++)
  1596. if (cmd == fNotifyNicks.ItemAt(i)->Text())
  1597. break;
  1598. // no dupes found, add it
  1599. if (i == fNotifyNicks.CountItems())
  1600. {
  1601. NotifyListItem *item (new NotifyListItem (cmd.String(), false));
  1602. vision_app->AddNotifyNick(fNetworkData.FindString("name"), cmd.String());
  1603. fNotifyNicks.AddItem (item);
  1604. }
  1605. }
  1606. fNotifyNicks.SortItems(SortNotifyItems);
  1607. BMessage updMsg (M_NOTIFYLIST_UPDATE);
  1608. updMsg.AddPointer ("list", &fNotifyNicks);
  1609. updMsg.AddPointer ("source", this);
  1610. Window()->PostMessage (&updMsg);
  1611. }
  1612. break;
  1613. case M_NOTIFYLIST_REMOVE:
  1614. {
  1615. BString cmd (msg->FindString("cmd"));
  1616. BString curNick;
  1617. int32 idx (-1);
  1618. // TODO: print notification message to user
  1619. while ((idx = cmd.IFindFirst(" ")) > 0)
  1620. {
  1621. cmd.MoveInto(curNick, 0, cmd.IFindFirst(" "));
  1622. // remove leading space
  1623. cmd.Remove(0, 1);
  1624. vision_app->RemoveNotifyNick(fNetworkData.FindString("name"), curNick.String());
  1625. for (int32 i = 0; i < fNotifyNicks.CountItems(); i++)
  1626. if (curNick.ICompare(fNotifyNicks.ItemAt(i)->Text()) == 0)
  1627. {
  1628. delete fNotifyNicks.RemoveItemAt(i);
  1629. }
  1630. curNick = "";
  1631. }
  1632. // catch last one
  1633. if (cmd.Length() > 0)
  1634. {
  1635. vision_app->RemoveNotifyNick(fNetworkData.FindString("name"), cmd.String());
  1636. for (int32 i = 0; i < fNotifyNicks.CountItems(); i++)
  1637. if (cmd.ICompare(fNotifyNicks.ItemAt(i)->Text()) == 0)
  1638. {
  1639. delete fNotifyNicks.RemoveItemAt(i);
  1640. }
  1641. }
  1642. BMessage updMsg (M_NOTIFYLIST_UPDATE);
  1643. updMsg.AddPointer ("list", &fNotifyNicks);
  1644. updMsg.AddPointer ("source", this);
  1645. Window()->PostMessage (&updMsg);
  1646. }
  1647. break;
  1648. case M_NOTIFYLIST_UPDATE:
  1649. {
  1650. // force agent to update (used for winlist switches)
  1651. BMessage newMsg (M_NOTIFYLIST_UPDATE);
  1652. newMsg.AddPointer("list", &fNotifyNicks);
  1653. newMsg.AddPointer("source", this);
  1654. Window()->PostMessage(&newMsg);
  1655. }
  1656. break;
  1657. #if 0
  1658. case M_IGNORE_ADD:
  1659. {
  1660. BString cmd (msg->FindString("cmd"));
  1661. for (int32 i = 0; i < fIgnoreNicks.CountItems(); i++)
  1662. {
  1663. if (cmd == *((BString *)fIgnoreNicks.ItemAt(i)))
  1664. break;
  1665. }
  1666. fIgnoreNicks.AddItem (new BString(cmd));
  1667. }
  1668. break;
  1669. #endif
  1670. default:
  1671. ClientAgent::MessageReceived (msg);
  1672. }
  1673. }