IRCServer.cpp 4.9 KB
Newer Older
1 2
/* 
 * File:   IRCServer.cpp
Andrew J. Dahl committed
3
 * Author: Andrew Dahl
4 5 6 7 8 9
 * 
 * Created on March 7, 2010, 4:07 AM
 */

#include "IRCServer.h"

10 11 12 13
IRCServer::IRCServer(string _hostname, int _port)
{
    this->hostname = _hostname;
    this->port = _port;
14 15
}

16 17 18
IRCServer::~IRCServer()
{

19 20
}

21 22 23 24 25 26 27 28 29 30
int IRCServer::Start()
{
    fd_set rfds,
           afds;
    int fd,
        nfds,
        msock;

    try
    {
Andrew J. Dahl committed
31
        //Create Socket
Andrew J. Dahl committed
32
        TCPServerSocket servSock(this->hostname,this->port, 32);
33 34 35 36 37 38 39 40 41
        msock = servSock.getSockDesc();
        nfds = getdtablesize();
        FD_ZERO(&afds);
        FD_SET(msock, &afds);

        while(true)
        {
            memcpy(&rfds, &afds, sizeof(rfds));

Andrew J. Dahl committed
42
            // Start Select().. Wait for file to be busy
43 44
            if (select(nfds, &rfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0) < 0)
            {
Andrew J. Dahl committed
45
                /* ERROR! */
46 47 48
                std::cerr << "Select: " << strerror(errno) << std::endl;
                return (1);
            }
49

50
            if(FD_ISSET(msock, &rfds))
51 52
            {   //We've got a new client!

53 54 55 56 57 58 59 60 61 62 63 64 65
                int ssock = this->getFD(servSock.Accept());
                if(ssock < 0)
                {
                    std::cerr << "Accept: " << strerror(errno) << std::endl;
                    return (1);
                }

                FD_SET(ssock, &afds);

            }

            for (fd=0; fd<nfds; ++fd)
            {
Andrew J. Dahl committed
66
                /* Check each descriptor */
67 68
                if (fd != msock && FD_ISSET(fd, &rfds))
                {
69
                    if (this->handleCommunication(fd) == -1)
70
                    {
Andrew J. Dahl committed
71
                        /* Client Quit! */
72 73 74 75 76 77 78 79 80 81 82 83 84
                        FD_CLR(fd, &afds);
                    }
                }
            }
        }
    }
    catch (SocketException e)
    {
        std::cerr << e.what() << std::endl;
        return 1;
    }
}

85
int IRCServer::handleCommunication(const int fd) const
86
{
87 88
    string message = "";
    int ret = 0;
89 90
    TCPSocket client(fd);

91 92 93 94 95 96 97 98 99
    try
    {
        ret = client.Recv(message);
    }
    catch(SocketException e)
    {
        std::cerr << e.what() << std::endl;
        return 1;
    }
100

101
    if (ret < 0)
102
    {
103
        std::cerr << "Read Error: " << strerror(errno) << std::endl;
104 105
        return(1);
    }
106 107 108

    if(this->clients.socketExists(fd))
    { /* Nick is set, this is a message */
109 110
        if(message == "\0")
        { /* EOF, close the socket */
111
            this->boradcastQUIT(clients.getClient(client.getSockDesc()));
112
            this->clients.removeClient(client.getSockDesc());
113
            client.closeSocket();
114 115 116 117
            return -1;
        }
        else
        {
Andrew J. Dahl committed
118
	    this->broadcastMSG(message,clients.getClient(fd));
119 120
            std::cout << "Message: " << message << std::endl;
        }
121 122
    }
    else /* Socket Not In List... Nick Not Set */
123
    {
124 125 126
        if(this->nickValid(message.substr(0,8)))
        {
            this->clients.addClient(message.substr(0,8),fd);
127
            this->broadcastJOIN(Client(message.substr(0,8),fd));
128
            this->broadcastJOINAll(Client(message.substr(0,8),fd));
129 130 131 132 133
        }
        else
        {
            client << "Username already taken or is invalid.  Please try again.\n";
        }
134
    }
135
    
136 137 138 139 140 141 142
    return 0;
}

int IRCServer::getFD(const TCPSocket *sock) const
{
    return sock->getSockDesc();
}
143 144 145 146

bool IRCServer::nickValid(const string _nick) const
{
    return !(clients.clientExists(_nick));
147 148 149 150 151
}

void IRCServer::broadcastJOIN(const Client _client) const
{
    string message;
Andrew J. Dahl committed
152 153
    message = "JOIN:" + this->formHeader(_client);
    
154
    clients.broadcastExcept(this->purify(message), _client);
Andrew J. Dahl committed
155 156
}

157
void IRCServer::broadcastJOINAll(const Client _client) const
Andrew J. Dahl committed
158 159
{
    string message;
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
    for(int i=0; i<clients.getClientNum(); i++)
    {
        message = "JOIN:" + this->formHeader(clients.getClientAt(i));

        _client.getSocket().Send(this->purify(message));
    }
}

void IRCServer::boradcastQUIT(const Client _client) const
{
    string message;
    message = "QUIT:" + this->formHeader(_client);

    clients.broadcastExcept(this->purify(message), _client);
}

string IRCServer::formHeader(const Client _client) const
{
    char _port[6];
    sprintf(_port,"%d",_client.getSocket().getForeignPort());
    string message = _client.getUsername() + ":" + _client.getSocket().getForeignAddress() + ":" + _port;
Andrew J. Dahl committed
181 182 183 184 185 186

    return message;
}

void IRCServer::broadcastMSG(const string message, const Client _client) const
{
187
   string newMessage = this->formHeader(_client) + " > " + message;
Andrew J. Dahl committed
188

189
   this->broadcast(newMessage, _client);
Andrew J. Dahl committed
190 191 192 193
}

void IRCServer::broadcast(const string message, const Client _client) const
{
194
    clients.broadcastExcept(this->purify(message), _client);
Andrew J. Dahl committed
195 196
}

197 198 199 200 201 202 203 204 205 206 207 208 209 210
string IRCServer::purify(const string message) const
{
    string newMessage = "";
    for(unsigned int i = 0;i < message.length(); i++)
    {
        if(message[i] <= 126 && message[i] >= 32 && message[i] != '\n')
        {
            newMessage += message[i];
        }
    }

    return newMessage + '\n';

}