<commit_before>/*------------------------------------------------------------------------------

    Copyright (c) 2004 Media Development Loan Fund

    This file is part of the LiveSupport project.
    http://livesupport.campware.org/
    To report bugs, send an e-mail to bugs@campware.org

    LiveSupport 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.

    LiveSupport is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with LiveSupport; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    Author   : $Author$
    Version  : $Revision$
    Location : $URL$

------------------------------------------------------------------------------*/

/* ============================================================ include files */

#ifdef HAVE_CONFIG_H
#include "configure.h"
#endif

#include <iostream>

#include "LiveSupport/Widgets/WidgetFactory.h"
#include "LiveSupport/Widgets/Colors.h"
#include "LiveSupport/Widgets/Button.h"

#include "LiveSupport/Widgets/DialogWindow.h"

using namespace LiveSupport::Widgets;

/* ===================================================  local data structures */

/* ================================================  local constants & macros */

/* ===============================================  local function prototypes */

/* =============================================================  module code */

/*------------------------------------------------------------------------------
 *  Constructor.
 *----------------------------------------------------------------------------*/
DialogWindow :: DialogWindow (Ptr<Glib::ustring>::Ref   message,
                              int                       buttonTypes,
                              Ptr<ResourceBundle>::Ref  bundle)
                                                                    throw ()
          : WhiteWindow("",
                        Colors::White,
                        WidgetFactory::getInstance()->getWhiteWindowCorners(),
                        WhiteWindow::isModal),
            LocalizedObject(bundle)
{
    Ptr<WidgetFactory>::Ref  widgetFactory = WidgetFactory::getInstance();

    Gtk::Label *        messageLabel = Gtk::manage(new Gtk::Label(*message,
                                                          Gtk::ALIGN_CENTER,
                                                          Gtk::ALIGN_CENTER ));
    messageLabel->set_justify(Gtk::JUSTIFY_CENTER);

    Gtk::Box *          messageBox = Gtk::manage(new Gtk::HBox);
    messageBox->pack_start(*messageLabel, true, false, 10);

    Gtk::ButtonBox *    buttonBox = Gtk::manage(new Gtk::HButtonBox(
                                                        Gtk::BUTTONBOX_END, 5));

    int     buttonCount = 0;
    try {
        if (buttonTypes & cancelButton) {
            Button *    button = Gtk::manage(widgetFactory->createButton(
                                    *getResourceUstring("cancelButtonLabel") ));
            button->signal_clicked().connect(sigc::mem_fun(*this,
                                    &DialogWindow::onCancelButtonClicked));
            buttonBox->pack_start(*button);
            ++buttonCount;
        }

        if (buttonTypes & noButton) {
            Button *    button = Gtk::manage(widgetFactory->createButton(
                                    *getResourceUstring("noButtonLabel") ));
            button->signal_clicked().connect(sigc::mem_fun(*this,
                                    &DialogWindow::onNoButtonClicked));
            buttonBox->pack_start(*button);
            ++buttonCount;
        }

        if (buttonTypes & yesButton) {
            Button *    button = Gtk::manage(widgetFactory->createButton(
                                    *getResourceUstring("yesButtonLabel") ));
            button->signal_clicked().connect(sigc::mem_fun(*this,
                                    &DialogWindow::onYesButtonClicked));
            buttonBox->pack_start(*button);
            ++buttonCount;
        }

        if (buttonTypes & okButton) {
            Button *    button = Gtk::manage(widgetFactory->createButton(
                                    *getResourceUstring("okButtonLabel") ));
            button->signal_clicked().connect(sigc::mem_fun(*this,
                                    &DialogWindow::onOkButtonClicked));
            buttonBox->pack_start(*button);
            ++buttonCount;
        }
    } catch (std::invalid_argument &e) {
        std::cerr << e.what() << std::endl;
        std::exit(1);
    }

    Gtk::Box *  bottomBox = Gtk::manage(new Gtk::HBox);
    bottomBox->pack_start(*buttonBox, true, true, 10);

    Gtk::Box *  layout = Gtk::manage(new Gtk::VBox);
    layout->pack_start(*messageBox, true, false, 5);
    layout->pack_start(*bottomBox, false, false, 0);

    set_default_size(100*buttonCount + 50, 120);
    property_window_position().set_value(Gtk::WIN_POS_CENTER);

    add(*layout);
}

/*------------------------------------------------------------------------------
 *  Destructor.
 *----------------------------------------------------------------------------*/
DialogWindow :: ~DialogWindow (void)                                throw ()
{
}

/*------------------------------------------------------------------------------
 *  Event handler for the Cancel button clicked
 *----------------------------------------------------------------------------*/
void
DialogWindow :: onCancelButtonClicked(void)                         throw ()
{
    buttonClicked = cancelButton;
    hide();
}

/*------------------------------------------------------------------------------
 *  Event handler for the No button clicked.
 *----------------------------------------------------------------------------*/
void
DialogWindow :: onNoButtonClicked(void)                             throw ()
{
    buttonClicked = noButton;
    hide();
}

/*------------------------------------------------------------------------------
 *  Event handler for the Yes button clicked.
 *----------------------------------------------------------------------------*/
void
DialogWindow :: onYesButtonClicked(void)                            throw ()
{
    buttonClicked = yesButton;
    hide();
}

/*------------------------------------------------------------------------------
 *  Event handler for the OK button clicked.
 *----------------------------------------------------------------------------*/
void
DialogWindow :: onOkButtonClicked(void)                             throw ()
{
    buttonClicked = okButton;
    hide();
}

/*------------------------------------------------------------------------------
 *  Show the window and return the button clicked.
 *----------------------------------------------------------------------------*/
DialogWindow::ButtonType
DialogWindow :: run(void)                                           throw ()
{
    show_all();
    Gtk::Main::run(*this);
    return buttonClicked;
}

<commit_msg>fixing the last part of #1755 (do not show dialog windows in the task bar as "untitled window") -- except for nicer icon images, which is now #1774<commit_after>/*------------------------------------------------------------------------------

    Copyright (c) 2004 Media Development Loan Fund

    This file is part of the LiveSupport project.
    http://livesupport.campware.org/
    To report bugs, send an e-mail to bugs@campware.org

    LiveSupport 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.

    LiveSupport is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with LiveSupport; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    Author   : $Author$
    Version  : $Revision$
    Location : $URL$

------------------------------------------------------------------------------*/

/* ============================================================ include files */

#ifdef HAVE_CONFIG_H
#include "configure.h"
#endif

#include <iostream>

#include "LiveSupport/Widgets/WidgetFactory.h"
#include "LiveSupport/Widgets/Colors.h"
#include "LiveSupport/Widgets/Button.h"

#include "LiveSupport/Widgets/DialogWindow.h"

using namespace LiveSupport::Widgets;

/* ===================================================  local data structures */

/* ================================================  local constants & macros */

/* ===============================================  local function prototypes */

/* =============================================================  module code */

/*------------------------------------------------------------------------------
 *  Constructor.
 *----------------------------------------------------------------------------*/
DialogWindow :: DialogWindow (Ptr<Glib::ustring>::Ref   message,
                              int                       buttonTypes,
                              Ptr<ResourceBundle>::Ref  bundle)
                                                                    throw ()
          : WhiteWindow("",
                        Colors::White,
                        WidgetFactory::getInstance()->getWhiteWindowCorners(),
                        WhiteWindow::isModal),
            LocalizedObject(bundle)
{
    Ptr<WidgetFactory>::Ref  widgetFactory = WidgetFactory::getInstance();

    Gtk::Label *        messageLabel = Gtk::manage(new Gtk::Label(*message,
                                                          Gtk::ALIGN_CENTER,
                                                          Gtk::ALIGN_CENTER ));
    messageLabel->set_justify(Gtk::JUSTIFY_CENTER);

    Gtk::Box *          messageBox = Gtk::manage(new Gtk::HBox);
    messageBox->pack_start(*messageLabel, true, false, 10);

    Gtk::ButtonBox *    buttonBox = Gtk::manage(new Gtk::HButtonBox(
                                                        Gtk::BUTTONBOX_END, 5));

    int     buttonCount = 0;
    try {
        if (buttonTypes & cancelButton) {
            Button *    button = Gtk::manage(widgetFactory->createButton(
                                    *getResourceUstring("cancelButtonLabel") ));
            button->signal_clicked().connect(sigc::mem_fun(*this,
                                    &DialogWindow::onCancelButtonClicked));
            buttonBox->pack_start(*button);
            ++buttonCount;
        }

        if (buttonTypes & noButton) {
            Button *    button = Gtk::manage(widgetFactory->createButton(
                                    *getResourceUstring("noButtonLabel") ));
            button->signal_clicked().connect(sigc::mem_fun(*this,
                                    &DialogWindow::onNoButtonClicked));
            buttonBox->pack_start(*button);
            ++buttonCount;
        }

        if (buttonTypes & yesButton) {
            Button *    button = Gtk::manage(widgetFactory->createButton(
                                    *getResourceUstring("yesButtonLabel") ));
            button->signal_clicked().connect(sigc::mem_fun(*this,
                                    &DialogWindow::onYesButtonClicked));
            buttonBox->pack_start(*button);
            ++buttonCount;
        }

        if (buttonTypes & okButton) {
            Button *    button = Gtk::manage(widgetFactory->createButton(
                                    *getResourceUstring("okButtonLabel") ));
            button->signal_clicked().connect(sigc::mem_fun(*this,
                                    &DialogWindow::onOkButtonClicked));
            buttonBox->pack_start(*button);
            ++buttonCount;
        }
    } catch (std::invalid_argument &e) {
        std::cerr << e.what() << std::endl;
        std::exit(1);
    }

    Gtk::Box *  bottomBox = Gtk::manage(new Gtk::HBox);
    bottomBox->pack_start(*buttonBox, true, true, 10);

    Gtk::Box *  layout = Gtk::manage(new Gtk::VBox);
    layout->pack_start(*messageBox, true, false, 5);
    layout->pack_start(*bottomBox, false, false, 0);

    set_default_size(100*buttonCount + 50, 120);
    property_window_position().set_value(Gtk::WIN_POS_CENTER);
    set_skip_taskbar_hint(true);    // do not show in the task bar

    add(*layout);
}

/*------------------------------------------------------------------------------
 *  Destructor.
 *----------------------------------------------------------------------------*/
DialogWindow :: ~DialogWindow (void)                                throw ()
{
}

/*------------------------------------------------------------------------------
 *  Event handler for the Cancel button clicked
 *----------------------------------------------------------------------------*/
void
DialogWindow :: onCancelButtonClicked(void)                         throw ()
{
    buttonClicked = cancelButton;
    hide();
}

/*------------------------------------------------------------------------------
 *  Event handler for the No button clicked.
 *----------------------------------------------------------------------------*/
void
DialogWindow :: onNoButtonClicked(void)                             throw ()
{
    buttonClicked = noButton;
    hide();
}

/*------------------------------------------------------------------------------
 *  Event handler for the Yes button clicked.
 *----------------------------------------------------------------------------*/
void
DialogWindow :: onYesButtonClicked(void)                            throw ()
{
    buttonClicked = yesButton;
    hide();
}

/*------------------------------------------------------------------------------
 *  Event handler for the OK button clicked.
 *----------------------------------------------------------------------------*/
void
DialogWindow :: onOkButtonClicked(void)                             throw ()
{
    buttonClicked = okButton;
    hide();
}

/*------------------------------------------------------------------------------
 *  Show the window and return the button clicked.
 *----------------------------------------------------------------------------*/
DialogWindow::ButtonType
DialogWindow :: run(void)                                           throw ()
{
    show_all();
    Gtk::Main::run(*this);
    return buttonClicked;
}

<|endoftext|>


<commit_before>/*
* TLS echo server using BSD sockets
* (C) 2014 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include "apps.h"

#if defined(BOTAN_HAS_TLS) \
  && defined(BOTAN_HAS_DSA) \
  && !defined(BOTAN_TARGET_OS_IS_WINDOWS)

#include <botan/tls_server.h>
#include <botan/hex.h>

#include <botan/rsa.h>
#include <botan/dsa.h>
#include <botan/x509self.h>
#include <botan/secqueue.h>

#include "credentials.h"

using namespace Botan;

using namespace std::placeholders;

#include <list>

#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>

#if !defined(MSG_NOSIGNAL)
  #define MSG_NOSIGNAL 0
#endif

namespace {

int make_server_socket(bool is_tcp, u16bit port)
   {
   const int type = is_tcp ? SOCK_STREAM : SOCK_DGRAM;

   int fd = ::socket(PF_INET, type, 0);
   if(fd == -1)
      throw std::runtime_error("Unable to acquire socket");

   sockaddr_in socket_info;
   ::memset(&socket_info, 0, sizeof(socket_info));
   socket_info.sin_family = AF_INET;
   socket_info.sin_port = htons(port);

   // FIXME: support limiting listeners
   socket_info.sin_addr.s_addr = INADDR_ANY;

   if(::bind(fd, (sockaddr*)&socket_info, sizeof(struct sockaddr)) != 0)
      {
      ::close(fd);
      throw std::runtime_error("server bind failed");
      }

   if(is_tcp)
      {
      if(::listen(fd, 100) != 0)
         {
         ::close(fd);
         throw std::runtime_error("listen failed");
         }
      }

   return fd;
   }

bool handshake_complete(const TLS::Session& session)
   {
   std::cout << "Handshake complete, " << session.version().to_string()
             << " using " << session.ciphersuite().to_string() << std::endl;

   if(!session.session_id().empty())
      std::cout << "Session ID " << hex_encode(session.session_id()) << std::endl;

   if(!session.session_ticket().empty())
      std::cout << "Session ticket " << hex_encode(session.session_ticket()) << std::endl;

   return true;
   }

void dgram_socket_write(int sockfd, const byte buf[], size_t length)
   {
   ssize_t sent = ::send(sockfd, buf, length, MSG_NOSIGNAL);

   if(sent == -1)
      std::cout << "Error writing to socket - " << strerror(errno) << std::endl;
   else if(sent != static_cast<ssize_t>(length))
      std::cout << "Packet of length " << length << " truncated to " << sent << std::endl;
   }

void stream_socket_write(int sockfd, const byte buf[], size_t length)
   {
   while(length)
      {
      ssize_t sent = ::send(sockfd, buf, length, MSG_NOSIGNAL);

      if(sent == -1)
         {
         if(errno == EINTR)
            sent = 0;
         else
            throw std::runtime_error("Socket write failed");
         }

      buf += sent;
      length -= sent;
      }
   }

void alert_received(TLS::Alert alert, const byte[], size_t)
   {
   std::cout << "Alert: " << alert.type_string() << std::endl;
   }

int tls_server(int argc, char* argv[])
   {
   if(argc != 4 && argc != 5)
      {
      std::cout << "Usage: " << argv[0] << " server.crt server.key port [tcp|udp]" << std::endl;
      return 1;
      }

   const std::string server_crt = argv[1];
   const std::string server_key = argv[2];
   const int port = to_u32bit(argv[3]);
   const std::string transport = (argc >= 5) ? argv[4] : "tcp";

   const bool is_tcp = (transport == "tcp");

   try
      {
      AutoSeeded_RNG rng;

      TLS::Policy policy;

      TLS::Session_Manager_In_Memory session_manager(rng);

      Basic_Credentials_Manager creds(rng, server_crt, server_key);

      auto protocol_chooser = [](const std::vector<std::string>& protocols) -> std::string {
         for(size_t i = 0; i != protocols.size(); ++i)
            std::cout << "Client offered protocol " << i << " = " << protocols[i] << std::endl;
         return "echo/1.0"; // too bad
      };

      std::cout << "Listening for new connections on " << transport << " port " << port << std::endl;

      int server_fd = make_server_socket(is_tcp, port);

      while(true)
         {
         try
            {
            int fd;

            if(is_tcp)
               fd = ::accept(server_fd, nullptr, nullptr);
            else
               {
               struct sockaddr_in from;
               socklen_t from_len = sizeof(sockaddr_in);

               if(::recvfrom(server_fd, nullptr, 0, MSG_PEEK,
                             (struct sockaddr*)&from, &from_len) != 0)
                  throw std::runtime_error("Could not peek next packet");

               if(::connect(server_fd, (struct sockaddr*)&from, from_len) != 0)
                  throw std::runtime_error("Could not connect UDP socket");

               fd = server_fd;
               }

            std::cout << "New connection received" << std::endl;

            auto socket_write = is_tcp ? std::bind(stream_socket_write, fd, _1, _2) :
                                         std::bind(dgram_socket_write, fd, _1, _2);

            std::string s;
            std::list<std::string> pending_output;

            auto proc_fn = [&](const byte input[], size_t input_len)
               {
               for(size_t i = 0; i != input_len; ++i)
                  {
                  const char c = static_cast<char>(input[i]);
                  s += c;
                  if(c == '\n')
                     {
                     pending_output.push_back(s);
                     s.clear();
                     }
                  }
               };

            TLS::Server server(socket_write,
                               proc_fn,
                               alert_received,
                               handshake_complete,
                               session_manager,
                               creds,
                               policy,
                               rng,
                               protocol_chooser,
                               !is_tcp);

            while(!server.is_closed())
               {
               byte buf[4*1024] = { 0 };
               ssize_t got = ::read(fd, buf, sizeof(buf));

               if(got == -1)
                  {
                  std::cout << "Error in socket read - " << strerror(errno) << std::endl;
                  break;
                  }

               if(got == 0)
                  {
                  std::cout << "EOF on socket" << std::endl;
                  break;
                  }

               server.received_data(buf, got);

               while(server.is_active() && !pending_output.empty())
                  {
                  std::string s = pending_output.front();
                  pending_output.pop_front();
                  server.send(s);

                  if(s == "quit\n")
                     server.close();
                  }
               }

            if(is_tcp)
               ::close(fd);

            }
         catch(std::exception& e)
            {
            std::cout << "Connection problem: " << e.what() << std::endl;
            return 1;
            }
         }
   }
   catch(std::exception& e)
      {
      std::cout << e.what() << std::endl;
      return 1;
      }

   return 0;
   }

REGISTER_APP(tls_server);

}

#endif
<commit_msg>Avoid building tls_server on MinGW. GH #39<commit_after>/*
* TLS echo server using BSD sockets
* (C) 2014 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include "apps.h"

#if defined(BOTAN_HAS_TLS) && defined(BOTAN_HAS_DSA) \
  && !defined(BOTAN_TARGET_OS_IS_WINDOWS) \
  && !defined(BOTAN_TARGET_OS_IS_MINGW)

#include <botan/tls_server.h>
#include <botan/hex.h>

#include <botan/rsa.h>
#include <botan/dsa.h>
#include <botan/x509self.h>
#include <botan/secqueue.h>

#include "credentials.h"

using namespace Botan;

using namespace std::placeholders;

#include <list>

#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>

#if !defined(MSG_NOSIGNAL)
  #define MSG_NOSIGNAL 0
#endif

namespace {

int make_server_socket(bool is_tcp, u16bit port)
   {
   const int type = is_tcp ? SOCK_STREAM : SOCK_DGRAM;

   int fd = ::socket(PF_INET, type, 0);
   if(fd == -1)
      throw std::runtime_error("Unable to acquire socket");

   sockaddr_in socket_info;
   ::memset(&socket_info, 0, sizeof(socket_info));
   socket_info.sin_family = AF_INET;
   socket_info.sin_port = htons(port);

   // FIXME: support limiting listeners
   socket_info.sin_addr.s_addr = INADDR_ANY;

   if(::bind(fd, (sockaddr*)&socket_info, sizeof(struct sockaddr)) != 0)
      {
      ::close(fd);
      throw std::runtime_error("server bind failed");
      }

   if(is_tcp)
      {
      if(::listen(fd, 100) != 0)
         {
         ::close(fd);
         throw std::runtime_error("listen failed");
         }
      }

   return fd;
   }

bool handshake_complete(const TLS::Session& session)
   {
   std::cout << "Handshake complete, " << session.version().to_string()
             << " using " << session.ciphersuite().to_string() << std::endl;

   if(!session.session_id().empty())
      std::cout << "Session ID " << hex_encode(session.session_id()) << std::endl;

   if(!session.session_ticket().empty())
      std::cout << "Session ticket " << hex_encode(session.session_ticket()) << std::endl;

   return true;
   }

void dgram_socket_write(int sockfd, const byte buf[], size_t length)
   {
   ssize_t sent = ::send(sockfd, buf, length, MSG_NOSIGNAL);

   if(sent == -1)
      std::cout << "Error writing to socket - " << strerror(errno) << std::endl;
   else if(sent != static_cast<ssize_t>(length))
      std::cout << "Packet of length " << length << " truncated to " << sent << std::endl;
   }

void stream_socket_write(int sockfd, const byte buf[], size_t length)
   {
   while(length)
      {
      ssize_t sent = ::send(sockfd, buf, length, MSG_NOSIGNAL);

      if(sent == -1)
         {
         if(errno == EINTR)
            sent = 0;
         else
            throw std::runtime_error("Socket write failed");
         }

      buf += sent;
      length -= sent;
      }
   }

void alert_received(TLS::Alert alert, const byte[], size_t)
   {
   std::cout << "Alert: " << alert.type_string() << std::endl;
   }

int tls_server(int argc, char* argv[])
   {
   if(argc != 4 && argc != 5)
      {
      std::cout << "Usage: " << argv[0] << " server.crt server.key port [tcp|udp]" << std::endl;
      return 1;
      }

   const std::string server_crt = argv[1];
   const std::string server_key = argv[2];
   const int port = to_u32bit(argv[3]);
   const std::string transport = (argc >= 5) ? argv[4] : "tcp";

   const bool is_tcp = (transport == "tcp");

   try
      {
      AutoSeeded_RNG rng;

      TLS::Policy policy;

      TLS::Session_Manager_In_Memory session_manager(rng);

      Basic_Credentials_Manager creds(rng, server_crt, server_key);

      auto protocol_chooser = [](const std::vector<std::string>& protocols) -> std::string {
         for(size_t i = 0; i != protocols.size(); ++i)
            std::cout << "Client offered protocol " << i << " = " << protocols[i] << std::endl;
         return "echo/1.0"; // too bad
      };

      std::cout << "Listening for new connections on " << transport << " port " << port << std::endl;

      int server_fd = make_server_socket(is_tcp, port);

      while(true)
         {
         try
            {
            int fd;

            if(is_tcp)
               fd = ::accept(server_fd, nullptr, nullptr);
            else
               {
               struct sockaddr_in from;
               socklen_t from_len = sizeof(sockaddr_in);

               if(::recvfrom(server_fd, nullptr, 0, MSG_PEEK,
                             (struct sockaddr*)&from, &from_len) != 0)
                  throw std::runtime_error("Could not peek next packet");

               if(::connect(server_fd, (struct sockaddr*)&from, from_len) != 0)
                  throw std::runtime_error("Could not connect UDP socket");

               fd = server_fd;
               }

            std::cout << "New connection received" << std::endl;

            auto socket_write = is_tcp ? std::bind(stream_socket_write, fd, _1, _2) :
                                         std::bind(dgram_socket_write, fd, _1, _2);

            std::string s;
            std::list<std::string> pending_output;

            auto proc_fn = [&](const byte input[], size_t input_len)
               {
               for(size_t i = 0; i != input_len; ++i)
                  {
                  const char c = static_cast<char>(input[i]);
                  s += c;
                  if(c == '\n')
                     {
                     pending_output.push_back(s);
                     s.clear();
                     }
                  }
               };

            TLS::Server server(socket_write,
                               proc_fn,
                               alert_received,
                               handshake_complete,
                               session_manager,
                               creds,
                               policy,
                               rng,
                               protocol_chooser,
                               !is_tcp);

            while(!server.is_closed())
               {
               byte buf[4*1024] = { 0 };
               ssize_t got = ::read(fd, buf, sizeof(buf));

               if(got == -1)
                  {
                  std::cout << "Error in socket read - " << strerror(errno) << std::endl;
                  break;
                  }

               if(got == 0)
                  {
                  std::cout << "EOF on socket" << std::endl;
                  break;
                  }

               server.received_data(buf, got);

               while(server.is_active() && !pending_output.empty())
                  {
                  std::string s = pending_output.front();
                  pending_output.pop_front();
                  server.send(s);

                  if(s == "quit\n")
                     server.close();
                  }
               }

            if(is_tcp)
               ::close(fd);

            }
         catch(std::exception& e)
            {
            std::cout << "Connection problem: " << e.what() << std::endl;
            return 1;
            }
         }
   }
   catch(std::exception& e)
      {
      std::cout << e.what() << std::endl;
      return 1;
      }

   return 0;
   }

REGISTER_APP(tls_server);

}

#endif
<|endoftext|>


<commit_before>//=====================================================================//
/*!	@file
	@brief	R8C MAX7219 メイン @n
			P1_0: DIN @n
			P1_1: /CS @n
			P1_2: CLK
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2017 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/R8C/blob/master/LICENSE
*/
//=====================================================================//
#include <cstring>
#include "common/vect.h"
#include "system.hpp"
#include "clock.hpp"
#include "port.hpp"
#include "intr.hpp"
#include "common/intr_utils.hpp"
#include "common/delay.hpp"
#include "common/port_map.hpp"
#include "common/fifo.hpp"
#include "common/uart_io.hpp"
#include "common/format.hpp"
#include "common/trb_io.hpp"
#include "common/spi_io.hpp"
#include "chip/MAX7219.hpp"

namespace {

	device::trb_io<utils::null_task, uint8_t> timer_b_;

	typedef utils::fifo<uint8_t, 16> buffer;
	typedef device::uart_io<device::UART0, buffer, buffer> uart;
	uart uart_;

	typedef device::PORT<device::PORT1, device::bitpos::B0> SPI_SDA;
	typedef device::PORT<device::PORT1, device::bitpos::B2> SPI_SCL;

	typedef device::spi_io<SPI_SCL, SPI_SDA, device::NULL_PORT> SPI;
	SPI spi_;

	typedef device::PORT<device::PORT1, device::bitpos::B1> SELECT;
	chip::MAX7219<SPI, SELECT> max7219_(spi_);
}

extern "C" {

	void sci_putch(char ch) {
		uart_.putch(ch);
	}

	char sci_getch(void) {
		return uart_.getch();
	}

	uint16_t sci_length() {
		return uart_.length();
	}

	void sci_puts(const char* str) {
		uart_.puts(str);
	}

	void TIMER_RB_intr(void) {
		timer_b_.itask();
	}

	void UART0_TX_intr(void) {
		uart_.isend();
	}

	void UART0_RX_intr(void) {
		uart_.irecv();
	}

}

//  __attribute__ ((section (".exttext")))
int main(int argc, char *argv[])
{
	using namespace device;

// クロック関係レジスタ・プロテクト解除
	PRCR.PRC0 = 1;

// 高速オンチップオシレーターへ切り替え(20MHz)
// ※ F_CLK を設定する事（Makefile内）
	OCOCR.HOCOE = 1;
	utils::delay::micro_second(1);  // >=30us(125KHz)
	SCKCR.HSCKSEL = 1;
	CKSTPR.SCKSEL = 1;

	// タイマーＢ初期化
	{
		uint8_t ir_level = 2;
		timer_b_.start_timer(60, ir_level);
	}

	// UART の設定 (P1_4: TXD0[out], P1_5: RXD0[in])
	// ※シリアルライターでは、RXD 端子は、P1_6 となっているので注意！
	{
		utils::PORT_MAP(utils::port_map::P14::TXD0);
		utils::PORT_MAP(utils::port_map::P15::RXD0);
		uint8_t ir_level = 1;
		uart_.start(57600, ir_level);
	}

	// SPI を開始
	{
		spi_.start(10);
	}

	// MAX7219 を開始
	{
		max7219_.start();
	}

	sci_puts("Start R8C MAX7219 sample\n");

	// LED シグナル用ポートを出力
	PD1.B0 = 1;

	for(uint8_t i = 0; i < 8; ++i) {
		max7219_.set_cha(i, '-');
	}

	uint8_t idx = 0;
	while(1) {
		timer_b_.sync();
		max7219_.service();
		max7219_.set_intensity(0);

		if(sci_length()) {
			if(idx > 7) {
				max7219_.shift_top();
				idx = 7;
			}
			char ch = sci_getch();
			sci_putch(ch);
			max7219_.set_cha(idx ^ 7, ch);
			++idx;
		}
	}
}
<commit_msg>update: spi_io typedef<commit_after>//=====================================================================//
/*!	@file
	@brief	R8C MAX7219 メイン @n
			P1_0: DIN @n
			P1_1: /CS @n
			P1_2: CLK
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2017 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/R8C/blob/master/LICENSE
*/
//=====================================================================//
#include <cstdint>
#include "common/vect.h"
#include "system.hpp"
#include "clock.hpp"
#include "port.hpp"
#include "intr.hpp"
#include "common/intr_utils.hpp"
#include "common/delay.hpp"
#include "common/port_map.hpp"
#include "common/fifo.hpp"
#include "common/uart_io.hpp"
#include "common/format.hpp"
#include "common/trb_io.hpp"
#include "common/spi_io.hpp"
#include "chip/MAX7219.hpp"

namespace {

	device::trb_io<utils::null_task, uint8_t> timer_b_;

	typedef utils::fifo<uint8_t, 16> buffer;
	typedef device::uart_io<device::UART0, buffer, buffer> uart;
	uart uart_;

	typedef device::PORT<device::PORT1, device::bitpos::B0> SPI_SDA;
	typedef device::PORT<device::PORT1, device::bitpos::B2> SPI_SCL;

	typedef device::spi_io<device::NULL_PORT, SPI_SDA, SPI_SCL, device::soft_spi_mode::CK10> SPI;
	SPI spi_;

	typedef device::PORT<device::PORT1, device::bitpos::B1> SELECT;
	chip::MAX7219<SPI, SELECT> max7219_(spi_);
}

extern "C" {

	void sci_putch(char ch) {
		uart_.putch(ch);
	}

	char sci_getch(void) {
		return uart_.getch();
	}

	uint16_t sci_length() {
		return uart_.length();
	}

	void sci_puts(const char* str) {
		uart_.puts(str);
	}

	void TIMER_RB_intr(void) {
		timer_b_.itask();
	}

	void UART0_TX_intr(void) {
		uart_.isend();
	}

	void UART0_RX_intr(void) {
		uart_.irecv();
	}

}

//  __attribute__ ((section (".exttext")))
int main(int argc, char *argv[])
{
	using namespace device;

// クロック関係レジスタ・プロテクト解除
	PRCR.PRC0 = 1;

// 高速オンチップオシレーターへ切り替え(20MHz)
// ※ F_CLK を設定する事（Makefile内）
	OCOCR.HOCOE = 1;
	utils::delay::micro_second(1);  // >=30us(125KHz)
	SCKCR.HSCKSEL = 1;
	CKSTPR.SCKSEL = 1;

	// タイマーＢ初期化
	{
		uint8_t ir_level = 2;
		timer_b_.start_timer(60, ir_level);
	}

	// UART の設定 (P1_4: TXD0[out], P1_5: RXD0[in])
	// ※シリアルライターでは、RXD 端子は、P1_6 となっているので注意！
	{
		utils::PORT_MAP(utils::port_map::P14::TXD0);
		utils::PORT_MAP(utils::port_map::P15::RXD0);
		uint8_t ir_level = 1;
		uart_.start(57600, ir_level);
	}

	// SPI を開始
	{
		spi_.start(10);
	}

	// MAX7219 を開始
	{
		max7219_.start();
	}

	sci_puts("Start R8C MAX7219 sample\n");

	// LED シグナル用ポートを出力
	PD1.B0 = 1;

	for(uint8_t i = 0; i < 8; ++i) {
		max7219_.set_cha(i, '-');
	}

	uint8_t idx = 0;
	while(1) {
		timer_b_.sync();
		max7219_.service();
		max7219_.set_intensity(0);

		if(sci_length()) {
			if(idx > 7) {
				max7219_.shift_top();
				idx = 7;
			}
			char ch = sci_getch();
			sci_putch(ch);
			max7219_.set_cha(idx ^ 7, ch);
			++idx;
		}
	}
}
<|endoftext|>


<commit_before>#include "cpu_generic.h"

//////////////////////////////////////////////////////////////////////
// GENERIC: register access
//////////////////////////////////////////////////////////////////////

static Value **
ptr_r(cpu_t *cpu)
{
	switch (cpu->reg_size) {
		case 8:
			return cpu->ptr_r8;
		case 16:
			return cpu->ptr_r16;
		case 32:
			return cpu->ptr_r32;
		case 64:
			return cpu->ptr_r64;
		default:
			return 0; /* can't happen */
	}
}

static Value **
ptr_f(cpu_t *cpu)
{
	switch (cpu->fp_reg_size) {
		case 32:
			return cpu->ptr_f32;
		case 64:
			return cpu->ptr_f64;
		case 80:
			return cpu->ptr_f80;
		case 128:
			return cpu->ptr_f128;
		default:
			return 0; /* can't happen */
	}
}

// GET REGISTER
Value *
arch_get_reg(cpu_t *cpu, uint32_t index, uint32_t bits, BasicBlock *bb) {
	Value *v;

	/* R0 is always 0 (on certain RISCs) */
	if (cpu->has_special_r0 && !index)
		return CONSTs(bits? bits : cpu->reg_size, 0);

	/* get the register */
	v = new LoadInst(ptr_r(cpu)[index], "", false, bb);

	/* optionally truncate it */
	if (bits && cpu->reg_size != bits)
		v = TRUNC(bits, v);

	return v;
}

Value *
arch_get_fp_reg(cpu_t *cpu, uint32_t index, uint32_t bits, BasicBlock *bb) {
	Value *v;

	/* get the register */
	return new LoadInst(ptr_f(cpu)[index], "", false, bb);
}

// PUT REGISTER
void
arch_put_reg(cpu_t *cpu, uint32_t index, Value *v, uint32_t bits, bool sext, BasicBlock *bb) {
	/*
	 * if the caller cares about bit size and
	 * the size is not the register size, we'll zext or sext
	 */
	if (bits && cpu->reg_size != bits)
		if (sext)
			v = SEXT(cpu->reg_size, v);
		else
			v = ZEXT(cpu->reg_size, v);

	/* store value, unless it's R0 (on certain RISCs) */
	if (!cpu->has_special_r0 || index)
		new StoreInst(v, ptr_r(cpu)[index], bb);
}

void
arch_put_fp_reg(cpu_t *cpu, uint32_t index, Value *v, uint32_t bits, BasicBlock *bb) {
	/* store value, unless it's R0 (on certain RISCs) */
	if (!cpu->has_special_fr0 || index)
		new StoreInst(v, ptr_f(cpu)[index], bb);
}

//XXX TODO
// The guest CPU can be little endian or big endian, so we need both
// host mode access routines as well as IR generators that deal with
// both modes. In practice, we need two sets of functions, one that
// deals with host native endianness, and one that deals with the other
// endianness; and interface functions that dispatch calls to endianness
// functions depending on the host endianness.
// i.e. there should be RAM32NE() which reads a 32 bit address from RAM,
// using the "Native Endianness" of the host, and RAM32SW() which does
// a swapped read. RAM32BE() and RAM32LE() should choose either of
// RAM32NE() and RAM32SW() depending on the endianness of the host.
//
// Swapped endianness can be implemented in different ways: by swapping
// every non-byte memory read and write, or by keeping aligned words
// in the host's native endianness, not swapping aligned reads and
// writes, and correcting unaligned accesses. (This makes more sense
// on guest CPUs that only allow aligned memory access.)
// The client should be able to specify a specific strategy, but each
// CPU frontend should default to the typically best strategy. Functions
// like RAM32SW() will have to respect the setting, so that all memory
// access is consistent with the strategy.

//////////////////////////////////////////////////////////////////////
// GENERIC: host memory access
//////////////////////////////////////////////////////////////////////
uint32_t
RAM32BE(uint8_t *RAM, addr_t a) {
	uint32_t v;
	v  = RAM[a+0] << 24;
	v |= RAM[a+1] << 16;
	v |= RAM[a+2] << 8;
	v |= RAM[a+3] << 0;
	return v;
}

//////////////////////////////////////////////////////////////////////
// GENERIC: memory access
//////////////////////////////////////////////////////////////////////

/* get a RAM pointer to a 32 bit value */
static Value *
arch_gep32(cpu_t *cpu, Value *a, BasicBlock *bb) {
	a = GetElementPtrInst::Create(cpu->ptr_RAM, a, "", bb);
	return new BitCastInst(a, PointerType::get(getType(Int32Ty), 0), "", bb);
}

/* load 32 bit ALIGNED value from RAM */
Value *
arch_load32_aligned(cpu_t *cpu, Value *a, BasicBlock *bb) {
	a = arch_gep32(cpu, a, bb);
#ifdef __LITTLE_ENDIAN__
	bool swap = !cpu->is_little_endian;
#else
	bool swap = cpu->is_little_endian;
#endif
	if(swap)
		return SWAP32(new LoadInst(a, "", false, bb));
	else
		return new LoadInst(a, "", false, bb);
}

/* store 32 bit ALIGNED value to RAM */
void
arch_store32_aligned(cpu_t *cpu, Value *v, Value *a, BasicBlock *bb) {
	a = arch_gep32(cpu, a, bb);
#ifdef __LITTLE_ENDIAN__
	bool swap = !cpu->is_little_endian;
#else
	bool swap = cpu->is_little_endian;
#endif
	new StoreInst(swap ? SWAP32(v) : v, a, bb);
}

//////////////////////////////////////////////////////////////////////
// GENERIC: endianness
//////////////////////////////////////////////////////////////////////

static Value *
arch_get_shift8(cpu_t *cpu, Value *addr, BasicBlock *bb)
{
	Value *shift = AND(addr,CONST(3));
	if (!cpu->is_little_endian)
		shift = XOR(shift, CONST(3));
	return SHL(CONST(3), shift);
}

static Value *
arch_get_shift16(cpu_t *cpu, Value *addr, BasicBlock *bb)
{
	Value *shift = AND(addr,CONST(1));
	if (!cpu->is_little_endian)
		shift = XOR(shift, CONST(1));
	return SHL(CONST(4), shift);
}

Value *
arch_load8(cpu_t *cpu, Value *addr, BasicBlock *bb) {
	Value *shift = arch_get_shift8(cpu, addr, bb);
	Value *val = arch_load32_aligned(cpu, AND(addr, CONST(~3ULL)), bb);
	return TRUNC8(LSHR(val, shift));
}

Value *
arch_load16_aligned(cpu_t *cpu, Value *addr, BasicBlock *bb) {
	Value *shift = arch_get_shift16(cpu, addr, bb);
	Value *val = arch_load32_aligned(cpu, AND(addr, CONST(~3ULL)), bb);
	return TRUNC16(LSHR(val, shift));
}

void
arch_store8(cpu_t *cpu, Value *val, Value *addr, BasicBlock *bb) {
	Value *shift = arch_get_shift8(cpu, addr, bb);
	addr = AND(addr, CONST(~3ULL));
	Value *mask = XOR(SHL(CONST(255), shift),CONST(-1ULL));
	Value *old = AND(arch_load32_aligned(cpu, addr, bb), mask);
	val = OR(old, SHL(AND(val, CONST(255)), shift));
	arch_store32_aligned(cpu, val, addr, bb);
}

void
arch_store16(cpu_t *cpu, Value *val, Value *addr, BasicBlock *bb) {
	Value *shift = arch_get_shift16(cpu, addr, bb);
	addr = AND(addr, CONST(~3ULL));
	Value *mask = XOR(SHL(CONST(65535), shift),CONST(-1ULL));
	Value *old = AND(arch_load32_aligned(cpu, addr, bb), mask);
	val = OR(old, SHL(AND(val, CONST(65535)), shift));
	arch_store32_aligned(cpu, val, addr, bb);
}

//////////////////////////////////////////////////////////////////////

Value *
arch_bswap(cpu_t *cpu, size_t width, Value *v, BasicBlock *bb) {
	Type const *ty = getIntegerType(width);
	return CallInst::Create(Intrinsic::getDeclaration(cpu->mod, Intrinsic::bswap, &ty, 1), v, "", bb);
}

Value *
arch_ctlz(cpu_t *cpu, size_t width, Value *v, BasicBlock *bb) {
	Type const *ty = getIntegerType(width);
	return CallInst::Create(Intrinsic::getDeclaration(cpu->mod, Intrinsic::ctlz, &ty, 1), v, "", bb);
}

Value *
arch_cttz(cpu_t *cpu, size_t width, Value *v, BasicBlock *bb) {
	Type const *ty = getIntegerType(width);
	return CallInst::Create(Intrinsic::getDeclaration(cpu->mod, Intrinsic::cttz, &ty, 1), v, "", bb);
}

// branches

void
arch_branch(bool flag_state, BasicBlock *target1, BasicBlock *target2, Value *v, BasicBlock *bb) {
	if (flag_state)
		BranchInst::Create(target1, target2, v, bb);
	else
		BranchInst::Create(target2, target1, v, bb);
}

void
arch_jump(BasicBlock *bb, BasicBlock *bb_target) {
	if (!bb_target) {
		printf("error: unknown jump target!\n");
		exit(1);
	}
	BranchInst::Create(bb_target, bb);
}

// decoding and encoding of bits in a bitfield (e.g. flags)

Value *
arch_encode_bit(Value *flags, Value *bit, int shift, int width, BasicBlock *bb)
{
	Value *n = new LoadInst(bit, "", false, bb);
	bit = new ZExtInst(n, getIntegerType(width), "", bb);
	bit = BinaryOperator::Create(Instruction::Shl, bit, ConstantInt::get(getIntegerType(width), shift), "", bb);
	return BinaryOperator::Create(Instruction::Or, flags, bit, "", bb);
}

void
arch_decode_bit(Value *flags, Value *bit, int shift, int width, BasicBlock *bb)
{
	Value *n = BinaryOperator::Create(Instruction::LShr, flags, ConstantInt::get(getIntegerType(width), shift), "", bb);
	n = new TruncInst(n, getIntegerType(1), "", bb);
	new StoreInst(n, bit, bb);
}

// FP

Value *
arch_sqrt(cpu_t *cpu, size_t width, Value *v, BasicBlock *bb) {
	Type const *ty = getFloatType(width);
	return CallInst::Create(Intrinsic::getDeclaration(cpu->mod, Intrinsic::sqrt, &ty, 1), v, "", bb);
}
<commit_msg>fix shifts.<commit_after>#include "cpu_generic.h"

//////////////////////////////////////////////////////////////////////
// GENERIC: register access
//////////////////////////////////////////////////////////////////////

static Value **
ptr_r(cpu_t *cpu)
{
	switch (cpu->reg_size) {
		case 8:
			return cpu->ptr_r8;
		case 16:
			return cpu->ptr_r16;
		case 32:
			return cpu->ptr_r32;
		case 64:
			return cpu->ptr_r64;
		default:
			return 0; /* can't happen */
	}
}

static Value **
ptr_f(cpu_t *cpu)
{
	switch (cpu->fp_reg_size) {
		case 32:
			return cpu->ptr_f32;
		case 64:
			return cpu->ptr_f64;
		case 80:
			return cpu->ptr_f80;
		case 128:
			return cpu->ptr_f128;
		default:
			return 0; /* can't happen */
	}
}

// GET REGISTER
Value *
arch_get_reg(cpu_t *cpu, uint32_t index, uint32_t bits, BasicBlock *bb) {
	Value *v;

	/* R0 is always 0 (on certain RISCs) */
	if (cpu->has_special_r0 && !index)
		return CONSTs(bits? bits : cpu->reg_size, 0);

	/* get the register */
	v = new LoadInst(ptr_r(cpu)[index], "", false, bb);

	/* optionally truncate it */
	if (bits && cpu->reg_size != bits)
		v = TRUNC(bits, v);

	return v;
}

Value *
arch_get_fp_reg(cpu_t *cpu, uint32_t index, uint32_t bits, BasicBlock *bb) {
	Value *v;

	/* get the register */
	return new LoadInst(ptr_f(cpu)[index], "", false, bb);
}

// PUT REGISTER
void
arch_put_reg(cpu_t *cpu, uint32_t index, Value *v, uint32_t bits, bool sext, BasicBlock *bb) {
	/*
	 * if the caller cares about bit size and
	 * the size is not the register size, we'll zext or sext
	 */
	if (bits && cpu->reg_size != bits)
		if (sext)
			v = SEXT(cpu->reg_size, v);
		else
			v = ZEXT(cpu->reg_size, v);

	/* store value, unless it's R0 (on certain RISCs) */
	if (!cpu->has_special_r0 || index)
		new StoreInst(v, ptr_r(cpu)[index], bb);
}

void
arch_put_fp_reg(cpu_t *cpu, uint32_t index, Value *v, uint32_t bits, BasicBlock *bb) {
	/* store value, unless it's R0 (on certain RISCs) */
	if (!cpu->has_special_fr0 || index)
		new StoreInst(v, ptr_f(cpu)[index], bb);
}

//XXX TODO
// The guest CPU can be little endian or big endian, so we need both
// host mode access routines as well as IR generators that deal with
// both modes. In practice, we need two sets of functions, one that
// deals with host native endianness, and one that deals with the other
// endianness; and interface functions that dispatch calls to endianness
// functions depending on the host endianness.
// i.e. there should be RAM32NE() which reads a 32 bit address from RAM,
// using the "Native Endianness" of the host, and RAM32SW() which does
// a swapped read. RAM32BE() and RAM32LE() should choose either of
// RAM32NE() and RAM32SW() depending on the endianness of the host.
//
// Swapped endianness can be implemented in different ways: by swapping
// every non-byte memory read and write, or by keeping aligned words
// in the host's native endianness, not swapping aligned reads and
// writes, and correcting unaligned accesses. (This makes more sense
// on guest CPUs that only allow aligned memory access.)
// The client should be able to specify a specific strategy, but each
// CPU frontend should default to the typically best strategy. Functions
// like RAM32SW() will have to respect the setting, so that all memory
// access is consistent with the strategy.

//////////////////////////////////////////////////////////////////////
// GENERIC: host memory access
//////////////////////////////////////////////////////////////////////
uint32_t
RAM32BE(uint8_t *RAM, addr_t a) {
	uint32_t v;
	v  = RAM[a+0] << 24;
	v |= RAM[a+1] << 16;
	v |= RAM[a+2] << 8;
	v |= RAM[a+3] << 0;
	return v;
}

//////////////////////////////////////////////////////////////////////
// GENERIC: memory access
//////////////////////////////////////////////////////////////////////

/* get a RAM pointer to a 32 bit value */
static Value *
arch_gep32(cpu_t *cpu, Value *a, BasicBlock *bb) {
	a = GetElementPtrInst::Create(cpu->ptr_RAM, a, "", bb);
	return new BitCastInst(a, PointerType::get(getType(Int32Ty), 0), "", bb);
}

/* load 32 bit ALIGNED value from RAM */
Value *
arch_load32_aligned(cpu_t *cpu, Value *a, BasicBlock *bb) {
	a = arch_gep32(cpu, a, bb);
#ifdef __LITTLE_ENDIAN__
	bool swap = !cpu->is_little_endian;
#else
	bool swap = cpu->is_little_endian;
#endif
	if(swap)
		return SWAP32(new LoadInst(a, "", false, bb));
	else
		return new LoadInst(a, "", false, bb);
}

/* store 32 bit ALIGNED value to RAM */
void
arch_store32_aligned(cpu_t *cpu, Value *v, Value *a, BasicBlock *bb) {
	a = arch_gep32(cpu, a, bb);
#ifdef __LITTLE_ENDIAN__
	bool swap = !cpu->is_little_endian;
#else
	bool swap = cpu->is_little_endian;
#endif
	new StoreInst(swap ? SWAP32(v) : v, a, bb);
}

//////////////////////////////////////////////////////////////////////
// GENERIC: endianness
//////////////////////////////////////////////////////////////////////

static Value *
arch_get_shift8(cpu_t *cpu, Value *addr, BasicBlock *bb)
{
	Value *shift = AND(addr,CONST(3));
	if (!cpu->is_little_endian)
		shift = XOR(shift, CONST(3));
	return SHL(shift, CONST(3));
}

static Value *
arch_get_shift16(cpu_t *cpu, Value *addr, BasicBlock *bb)
{
	Value *shift = AND(addr,CONST(1));
	if (!cpu->is_little_endian)
		shift = XOR(shift, CONST(1));
	return SHL(shift, CONST(4));
}

Value *
arch_load8(cpu_t *cpu, Value *addr, BasicBlock *bb) {
	Value *shift = arch_get_shift8(cpu, addr, bb);
	Value *val = arch_load32_aligned(cpu, AND(addr, CONST(~3ULL)), bb);
	return TRUNC8(LSHR(val, shift));
}

Value *
arch_load16_aligned(cpu_t *cpu, Value *addr, BasicBlock *bb) {
	Value *shift = arch_get_shift16(cpu, addr, bb);
	Value *val = arch_load32_aligned(cpu, AND(addr, CONST(~3ULL)), bb);
	return TRUNC16(LSHR(val, shift));
}

void
arch_store8(cpu_t *cpu, Value *val, Value *addr, BasicBlock *bb) {
	Value *shift = arch_get_shift8(cpu, addr, bb);
	addr = AND(addr, CONST(~3ULL));
	Value *mask = XOR(SHL(CONST(255), shift),CONST(-1ULL));
	Value *old = AND(arch_load32_aligned(cpu, addr, bb), mask);
	val = OR(old, SHL(AND(val, CONST(255)), shift));
	arch_store32_aligned(cpu, val, addr, bb);
}

void
arch_store16(cpu_t *cpu, Value *val, Value *addr, BasicBlock *bb) {
	Value *shift = arch_get_shift16(cpu, addr, bb);
	addr = AND(addr, CONST(~3ULL));
	Value *mask = XOR(SHL(CONST(65535), shift),CONST(-1ULL));
	Value *old = AND(arch_load32_aligned(cpu, addr, bb), mask);
	val = OR(old, SHL(AND(val, CONST(65535)), shift));
	arch_store32_aligned(cpu, val, addr, bb);
}

//////////////////////////////////////////////////////////////////////

Value *
arch_bswap(cpu_t *cpu, size_t width, Value *v, BasicBlock *bb) {
	Type const *ty = getIntegerType(width);
	return CallInst::Create(Intrinsic::getDeclaration(cpu->mod, Intrinsic::bswap, &ty, 1), v, "", bb);
}

Value *
arch_ctlz(cpu_t *cpu, size_t width, Value *v, BasicBlock *bb) {
	Type const *ty = getIntegerType(width);
	return CallInst::Create(Intrinsic::getDeclaration(cpu->mod, Intrinsic::ctlz, &ty, 1), v, "", bb);
}

Value *
arch_cttz(cpu_t *cpu, size_t width, Value *v, BasicBlock *bb) {
	Type const *ty = getIntegerType(width);
	return CallInst::Create(Intrinsic::getDeclaration(cpu->mod, Intrinsic::cttz, &ty, 1), v, "", bb);
}

// branches

void
arch_branch(bool flag_state, BasicBlock *target1, BasicBlock *target2, Value *v, BasicBlock *bb) {
	if (flag_state)
		BranchInst::Create(target1, target2, v, bb);
	else
		BranchInst::Create(target2, target1, v, bb);
}

void
arch_jump(BasicBlock *bb, BasicBlock *bb_target) {
	if (!bb_target) {
		printf("error: unknown jump target!\n");
		exit(1);
	}
	BranchInst::Create(bb_target, bb);
}

// decoding and encoding of bits in a bitfield (e.g. flags)

Value *
arch_encode_bit(Value *flags, Value *bit, int shift, int width, BasicBlock *bb)
{
	Value *n = new LoadInst(bit, "", false, bb);
	bit = new ZExtInst(n, getIntegerType(width), "", bb);
	bit = BinaryOperator::Create(Instruction::Shl, bit, ConstantInt::get(getIntegerType(width), shift), "", bb);
	return BinaryOperator::Create(Instruction::Or, flags, bit, "", bb);
}

void
arch_decode_bit(Value *flags, Value *bit, int shift, int width, BasicBlock *bb)
{
	Value *n = BinaryOperator::Create(Instruction::LShr, flags, ConstantInt::get(getIntegerType(width), shift), "", bb);
	n = new TruncInst(n, getIntegerType(1), "", bb);
	new StoreInst(n, bit, bb);
}

// FP

Value *
arch_sqrt(cpu_t *cpu, size_t width, Value *v, BasicBlock *bb) {
	Type const *ty = getFloatType(width);
	return CallInst::Create(Intrinsic::getDeclaration(cpu->mod, Intrinsic::sqrt, &ty, 1), v, "", bb);
}
<|endoftext|>


<commit_before>#include <netdb.h>
#include <unistd.h>
#include <sys/fcntl.h>

#include "client.h"
#include "duckchat.h"
#include "raw.h"

// Client connects, logs in, and joins “Common”.
// Client reads lines from the user and parses commands.
// Client correctly sends Say message.
// Client uses select() to wait for input from the user and the server.
// Client correctly sends Join, Leave, Login, and Logout and TODO handles Switch.
// TODO Client correctly sends List and Who.
// TODO Server can accept connections.
// TODO Server handles Login and Logout from users, and keeps records of which users are logged in.
// TODO Server handles Join and Leave from users, keeps records of which channels a user belongs to,
// and keeps records of which users are in a channel.
// TODO Server handles the Say message.
// TODO Server correctly handles List and Who.
// TODO Create copies of your client and server source. Modify them to send invalid packets to your good client
// and server, to see if you can make your client or server crash. Fix any bugs you find.

// Variables
struct sockaddr_in client_addr;
struct sockaddr_in server_addr;
int client_socket;
struct addrinfo *server_info;
char *current_channel;
std::vector<char *> channels;

// Prints an error message and exits the program.
void Error(const char *msg) {
  std::cerr << msg << std::endl;
  exit(1);
}

void PrintPrompt() {
  std::cout << "> " << std::flush;
}

// Splits strings around spaces.
std::vector<std::string> StringSplit(std::string input) {
  std::istringstream iss(input);
  std::vector<std::string> result{std::istream_iterator<std::string>{iss}, std::istream_iterator<std::string>{}};

  return result;
}

// Splits strings around spaces.
std::vector<std::string> SplitString(char *input, char delimiter) {
  std::vector<std::string> result;
  std::string word = "";

  size_t input_size = strlen(input);
  for (size_t i = 0; i < input_size; i++) {
    if (input[i] != delimiter) {
      word += input[i];
    } else {
      result.push_back(word);
      word = "";
    }
  }
  result.push_back(word);

  return result;
}

void StripChar(char *input, char c) {
  size_t size = strlen(input);
  for (size_t i = 0; i < size; i++) {
    if (input[i] == c) {
      input[i] = '\0';
    }
  }
}

// Gets the address info of the server at a the given port and creates the client's socket.
void CreateSocket(char *domain, const char *port) {
  std::cout << "Connecting to " << domain << std::endl;

  struct addrinfo hints;
  struct addrinfo *server_info_tmp;
  int status;

  memset(&hints, 0, sizeof(hints));
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_DGRAM;
  hints.ai_protocol = 0;

  if ((status = getaddrinfo(domain, port, &hints, &server_info_tmp)) != 0) {
    std::cerr << "client: unable to resolve address: " << gai_strerror(status) << std::endl;
    exit(1);
  }

  // getaddrinfo() returns a list of address structures into server_info_tmp.
  // Tries each address until a successful connect().
  // If socket() (or connect()) fails, closes the socket and tries the next address.

  for (server_info = server_info_tmp; server_info != NULL; server_info = server_info->ai_next) {
    if ((client_socket = socket(server_info->ai_family, server_info->ai_socktype, server_info->ai_protocol)) < 0) {
      continue;
    }
    if (connect(client_socket, server_info->ai_addr, server_info->ai_addrlen) != -1) {
      fcntl(client_socket, F_SETFL, O_NONBLOCK);
      break; // Success
    }
    close(client_socket);
  }

  if (server_info == NULL) {
    Error("client: all sockets failed to connect");
  }
}

// Sends a message to all users in on the active channel.
int SendSay(const char *message) {
  struct request_say say;
  memset(&say, 0, sizeof(say));
  say.req_type = REQ_SAY;
  strncpy(say.req_text, message, SAY_MAX);
  strncpy(say.req_channel, current_channel, CHANNEL_MAX);

  if (sendto(client_socket, &say, sizeof(say), 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to send message\n");
  }

  return 0;
}

// Sends login requests to the server.
int SendLogin(char *username) {
  struct request_login login;
  memset(&login, 0, sizeof(login));
  login.req_type = REQ_LOGIN;
  strncpy(login.req_username, username, USERNAME_MAX);

  size_t message_size = sizeof(struct request_login);

  if (sendto(client_socket, &login, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request login\n");
  }

  return 0;
}

// Sends logout requests to the server.
int SendLogout() {
  struct request_logout logout;
  memset((char *) &logout, 0, sizeof(logout));
  logout.req_type = REQ_LOGOUT;

  size_t message_size = sizeof(struct request_logout);

  if (sendto(client_socket, &logout, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request logout\n");
  }

  return 0;
}

// Sends join requests to the server.
int SendJoin(const char *channel) {
  struct request_join join;
  memset((char *) &join, 0, sizeof(join));
  join.req_type = REQ_JOIN;
  strncpy(join.req_channel, channel, CHANNEL_MAX);

  size_t message_size = sizeof(struct request_join);

  if (sendto(client_socket, &join, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request join\n");
  }

  channels.push_back((char *) channel);

  return 0;
}

// Switches to a channel the user has already joined.
int SwitchChannel(const char *channel) {
  bool isSubscribed = false;

  if (channels.size() > 0) {
    for (auto c: channels) {
      std::cout << "c: " << c << " channel: " << channel << std::endl;
      if (channel == c) {
        current_channel = (char *) channel;
        isSubscribed = true;
      }
    }
  }

  if (!isSubscribed) {
    std::cout << "You have not subscribed to channel " << channel << std::endl;
  }

  return 0;
}

// Handles TXT-SAY server messages.
void HandleTextSay(char *receive_buffer, char *output) {
  struct text_say say;
  memcpy(&say, receive_buffer, sizeof(struct text_say));

  std::string backspaces = "";
  for (int i = 0; i < SAY_MAX; i++) {
    backspaces.append("\b");
  }
  std::cout << backspaces;
  std::cout << "[" << say.txt_channel << "]" << "[" << say.txt_username << "]: " << say.txt_text << std::endl;
  PrintPrompt();
  std::cout << output << std::flush;
}

// Processes the input string to decide what type of command it is.
bool ProcessInput(std::string input) {
  std::vector<std::string> inputs = StringSplit(input);

  if (inputs[0] == "/exit") {
    SendLogout();
    cooked_mode();
    return false;
  } else if (inputs[0] == "/list") {

  } else if (inputs[0] == "/join" && inputs.size() > 1) {
    SendJoin(inputs[1].c_str());
  } else if (inputs[0] == "/leave") {

  } else if (inputs[0] == "/who") {

  } else if (inputs[0] == "/switch" && inputs.size() > 1) {
    SwitchChannel(inputs[1].c_str());
  } else {
    std::cout << "*Unknown command" << std::endl;
  }

  PrintPrompt();
  return true;
}

int main(int argc, char *argv[]) {
  char *domain;
  char *port_str;
  int port_num;
  char *username;
  char *input;
  char *output = (char *) "";
  fd_set read_set;
  int result;

  char stdin_buffer[SAY_MAX + 1];
  char *stdin_buffer_pointer = stdin_buffer;

  char receive_buffer[kBufferSize];
  memset(&receive_buffer, 0, kBufferSize);

  if (argc < 4) {
    Error("usage: client [server name] [port] [username]");
  }

  domain = argv[1];
  port_str = argv[2];
  port_num = atoi(argv[2]);
  username = argv[3];

  if (strlen(domain) > UNIX_PATH_MAX) {
    Error("client: server name must be less than 108 characters");
  }

  if (port_num < 0 || port_num > 65535) {
    Error("client: port number must be between 0 and 65535");
  }

  if (strlen(username) > USERNAME_MAX) {
    Error("client: username must be less than 32 characters");
  }

  CreateSocket(domain, port_str);

  SendLogin(username);

  current_channel = (char *) "Common";
  channels.push_back(current_channel);
  SendJoin(current_channel);

  if (raw_mode() != 0){
    Error("client: error using raw mode");
  }

  PrintPrompt();

  while (1) {
    FD_ZERO(&read_set);
    FD_SET(client_socket, &read_set);
    FD_SET(STDIN_FILENO, &read_set);

    if ((result = select(client_socket + 1, &read_set, NULL, NULL, NULL)) < 0) {
      Error("client: problem using select");
    }

    if (result > 0) {
      if (FD_ISSET(STDIN_FILENO, &read_set)) {
        // User entered a char.
        char c = (char) getchar();
        if (c == '\n') {
          // Increments pointer and adds NULL char.
          *stdin_buffer_pointer++ = '\0';

          // Resets stdin_buffer_pointer to the start of stdin_buffer.
          stdin_buffer_pointer = stdin_buffer;

          std::cout << "\n" << std::flush;

          // Prevents output from printing on the new prompt after a newline char.
          output = (char *) "";

          input = stdin_buffer;
          if (input[0] == '/') {
            if (!ProcessInput(input)) {
              break;
            }
          } else {
            // Sends chat messages.
            SendSay(input);
          }
        } else if (stdin_buffer_pointer != stdin_buffer + SAY_MAX) {
          // Increments pointer and adds char c.
          *stdin_buffer_pointer++ = c;

          std::cout << c << std::flush;

          // Copies pointer into output.
          output = stdin_buffer_pointer;
          // Increments and sets NULL char.
          *output++ = '\0';
          // Copies stdin_buffer into part of output before NULL char.
          output = stdin_buffer;
        }
      } else if (FD_ISSET(client_socket, &read_set)) {
        // Socket has data.
        ssize_t read_size = read(client_socket, receive_buffer, kBufferSize);

        if (read_size != 0) {
          struct text message;
          memcpy(&message, receive_buffer, sizeof(struct text));
          text_t text_type = message.txt_type;

          switch (text_type) {
            case TXT_SAY:
              HandleTextSay(receive_buffer, output);
              break;
            default:
              break;
          }
        }

        memset(&receive_buffer, 0, SAY_MAX);
      } // end of if client_socket

    } // end of if result

  } // end of while

  return 0;
}<commit_msg>print testing in join<commit_after>#include <netdb.h>
#include <unistd.h>
#include <sys/fcntl.h>

#include "client.h"
#include "duckchat.h"
#include "raw.h"

// Client connects, logs in, and joins “Common”.
// Client reads lines from the user and parses commands.
// Client correctly sends Say message.
// Client uses select() to wait for input from the user and the server.
// Client correctly sends Join, Leave, Login, and Logout and TODO handles Switch.
// TODO Client correctly sends List and Who.
// TODO Server can accept connections.
// TODO Server handles Login and Logout from users, and keeps records of which users are logged in.
// TODO Server handles Join and Leave from users, keeps records of which channels a user belongs to,
// and keeps records of which users are in a channel.
// TODO Server handles the Say message.
// TODO Server correctly handles List and Who.
// TODO Create copies of your client and server source. Modify them to send invalid packets to your good client
// and server, to see if you can make your client or server crash. Fix any bugs you find.

// Variables
struct sockaddr_in client_addr;
struct sockaddr_in server_addr;
int client_socket;
struct addrinfo *server_info;
char *current_channel;
std::vector<char *> channels;

// Prints an error message and exits the program.
void Error(const char *msg) {
  std::cerr << msg << std::endl;
  exit(1);
}

void PrintPrompt() {
  std::cout << "> " << std::flush;
}

// Splits strings around spaces.
std::vector<std::string> StringSplit(std::string input) {
  std::istringstream iss(input);
  std::vector<std::string> result{std::istream_iterator<std::string>{iss}, std::istream_iterator<std::string>{}};

  return result;
}

// Splits strings around spaces.
std::vector<std::string> SplitString(char *input, char delimiter) {
  std::vector<std::string> result;
  std::string word = "";

  size_t input_size = strlen(input);
  for (size_t i = 0; i < input_size; i++) {
    if (input[i] != delimiter) {
      word += input[i];
    } else {
      result.push_back(word);
      word = "";
    }
  }
  result.push_back(word);

  return result;
}

void StripChar(char *input, char c) {
  size_t size = strlen(input);
  for (size_t i = 0; i < size; i++) {
    if (input[i] == c) {
      input[i] = '\0';
    }
  }
}

// Gets the address info of the server at a the given port and creates the client's socket.
void CreateSocket(char *domain, const char *port) {
  std::cout << "Connecting to " << domain << std::endl;

  struct addrinfo hints;
  struct addrinfo *server_info_tmp;
  int status;

  memset(&hints, 0, sizeof(hints));
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_DGRAM;
  hints.ai_protocol = 0;

  if ((status = getaddrinfo(domain, port, &hints, &server_info_tmp)) != 0) {
    std::cerr << "client: unable to resolve address: " << gai_strerror(status) << std::endl;
    exit(1);
  }

  // getaddrinfo() returns a list of address structures into server_info_tmp.
  // Tries each address until a successful connect().
  // If socket() (or connect()) fails, closes the socket and tries the next address.

  for (server_info = server_info_tmp; server_info != NULL; server_info = server_info->ai_next) {
    if ((client_socket = socket(server_info->ai_family, server_info->ai_socktype, server_info->ai_protocol)) < 0) {
      continue;
    }
    if (connect(client_socket, server_info->ai_addr, server_info->ai_addrlen) != -1) {
      fcntl(client_socket, F_SETFL, O_NONBLOCK);
      break; // Success
    }
    close(client_socket);
  }

  if (server_info == NULL) {
    Error("client: all sockets failed to connect");
  }
}

// Sends a message to all users in on the active channel.
int SendSay(const char *message) {
  struct request_say say;
  memset(&say, 0, sizeof(say));
  say.req_type = REQ_SAY;
  strncpy(say.req_text, message, SAY_MAX);
  strncpy(say.req_channel, current_channel, CHANNEL_MAX);

  if (sendto(client_socket, &say, sizeof(say), 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to send message\n");
  }

  return 0;
}

// Sends login requests to the server.
int SendLogin(char *username) {
  struct request_login login;
  memset(&login, 0, sizeof(login));
  login.req_type = REQ_LOGIN;
  strncpy(login.req_username, username, USERNAME_MAX);

  size_t message_size = sizeof(struct request_login);

  if (sendto(client_socket, &login, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request login\n");
  }

  return 0;
}

// Sends logout requests to the server.
int SendLogout() {
  struct request_logout logout;
  memset((char *) &logout, 0, sizeof(logout));
  logout.req_type = REQ_LOGOUT;

  size_t message_size = sizeof(struct request_logout);

  if (sendto(client_socket, &logout, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request logout\n");
  }

  return 0;
}

// Sends join requests to the server.
int SendJoin(const char *channel) {

  std::cout << "join channel: " << channel << std::endl;

  struct request_join join;
  memset((char *) &join, 0, sizeof(join));
  join.req_type = REQ_JOIN;
  strncpy(join.req_channel, channel, CHANNEL_MAX);

  size_t message_size = sizeof(struct request_join);

  if (sendto(client_socket, &join, message_size, 0, server_info->ai_addr, server_info->ai_addrlen) < 0) {
    Error("client: failed to request join\n");
  }

  channels.push_back((char *) channel);

  for (auto c : channels) {
    std::cout << "channel in channels: " << c << std::endl;
  }

  return 0;
}

// Switches to a channel the user has already joined.
int SwitchChannel(const char *channel) {
  bool isSubscribed = false;

  if (channels.size() > 0) {
    for (auto c: channels) {
      std::cout << "c: " << c << " channel: " << channel << std::endl;
      if (channel == c) {
        current_channel = (char *) channel;
        isSubscribed = true;
      }
    }
  }

  if (!isSubscribed) {
    std::cout << "You have not subscribed to channel " << channel << std::endl;
  }

  return 0;
}

// Handles TXT-SAY server messages.
void HandleTextSay(char *receive_buffer, char *output) {
  struct text_say say;
  memcpy(&say, receive_buffer, sizeof(struct text_say));

  std::string backspaces = "";
  for (int i = 0; i < SAY_MAX; i++) {
    backspaces.append("\b");
  }
  std::cout << backspaces;
  std::cout << "[" << say.txt_channel << "]" << "[" << say.txt_username << "]: " << say.txt_text << std::endl;
  PrintPrompt();
  std::cout << output << std::flush;
}

// Processes the input string to decide what type of command it is.
bool ProcessInput(std::string input) {
  std::vector<std::string> inputs = StringSplit(input);

  if (inputs[0] == "/exit") {
    SendLogout();
    cooked_mode();
    return false;
  } else if (inputs[0] == "/list") {

  } else if (inputs[0] == "/join" && inputs.size() > 1) {
    SendJoin(inputs[1].c_str());
  } else if (inputs[0] == "/leave") {

  } else if (inputs[0] == "/who") {

  } else if (inputs[0] == "/switch" && inputs.size() > 1) {
    SwitchChannel(inputs[1].c_str());
  } else {
    std::cout << "*Unknown command" << std::endl;
  }

  PrintPrompt();
  return true;
}

int main(int argc, char *argv[]) {
  char *domain;
  char *port_str;
  int port_num;
  char *username;
  char *input;
  char *output = (char *) "";
  fd_set read_set;
  int result;

  char stdin_buffer[SAY_MAX + 1];
  char *stdin_buffer_pointer = stdin_buffer;

  char receive_buffer[kBufferSize];
  memset(&receive_buffer, 0, kBufferSize);

  if (argc < 4) {
    Error("usage: client [server name] [port] [username]");
  }

  domain = argv[1];
  port_str = argv[2];
  port_num = atoi(argv[2]);
  username = argv[3];

  if (strlen(domain) > UNIX_PATH_MAX) {
    Error("client: server name must be less than 108 characters");
  }

  if (port_num < 0 || port_num > 65535) {
    Error("client: port number must be between 0 and 65535");
  }

  if (strlen(username) > USERNAME_MAX) {
    Error("client: username must be less than 32 characters");
  }

  CreateSocket(domain, port_str);

  SendLogin(username);

  current_channel = (char *) "Common";
  channels.push_back(current_channel);
  SendJoin(current_channel);

  if (raw_mode() != 0){
    Error("client: error using raw mode");
  }

  PrintPrompt();

  while (1) {
    FD_ZERO(&read_set);
    FD_SET(client_socket, &read_set);
    FD_SET(STDIN_FILENO, &read_set);

    if ((result = select(client_socket + 1, &read_set, NULL, NULL, NULL)) < 0) {
      Error("client: problem using select");
    }

    if (result > 0) {
      if (FD_ISSET(STDIN_FILENO, &read_set)) {
        // User entered a char.
        char c = (char) getchar();
        if (c == '\n') {
          // Increments pointer and adds NULL char.
          *stdin_buffer_pointer++ = '\0';

          // Resets stdin_buffer_pointer to the start of stdin_buffer.
          stdin_buffer_pointer = stdin_buffer;

          std::cout << "\n" << std::flush;

          // Prevents output from printing on the new prompt after a newline char.
          output = (char *) "";

          input = stdin_buffer;
          if (input[0] == '/') {
            if (!ProcessInput(input)) {
              break;
            }
          } else {
            // Sends chat messages.
            SendSay(input);
          }
        } else if (stdin_buffer_pointer != stdin_buffer + SAY_MAX) {
          // Increments pointer and adds char c.
          *stdin_buffer_pointer++ = c;

          std::cout << c << std::flush;

          // Copies pointer into output.
          output = stdin_buffer_pointer;
          // Increments and sets NULL char.
          *output++ = '\0';
          // Copies stdin_buffer into part of output before NULL char.
          output = stdin_buffer;
        }
      } else if (FD_ISSET(client_socket, &read_set)) {
        // Socket has data.
        ssize_t read_size = read(client_socket, receive_buffer, kBufferSize);

        if (read_size != 0) {
          struct text message;
          memcpy(&message, receive_buffer, sizeof(struct text));
          text_t text_type = message.txt_type;

          switch (text_type) {
            case TXT_SAY:
              HandleTextSay(receive_buffer, output);
              break;
            default:
              break;
          }
        }

        memset(&receive_buffer, 0, SAY_MAX);
      } // end of if client_socket

    } // end of if result

  } // end of while

  return 0;
}<|endoftext|>


<commit_before><commit_msg>This change is patched from http://codereview.chromium.org/276071 by randy.posynick@gmail.com<commit_after><|endoftext|>


<commit_before>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <boost/lexical_cast.hpp>
#include "packet.h"

#define BUFSIZE 121
#define FILENAME "Testfile"
#define TEST_FILENAME "Testfile2"
#define PORT 10038
#define PAKSIZE 128
#define ACK 0
#define NAK 1
#define WIN_SIZE 16

using namespace std;

bool gremlin(Packet * pack, int corruptProb, int lossProb);
bool init(int argc, char** argv);
bool loadFile();
bool sendFile();
bool getFile();
char * recvPkt();
bool isvpack(unsigned char * p);
Packet createPacket(int index);
bool sendPacket();
bool isAck();
void handleAck();
void handleNak(int& x);

int seqNum;
int s;
int probCorrupt;
int probLoss;
string hs;
short int port;
char * file;
unsigned char* window[16]; //packet window
int base; //used to determine position in window of arriving packets
int length;
struct sockaddr_in a;
struct sockaddr_in sa;
socklen_t salen;
string fstr;
bool dropPck;
Packet p;
int delayT;
unsigned char b[BUFSIZE];

int main(int argc, char** argv) {

  if(!init(argc, argv)) return -1;

  if(sendto(s, "GET Testfile", BUFSIZE + 7, 0, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
    cout << "Package sending failed. (socket s, server address sa, message m)" << endl;
    return false;
  }

  getFile();

  return 0;
}

bool init(int argc, char** argv) {
  base = 0; //initialize base
  s = 0;

  hs = string("131.204.14.") + argv[1]; /* Needs to be updated? Might be a string like "tux175.engr.auburn.edu." */
  port = 10038; /* Can be any port within 10038-10041, inclusive. */

  char* delayTStr = argv[2];
  delayT = boost::lexical_cast<int>(delayTStr);

  /*if(!loadFile()) {
    cout << "Loading file failed. (filename FILENAME)" << endl;
    return false;
  }*/

  if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
    cout << "Socket creation failed. (socket s)" << endl;
    return false;
  }

  memset((char *)&a, 0, sizeof(a));
  a.sin_family = AF_INET;
  a.sin_addr.s_addr = htonl(INADDR_ANY); //why does this always give us 0?
  a.sin_port = htons(0);

  if (bind(s, (struct sockaddr *)&a, sizeof(a)) < 0){
    cout << "Socket binding failed. (socket s, address a)" << endl;
    return false;
  }

  memset((char *)&sa, 0, sizeof(sa));
  sa.sin_family = AF_INET;
  sa.sin_port = htons(port);
  inet_pton(AF_INET, hs.c_str(), &(sa.sin_addr));

  cout << endl;

  cout << "Server address (inet mode): " << inet_ntoa(sa.sin_addr) << endl;
  cout << "Port: " << ntohs(sa.sin_port) << endl;

  cout << endl << endl;

  /*fstr = string(file);

  cout << "File: " << endl << fstr << endl << endl;*/

  seqNum = 0;
  dropPck = false;
  return true;
}

bool loadFile() {

  ifstream is (FILENAME, ifstream::binary);

  if(is) {
    is.seekg(0, is.end);
    length = is.tellg();
    is.seekg(0, is.beg);

    file = new char[length];

    cout << "Reading " << length << " characters..." << endl;
    is.read(file, length);

    if(!is) { cout << "File reading failed. (filename " << FILENAME << "). Only " << is.gcount() << " could be read."; return false; }
    is.close();
  }
  return true;
}

bool sendFile() {

  for(int x = 0; x <= length / BUFSIZE; x++) {
    p = createPacket(x);
    if(!sendPacket()) continue;

    if(isAck()) {
      handleAck();
    } else {
      handleNak(x);
    }

    memset(b, 0, BUFSIZE);
  }
  return true;
}

Packet createPacket(int index){
    cout << endl;
    cout << "=== TRANSMISSION START" << endl;
    string mstr = fstr.substr(index * BUFSIZE, BUFSIZE);
    if(index * BUFSIZE + BUFSIZE > length) {
      mstr[length - (index * BUFSIZE)] = '\0';
    }
    return Packet (seqNum, mstr.c_str());
}

bool sendPacket(){
    int pc = probCorrupt; int pl = probLoss;
    if((dropPck = gremlin(&p, pc, pl)) == false){
      if(sendto(s, p.str(), BUFSIZE + 7, 0, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
        cout << "Package sending failed. (socket s, server address sa, message m)" << endl;
        return false;
      }
      return true;
    } else return false;
}
bool isAck() {
    recvfrom(s, b, BUFSIZE + 7, 0, (struct sockaddr *)&sa, &salen);

    cout << endl << "=== SERVER RESPONSE TEST" << endl;
    cout << "Data: " << b << endl;
    if(b[6] == '0') return true;
    else return false;
}
void handleAck() {

}
void handleNak(int& x) {

      char * sns = new char[2];
      memcpy(sns, &b[0], 1);
      sns[1] = '\0';

      char * css = new char[5];
      memcpy(css, &b[1], 5);

      char * db = new char[BUFSIZE + 1];
      memcpy(db, &b[2], BUFSIZE);
      db[BUFSIZE] = '\0';

      cout << "Sequence number: " << sns << endl;
      cout << "Checksum: " << css << endl;

      Packet pk (0, db);
      pk.setSequenceNum(boost::lexical_cast<int>(sns));
      pk.setCheckSum(boost::lexical_cast<int>(css));

      if(!pk.chksm()) x--;
      else x = (x - 2 > 0) ? x - 2 : 0;
}

bool gremlin(Packet * pack, int corruptProb, int lossProb){
  bool dropPacket = false;
  int r = rand() % 100;

  cout << "Corruption probability: " << corruptProb << endl;
  cout << "Random number: " << r << endl;

  if(r <= (lossProb)){
    dropPacket = true;
    cout << "Dropped!" << endl;
  }
  else if(r <= (corruptProb)){
    cout << "Corrupted!" << endl;
    pack->loadDataBuffer((char*)"GREMLIN LOL");
  }
  else seqNum = (seqNum) ? false : true;
  cout << "Seq. num: " << pack->getSequenceNum() << endl;
  cout << "Checksum: " << pack->getCheckSum() << endl;
  cout << "Message: "  << pack->getDataBuffer() << endl;

  return dropPacket;
}

bool isvpack(unsigned char * p) {
  cout << endl << "=== IS VALID PACKET TESTING" << endl;

  char * sns = new char[3];
  memcpy(sns, &p[0], 3);
  sns[2] = '\0';

  char * css = new char[6];
  memcpy(css, &p[2], 6);
  css[5] = '\0';

  char * db = new char[121 + 1];
  memcpy(db, &p[8], 122);
  db[121] = '\0';

  cout << "Seq. num: " << sns << endl;
  cout << "Checksum: " << css << endl;
  cout << "Message: " << db << endl;

  int sn = boost::lexical_cast<int>(sns);
  int cs = boost::lexical_cast<int>(css);

  Packet pk (0, db);
  pk.setSequenceNum(sn);

  // change to validate based on checksum and sequence number

  cout << "cs: " << cs << endl;
  cout << "pk.generateCheckSum(): " << pk.generateCheckSum() << endl;

  if(!(sn >= base && sn < base + WIN_SIZE)) return false;
  if(cs != pk.generateCheckSum()) return false;
  return true;
}

bool getFile(){
  /* Loop forever, waiting for messages from a client. */
  cout << "Waiting on port " << PORT << "..." << endl;

  ofstream file("Dumpfile");

  int rlen;
  int ack;

  for (;;) {
    unsigned char packet[PAKSIZE + 1];
    unsigned char dataPull[PAKSIZE - 7 + 1];
    rlen = recvfrom(s, packet, PAKSIZE, 0, (struct sockaddr *)&sa, &salen);

	/* Begin Window Loading */
	int tempSeqNum = boost::lexical_cast<int>(packet[0]);
	int properIndex = tempSeqNum - base;

	window[properIndex] = packet;
	cout << "Packet loaded into window" << endl;
	char* tempTest = new char[6];
		memcpy(tempTest, &window[1], 0);
		tempTest[5] = '\0';

	cout << "The Checksum pulled from client window: " << tempTest[0] << endl;

	for(int x = 0; x < PAKSIZE - 7; x++) {
      dataPull[x] = packet[x + 7];
    }
    dataPull[PAKSIZE - 7] = '\0';
    packet[PAKSIZE] = '\0';
    if (rlen > 0) {
	  char * sns = new char[3];
	  memcpy(sns, &packet[0], 3);
	  sns[2] = '\0';

      char * css = new char[6];
      memcpy(css, &packet[2], 5);
      css[5] = '\0';
      cout << endl << endl << "=== RECEIPT" << endl;
      cout << "Seq. num: " << sns << endl;
      cout << "Checksum: " << css << endl;
      cout << "Received message: " << dataPull << endl;
      if(isvpack(packet)) {
        int x = boost::lexical_cast<int>(sns);
		cout << "sns: " << sns << endl;
		cout << "x (sns as int): " << x << endl;
		if(x == base) base++; //increment base of window //FIXME
        file << dataPull;
		file.flush();
      }
      cout << "Sent response: ";
      cout << "ACK " << base << endl;

	  if(packet[6] == '1') usleep(delayT*1000);

	  string wbs = to_string((long long)base);
	  const char * ackval = wbs.c_str();

      if(sendto(s, ackval, PAKSIZE, 0, (struct sockaddr *)&sa, salen) < 0) {
        cout << "Acknowledgement failed. (socket s, acknowledgement message ack, client address ca, client address length calen)" << endl;
        return 0;
      }
      delete css;
    }
  }
  file.close();
  return true;
}
<commit_msg>Possibly fix checksum verification<commit_after>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <boost/lexical_cast.hpp>
#include "packet.h"

#define BUFSIZE 121
#define FILENAME "Testfile"
#define TEST_FILENAME "Testfile2"
#define PORT 10038
#define PAKSIZE 128
#define ACK 0
#define NAK 1
#define WIN_SIZE 16

using namespace std;

bool gremlin(Packet * pack, int corruptProb, int lossProb);
bool init(int argc, char** argv);
bool loadFile();
bool sendFile();
bool getFile();
char * recvPkt();
bool isvpack(unsigned char * p);
Packet createPacket(int index);
bool sendPacket();
bool isAck();
void handleAck();
void handleNak(int& x);

int seqNum;
int s;
int probCorrupt;
int probLoss;
string hs;
short int port;
char * file;
unsigned char* window[16]; //packet window
int base; //used to determine position in window of arriving packets
int length;
struct sockaddr_in a;
struct sockaddr_in sa;
socklen_t salen;
string fstr;
bool dropPck;
Packet p;
int delayT;
unsigned char b[BUFSIZE];

int main(int argc, char** argv) {

  if(!init(argc, argv)) return -1;

  if(sendto(s, "GET Testfile", BUFSIZE + 7, 0, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
    cout << "Package sending failed. (socket s, server address sa, message m)" << endl;
    return false;
  }

  getFile();

  return 0;
}

bool init(int argc, char** argv) {
  base = 0; //initialize base
  s = 0;

  hs = string("131.204.14.") + argv[1]; /* Needs to be updated? Might be a string like "tux175.engr.auburn.edu." */
  port = 10038; /* Can be any port within 10038-10041, inclusive. */

  char* delayTStr = argv[2];
  delayT = boost::lexical_cast<int>(delayTStr);

  /*if(!loadFile()) {
    cout << "Loading file failed. (filename FILENAME)" << endl;
    return false;
  }*/

  if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
    cout << "Socket creation failed. (socket s)" << endl;
    return false;
  }

  memset((char *)&a, 0, sizeof(a));
  a.sin_family = AF_INET;
  a.sin_addr.s_addr = htonl(INADDR_ANY); //why does this always give us 0?
  a.sin_port = htons(0);

  if (bind(s, (struct sockaddr *)&a, sizeof(a)) < 0){
    cout << "Socket binding failed. (socket s, address a)" << endl;
    return false;
  }

  memset((char *)&sa, 0, sizeof(sa));
  sa.sin_family = AF_INET;
  sa.sin_port = htons(port);
  inet_pton(AF_INET, hs.c_str(), &(sa.sin_addr));

  cout << endl;

  cout << "Server address (inet mode): " << inet_ntoa(sa.sin_addr) << endl;
  cout << "Port: " << ntohs(sa.sin_port) << endl;

  cout << endl << endl;

  /*fstr = string(file);

  cout << "File: " << endl << fstr << endl << endl;*/

  seqNum = 0;
  dropPck = false;
  return true;
}

bool loadFile() {

  ifstream is (FILENAME, ifstream::binary);

  if(is) {
    is.seekg(0, is.end);
    length = is.tellg();
    is.seekg(0, is.beg);

    file = new char[length];

    cout << "Reading " << length << " characters..." << endl;
    is.read(file, length);

    if(!is) { cout << "File reading failed. (filename " << FILENAME << "). Only " << is.gcount() << " could be read."; return false; }
    is.close();
  }
  return true;
}

bool sendFile() {

  for(int x = 0; x <= length / BUFSIZE; x++) {
    p = createPacket(x);
    if(!sendPacket()) continue;

    if(isAck()) {
      handleAck();
    } else {
      handleNak(x);
    }

    memset(b, 0, BUFSIZE);
  }
  return true;
}

Packet createPacket(int index){
    cout << endl;
    cout << "=== TRANSMISSION START" << endl;
    string mstr = fstr.substr(index * BUFSIZE, BUFSIZE);
    if(index * BUFSIZE + BUFSIZE > length) {
      mstr[length - (index * BUFSIZE)] = '\0';
    }
    return Packet (seqNum, mstr.c_str());
}

bool sendPacket(){
    int pc = probCorrupt; int pl = probLoss;
    if((dropPck = gremlin(&p, pc, pl)) == false){
      if(sendto(s, p.str(), BUFSIZE + 7, 0, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
        cout << "Package sending failed. (socket s, server address sa, message m)" << endl;
        return false;
      }
      return true;
    } else return false;
}
bool isAck() {
    recvfrom(s, b, BUFSIZE + 7, 0, (struct sockaddr *)&sa, &salen);

    cout << endl << "=== SERVER RESPONSE TEST" << endl;
    cout << "Data: " << b << endl;
    if(b[6] == '0') return true;
    else return false;
}
void handleAck() {

}
void handleNak(int& x) {

      char * sns = new char[2];
      memcpy(sns, &b[0], 1);
      sns[1] = '\0';

      char * css = new char[5];
      memcpy(css, &b[1], 5);

      char * db = new char[BUFSIZE + 1];
      memcpy(db, &b[2], BUFSIZE);
      db[BUFSIZE] = '\0';

      cout << "Sequence number: " << sns << endl;
      cout << "Checksum: " << css << endl;

      Packet pk (0, db);
      pk.setSequenceNum(boost::lexical_cast<int>(sns));
      pk.setCheckSum(boost::lexical_cast<int>(css));

      if(!pk.chksm()) x--;
      else x = (x - 2 > 0) ? x - 2 : 0;
}

bool gremlin(Packet * pack, int corruptProb, int lossProb){
  bool dropPacket = false;
  int r = rand() % 100;

  cout << "Corruption probability: " << corruptProb << endl;
  cout << "Random number: " << r << endl;

  if(r <= (lossProb)){
    dropPacket = true;
    cout << "Dropped!" << endl;
  }
  else if(r <= (corruptProb)){
    cout << "Corrupted!" << endl;
    pack->loadDataBuffer((char*)"GREMLIN LOL");
  }
  else seqNum = (seqNum) ? false : true;
  cout << "Seq. num: " << pack->getSequenceNum() << endl;
  cout << "Checksum: " << pack->getCheckSum() << endl;
  cout << "Message: "  << pack->getDataBuffer() << endl;

  return dropPacket;
}

bool isvpack(unsigned char * p) {
  cout << endl << "=== IS VALID PACKET TESTING" << endl;

  char * sns = new char[3];
  memcpy(sns, &p[0], 3);
  sns[2] = '\0';

  char * css = new char[6];
  memcpy(css, &p[2], 5);
  css[5] = '\0';

  char * db = new char[121 + 1];
  memcpy(db, &p[8], 122);
  db[121] = '\0';

  cout << "Seq. num: " << sns << endl;
  cout << "Checksum: " << css << endl;
  cout << "Message: " << db << endl;

  int sn = boost::lexical_cast<int>(sns);
  int cs = boost::lexical_cast<int>(css);

  Packet pk (0, db);
  pk.setSequenceNum(sn);

  // change to validate based on checksum and sequence number

  cout << "cs: " << cs << endl;
  cout << "pk.generateCheckSum(): " << pk.generateCheckSum() << endl;

  if(!(sn >= base && sn < base + WIN_SIZE)) return false;
  if(cs != pk.generateCheckSum()) return false;
  return true;
}

bool getFile(){
  /* Loop forever, waiting for messages from a client. */
  cout << "Waiting on port " << PORT << "..." << endl;

  ofstream file("Dumpfile");

  int rlen;
  int ack;

  for (;;) {
    unsigned char packet[PAKSIZE + 1];
    unsigned char dataPull[PAKSIZE - 7 + 1];
    rlen = recvfrom(s, packet, PAKSIZE, 0, (struct sockaddr *)&sa, &salen);

	/* Begin Window Loading */
	int tempSeqNum = boost::lexical_cast<int>(packet[0]);
	int properIndex = tempSeqNum - base;

	window[properIndex] = packet;
	cout << "Packet loaded into window" << endl;
	char* tempTest = new char[6];
		memcpy(tempTest, &window[1], 0);
		tempTest[5] = '\0';

	cout << "The Checksum pulled from client window: " << tempTest[0] << endl;

	for(int x = 0; x < PAKSIZE - 7; x++) {
      dataPull[x] = packet[x + 7];
    }
    dataPull[PAKSIZE - 7] = '\0';
    packet[PAKSIZE] = '\0';
    if (rlen > 0) {
	  char * sns = new char[3];
	  memcpy(sns, &packet[0], 3);
	  sns[2] = '\0';

      char * css = new char[6];
      memcpy(css, &packet[2], 5);
      css[5] = '\0';
      cout << endl << endl << "=== RECEIPT" << endl;
      cout << "Seq. num: " << sns << endl;
      cout << "Checksum: " << css << endl;
      cout << "Received message: " << dataPull << endl;
      if(isvpack(packet)) {
        int x = boost::lexical_cast<int>(sns);
		cout << "sns: " << sns << endl;
		cout << "x (sns as int): " << x << endl;
		if(x == base) base++; //increment base of window //FIXME
        file << dataPull;
		file.flush();
      }
      cout << "Sent response: ";
      cout << "ACK " << base << endl;

	  if(packet[6] == '1') usleep(delayT*1000);

	  string wbs = to_string((long long)base);
	  const char * ackval = wbs.c_str();

      if(sendto(s, ackval, PAKSIZE, 0, (struct sockaddr *)&sa, salen) < 0) {
        cout << "Acknowledgement failed. (socket s, acknowledgement message ack, client address ca, client address length calen)" << endl;
        return 0;
      }
      delete css;
    }
  }
  file.close();
  return true;
}
<|endoftext|>


<commit_before><commit_msg>Fix a leak in newly added sync channel unit tests.<commit_after><|endoftext|>