Esempio n. 1
0
int Drawboard::sendDrawdata(Client *client,std::vector<uint8_t> data, uint8_t chan)
{
  uint8_t tempdata[4];
  std::vector<uint8_t> drawdata;

  //ToDo: add compression

  //Type byte
  drawdata.push_back(ACTION_DRAW_DATA);
  
  //Msg len, allocate the space
  drawdata.insert(drawdata.end(),&tempdata[0],&tempdata[0]+2);

  //UID
  putUint16(&tempdata[0],client->UID);
  drawdata.insert(drawdata.end(),&tempdata[0],&tempdata[0]+2);

  //the data
  drawdata.insert(drawdata.end(),&data[0],&data[0]+data.size());

  //Fill in the length information
  putUint16(&drawdata[1], drawdata.size()-3);

  sendAll((uint8_t *)&drawdata[0],drawdata.size());

  return 1;
}
Esempio n. 2
0
bool Drawboard::sendUserlist(Client* client)
{
  uint8_t tempdata[2];
  std::vector<uint8_t> data;
  uint8_t users = 0;
  data.push_back(ACTION_USER_ADD);

  data.push_back(0); data.push_back(0); //Datalen

  data.push_back(0); //Add

  data.push_back(0); //Client number (fill at the end)

  for (std::vector<Client*>::iterator it = m_clients.begin(); it!=m_clients.end(); ++it)
  {
    if((*it)->UID > 0)
    {
      putUint16(&tempdata[0],(*it)->UID);
      data.insert(data.end(),&tempdata[0],&tempdata[0]+2);
      data.push_back((uint8_t)((*it)->nick).size());
      data.insert(data.end(),((*it)->nick).data(),((*it)->nick).data()+((*it)->nick).size());

      users++;
    }
  }

  data[4] = users;

  //Fill in the length information
  putUint16(&data[1], data.size()-3);

  send(client->getFd(), (uint8_t *)&data[0],data.size());

  return true;
}
Esempio n. 3
0
//Search for the cliend and remove
bool Drawboard::remClient(int m_fd)
{
  uint32_t UID = -1;
  std::string nick;
  for (std::vector<Client*>::iterator it = m_clients.begin(); it!=m_clients.end(); ++it)
  {
    if((*it)->getFd() == m_fd)
    {
      if((*it)->UID > 0)
      {
        UID = (*it)->UID;
        nick = (*it)->nick;
      }
      //Close client socket
      #ifdef WIN32
        closesocket(m_fd);
      #else
        close(m_fd);
      #endif
      
      delete *it;
      m_clients.erase(it);
      break;
    }
  }

  //ToDo: send info of removed client
  if(UID != -1)
  {
    uint8_t tempdata[2];
    std::vector<uint8_t> remdata;

    //Type byte
    remdata.push_back(ACTION_USER_REM);

    //Datalen
    putUint16(&tempdata[0],4);
    remdata.insert(remdata.end(),&tempdata[0],&tempdata[0]+2);

    remdata.push_back(1); //Rem

    remdata.push_back(1); //Number of users    

    //UID
    putUint16(&tempdata[0],UID);
    remdata.insert(remdata.end(),&tempdata[0],&tempdata[0]+2);

    sendAll((uint8_t *)&remdata[0],remdata.size());
  }

  std::cout << "Client removed" << std::endl;

  return true;
}
Esempio n. 4
0
int Drawboard::sendChat(Client *client,std::string data, uint8_t chan)
{
  uint8_t tempdata[4];
  std::vector<uint8_t> chatdata;

  //Type byte
  chatdata.push_back(ACTION_CHAT_DATA);
  
  //Msg len, allocate the space
  chatdata.insert(chatdata.end(),&tempdata[0],&tempdata[0]+2);

  //UID
  putUint16(&tempdata[0],client->UID);
  chatdata.insert(chatdata.end(),&tempdata[0],&tempdata[0]+2);

  //Nick size
  chatdata.push_back(client->nick.size());

  //Nick
  chatdata.insert(chatdata.end(),client->nick.data(),client->nick.data()+client->nick.size());

  //Channel ID
  chatdata.push_back(0);

  //Msg size
  chatdata.push_back(data.size());

  //Nick
  chatdata.insert(chatdata.end(),data.data(), data.data()+data.size());

  //Fill in the length information
  putUint16(&chatdata[1], chatdata.size()-3);

  sendAll((uint8_t *)&chatdata[0],chatdata.size());

  return 1;
}
Esempio n. 5
0
extern "C" void client_callback(int fd, short ev, void* arg)
{
  Client* client = reinterpret_cast<Client*>(arg);
  std::vector<uint8_t> outBuf;

  if (ev & EV_READ)
  {
    int read = 1;

    read = recv(fd, clientBuf, BUFSIZE, 0);
    #ifdef DEBUG
    std::cout << "Read from socket " << read << std::endl;
    #endif
    if (read == 0)
    {
      #ifdef DEBUG
      std::cout << "Socket closed properly" << std::endl;
      #endif
      Drawboard::get()->remClient(fd);
      
      return;
    }

    if (read == SOCKET_ERROR)
    {
      #ifdef DEBUG
      std::cout << "Socket had no data to read" << std::endl;
      #endif
      Drawboard::get()->remClient(fd);

      return;
    }

    //Store the time
    //client->lastData = time(NULL);
        
    client->buffer.insert(client->buffer.end(), clientBuf,clientBuf+read);
        
    //Handle the data
    while (client->buffer.size()>2)
    {
      //If user has not authenticated and tries to send other data
      if(client->buffer[0] != 0x05 && client->UID == -1)
      {
        #ifdef DEBUG
        std::cout << "First data was not auth, closing" << std::endl;
        #endif
        Drawboard::get()->remClient(fd);
        return;
      }
      int curpos = 1;
      switch(client->buffer[0])
      {
        //uncompressed draw data
        case ACTION_DRAW_DATA:
        case ACTION_COMPRESSED_DRAW_DATA:
          {
            //Datalen
            uint32_t len=getUint16((uint8_t *)(&client->buffer[0]+curpos));  curpos += 2;


            #ifdef DEBUG
            std::cout << "  Draw data " << len << std::endl;
            #endif
            //Wait for more data
            if( (client->buffer.size() - curpos) < len)
            {
              event_set(&client->m_event, fd, EV_READ, client_callback, client);
              event_add(&client->m_event, NULL);
              return;
            }

            std::vector<uint8_t> drawdata;
            drawdata.insert(drawdata.begin(),&client->buffer[0]+curpos, &client->buffer[0]+curpos+len);

            //If compressed, uncompress
            if(client->buffer[0] == ACTION_COMPRESSED_DRAW_DATA)
            {
              uint32_t read=2000;
              uint8_t *out=(uint8_t *)malloc(2000);

              //Uncompress the data, kick client if invalid
              if(uncompress((Bytef *)out, (uLongf *)&read, (Bytef *)&drawdata[0], drawdata.size())!=0)
              {
                free(out);
                Drawboard::get()->remClient(fd);
                return;
              }
              drawdata.clear();
              drawdata.insert(drawdata.begin(),out, out+read);
            }
            //Echo to others
            if(drawdata.size())
            {
              Drawboard::get()->sendDrawdata(client,drawdata,0);
            }

            client->eraseFromBuffer(curpos+len);
          }
          break;

          //compressed draw data
        case ACTION_PNG_REQUEST:
          {
            //Datalen
            uint32_t len=getUint16((uint8_t *)(&client->buffer[0]+curpos));  curpos += 2;

            #ifdef DEBUG
            std::cout << "  PNG request " << len << std::endl;
            #endif
            //Wait for more data
            if( (client->buffer.size() - curpos) < len)
            {
              event_set(&client->m_event, fd, EV_READ, client_callback, client);
              event_add(&client->m_event, NULL);
              return;
            }

            //Clear the data from buffer
            client->eraseFromBuffer(curpos+len);
          }
          break;
          
        //Chat data
        case ACTION_CHAT_DATA:
          {

            //Datalen
            uint32_t len=getUint16((uint8_t *)(&client->buffer[0]+curpos));  curpos += 2;

            #ifdef DEBUG
            std::cout << "  Got chat data with length " << len << std::endl;
            #endif
            //Wait for more data
            if( (client->buffer.size() - curpos) < len)
            {
              event_set(&client->m_event, fd, EV_READ, client_callback, client);
              event_add(&client->m_event, NULL);
              return;
            }

            //ToDo: maybe check the data, now we just echo everything
            uint8_t chan = client->buffer[curpos];    curpos++;
            uint8_t datalen=client->buffer[curpos];   curpos++;

            if(datalen)
            {
              std::string chatdata(&client->buffer[curpos], &client->buffer[curpos]+datalen);
            
              #ifdef DEBUG
              std::cout << "    Repeating chat data" << std::endl;
              #endif
              Drawboard::get()->sendChat(client, chatdata, chan);
            }

            //Clear the data from the buffer
            client->eraseFromBuffer(curpos+datalen);


          }
          break;
        //Authentication
        case ACTION_AUTH:
        {
          #ifdef DEBUG
            std::cout << "  Got auth " << std::endl;
          #endif
          int response = Drawboard::get()->authenticate(client);

          if(response == NEED_MORE_DATA)
          {
            #ifdef DEBUG
            std::cout << "    NEED_MORE_DATA" << std::endl;
            #endif
            event_set(&client->m_event, fd, EV_READ, client_callback, client);
            event_add(&client->m_event, NULL);          
            return;
          }
          else if(response == DATA_ERROR)
          {
            Drawboard::get()->remClient(fd);
            return;
          }

          //Send userlist to the new client

          //Generate uid for the user
          client->UID = Drawboard::get()->generateUID();

          {
            //Send others info about this client
            uint8_t tempdata[2];
            std::vector<uint8_t> data;

            //Type byte
            data.push_back(ACTION_USER_REM);

            //Datalen
            putUint16(&tempdata[0],5+client->nick.size());
            data.insert(data.end(),&tempdata[0],&tempdata[0]+2);

            data.push_back(0); //Add
            data.push_back(1); //Number of users    

            //UID
            putUint16(&tempdata[0],client->UID);
            data.insert(data.end(),&tempdata[0],&tempdata[0]+2);

            data.push_back((uint8_t)client->nick.size());
            data.insert(data.end(),(client->nick).data(),(client->nick).data()+(client->nick).size());

            Drawboard::get()->sendAll((uint8_t *)&data[0],data.size(), client->getFd());
          }
          //Send userlist to the new client
          Drawboard::get()->sendUserlist(client);
        }
        break;

        //If something else, remove the client
        default:
          Drawboard::get()->remClient(fd);
          return;
          break;
      }

      /*
      event_set(&client->m_event, fd, EV_READ, client_callback, client);
      event_add(&client->m_event, NULL);
      return;
      */
    } // while(user->buffer)
    
    if(outBuf.size())
    {
      if(Drawboard::get()->send(fd,(uint8_t *)outBuf.data(), outBuf.size()) == -1)
      {
        return;
      }
    }

  }
 
  event_set(&client->m_event, fd, EV_READ, client_callback, client);
  event_add(&client->m_event, NULL);
}