IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Réseau C Discussion :

Mon bot IRC (version très basique)


Sujet :

Réseau C

  1. #1
    Invité
    Invité(e)
    Par défaut Mon bot IRC (version très basique)
    Bonjour a tous, voila, mon code fonctionne et je le poste ici afin de receuillir vos avis, c'est mon 1er réel projet donc ne soyez pas trop sevères s'il vous plait :p Bien sur ce n'est qu'une 1ere version, mais le plus gros est fait, il me reste des commandes a ajouter, l'entree du nom du bot, de ses info et du channel a rejoindre a partir d'un fichier, et apres je verrais, j'attend surtout vos avis sur la facon dont j'ai pensé ce bot car je ne me suis inspiré de personne du coups je suis peut etre passé a coté de quelquechose qui pourrait me faciliter le travail

    main.c :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <netdb.h>
    #include <sys/types.h>
        #include <sys/socket.h>
        #include <netinet/in.h>
        #include <arpa/inet.h>
        #include <unistd.h>
     
        typedef int SOCKET;
        typedef struct sockaddr_in SOCKADDR_IN;
        typedef struct sockaddr SOCKADDR;
        #include "irc.h"
        #define INVALID_SOCKET -1
        #define SOCKET_ERROR -1
        #define closesocket(s) close(s)
     
    int main(int argc, char *argv[])
    {
     
        int err;
        SOCKADDR_IN cserv;
        struct timeval temps;
        temps.tv_sec = 0;
        temps.tv_usec = 100;
        struct irc_msg *ircmsg = malloc(sizeof(struct irc_msg));
        int serv = socket(AF_INET, SOCK_STREAM, 0);
        (*ircmsg).serv = serv;
        ircmsg->nick = malloc(50 * sizeof(char));
        ircmsg->text = malloc(500 * sizeof(char));
        ircmsg->chaine = malloc(512 * sizeof(char));
        ircmsg->name = malloc(50 * sizeof(char));
        ircmsg->domain = malloc(50 * sizeof(char));
        ircmsg->event = malloc(50 * sizeof(char));
        struct hostent *adresse;
        fd_set read;
     
        if(argc == 1) {
            free(ircmsg);
            printf("Veuillez renseigner le serveur\n");
            return 0;
        }
        adresse = gethostbyname(argv[1]);
        cserv.sin_addr = *((struct in_addr *)(adresse->h_addr));
        cserv.sin_family = AF_INET;
        cserv.sin_port = htons(6667);
        err = connect(ircmsg->serv, (SOCKADDR*)&cserv, sizeof(cserv));
     
        printf("Connexion a %s\n", inet_ntoa(cserv.sin_addr));
        if(err == -1) {
                printf("Err connection\n");
                return 0;
        }
        printf("Connécté au serveur %s\n", argv[1]);
        send_line(ircmsg->serv, "NICK Bot-fox \r\n\r\n");
        send_line(ircmsg->serv, "PRIVMSG nickserv identify ganjaman\r\n\r\n");
        send_line(ircmsg->serv, "USER a a a a \r\n\r\n");      // A remplir correctement meme si le serveur s'en charge généralement
        send_line(ircmsg->serv, "JOIN #romfox\r\n\r\n");
     
        while(1) {
            recv_line(ircmsg);
            FD_ZERO(&read);
            FD_SET(STDIN_FILENO, &read);
            select(STDIN_FILENO+1, &read,NULL,NULL,&temps);
            if(FD_ISSET(STDIN_FILENO, &read)) {
                closesocket(ircmsg->serv);
                printf("Connection fermée\n");
                free(ircmsg);
                return 0;
            }
     
     
        }
        return 0;
    }
    irc.h :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    struct irc_msg {
        SOCKET serv;
        char *nick;
        char *event;
        char *text;
        char *chaine;
        char *name;
        char *domain;
    };
     
    void send_line(SOCKET Client, char* buffer) {
        int i = 0;
     
        while(i< strlen(buffer)) {
               send(Client, (char *)&buffer[i], 1, 0);
               i++;
        }
    }
     
    int range(struct irc_msg *ircmsg) {
        int ret, i = 0;
        char *txt = NULL;
        ret = sscanf(ircmsg->chaine, ":%s %s", ircmsg->nick, ircmsg->event);
            txt = strstr(ircmsg->nick, "!");
            if(txt != NULL) {                      // Si c'est un méssage de client
                txt = NULL;
                ret = sscanf(ircmsg->chaine, ":%[^!]!%s %[^\n]", ircmsg->nick, ircmsg->domain, ircmsg->text);
                txt = strstr(ircmsg->text, ":");
                if (txt != NULL && ret == 3) {
                     while(txt[i+1] != '\n') {      // Lecture du texte
                          ircmsg->text[i] = txt[i+1];
                          i++;
                     }
                 printf("%s : %s %s\n\n", ircmsg->nick, ircmsg->event, ircmsg->text);
                 return 0;
                 }
                 printf("%s : %s\n\n", ircmsg->nick, ircmsg->text);
                 return 0;
        }                                          // End méssage clients
        printf("%s\n", ircmsg->chaine);
        return 0;
    }
     
    int fonctions(struct irc_msg *ircmsg) {
     
        char *txt = NULL;
        int t_buff = 0, ret;
        FILE* file = NULL;
        char buff[500] = "";
        char buff2[500] = "";
     
        txt = strstr(ircmsg->chaine, "PING");          // PING
        if (txt != NULL && ircmsg->chaine[0] == 'P') {
            ircmsg->chaine[1] = 'O';
            send_line(ircmsg->serv, ircmsg->chaine);
            send_line(ircmsg->serv, "\r\n\r\n");
            return 0;
        }                                                 // End PING
        file = fopen("b_words.txt", "r");
        while(fgets(buff, 20, file) != NULL) {
            t_buff = strlen(buff);
            buff[t_buff - 1] = '\0';           // Gros mots
            txt = strstr(ircmsg->text, buff);
            if (txt != NULL && strcmp(ircmsg->nick, "romfox") != 0) {
                sprintf(buff2, "KICK #romfox %s\r\n\r\n",ircmsg->nick);
                send_line(ircmsg->serv, buff2);
                return 0;
        }
        }                                // End gros mots
        fclose(file);
                                           // JOIN
        if(strcmp(ircmsg->event, "JOIN") == 0 && strcmp(ircmsg->nick, "Bot-fox") != 0) {
            file = fopen("bvn.txt", "r");
            fgets(buff, 500, file);
            fclose(file);
            sprintf(buff2, "PRIVMSG #romfox :Bonjour %s\r\n\r\n", ircmsg->nick);
            send_line(ircmsg->serv, buff2);
            sprintf(buff2, "PRIVMSG %s :%s\r\n\r\n", ircmsg->nick, buff);
            send_line(ircmsg->serv, buff2);
            return 0;
        }                                      // End JOIN
     
        txt = NULL;
        txt = strstr(ircmsg->text, "!say");        // !SAY
        if (txt != NULL && txt[0] == '!') {
            ret = sscanf(ircmsg->text, "!say %[^\n]", buff);
            sprintf(buff2, "PRIVMSG #romfox :%s\r\n\r\n", buff);
            send_line(ircmsg->serv, buff2);
            return 0;
        }                                         // End !SAY
     
        txt = NULL;
        txt = strstr(ircmsg->text, "!voice");        // !VOICE
        if(txt != NULL && ircmsg->text[1] == 'v') {
            sprintf(buff, "MODE #romfox +v %s\r\n\r\n", ircmsg->nick);
            send_line(ircmsg->serv, buff);
            return 0;
        }                                           // End !VOICE
     
        txt = NULL;                                 // !KICK
        txt = strstr(ircmsg->text, "!kick");
        if(txt != NULL && ircmsg->text[1] == 'k') {
            sscanf(ircmsg->text, "!kick %[^\n]", buff);
            txt = NULL;
            txt = strstr(buff, "romfox");
            if (txt == NULL) {
               sprintf(buff2, "KICK #romfox %s\r\n\r\n", buff);
               send_line(ircmsg->serv, buff2);
            }
            return 0;                                  // End !KICK
     
        return 0;
     
    }
    }
     
    int recv_line(struct irc_msg *irc_mss) {
        int i = 0, t_buff;
        struct timeval temps;
        temps.tv_sec = 0;
        temps.tv_usec = 100;
        fd_set read;
        FD_ZERO(&read);
        FD_SET(irc_mss->serv, &read);
        select(irc_mss->serv+1, &read, NULL, NULL, &temps);
        if(FD_ISSET(irc_mss->serv, &read)) {
            t_buff = recv(irc_mss->serv, irc_mss->chaine, 512, 0);
            irc_mss->chaine[t_buff] = '\0';
            range(irc_mss);
            fonctions(irc_mss);
        }
        return 0;
    }
    Pour le tester vous n'avez qu'a changer le nom du chan de connection et dans les fonctions, c'est pour cela que je dois vite implémenter les entrees par fichier (ou paramètre au lancement mais sa serait lourd). Merci

  2. #2
    Membre émérite
    Avatar de D[r]eadLock
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    504
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 504
    Par défaut
    Citation Envoyé par romfox17 Voir le message
    Bonjour a tous, voila, mon code fonctionne et je le poste ici afin de receuillir vos avis, c'est mon 1er réel projet donc ne soyez pas trop sevères s'il vous plait :p
    On va essayer

    Partie 'utilisation':
    • s'il n'y a pas de paramètre ou des erreurs, c'est bien de mettre un 'usage', genre
      "Usage: monproc <serveur-name>...". Mon exeperience: $ ./chat
      Veuillez renseigner le serveur
      $ ./chat --help
      Segmentation fault (core dumped)
    • il faut valider les entrées de l'utilisateur (cf. ci-dessus).


    Partie 'code':
    • il ne faut pas mettre de code dans les .h (ou au pire des inline)
    • tu ne vérifie pas le retour de gethostbyname() (cf. mon segfault ci-dessus)
    • tu ne vérifie pas le retour de send() (et du coup de send_line())
    • en gros tu ne vérifie pas les retour des fonctions appelées (send, recv, sscanf, gethostbyname, range, fonctions). La gestion des erreurs est donc très hasardeuse (et risque de générer des segfaults)
    • à mon avis, tout devrait être dans irc.c (et pas dans le main, qui devrait juste de valider les entrées utilisateur)
    • les sscanf() devraient être protégés, i.e. en spécifiant la taille des buffers que tu passe, i.e. "%50s"
    • tu devrais plutôt faire recv(fd, foo, sizeof(*foo), 0), plutôt que spécifier à la main la taille de ton buffer que tu as fixé ailleurs (ou alors utiliser des macros #define MAIN_SZ (500))
    • recv peut renvoyer une valeur négative !
    • l'indentation est douteuse
    • ça ne sert à rien de faire txt=NULL; txt =...
    • pourquoi faire des typedef assez 'basiques' (genre passer en majuscule) ?
    • ce serait bien d'afficher l'errno (strerror()) quand les fonctions système échouent (connect, recv, send...)

    Algorithmie:
    • envoyer les caractères 1 par 1 (dans send_line) est un peu dommage
    • c'est dommage d'ouvrir le fichier b_words.txt à chaque fois. L'idéal serait qu'il soit lu et parsé une seule fois (genre dans le main)
    • pour parser les actions (dans fonctions()), pourquoi fais-tu strstr() puis txt[0]=='!', si tu as !voice !say, tu passeras malheureusement dans // !SAY. Il faudrait plutôt utiliser strncmp() ou strtok_r()
    • select() modifie &temps (du moins sous linux)


    Allez, pour la route, il n'y a pas d'accents dans "message'
    Désolé d'avoir été 'sévère', mais ça te permets de voir tout ce que tu améliorer (pour améliorer la qualité et l'utilisabilité de ton prog).

  3. #3
    Invité
    Invité(e)
    Par défaut
    Tout d'abord bonjour, et merci de cette réponse claire :p.
    Ensuite, nul besoin de t'excuser pour la 'sévèrité' (je suis pas sur pour les accents), car c'est tout à fait ce que je demandais comme réponse. Bon pour la partie utilisation, je n'en suis qu'au début du programme donc je n'ai géré que le cas ou il n'y a rien de renseigné.
    (Mode questions en bloc)
    Je dois donc mettre mon code dans un .c ?
    pour parser les actions (dans fonctions()), pourquoi fais-tu strstr() puis txt[0]=='!'
    Je vais changer cela en txt[1] == 's' , non ?
    Comment ça select modifie &temps ? En mettant un temps extremement petit on arrive a rendre cela insignifiant non? En tout cas je ne le ressent pas.
    Je pensais qu'en faisant : %50s je lisais 50 caractères, ni plus ni moins, tu m'apprend que cela limite simplement, merci. (J'utilise fgets pour la saisie sécurisée)
    J'initialise txt a NULL par habitude :p, mais j'oubliais que strstr retourne NULL si il n'y a pas de retour a faire.

    Pour ce qui est des valeurs en brute dans le code, c'est du au fait que mon code a été beaucoup modifié avant de se retrouver ainsi, et du coups je ne l'ai pas encore totalement optimisé, c'était surtout pour être sur de ne rien rater avant de continuer.

    Je m'en vais donc optimiser mon code, merci !

Discussions similaires

  1. bot IRC: posix threads et autres remarques
    Par keikoz dans le forum Réseau
    Réponses: 6
    Dernier message: 19/11/2006, 00h52
  2. Bot irc, questions !
    Par Fabouney dans le forum Programmation et administration système
    Réponses: 4
    Dernier message: 02/08/2006, 11h28
  3. bot irc: problème d'affichage et d'envoie
    Par alceste dans le forum C++
    Réponses: 21
    Dernier message: 21/06/2006, 14h47
  4. Creation d'un bot IRC
    Par kedare dans le forum Bibliothèques tierces
    Réponses: 2
    Dernier message: 28/11/2005, 21h29
  5. curses très basiques ...
    Par Akoino dans le forum C
    Réponses: 4
    Dernier message: 05/12/2003, 18h21

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo