tags:

views:

49

answers:

2

Good evening, everyone.

I've now run into an odd warning, and for the life of me I can't figure out where it's going wrong. I've tried so many different options I can't remember.

The error is:

assignment from incompatible pointer type

Relative code:

// Server structure
typedef struct {
    struct addrinfo address;        // Address info
    char buffer[1024];              // Read biffer
    fd_set connections;             // Current connections
    int connections_max;            // Max file descriptor
    int listener;                   // Listener fd
    int port;                       // The port for the server to listen on
    struct addrinfo socket_hints;   // Server's socket hints
    struct timeval socket_timeout;  // When should the socket timeout?
    struct User *users;             // Currently connected users
} Server;

// User structure
typedef struct {
    struct sockaddr_storage address;    // User's address
    socklen_t address_length;           // Length of users address
    int fs_id;                          // ID to the socket they belong to
    char ip_address[INET6_ADDRSTRLEN];  // User's IP address
    char *name;                         // Pointer to the user's name
    struct User *nextUser;              // Next user in the list
} User;

/**
 * Handles sockets on the provided server
 */
void handle_sockets(Server *passed_server) {
    int current_fd;             // Current file descriptor
    int new_connection;         // Socket ID of new connections
    fd_set read_sockets;        // Sockets to read from
    FD_ZERO(&read_sockets);
    struct timeval timeout;     // Sets the timeout for select 

    // See if we have sockets to read
    read_sockets = passed_server->connections;
    timeout = passed_server->socket_timeout;
    if(select(passed_server->connections_max+1, &read_sockets, NULL, NULL, &timeout) == -1) {
        perror("Selecting sockets");
        exit(1);
    }

    // Loop through all of the sockets
    for(current_fd = 0; current_fd <= passed_server->connections_max; current_fd++) {
        if(!FD_ISSET(current_fd, &read_sockets)) {
            continue;
        }

        // Handle new connection
        if(current_fd == passed_server->listener) {
            User *new_user = malloc(sizeof *new_user); 
            memset(&new_user->address, 0, sizeof new_user->address);

            // Get the new address
            new_user->address_length = sizeof new_user->address;
            new_user->fs_id = accept(passed_server->listener, (struct sockaddr *)&new_user->address, &new_user->address_length);

            // Did we have an issue connecting?
            if(new_user->fs_id == -1) {
                free(new_user);
                perror("Accepting new connection");
                continue;
            }

            // Add the user socket to the master list
            FD_SET(new_user->fs_id, &passed_server->connections);
            if(new_user->fs_id > passed_server->connections_max) {
                passed_server->connections_max = new_user->fs_id;
            }

            // Add the user to the list

            //*******************
            // ERRORS IN THE NEXT TWO ASSIGNMENTS
            //*******************

            if(passed_server->users == NULL) {
                passed_server->users = new_user;
            } else {
                new_user->nextUser = passed_server->users;
                passed_server->users = new_user;
            }

            // Let them know we got one!
            printf("Server: New connection from %s on socket %d. Send hello.\n",
                    inet_ntop(
                            new_user->address.ss_family, 
                            get_address((struct sockaddr*)&new_user->address),
                            new_user->ip_address,
                            INET6_ADDRSTRLEN
                    ),
                    new_user->fs_id
            );

            // Can we get to the user from the server?
            //printf("Repeat, the IP address is %s\n", passed_server->users->ip_address);

            // Move on to the next file descriptor
            continue;
        }
    }
}

Full Code

+1  A: 

Pointers are declared to point to a certain type of variable, and with the exception of void*, you will get that warning if you try to assign a pointer that was declared to point to one type to a pointer that was declared to point to some other type.

Pointers need to have a type in order to interpret the contents of memory at that location. For example, a pointer to a float somehow needs to know to read four bytes instead of two or three. This information is provided in the pointer type.

So make sure you either assign pointers with compatible types, or use a cast if you are sure you want to change the type.

bde
I had thought I was doing that, but as bstpierre pointed out, I needed to change the struct around.
Codeacula
Glad it is working now.
bde
+3  A: 
typedef struct User {
    struct sockaddr_storage address;    // User's address
    socklen_t address_length;           // Length of users address
    int fs_id;                          // ID to the socket they belong to
    char ip_address[INET6_ADDRSTRLEN];  // User's IP address
    char *name;                         // Pointer to the user's name
    struct User *nextUser;              // Next user in the list
} User;

Add the "struct User" at the top so that you can reference it within the struct.

Also, you need to swap the order of your declarations so that the Server struct knows about the User struct.

bstpierre
Thanks, that seems to be the trick.I had thought about placing User before Server, but the compiler was letting me go on my merry way having it as I did in the provided code, so I figured all was well. Thanks for the help!
Codeacula
For the server, since its only pointing to a User, do I really need to put User first? If not (Server just needs to know it's pointing to a user not what the user is, right?), then I can separate the server/user stuff into separate source files.
Codeacula