Beispiel #1
0
// Thread which gets lines from the DCC Q, and processes it.
void DCCThr(XChange *XGlobal) {
char IRC_Line[1024];
IRCLineInterpret LineInterpret;
TCPConnect *DCCChat, *FServChat, *DCCAccept, *SwarmConnect;
DCC_Container_t *DCC_Container;
THR_EXITCODE thr_exit = 1;
THR_HANDLE DCCChatThrH = 0, FileServerThrH = 0, TransferThrH = 0;
bool retvalb;
int retval;
char MyNick[64];
LineParse LineP;
const char *parseptr;
char *tmpbuf;
CSHA1 SHA;
FilesDetail *FD;
char Response[1024];
Helper H;
TCPConnect T; // Just for a little help.
THREADID tempTID;
size_t my_resume_position;
char DotIp[20]; // cant be more than 3 + 1 + 3 + 1 + 3 + 1 + 3
int SwarmIndex;
bool isSwarmed;

   TRACE_INIT_CRASH("DCCThr");
   TRACE();
   H.init(XGlobal);
   while (true) {
      XGlobal->IRC_DCC.getLineAndDelete(IRC_Line);
      if (XGlobal->isIRC_QUIT()) break;
      if (XGlobal->isIRC_DisConnected()) continue;

      LineInterpret = IRC_Line;
      switch (LineInterpret.Command) {

        case IC_CTCPFILESHA1REPLY:
           // Compare FileName, FileSize, SHA1 and update Server UI.
           // If FileSize = 0 and SHA1 = 0, => error string present in FileName
           XGlobal->lock();
           if ( (XGlobal->SHA1_FileName) &&
                (XGlobal->SHA1_SHA1) &&
                (strcasecmp(LineInterpret.FileName, XGlobal->SHA1_FileName) == 0) &&
                (LineInterpret.FileSize == XGlobal->SHA1_FileSize) ) {
              // Reply matches what we are waiting for.
              // Compare SHAs
              if (strcasecmp(XGlobal->SHA1_SHA1, LineInterpret.InfoLine) == 0) {
                 sprintf(Response, "Server 04[%s FILECHECK REPLY]: \"%s\" can be resumed from me", LineInterpret.From.Nick, LineInterpret.FileName);
              }
              else {
                 sprintf(Response, "Server 04[%s FILECHECK REPLY]: \"%s\" CANNOT be resumed from me", LineInterpret.From.Nick, LineInterpret.FileName);
              }
              // Delete the Global as we are done with this.
              delete [] XGlobal->SHA1_FileName;
              XGlobal->SHA1_FileName = NULL;
              delete [] XGlobal->SHA1_SHA1;
              XGlobal->SHA1_SHA1 = NULL;
           }
           else {
              sprintf(Response, "Server 04[%s FILECHECK REPLY]: %s", LineInterpret.From.Nick, LineInterpret.FileName);
           }
           XGlobal->unlock();
           XGlobal->IRC_ToUI.putLine(Response);
           break;

        case IC_CTCPFILESHA1:
           // Reply back to his request with a IC_CTCPFILESHA1REPLY
           // Same thing that we did in the UI to generate IC_CTCPFILESHA1
           // Here we will search for the file in MyFilesDB. If not found
           // there, we use MyPartialFilesDB.
           FD = XGlobal->MyFilesDB.getFilesDetailListMatchingFileName(LineInterpret.FileName);
           if (FD == NULL) {
              // Lets try MyPartialFilesDB.
              FD = XGlobal->MyPartialFilesDB.getFilesDetailListMatchingFileName(LineInterpret.FileName);
              if (FD == NULL) {
                 sprintf(Response, "Server 04[%s FILECHECK]: File: %s FileSize: %lu - We do not have this file.", LineInterpret.From.Nick, LineInterpret.FileName, LineInterpret.FileSize);
                 XGlobal->IRC_ToUI.putLine(Response);
                 sprintf(Response, "NOTICE %s :\001FILESHA1 0 0 I do not have the file requested: %s\001", LineInterpret.From.Nick, LineInterpret.FileName);
                 XGlobal->IRC_ToServer.putLine(Response);
                 break;
              }
              else {
                 // File in MyPartialFilesDB. Prepare filename in Response
                 XGlobal->lock();
                 sprintf(Response, "%s%s%s", XGlobal->PartialDir, DIR_SEP, LineInterpret.FileName);
                 XGlobal->unlock();
              }
           }
           else {
              // File in MyFilesDB. Prepare filename in Response
              XGlobal->lock();
              if (FD->DirName) {
                 sprintf(Response, "%s%s%s%s%s", XGlobal->ServingDir[FD->ServingDirIndex], DIR_SEP, FD->DirName, DIR_SEP, LineInterpret.FileName);
              }
              else {
                 sprintf(Response, "%s%s%s", XGlobal->ServingDir[FD->ServingDirIndex], DIR_SEP, LineInterpret.FileName);
              }
              XGlobal->unlock();
           }

           XGlobal->MyFilesDB.freeFilesDetailList(FD);
           FD = NULL;

           // we are here => Response has full file path.
           tmpbuf = new char[FILE_RESUME_GAP];
           if (getFileResumeChunk(Response, LineInterpret.FileSize, tmpbuf) == false) {
              sprintf(Response, "Server 04[%s FILECHECK]: File: %s FileSize: %lu - Error Reading Chunk.", LineInterpret.From.Nick, LineInterpret.FileName, LineInterpret.FileSize);
              XGlobal->IRC_ToUI.putLine(Response);
              sprintf(Response, "NOTICE %s :\001FILESHA1 0 0 Error reading chunk: %s\001", LineInterpret.From.Nick, LineInterpret.FileName);
              XGlobal->IRC_ToServer.putLine(Response);
              delete [] tmpbuf;
              break;
           }

           SHA.Reset();
           SHA.Update((UINT_8 *) tmpbuf, (UINT_32) FILE_RESUME_GAP);
           SHA.Final();
           SHA.ReportHash(tmpbuf);

           sprintf(Response, "Server 04[%s FILECHECK]: File: %s FileSize: %lu.", LineInterpret.From.Nick, LineInterpret.FileName, LineInterpret.FileSize);
           XGlobal->IRC_ToUI.putLine(Response);
           sprintf(Response, "NOTICE %s :\001FILESHA1 %lu %s %s\001",
                    LineInterpret.From.Nick,
                    LineInterpret.FileSize,
                    tmpbuf,
                    LineInterpret.FileName);
           XGlobal->IRC_ToServer.putLine(Response);
           delete [] tmpbuf;

           break;

        case IC_USERHOST:
           char windowname[32];
           unsigned long longip, myip;
           char *correct_nick;
           COUT(cout << "IC_USERHOST: IRCLine: " << IRC_Line << endl;)
           COUT(LineInterpret.printDebug();)
//      InfoLine contains: [email protected]
//      batata_wada*[email protected] (ircop)
//         We parse it nice and update XGlobal with dotted ip and long ip
//         if its our nick, and update NickList with long ip.

           LineP = LineInterpret.InfoLine;
           LineP.setDeLimiter('@');
           parseptr = LineP.getWord(2);
           longip = T.getLongFromHostName((char *) parseptr);
           T.getDottedIpAddressFromLong(longip, DotIp);

           // Lets get our nick.
           XGlobal->getIRC_Nick(MyNick);
           XGlobal->resetIRC_Nick_Changed();
           LineP.setDeLimiter('=');
           parseptr = LineP.getWord(1);
           correct_nick = new char[strlen(parseptr) + 1];
           strcpy(correct_nick, parseptr);
           if (correct_nick[strlen(correct_nick) - 1] == '*') {
              // Remove the * at end of ircop nick.
              correct_nick[strlen(correct_nick) - 1] = '\0';
           }
           // correct_nick contains corrected nick.

           if (strcasecmp(correct_nick, MyNick) == 0) {
              // Its my own Nick
              XGlobal->putIRC_IP(longip, DotIp);
              sprintf(Response, "Server 09USERHOST: DottedIP: %s LongIP: %lu", DotIp, longip);
              XGlobal->IRC_ToUI.putLine(Response);
           }

           // Update the XGlobal->NickList
           XGlobal->NickList.setNickIP(correct_nick, longip);

           // For testing.
           if (longip != 0) {
              sprintf(Response, "Server 09USERHOST: Nick: %s DottedIP: %s LongIP: %lu", correct_nick, DotIp, longip);
           } 
           else {
              sprintf(Response, "Server 04USERHOST: Nick: %s DottedIP: %s LongIP: %lu", correct_nick, DotIp, longip);
           }
           XGlobal->IRC_ToUI.putLine(Response);

           // If the USERHOST response is of Nick which is same as in
           // XChange->DCCChatnick, then we need to try to Chat with this nick.
           retval = 1;
           XGlobal->lock();
           if (XGlobal->DCCChatNick) {
              retval = strcasecmp(correct_nick, XGlobal->DCCChatNick);
           }
           XGlobal->unlock();

           if (retval == 0) {
              FilesDetail *FD;

              XGlobal->lock();
              delete [] XGlobal->DCCChatNick;
              XGlobal->DCCChatNick = NULL;
              XGlobal->unlock();

              // Check if a DCCChat is already in progress. (allow only 1)
              if (XGlobal->DCCChatInProgress.getCount(NULL) != 0) {
                 sprintf(Response, "Server * 04DCC-CHAT: A CHAT is already in progress.");
                 XGlobal->IRC_ToUI.putLine(Response);
                 delete [] correct_nick;
                 break;
              }

              if (longip != 0) {
                 // Try to connect to his DCCServer as a CHAT.
                 TCPConnect *DCCChat = new TCPConnect;
                 DCCChat->TCPConnectionMethod = XGlobal->getIRC_CM();
                 XGlobal->resetIRC_CM_Changed();
                 retvalb = DCCChat->getConnection(DotIp, DCCSERVER_PORT);
                 Response[0] = '\0';
                 if (retvalb) {
                    // Connection was successful
                    sprintf(Response, "100 %s\n", MyNick);
                    DCCChat->writeData(Response, strlen(Response), DCCSERVER_TIMEOUT);
                    retval = DCCChat->readLine(Response, sizeof(Response) - 1, DCCSERVER_TIMEOUT);
                    LineP = Response;
                    parseptr = LineP.getWord(1);
                    if (retval && strcasecmp(parseptr, "101") == 0) {
                       // Now also check if the nick matches. Else he has some
                       // other client listening at that port.
                       parseptr = LineP.getWord(2);
                       if (strcasecmp(parseptr, correct_nick) == 0) {
                          // We have established a CHAT.
                          // Now we pass the buck on to the DCC Chat Thr
                          // It will add it in DCCChatInProgress etc.
                          COUT(cout << "DCCChatThr: IC_DCC_CHAT (DCC)" << endl;)
                          // Here we spawn a thread to take care of this DCC Chat.
                          // We pass it the ESTABLISED connection
                          // The created thread should free this structure before exiting.
                          DCC_Container = new DCC_Container_t;
                          DCC_CONTAINER_INIT(DCC_Container);
                          DCC_Container->RemoteNick = new char [strlen(parseptr) + 1];
                          strcpy(DCC_Container->RemoteNick, parseptr);
                          DCC_Container->Connection = DCCChat;
                          DCC_Container->XGlobal = XGlobal;

                          // Have to set DCC_Container->RemoteLongIP.
                          DCC_Container->RemoteDottedIP = new char[strlen(DotIp) + 1];
                          strcpy(DCC_Container->RemoteDottedIP, DotIp);
                          DCC_Container->RemoteLongIP = longip;

#ifdef __MINGW32__
                          DCCChatThrH = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) DCCChatThr, DCC_Container, 0, &tempTID);
#else
                          {
                             pthread_attr_t thread_attr;
                             pthread_attr_init(&thread_attr);
                             pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
                             pthread_create(&DCCChatThrH, &thread_attr, (void * (*)(void *)) DCCChatThr, DCC_Container);
                          }
#endif
                          delete [] correct_nick;
                          break;
                       }