Program crashes when trying to connect Glib::signal_io



Hi,

I have a Socket class, which connects the Glib::signal_io signal. But when I run the project, it crashes, with no other information. I'm currently on windows, and I read that Glib uses the select() and poll() functions to determine which socket to read. But when I look at the winsock functions reference, I see no poll() function. Could that be the problem?

Here's my code:

#
#-----[ socket.h ]---------------------------------------------------------------
#
/**
 * Lucky Bot C++ Version 1.0
 * An extendable IRC Bot written in C++
 *
 * Copyright 2007 by Lucas van Dijk ( info lucasvd nl)
 * http://www.lucasvd.nl
 *
 * @author Lucas van Dijk
 * @license http://www.opensource.org/osi3.0/licenses/gpl-license.php
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

#ifndef SOCKET_H_INCLUDED
#define SOCKET_H_INCLUDED

#ifdef WIN32
#include <winsock.h >
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif // ifdef WIN32

#include "../../stdinc.h"

namespace LuckyBot { namespace Sockets
{
    /**
     * This is our main Socket class
     * It uses the GTKmm IO monitoring functions, so it's non blocking.
     */
    class Socket
    {
        // Members
        protected:
            /// Keeps track of the number of sockets open
            static int num_sockets;

            /// Holds the socket file descriptor
            int socket;

            /// This is a Glib::iochannel which is used for non blocking I/O
            Glib::RefPtr<Glib::IOChannel> iochannel;

            /// Holds address info
            sockaddr_in address;

            virtual bool OnIOCallback(Glib::IOCondition condition) = 0;

        // Methods
        public:
            Socket();
            virtual ~Socket();

            virtual bool connect(Glib::ustring hostname, int port);
            virtual void send(Glib::ustring message);
            virtual Glib::ustring receive(int length = -1);
    };
}
}

#endif // SOCKET_H_INCLUDED

#
#-----[ socket.cpp ]------------------------------------------------------------------------------
#
/**
 * Lucky Bot C++ Version 1.0
 * An extendable IRC Bot written in C++
 *
 * Copyright 2007 by Lucas van Dijk (info lucasvd nl)
 * http://www.lucasvd.nl
 *
 * @author Lucas van Dijk
 * @license http://www.opensource.org/osi3.0/licenses/gpl-license.php
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

#include "socket.h "

int LuckyBot::Sockets::Socket::num_sockets = 0;

namespace LuckyBot { namespace Sockets
{
    /**
     * Constructor, initializes the socket
     * If we're on windows, the WSAData struct will be automaticly initialized,
     * then a new socket file descriptor is created
     */
    Socket::Socket()
    {
        std::cout << "Number of sockets before: " << num_sockets << std::endl;
        // If we're on windows, we need to initialize the wsa
        #ifdef WIN32
        // We need to initialize it only once
        if(num_sockets == 0)
        {
            std::cout << "Initializing WSA" << std::endl;

            WSADATA wsa_data;
            if (WSAStartup(MAKEWORD(1, 1), &wsa_data) != 0)
            {
                std::cout << "WSA Startup failed" << std::endl;
                exit(1);
            }
        }
        #endif // WIN32

        // Initialize socket
        this -> socket = ::socket(PF_INET, SOCK_STREAM, 0);

        char yes = '1';
        if (setsockopt(this -> socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1)
        {
            std::cout << "Could not set socket option" << std::endl;
            Gtk::Main::quit();
        }

        this -> address.sin_family = AF_INET;
        memset(&(this -> address.sin_zero), '\0', 8);

        // Increment number of sockets
        num_sockets++;

        std::cout << "Number of sockets after: " << num_sockets << std::endl;

        // Connect to Glib IO Signal
        Glib::signal_io().connect(sigc::mem_fun(*this, &Socket::OnIOCallback), this -> iochannel, Glib::IO_IN);
    }

    /**
     * Connect to the given adress.
     * Does nothing special except using the connect() function to connect to the socket
     * @return true on success, else false
     */
    bool Socket::connect(Glib::ustring hostname, int port)
    {
        // Resolve DNS
        hostent * host = gethostbyname(hostname.c_str());

        if(host == 0)
        {
            std::cout << "Could not resolve DNS: " << hostname.c_str() << " Error code: " << h_errno << std::endl;
            throw std::runtime_error("Could not resolve DNS");
        }

        // Copy address
        memcpy(&this -> address.sin_addr, host->h_addr_list[0], host->h_length);

        this -> address.sin_port = htons(port);

        // Let's connect to the adress
        int result = ::connect(this -> socket, (sockaddr *) &(this -> address), sizeof(sockaddr));

        if(result == -1)
        {
            std::cout << "Could not connect" << std::endl;
            return false;
        }
        else
        {
            // Initialize IOChannel object
            this -> iochannel = Glib::IOChannel::create_from_fd(this -> socket);

            return true;
        }
    }

    /**
     * Sends a given string to the socket
     * @param message The message to send
     * @return Number of bytes actually sent
     */
    void Socket::send(Glib::ustring message)
    {
        this -> iochannel -> write(message);
    }

    /**
     * Receives data from the socket
     * @param buffer the buffer for the contents
     * @param the max number of bytes to receive
     * @return The message received
     */
    Glib::ustring Socket::receive(int length)
    {
        Glib::ustring buffer;
        if(length == -1)
        {
            // reads a line
            this -> iochannel -> read_line(buffer);
        }
        else
        {
            this -> iochannel -> read(buffer, length);
        }

        return buffer;
    }

    /**
     * Destructor, closes the socket
     * If this is the last open socket, and we're on windows, the WSAData struct is also automaticly cleaned up
     */
    Socket::~Socket()
    {
        // Decrement the number of sockets
        num_sockets--;

        ::shutdown(this -> socket, 2);

        // Clean up WSA
        #ifdef WIN32
        if(num_sockets == 0)
        {
            WSACleanup();
        }
        #endif // WIN32
    }
}
}


Thanks in advance. :)

--
Lucas

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]