Eigenen ICQ-Login-Proxy programmieren



  • Hallo,

    ich habe es mir zur Aufgabe gemacht, einen kleinen Proxy zu schreiben, welcher beim Login aktiv sein soll.

    Ich habe herausgefunden, dass beim Einloggen in ICQ beim Klick auf den Button "Verbinden" nicht sofort die Userdaten mitgeschickt werden, sondern erst mal der Server angepingt wird (wahrscheinlich um zu testen, ob eine Verbindung überhaupt möglich ist).
    Daraus schließe ich, dass das ICQ-Programm dann solange wartet, bis es vom ICQ-Server eine Bestätigung bekommt.
    Das stimmt auch, denn ich habe mal aus Spaß einfach eine "1" als Bestätigung zurückgeschickt, und ICQ gab eine Fehlermeldung aus, dass die Verbindung fehlgeschlagen ist.

    Hier der Ablauf:
    - Proxy wird hochgefahren und wartet auf eingehende Sockets
    - Nun ändert man bei den Verbindungseinstellungen von ICQ den Server von "login.icq.com" auf "127.0.0.1" und loggt sich in ICQ ein
    - der Proxy reagiert dann und pingt mit einem neuen Socket den ICQ-Server (login.icq.com) an
    - nun wartet der Proxy, bis der ICQ-Server antwortet
    - diese Antwort schickt der Proxy dann sofort an den ICQ-User weiter

    Nun ist jedoch mein Problem, dass das ICQ-Programm auch nicht auf die von mir weitergeleitete ICQ-Server-Anwort reagiert, sondern weiterhin blockiert...wieso???

    Ich hoffe mir kann jemand helfen!
    Viele Grüße
    Gapa



  • 1. mit deiner beschreibung kann man nicht viel anfangen. du musst schon den problematischen code herzeigen.
    2. falsches forum. hier geht es um c++ (die programmiersprache), nicht um icq oder proxies



  • Hallo,

    hier etwas Code:

    Header:

    //Management.h
    
    #ifndef MANAGEMENT_H
    #define MANAGEMENT_H
    
    #include <iostream>
    #include "windows.h"
    #include "winsock.h"
    
    class Management
    {
      private:
        WSADATA wsa;
        SOCKADDR_IN main, icq_server;
        long handle;
        SOCKET sock_main, sock_icq_server, sock_icq_client;
        char data_send[1000], data_receive[1000];
    
      public:
        Management();
        ~Management();
        void Start();
    };
    
    #endif
    

    Cpp:

    //Management.cpp
    
    #include "Management.h"
    
    using namespace std;
    
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //---Konstruktor---
    
    Management::Management()
    {
      memset(&wsa, 0, sizeof(WSADATA));
      memset(&main, 0, sizeof(SOCKADDR));
      memset(&icq_server, 0, sizeof(SOCKADDR));
      memset(&handle, 0, sizeof(handle));
      memset(&sock_main, 0, sizeof(SOCKET));
      memset(&sock_icq_server, 0, sizeof(SOCKET));
      memset(&sock_icq_client, 0, sizeof(SOCKET));
      memset(&data_send, 0, sizeof(data_send));
      memset(&data_receive, 0, sizeof(data_receive));
    
      main.sin_port = htons(5190);
      main.sin_family = AF_INET;
      main.sin_addr.s_addr = ADDR_ANY;
      //main.sin_addr.s_addr = inet_addr("127.0.0.1");
    
      icq_server.sin_port = htons(5190);
      icq_server.sin_family = AF_INET;
      icq_server.sin_addr.s_addr = inet_addr("64.12.161.153");
    }
    
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //---Destruktor---
    
    Management::~Management()
    {
    }
    
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //---Connect---
    
    void Management::Start()
    {
      handle = WSAStartup(MAKEWORD(2,2), &wsa);
      if(handle == SOCKET_ERROR)
      {
        cout << "Fehler! WinSock konnte nicht gestartet werden!\nZum Beenden ENTER druecken...";
        system("pause>nul");
       return;
      }
      cout << "WinSock gestartet!\n"; 
    
      sock_main = socket(AF_INET, SOCK_STREAM, 0);
      if(sock_main == INVALID_SOCKET)
      {
        cout << "Fehler! Main-Socket konnte nicht erstellt werden!\nZum Beenden ENTER druecken...";
        system("pause>nul");
       return;
      }
      cout << "Socket erstellt!\n";
    
      handle = bind(sock_main, (SOCKADDR*)&main, sizeof(SOCKADDR));
      if(handle == SOCKET_ERROR)
      {
        cout << "Fehler! Main-Socket konnte nicht an Server gebunden werden!\nZum Beenden ENTER druecken...";
        system("pause>nul");
       return;
      }
      cout << "Main-Socket wurde an Server gebunden!\n";
    
      handle = listen(sock_main, 10);
      if(handle == SOCKET_ERROR)
      {
        cout << "Fehler! Funktion 'listen' fehlgeschlagen!\nZum Beenden ENTER druecken...";
        system("pause>nul");
       return;
      }
      cout << "Server lauscht...\n";
    
      sock_icq_client = accept(sock_main, 0, 0);
      if(sock_icq_client == INVALID_SOCKET)
      {
        cout << "Fehler! Es konnte keine neue Verbindung eingegangen werden!\nZum Beenden ENTER druecken...";
        system("pause>nul");
       return;
      }
    
    //////////
    
      cout << "Neue Verbindung akzeptiert!\n\n\n\nProtokoll:\n\n";
    
      sock_icq_server = socket(AF_INET, SOCK_STREAM, 0);
      if(sock_icq_server == INVALID_SOCKET)
      {
        cout << "Fehler! ICQ_Server_Socket konnte nicht erstellt werden!\nZum Beenden ENTER druecken...";
        system("pause>nul");
      }
      else
        cout << "Socket erstellt!\n";
    
      handle = connect(sock_icq_server, (SOCKADDR*)&icq_server, sizeof(SOCKADDR));
      if(handle == SOCKET_ERROR)
      {
        cout << "Fehler! Verbindung zum ICQ_Server fehlgeschlagen!\nZum Beenden ENTER druecken...";
        system("pause>nul");
       return;
      }
    
      cout << "Socket wurde mit ICQ_Server verbunden!";
    
      handle = recv(sock_icq_server, data_receive, 256, 0);
      if(handle == SOCKET_ERROR)
      {
        cout << "Fehler beim Empfangen von Datenpaketen!\nZum Beenden ENTER druecken...";
       return;
      }
      else if(handle == 0)
      {
        cout << "Gegenseite hat die Verbindung getrennt!\nZum Beenden ENTER druecken...";
       return;
      }
      data_receive[strlen(data_receive) + 1] = '\0';
      cout << "\nDaten wurden erfolgreich von ICQ_Server empfangen: " << data_receive;
    
      handle = send(sock_icq_client, data_receive, strlen(data_receive), 0);
      if(handle == SOCKET_ERROR)
      {
        cout << "Fehler beim Senden von Datenpaketen an ICQ_Client!\nZum Beenden ENTER druecken...";
       return;
      }
    
      cout << "\nDaten wurden erfolgreich an ICQ_Client gesendet: " << data_receive;
    
      handle = recv(sock_icq_client, data_receive, 256, 0);
      if(handle == SOCKET_ERROR)
      {
        cout << "Fehler beim Empfangen von Datenpaketen von ICQ_Client!\nZum Beenden ENTER druecken...";
       return;
      }
      else if(handle == 0)
      {
        cout << "ICQ_Client hat die Verbindung getrennt!\nZum Beenden ENTER druecken...";
       return;
      }
      data_receive[strlen(data_receive) + 1] = '\0';
      cout << "UserDaten: " << data_receive;
      system("pause>nul");
     return;
    }
    

    Main:

    using namespace std;
    
    int main(int argc, char *argv[])
    {
      Management manager;
      manager.Start();
      system("pause>nul");
     return 0;
    }
    

    Hoffe auf Hilfe!
    Gapa



  • Gapa schrieb:

    Nun ist jedoch mein Problem, dass das ICQ-Programm auch nicht auf die von mir weitergeleitete ICQ-Server-Anwort reagiert, sondern weiterhin blockiert...wieso???

    Ich kenne das ICQ-Protokoll nicht, aber evtl will es noch weitere Infos holen (z.B. Kontaktliste oder so)?



  • Hallo,

    Ich kenne das ICQ-Protokoll nicht, aber evtl will es noch weitere Infos holen (z.B. Kontaktliste oder so)?

    Ja aber wie denn? Ich hole doch stets alle Nachrichten vom ICQ-Server bzw. vom ICQ-Programm ab...
    Wenn man sich in ICQ einloggt, so wird, und das habe ich getestet indem ich mal versucht habe nach empfangenen Daten zu suchen, zuerst nur der ICQ-Server konnektiert ohne irgendwelchen Datentransfer...
    Daraus kann man also schließen, dass das ICQ-Programm auf eine Bestätigung vom ICQ-Server wartet.
    Also habe ich den Ping vom ICQ-Programm einfach weitergeleitet an den ICQ-Server und habe dann auf eine Antwort gewartet, welche ich dann auch gleich an das ICQ-Programm übergeben habe.
    Jedoch reagiert das ICQ-Programm immer noch nicht, aber wieso??
    Ich weiß immerhin schon, dass das ICQ-Programm nur auf diese vom Server stammenden Daten nicht reagiert. Schicke ich beispielsweise einen ASCII-String (beliebig) an das ICQ-Programm zurück, so kommt sofort die Fehlermeldung: "Hoppla, da ist was schiefgelaufen" (oder so ähnlich)...
    D.h, die Daten vom Server werden ja eig. richtig weitergeleitet...nur das ICQ-Programm macht dann nicht mehr weiter...!! 😡

    HILFE!
    Gapa



  • Hm, tut mir Leid, aber ich hab noch eine Idee 🙂

    Und zwar kommt mir dein Nullterminieren vom vom Server empfangenen String komisch vor. Der Rückgabewert von recv gibt dir die Anzahl der Bytes zurück.
    Also ich würd's eher so machen:

    handle = recv(sock_icq_server, data_receive, 256, 0);
      if(handle == SOCKET_ERROR)
          throw  "Fehler beim Empfangen von Datenpaketen!\nZum Beenden ENTER druecken...";
      else if(handle == 0)
          throw "Gegenseite hat die Verbindung getrennt!\nZum Beenden ENTER druecken...";
    
      // data_receive[strlen(data_receive) + 1] = '\0'; <- Das hier weg
      cout << "\nDaten wurden erfolgreich von ICQ_Server empfangen: " << data_receive;
    
      handle = send(sock_icq_client, data_receive, handle /*<- Genauso viele Bytes schicken wie empfangen*/, 0);
      if(handle == SOCKET_ERROR)
          throw "Fehler beim Senden von Datenpaketen an ICQ_Client!\nZum Beenden ENTER druecken...";
    

    PS: In C++ arbeitet man mit Exceptions 😉
    PPS: Dein Senden und Empfangen ist allgemein auch nicht so astrein, für ICQ-Login könnte es trotzdem reichen. Wenn du Interesse hast, könntest du dir das viel einfachere SFML mal anschauen 🙂
    PPPS: Fangen kannst du die Exceptions etwa so:

    int main()
    {
        try
        {
             // Hier alles Zeugs rein
        }
        catch ( const char* e )
        {
            cout << e << endl;
        }
    }
    

    Sehr spätes Edit: Drakon hat natürlich Recht, eine Exception soll nur den Fehler beschreiben, also sollte das "\nZum Beenden ENTER druecken..." am Ende der Fehlerstrings weg und stattdessen bei der Ausgabe im catch in der main erscheinen (wenn überhaupt).



  • PS: In C++ arbeitet man mit Exceptions

    So, wie du die da nutzt, bringt das aber nicht viel. 😉
    Wie will man den selbst drauf reagieren und bestimmen, was passiert, wenn du schon "vorgibst", dass das Programm beendet wird? 🙂

    Vor allem bei einem Netzwerkprogramm möchte ich nicht, dass, wenn halt mal etwas schief läuft (was ja mehr, als häufig vorkommt) ich das ganze Programm nochmal starten/konfigurieren muss. Einfach wieder alles abbrechen und dann fragen, ob er es nochmal versuchen soll.



  • drakon schrieb:

    Wie will man den selbst drauf reagieren und bestimmen, was passiert, wenn du schon "vorgibst", dass das Programm beendet wird? 🙂

    Exception heißt ja nicht, dass das Programm beendet wird. Hier ja, ist halt dem Original-Code nachempfunden.

    drakon schrieb:

    Einfach wieder alles abbrechen und dann fragen, ob er es nochmal versuchen soll.

    Dann baust du halt noch eine Schleife irgendwo drum 🙂



  • Badestrand schrieb:

    drakon schrieb:

    Wie will man den selbst drauf reagieren und bestimmen, was passiert, wenn du schon "vorgibst", dass das Programm beendet wird? 🙂

    Exception heißt ja nicht, dass das Programm beendet wird. Hier ja, ist halt dem Original-Code nachempfunden.

    Ja, aber deine Ausgabe mit "Zum Beenden ENTER druecken..." ist schon recht eindeutig. 😉
    Mir ist schon klar, dass dir der "richtige" Einsatz von exceptions schon klar ist, aber ich fand nur das Beispiel verkörpert überhaupt nicht den Fall, wie man ihn mit exceptions lösen sollte/kann.



  • drakon schrieb:

    [Ja, aber deine Ausgabe mit "Zum Beenden ENTER druecken..." ist schon recht eindeutig. 😉

    Ups, hatte den Fehlertext gar nicht großartig gelesen 😞

    drakon schrieb:

    ich fand nur das Beispiel verkörpert überhaupt nicht den Fall, wie man ihn mit exceptions lösen sollte/kann.

    Meinst du das Anwendungsgebiet (also Sockets, verbinden/schicken/...)? Außer dass ich hier keine rohen Sockets benutzen würde, kann ich das nicht ganz nachvollziehen, wie würdest du hier denn die Fehlerbehandlung lösen?



  • Badestrand schrieb:

    drakon schrieb:

    ich fand nur das Beispiel verkörpert überhaupt nicht den Fall, wie man ihn mit exceptions lösen sollte/kann.

    Meinst du das Anwendungsgebiet (also Sockets, verbinden/schicken/...)? Außer dass ich hier keine rohen Sockets benutzen würde, kann ich das nicht ganz nachvollziehen, wie würdest du hier denn die Fehlerbehandlung lösen?

    Nicht speziell darauf bezogen. Aber so Verbindungsfehler sind ja nicht wirklich selten. *Uups* Vergessen Router einzuschalten. Aber dann dafür nochmal das Programm starten will ich nicht müssen. 😉
    Es war ja nur gesagt. Ich fand einfach das "Zum Beenden ENTER druecken" schon recht witzig in dem Zusammenhang. 😉


Anmelden zum Antworten