~aritra1911/mc_client

7c6f5d267067561432608df1c1aae26efc44ac12 — Aritra Sarkar 2 years ago 33adb74 response_codes
Parse response codes
3 files changed, 81 insertions(+), 33 deletions(-)

M main.c
M message.c
M message.h
M main.c => main.c +28 -5
@@ 128,7 128,7 @@ int main(int argc, char **argv)
    int sockfd;
    char buf[BUFLEN];

    if ( argc < 3 ) {
    if ( argc < 2 ) {
        printf("Usage : %s hostname port\n", argv[0]);
        return EXIT_FAILURE;
    }


@@ 144,8 144,12 @@ int main(int argc, char **argv)
    pfds[0].fd = STDIN_FILENO;  /* File descriptor for stdin (usually 0) */
    pfds[0].events = POLLIN;    /* Let me know when data is ready to be read */

    char port[] = PORT;
    if ( argc > 2 )
        strcpy(port, argv[2]);

    /* Let us try to get that socket connection now */
    if ( (sockfd = get_connection(argv[1], argv[2])) == -1 ) {
    if ( (sockfd = get_connection(argv[1], port)) == -1 ) {
        return EXIT_FAILURE;
    }



@@ 219,7 223,7 @@ int main(int argc, char **argv)
                break;
            }

            separate_nick(buf, numbytes, &msg);
            parse_response(buf, numbytes, &msg);

            if ( overwrite ) {
                /* Alter above line with server's echo */


@@ 227,8 231,27 @@ int main(int argc, char **argv)
                overwrite = 0;
            }

            /* Decorate nick and print */
            printf("<%s> %s", msg.nick, msg.content);
            switch(msg.type) {
                case NORMAL:
                    /* Decorate nick and print */
                    printf("<%s> %s", msg.nick, msg.content);
                    break;

                case JOIN:
                    /* Announce join */
                    printf("[!] %s has joined", msg.nick);
                    break;

                case SETNICK:
                    /* Announce nick change */
                    printf("[!] %s is now known as %s", msg.nick, msg.new_nick);
                    break;

                case ACTION:
                    printf(" * %s %s", msg.nick, msg.content);
                    break;
            }


            if ( buf[numbytes - 1] != '\n' ) {
                /* We wanna make sure we're polling on a newline always */

M message.c => message.c +41 -26
@@ 18,44 18,59 @@
 * https://www.gnu.org/licenses/gpl-3.0.txt
 */

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#include "message.h"

int get_space_index(const char *, const int, const int);

int get_space_index(const char *s, const int len, const int start)
int parse_response(const char *buf, int len, Message *msg)
{
    int i = -1;

    for ( int i = start; i < len; i++ ) {
        /* Look for the first space character */
        if ( isspace(s[i]) ) {
            /* `i` will hold the index of that space character */
            return i;
        }
    }
    /* The first byte of `buf` is the response code */
    msg->type = (ResponseCode) buf[0];

    return i;
}
    /* Skip the response code */
    buf++;
    len--;

int separate_nick(const char *buf, const int len, Message *msg)
{
    /* Tear `buf` apart into its components : `nick` and `content` */
    /* The response code tells us what kind of message to expect */
    switch (msg->type) {
        case NORMAL:
        case ACTION:
            /* buf = "<nick> <content>" */

    /* Get index of first whitespace */
    int idx = get_space_index(buf, len, 0);
            /* Extract the first word as nick */
            sscanf(buf, "%s", msg->nick);
            buf += strlen(msg->nick);
            len -= strlen(msg->nick);

    /* Copy nick and terminate it */
    strncpy(msg->nick, buf, idx); 
    msg->nick[idx] = '\0';
            /* Get `buf` to the first byte of content */
            while ( len && buf[0] != '\0' && isspace(buf[0]) ) {
                buf++;
                len--;
            }

    /* Now copy the message content starting right after the nick */
    strncpy(msg->content, buf + idx + 1, len - idx - 1);
            strncpy(msg->content, buf, len);
            msg->content[len] = '\0';
            break;

    /* And terminate it at the proper place. */
    msg->content[len - idx - 1] = '\0';
        case JOIN:
            /* buf = "<nick>" */

            /* Extract the first word as nick */
            sscanf(buf, "%s", msg->nick);
            msg->nick[len] = '\0';
            break;

        case SETNICK:
            /* buf = "<nick> <new_nick>" */
            sscanf(buf, "%s %s", msg->nick, msg->new_nick);
            msg->new_nick[len - strlen(msg->nick) - 1] = '\0';
            break;

        default:
            return -1;
    }

    return 0;
}

M message.h => message.h +12 -2
@@ 20,10 20,20 @@
                        with that. Remember that we gotta store an array of
                        them. */

typedef enum _ResponseCode {
    NORMAL=0,  /* Normal group messages */
    JOIN,      /* User joins */
    SETNICK,   /* Nick changes */
    ACTION,    /* Actions */
} ResponseCode;

typedef struct _Message {
    char nick[NICKLEN], content[CONLEN];
    ResponseCode type;
    char nick[NICKLEN],
         new_nick[NICKLEN],
         content[CONLEN];
} Message;

int separate_nick(const char *, const int, Message *);
int parse_response(const char *, int, Message *);

#endif