<commit_before>/****************************************************************
 * Copyright (c) 2014, The Pennsylvania State University
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms,
 * with or without modification, are permitted for
 * personal and commercial purposes provided that the
 * following conditions are met:
 *
 * 1. Redistribution of source code must retain the
 *    above copyright notice, this list of conditions
 *    and the following disclaimer.
 *
 * 2. Redistribution in binary form must reproduce the
 *    above copyright notice, this list of conditions
 *    and the following disclaimer.
 *
 * 3. Neither the name of The Pennsylvania State University
 *    nor the names of its contributors may be used to
 *    endorse or promote products derived from this software
 *    without the specific prior written permission of The
 *    Pennsylvania State University.
 *
 * THIS SOFTWARE IS PROVIDED BY THE PENNSYLVANIA STATE UNIVERSITY
 * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT OF
 * INTELLECTUAL PROPERTY ARE EXPRESSLY DISCLAIMED. IN NO EVENT
 * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGE.
 ****************************************************************/

#include "gridmaker.h"
#include "logging.h"
#include <vector>
#include <iostream>
#include <string>

void usage(){
    std::cerr<<"dxgridmaker generates a points file for use in RADIANCE analysis programs.  The program allows any number of polygons and any number of layer names to be used for the placement of points.  grid_maker will then join all of the polygons and create an array of points within the bounding rectangle and tests each point to determine whether it is within the joined polygon.  These points will then be written out to a given file name for use as input to other programs.  It is assumed that the units of the radiance geometry file are the same as the input units for the spacing, offset, and Z height."<<std::endl;
    std::cerr<<std::endl<<"-f name\tSet the input file to name. This file contains the radiance polygons that will be used for creating the analysis points.  This is a mandatory option."<<std::endl;
    std::cerr<<"-sx val\tSet the spacing in the x direction between the analysis points to val.  This is a mandatory option. "<<std::endl;
    std::cerr<<"-sy val\tSet the spacing in the y direction between the analysis points to val.  This is a mandatory option."<<std::endl;
    std::cerr<<"-ox val\tSet the offset in the x direction from the left side of the bounding rectangle to val."<<std::endl;
    std::cerr<<"-oy val\tSet the offset in the y direction from the lower side of the bounding rectangle to val."<<std::endl;
    std::cerr<<"-oz val\tSet the offset in the z direction from the average height of the floor polygons to val."<<std::endl;
    std::cerr<<"-o val\tSet the offset for both the x and y direction from the perimeter of the floor polygons to val."<<std::endl;
    std::cerr<<"-z val\tSet the z height of the analysis points using world coordinates to val."<<std::endl;
    std::cerr<<"-l name\tSet the layer name that will be used to find the polygons for use in creating the analysis grid to name.  Multiple layer names can be used, but each one must have a -l preceding it.  This is a mandatory option."<<std::endl;
    std::cerr<<"-r name\tSet the output file to name.  This file contains a space separated file in the following format per line:   x y z xd yd zd."<<std::endl;
    std::cerr<<"-t dist\tSet the threshold distance."<<std::endl;
    std::cerr<<"-vp location\tSet the location that the files should be placed for creating the parallel projection .bmp.  This should end in the directory separator."<<std::endl;
    std::cerr<<"-vse location\tSet the location that the files should be placed for creating the South East isometric .bmp.  This should end in the directory separator."<<std::endl;
    std::cerr<<"-vsw location\tSet the location that the files should be placed for creating the South West isometric .bmp.  This should end in the directory separator."<<std::endl;
    std::cerr<<"-vne location\tSet the location that the files should be placed for creating the North East isometric .bmp.  This should end in the directory separator."<<std::endl;
    std::cerr<<"-vnw location\tSet the location that the files should be placed for creating the North West isometric .bmp.  This should end in the directory separator."<<std::endl;
    std::cerr<<"-p name\tSet the ouput for the joined polygon to name. This file contains the joined polygon in the radiance polygon format with a modifier of \"floor\" and an identifier of \"floor1\"."<<std::endl;
    std::cerr<<"-csv name\tSet the csv formatted output file to name.  This file contains the points file output in a csv format."<<std::endl;
}

int main (int argc, char *argv[])
{
    if(argc == 1) {
        usage();
    }
    std::vector<std::string> fileName;
    std::string resultFile;
    std::string csvFile;
    std::string polyFile;
    std::string viewLocation;
    std::string vType;
    std::vector<std::string> layerNames;
    bool useZOffset=false;
    bool useOffset=false;
    double sx, sy, ox, oy, oz, offset,z;
    sx=0;
    sy=0;
    ox=0;
    oy=0;
    oz=0;
    offset=0;
    z=0;
    for (int i=1;i<argc;i++){
        if (std::strcmp(argv[i],"-f")==0){
            i++;
            fileName.push_back(argv[i]);
        }else if (std::strcmp(argv[i],"-sx")==0){
            i++;
            sx=atof(argv[i]);
        }else if (std::strcmp(argv[i],"-sy")==0){
            i++;
            sy=atof(argv[i]);
        }else if (std::strcmp(argv[i],"-ox")==0){
            i++;
            ox=atof(argv[i]);
        }else if (std::strcmp(argv[i],"-oy")==0){
            i++;
            oy=atof(argv[i]);
        }else if (std::strcmp(argv[i],"-oz")==0){
            i++;
            useZOffset=true;
            oz=atof(argv[i]);
        }else if (std::strcmp(argv[i],"-o")==0){
            i++;
            useOffset=true;
            offset=atof(argv[i]);
        }else if (std::strcmp(argv[i],"-z")==0){
            i++;
            z=atof(argv[i]);
        }else if (std::strcmp(argv[i],"-r")==0){
            i++;
            resultFile=argv[i];
        }else if(std::strcmp(argv[i],"-l")==0){
            i++;
            layerNames.push_back(argv[i]);
        }else if(std::strcmp(argv[i],"-vp")==0){
            i++;
            viewLocation=argv[i];
            vType="p";
        }else if(std::strcmp(argv[i],"-vse")==0){
            i++;
            viewLocation=argv[i];
            vType="se";
        }else if(std::strcmp(argv[i],"-vne")==0){
            i++;
            viewLocation=argv[i];
            vType="ne";
        }else if(std::strcmp(argv[i],"-vsw")==0){
            i++;
            viewLocation=argv[i];
            vType="sw";
        }else if(std::strcmp(argv[i],"-vnw")==0){
            i++;
            viewLocation=argv[i];
            vType="nw";
        }else if(std::strcmp(argv[i],"-p")==0){
            i++;
            polyFile=argv[i];
        }else if(std::strcmp(argv[i],"-csv")==0){
            i++;
            csvFile=argv[i];
        }else{
            std::string temp=argv[i];
            STADIC_WARNING("The argument "+temp+" is an unkown argument.");
        }
    }
    if (sx==0 ||sy==0){
        STADIC_ERROR(std::string("The x and y spacing are needed to complete the calculation.\n\tSpecify with \"-sx\" and \"-sy\"."));
        return EXIT_FAILURE;
    }
    if (fileName.empty()){
        STADIC_ERROR(std::string("The rad file name must be specified.\n\tSpecify with \"-f\"."));
        return EXIT_FAILURE;
    }

    //Instantiate GridMaker Object
    stadic::GridMaker grid(fileName);
    grid.setLayerNames(layerNames);
    grid.setSpaceX(sx);
    grid.setSpaceY(sy);
    if (useOffset){
        grid.setOffset(offset);
    }else{
    grid.setOffsetX(ox);
    grid.setOffsetY(oy);
    }
    if (useZOffset){
        grid.setOffsetZ(oz);
    }else{
    grid.setZHeight(z);
    }
    if (!grid.makeGrid()){
        return EXIT_FAILURE;
    }
    if (resultFile.empty()){
        if(!grid.writePTS()){
            STADIC_ERROR(std::string("The writing of the points file to the standard output has failed."));
            return EXIT_FAILURE;
        }
    }else{
        if (!grid.writePTS(resultFile)){
            STADIC_ERROR(std::string("The writing of the points file failed."));
            return EXIT_FAILURE;
        }
    }
    /*
    if (!polyFile.empty()){
        if (!grid.writeRadPoly(polyFile)){
            return EXIT_FAILURE;
        }
    }
    */
    if (!csvFile.empty()){
        if (!grid.writePTScsv(csvFile)){
            return EXIT_FAILURE;
        }
    }
    if (!viewLocation.empty()){
        if (!grid.viewPTS(viewLocation, vType)){
            return EXIT_FAILURE;
        }
    }
    return EXIT_SUCCESS;
}
<commit_msg>Added threshold argument to dxgridmaker.<commit_after>/****************************************************************
 * Copyright (c) 2014, The Pennsylvania State University
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms,
 * with or without modification, are permitted for
 * personal and commercial purposes provided that the
 * following conditions are met:
 *
 * 1. Redistribution of source code must retain the
 *    above copyright notice, this list of conditions
 *    and the following disclaimer.
 *
 * 2. Redistribution in binary form must reproduce the
 *    above copyright notice, this list of conditions
 *    and the following disclaimer.
 *
 * 3. Neither the name of The Pennsylvania State University
 *    nor the names of its contributors may be used to
 *    endorse or promote products derived from this software
 *    without the specific prior written permission of The
 *    Pennsylvania State University.
 *
 * THIS SOFTWARE IS PROVIDED BY THE PENNSYLVANIA STATE UNIVERSITY
 * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT OF
 * INTELLECTUAL PROPERTY ARE EXPRESSLY DISCLAIMED. IN NO EVENT
 * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGE.
 ****************************************************************/

#include "gridmaker.h"
#include "logging.h"
#include <vector>
#include <iostream>
#include <string>

void usage(){
    std::cerr<<"dxgridmaker generates a points file for use in RADIANCE analysis programs.  The program allows any number of polygons and any number of layer names to be used for the placement of points.  grid_maker will then join all of the polygons and create an array of points within the bounding rectangle and tests each point to determine whether it is within the joined polygon.  These points will then be written out to a given file name for use as input to other programs.  It is assumed that the units of the radiance geometry file are the same as the input units for the spacing, offset, and Z height."<<std::endl;
    std::cerr<<std::endl<<"-f name\tSet the input file to name. This file contains the radiance polygons that will be used for creating the analysis points.  This is a mandatory option."<<std::endl;
    std::cerr<<"-sx val\tSet the spacing in the x direction between the analysis points to val.  This is a mandatory option. "<<std::endl;
    std::cerr<<"-sy val\tSet the spacing in the y direction between the analysis points to val.  This is a mandatory option."<<std::endl;
    std::cerr<<"-ox val\tSet the offset in the x direction from the left side of the bounding rectangle to val."<<std::endl;
    std::cerr<<"-oy val\tSet the offset in the y direction from the lower side of the bounding rectangle to val."<<std::endl;
    std::cerr<<"-oz val\tSet the offset in the z direction from the average height of the floor polygons to val."<<std::endl;
    std::cerr<<"-o val\tSet the offset for both the x and y direction from the perimeter of the floor polygons to val."<<std::endl;
    std::cerr<<"-z val\tSet the z height of the analysis points using world coordinates to val."<<std::endl;
    std::cerr<<"-l name\tSet the layer name that will be used to find the polygons for use in creating the analysis grid to name.  Multiple layer names can be used, but each one must have a -l preceding it.  This is a mandatory option."<<std::endl;
    std::cerr<<"-r name\tSet the output file to name.  This file contains a space separated file in the following format per line:   x y z xd yd zd."<<std::endl;
    std::cerr<<"-t dist\tSet the threshold distance."<<std::endl;
    std::cerr<<"-vp location\tSet the location that the files should be placed for creating the parallel projection .bmp.  This should end in the directory separator."<<std::endl;
    std::cerr<<"-vse location\tSet the location that the files should be placed for creating the South East isometric .bmp.  This should end in the directory separator."<<std::endl;
    std::cerr<<"-vsw location\tSet the location that the files should be placed for creating the South West isometric .bmp.  This should end in the directory separator."<<std::endl;
    std::cerr<<"-vne location\tSet the location that the files should be placed for creating the North East isometric .bmp.  This should end in the directory separator."<<std::endl;
    std::cerr<<"-vnw location\tSet the location that the files should be placed for creating the North West isometric .bmp.  This should end in the directory separator."<<std::endl;
    std::cerr<<"-p name\tSet the ouput for the joined polygon to name. This file contains the joined polygon in the radiance polygon format with a modifier of \"floor\" and an identifier of \"floor1\"."<<std::endl;
    std::cerr<<"-csv name\tSet the csv formatted output file to name.  This file contains the points file output in a csv format."<<std::endl;
}

int main (int argc, char *argv[])
{
    if(argc == 1) {
        usage();
    }
    std::vector<std::string> fileName;
    std::string resultFile;
    std::string csvFile;
    std::string polyFile;
    std::string viewLocation;
    std::string vType;
    std::vector<std::string> layerNames;
    bool useZOffset=false;
    bool useOffset=false;
    bool useThreshold=false;
    double sx, sy, ox, oy, oz, offset,z, threshold;
    sx=0;
    sy=0;
    ox=0;
    oy=0;
    oz=0;
    offset=0;
    z=0;
    for (int i=1;i<argc;i++){
        if (std::strcmp(argv[i],"-f")==0){
            i++;
            fileName.push_back(argv[i]);
        }else if (std::strcmp(argv[i],"-sx")==0){
            i++;
            sx=atof(argv[i]);
        }else if (std::strcmp(argv[i],"-sy")==0){
            i++;
            sy=atof(argv[i]);
        }else if (std::strcmp(argv[i],"-ox")==0){
            i++;
            ox=atof(argv[i]);
        }else if (std::strcmp(argv[i],"-oy")==0){
            i++;
            oy=atof(argv[i]);
        }else if (std::strcmp(argv[i],"-oz")==0){
            i++;
            useZOffset=true;
            oz=atof(argv[i]);
        }else if (std::strcmp(argv[i],"-o")==0){
            i++;
            useOffset=true;
            offset=atof(argv[i]);
        }else if (std::strcmp(argv[i],"-z")==0){
            i++;
            z=atof(argv[i]);
        }else if (std::strcmp(argv[i],"-r")==0){
            i++;
            resultFile=argv[i];
        }else if(std::strcmp(argv[i],"-l")==0){
            i++;
            layerNames.push_back(argv[i]);
        }else if(std::strcmp(argv[i],"-vp")==0){
            i++;
            viewLocation=argv[i];
            vType="p";
        }else if(std::strcmp(argv[i],"-vse")==0){
            i++;
            viewLocation=argv[i];
            vType="se";
        }else if(std::strcmp(argv[i],"-vne")==0){
            i++;
            viewLocation=argv[i];
            vType="ne";
        }else if(std::strcmp(argv[i],"-vsw")==0){
            i++;
            viewLocation=argv[i];
            vType="sw";
        }else if(std::strcmp(argv[i],"-vnw")==0){
            i++;
            viewLocation=argv[i];
            vType="nw";
        }else if(std::strcmp(argv[i],"-p")==0){
            i++;
            polyFile=argv[i];
        }else if(std::strcmp(argv[i],"-csv")==0){
            i++;
            csvFile=argv[i];
        }else if(std::strcmp(argv[i],"-t")==0){
            i++;
            threshold==atof(argv[i]);
            useThreshold=true;
        }else{
            std::string temp=argv[i];
            STADIC_WARNING("The argument "+temp+" is an unkown argument.");
        }
    }
    if (sx==0 ||sy==0){
        STADIC_ERROR(std::string("The x and y spacing are needed to complete the calculation.\n\tSpecify with \"-sx\" and \"-sy\"."));
        return EXIT_FAILURE;
    }
    if (fileName.empty()){
        STADIC_ERROR(std::string("The rad file name must be specified.\n\tSpecify with \"-f\"."));
        return EXIT_FAILURE;
    }

    //Instantiate GridMaker Object
    stadic::GridMaker grid(fileName);
    grid.setLayerNames(layerNames);
    grid.setSpaceX(sx);
    grid.setSpaceY(sy);
    if (useOffset){
        grid.setOffset(offset);
    }else{
    grid.setOffsetX(ox);
    grid.setOffsetY(oy);
    }
    if (useZOffset){
        grid.setOffsetZ(oz);
    }else{
    grid.setZHeight(z);
    }
    if (useThreshold){
        grid.setThreshold(threshold);
    }
    if (!grid.makeGrid()){
        return EXIT_FAILURE;
    }
    if (resultFile.empty()){
        if(!grid.writePTS()){
            STADIC_ERROR(std::string("The writing of the points file to the standard output has failed."));
            return EXIT_FAILURE;
        }
    }else{
        if (!grid.writePTS(resultFile)){
            STADIC_ERROR(std::string("The writing of the points file failed."));
            return EXIT_FAILURE;
        }
    }
    /*
    if (!polyFile.empty()){
        if (!grid.writeRadPoly(polyFile)){
            return EXIT_FAILURE;
        }
    }
    */
    if (!csvFile.empty()){
        if (!grid.writePTScsv(csvFile)){
            return EXIT_FAILURE;
        }
    }
    if (!viewLocation.empty()){
        if (!grid.viewPTS(viewLocation, vType)){
            return EXIT_FAILURE;
        }
    }
    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include <stdlib.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <cstring>
#include <stdio.h>
#include <string>
#include <iostream>
#include <list>
#include <map>
#include <set>
#include <memory>

#include "server.h"
#include "duckchat.h"

// TODO Handle domain
// Server can accept connections.
// Server handles Login and Logout from users, and keeps records of which users are logged in.
// 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.

// TODO should users always receive messages on Common?

class Channel {
public:
  std::string name;
  std::list<std::shared_ptr<User>> users;

  Channel(std::string name): name(name) {};
};

class User {
public:
  std::string name;
  in_addr_t address;
  unsigned short port;

  User(std::string name, in_addr_t address, unsigned short port): name(name), address(address), port(port) {};
};

std::map<std::string, std::shared_ptr<User>> kUsers;
std::map<std::string, std::shared_ptr<Channel>> kChannels;

/**
 * Prints an error message and exists.
 */
void Error(const char *message) {
  perror(message);
  exit(1);
}

/**
 * Removes a users from every channel and from the global users list.
 *
 * @user is the user to remove.
 */
void RemoveUser(User *user) {
  for (auto channel : kChannels) {
    for (auto channel_user : channel.second->users) {
      if (channel_user->name == user->name) {
        channel.second->users.remove(channel_user);
        delete(user);
        break;
      }
    }
  }
  for (auto current_user : kUsers) {
    if (current_user.second->name == user->name) {
      kUsers.erase(user->name);
      delete(user);
    }
  }
}

struct sockaddr_in* CreateSockAddr(unsigned short port, in_addr_t address) {
  struct sockaddr_in *client_addr;
  memset(&client_addr, 0, sizeof(struct sockaddr_in));
  client_addr->sin_family = AF_INET;
  client_addr->sin_port = port;
  client_addr->sin_addr.s_addr = address;
  return client_addr;
}

/**
 * Logs in a user.
 *
 * @buffer is the login_request
 * @request_address is the user's address.
 * @request_port is the user's port.
 */
void HandleLoginRequest(void *buffer, in_addr_t request_address, unsigned short request_port) {
  struct request_login login_request;
  memcpy(&login_request, buffer, sizeof(struct request_login));

  std::shared_ptr<User> current_user = std::make_shared<User>(login_request.req_username, request_address, request_port);
//  RemoveUser(current_user);
  kUsers.insert({std::string(login_request.req_username), current_user});

  std::cout << "server: " << login_request.req_username << " logs in" << std::endl;
}

/**
 * Logs out a user.
 *
 * @buffer is the logout_request
 * @request_address is the user's address.
 * @request_port is the user's port.
 */
void HandleLogoutRequest(void *buffer, in_addr_t request_address, unsigned short request_port) {
  struct request_logout logout_request;
  memcpy(&logout_request, buffer, sizeof(struct request_logout));

  for (auto user : kUsers) {
    unsigned short current_port = user.second->port;
    in_addr_t current_address = user.second->address;

    if (current_port == request_port && current_address == request_address) {
      std::cout << "server: " << user.first << " logs out" << std::endl;
      kUsers.erase(user.first);
//      RemoveUser(user.second);
      for (auto c : kChannels) {
        for (auto u : c.second->users) {
          if (u->name == user.first) {
            c.second->users.remove(user.second);
//            delete(user.second);;
          }
        }
      }
//      delete(user.second);
      break;
    }
  }
}

/**
 * Adds a user to the requested channel.
 *
 * @buffer is the logout_request
 * @request_address is the user's address.
 * @request_port is the user's port.
 */
void HandleJoinRequest(void *buffer, in_addr_t request_address, unsigned short request_port) {
  struct request_join join_request;
  memcpy(&join_request, buffer, sizeof(struct request_join));
  bool is_new_channel = true;
  bool is_channel_user;
  std::shared_ptr<Channel> channel;

  // If channel does exists in global map, set local channel to channel from kChannels
  for (auto ch : kChannels) {
    if (join_request.req_channel == ch.second->name) {
      is_new_channel = false;
      channel = ch.second;
      break;
    }
  }

  // If channel is new create it
  if (is_new_channel) {
    channel = std::make_shared<Channel>(join_request.req_channel);
  }

  for (auto user : kUsers) {
    unsigned short current_port = user.second->port;
    in_addr_t current_address = user.second->address;
    if (current_port == request_port && current_address == request_address) {
      std::cout << "server: " << user.first << " joins channel "<< channel->name << std::endl;

      is_channel_user = false;
      for (auto u : channel->users) {
        if (u->name == user.second->name) {
          is_channel_user = true;
          break;
        }
      }

      if (!is_channel_user) {
        channel->users.push_back(user.second);
      }

      // Otherwise
      if (is_new_channel) {
        kChannels.insert({channel->name, channel});
      }
      break;
    }
  }
}

/**
 * Removes a user from the requested channel.
 *
 * @buffer is the logout_request
 * @request_address is the user's address.
 * @request_port is the user's port.
 */
void HandleLeaveRequest(void *buffer, in_addr_t request_address, unsigned short request_port) {
  std::shared_ptr<Channel> channel;
  std::string current_channel;
  std::list<std::shared_ptr<User>>::const_iterator it;
  bool is_channel;
  struct request_leave leave_request;

  memcpy(&leave_request, buffer, sizeof(struct request_leave));
  current_channel = leave_request.req_channel;

  for (auto user : kUsers) {
    unsigned short current_port = user.second->port;
    in_addr_t current_address = user.second->address;

    if (current_port == request_port && current_address == request_address) {
      is_channel = false;
      for (auto ch : kChannels) {
        if (ch.first == current_channel) {
          is_channel = true;
          break;
        }
      }

      if (is_channel) {
        channel = kChannels[current_channel];

        for (it = channel->users.begin(); it != channel->users.end(); ++it) {
          if ((*it)->name == user.first) {
            break;
          }
        }

        if (it != channel->users.end()) {
          channel->users.remove(*it);
          std::cout << user.first << " leaves channel " << channel->name << std::endl;
          if (channel->users.size() == 0) {
            kChannels.erase(channel->name);
//            delete(channel);
            std::cout << "server: removing empty channel " << channel->name << std::endl;
          }
        }
        break;
      } else {
        std::cout << "server: " << user.first << " trying to leave non-existent channel " << current_channel << std::endl;
      }

    }
  }
}

/**
 * Sends message from a user to the requested channel.
 *
 * @server_socket is the socket to send on.
 * @buffer is the logout_request
 * @request_address is the user's address.
 * @request_port is the user's port.
 */
void HandleSayRequest(int server_socket, void *buffer, in_addr_t request_address, unsigned short request_port) {
  struct request_say say_request;
  memcpy(&say_request, buffer, sizeof(struct request_say));

  for (auto user : kUsers) {
    unsigned short current_port = user.second->port;
    in_addr_t current_address = user.second->address;

    if (current_port == request_port && current_address == request_address) {
      for (auto channel_user : kChannels[say_request.req_channel]->users) {
        struct sockaddr_in client_addr;
        memset(&client_addr, 0, sizeof(struct sockaddr_in));

        struct text_say say;
        memcpy(&say, buffer, sizeof(struct text_say));

        client_addr.sin_family = AF_INET;
        client_addr.sin_port = channel_user->port;
        client_addr.sin_addr.s_addr = channel_user->address;

        // copy message into struct being sent
        strncpy(say.txt_channel, say_request.req_channel, CHANNEL_MAX);
        strncpy(say.txt_text, say_request.req_text, SAY_MAX);
        say.txt_type = TXT_SAY;
        strncpy(say.txt_username, user.second->name.c_str(), USERNAME_MAX);

        size_t message_size = sizeof(struct text_say);

        if (sendto(server_socket, &say, message_size, 0, (struct sockaddr*) &client_addr, sizeof(client_addr)) < 0) {
          Error("server: failed to send say\n");
        }
      }
      std::cout << user.second->name << " sends say message in " << say_request.req_channel << std::endl;
      break;
    }
  }
}

/**
 * Sends a text list packet containing every channel to the requesting user.
 *
 * @server_socket is the socket to send on.
 * @request_address is the address to send to.
 * @request_port is the port to send to.
 */
void HandleListRequest(int server_socket, in_addr_t request_address, unsigned short request_port) {
  struct sockaddr_in client_addr;
  size_t list_size = sizeof(text_list) + (kChannels.size() * sizeof(channel_info));
  struct text_list *list = (text_list *) malloc(list_size);
  memset(list, '\0', list_size);;

  list->txt_type = TXT_LIST;
  list->txt_nchannels = (int) kChannels.size();

  // Fills the packet's channels array.
  int i = 0;
  for (auto ch : kChannels) {
    strncpy(list->txt_channels[i++].ch_channel, ch.first.c_str(), CHANNEL_MAX);
  }

  // TODO Print test
  std::cout << "Channels:" << std::endl;
  for (i = 0; i < (int) kChannels.size(); i++) {
    std::cout << list->txt_channels[i].ch_channel << std::endl;
  }

  // Finds the requesting users address and port and sends the packet.
  for (auto user : kUsers) {
    unsigned short port = user.second->port;
    in_addr_t address = user.second->address;

    if (port == request_port && address == request_address) {
      memset(&client_addr, 0, sizeof(struct sockaddr_in));
      client_addr.sin_family = AF_INET;
      client_addr.sin_port = port;
      client_addr.sin_addr.s_addr = address;

      if (sendto(server_socket, list, list_size, 0, (struct sockaddr*) &client_addr, sizeof(client_addr)) < 0) {
        Error("server: failed to send list\n");
      }

      std::cout << "server: " << user.first << " lists channels" << std::endl;
      break;
    }
  }

  free(list);
}

/**
 * Sends a list of every user on the requested channel.
 *
 * @server_socket is the socket to send on.
 * @request_address is the address to send to.
 * @request_port is the port to send to.
 */
void HandleWhoRequest(int server_socket, in_addr_t request_address, unsigned short request_port) {
  std::cout << "Not implemented yet." << std::endl;
  std::cout << "server_socket: " << server_socket << std::endl;
  std::cout << "request_address: " << request_address << std::endl;
  std::cout << "request_port: " << request_port << std::endl;
}

/**
 * Processes a request.
 *
 * @server_socket is the socket to send on.
 * @buffer is the request
 * @request_address is the address to send to.
 * @request_port is the port to send to.
 */
void ProcessRequest(int server_socket, void *buffer, in_addr_t request_address, unsigned short request_port) {
  struct request current_request;
  memcpy(&current_request, buffer, sizeof(struct request));
  request_t request_type = current_request.req_type;

  switch(request_type) {
    case REQ_LOGIN:
      HandleLoginRequest(buffer, request_address, request_port);
      break;
    case REQ_LOGOUT:
      HandleLogoutRequest(buffer, request_address, request_port);
      break;
    case REQ_JOIN:
      HandleJoinRequest(buffer, request_address, request_port);
      break;
    case REQ_LEAVE:
      HandleLeaveRequest(buffer, request_address, request_port);
      break;
    case REQ_SAY:
      HandleSayRequest(server_socket, buffer, request_address, request_port);
      break;
    case REQ_LIST:
      HandleListRequest(server_socket, request_address, request_port);
      break;
    case REQ_WHO:
      HandleWhoRequest(server_socket, request_address, request_port);
      break;
    default:
      break;
  }
}

int main(int argc, char *argv[]) {
  struct sockaddr_in server_addr;

  int server_socket;
  int receive_len;
  void* buffer[kBufferSize];
  int port;
//  std::string domain;

  if (argc < 3) {
    std::cerr << "Usage: ./server domain_name port_num" << std::endl;
    exit(1);
  }

//  domain = argv[1];
  port = atoi(argv[2]);

  memset((char *) &server_addr, 0, sizeof(server_addr));
  server_addr.sin_family = AF_INET;
  server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  server_addr.sin_port = htons(port);

  if ((server_socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    Error("server: can't open socket\n");
  }

  if (bind(server_socket, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) {
    Error("server: bind failed\n");
  }

  printf("server: waiting on port %d\n", port);
  while (1) {
    struct sockaddr_in client_addr;
    socklen_t client_addr_len = sizeof(client_addr);
    receive_len = recvfrom(server_socket, buffer, kBufferSize, 0, (struct sockaddr *) &client_addr, &client_addr_len);

    if (receive_len > 0) {
      buffer[receive_len] = 0;

      ProcessRequest(server_socket, buffer, client_addr.sin_addr.s_addr, client_addr.sin_port);
    }
  }

//  for (auto user : kUsers) {
//    delete(user.second);
//  }
//  for (auto channel : kChannels) {
//    delete(channel.second);
//  }
}
<commit_msg>remove last change<commit_after>#include <stdlib.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <cstring>
#include <stdio.h>
#include <string>
#include <iostream>
#include <list>
#include <map>
#include <set>
#include <memory>

#include "server.h"
#include "duckchat.h"

// TODO Handle domain
// Server can accept connections.
// Server handles Login and Logout from users, and keeps records of which users are logged in.
// 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.

// TODO should users always receive messages on Common?

class Channel {
public:
  std::string name;
  std::list<std::shared_ptr<User>> users;

  Channel(std::string name): name(name) {};
};

class User {
public:
  std::string name;
  in_addr_t address;
  unsigned short port;

  User(std::string name, in_addr_t address, unsigned short port): name(name), address(address), port(port) {};
};

std::map<std::string, std::shared_ptr<User>> kUsers;
std::map<std::string, std::shared_ptr<Channel>> kChannels;

/**
 * Prints an error message and exists.
 */
void Error(const char *message) {
  perror(message);
  exit(1);
}

/**
 * Removes a users from every channel and from the global users list.
 *
 * @user is the user to remove.
 */
void RemoveUser(User *user) {
  for (auto channel : kChannels) {
    for (auto channel_user : channel.second->users) {
      if (channel_user->name == user->name) {
        channel.second->users.remove(channel_user);
        delete(user);
        break;
      }
    }
  }
  for (auto current_user : kUsers) {
    if (current_user.second->name == user->name) {
      kUsers.erase(user->name);
      delete(user);
    }
  }
}

struct sockaddr_in* CreateSockAddr(unsigned short port, in_addr_t address) {
  struct sockaddr_in *client_addr;
  memset(&client_addr, 0, sizeof(struct sockaddr_in));
  client_addr->sin_family = AF_INET;
  client_addr->sin_port = port;
  client_addr->sin_addr.s_addr = address;
  return client_addr;
}

/**
 * Logs in a user.
 *
 * @buffer is the login_request
 * @request_address is the user's address.
 * @request_port is the user's port.
 */
void HandleLoginRequest(void *buffer, in_addr_t request_address, unsigned short request_port) {
  struct request_login login_request;
  memcpy(&login_request, buffer, sizeof(struct request_login));

  std::shared_ptr<User> current_user = std::make_shared<User>(login_request.req_username, request_address, request_port);
//  RemoveUser(current_user);
  kUsers.insert({std::string(login_request.req_username), current_user});

  std::cout << "server: " << login_request.req_username << " logs in" << std::endl;
}

/**
 * Logs out a user.
 *
 * @buffer is the logout_request
 * @request_address is the user's address.
 * @request_port is the user's port.
 */
void HandleLogoutRequest(void *buffer, in_addr_t request_address, unsigned short request_port) {
  struct request_logout logout_request;
  memcpy(&logout_request, buffer, sizeof(struct request_logout));

  for (auto user : kUsers) {
    unsigned short current_port = user.second->port;
    in_addr_t current_address = user.second->address;

    if (current_port == request_port && current_address == request_address) {
      std::cout << "server: " << user.first << " logs out" << std::endl;
      kUsers.erase(user.first);
//      RemoveUser(user.second);
//      for (auto c : kChannels) {
//        for (auto u : c.second->users) {
//          if (u->name == user.first) {
//            c.second->users.e(user.second);
////            delete(user.second);;
//          }
//        }
//      }
//      delete(user.second);
      break;
    }
  }
}

/**
 * Adds a user to the requested channel.
 *
 * @buffer is the logout_request
 * @request_address is the user's address.
 * @request_port is the user's port.
 */
void HandleJoinRequest(void *buffer, in_addr_t request_address, unsigned short request_port) {
  struct request_join join_request;
  memcpy(&join_request, buffer, sizeof(struct request_join));
  bool is_new_channel = true;
  bool is_channel_user;
  std::shared_ptr<Channel> channel;

  // If channel does exists in global map, set local channel to channel from kChannels
  for (auto ch : kChannels) {
    if (join_request.req_channel == ch.second->name) {
      is_new_channel = false;
      channel = ch.second;
      break;
    }
  }

  // If channel is new create it
  if (is_new_channel) {
    channel = std::make_shared<Channel>(join_request.req_channel);
  }

  for (auto user : kUsers) {
    unsigned short current_port = user.second->port;
    in_addr_t current_address = user.second->address;
    if (current_port == request_port && current_address == request_address) {
      std::cout << "server: " << user.first << " joins channel "<< channel->name << std::endl;

      is_channel_user = false;
      for (auto u : channel->users) {
        if (u->name == user.second->name) {
          is_channel_user = true;
          break;
        }
      }

      if (!is_channel_user) {
        channel->users.push_back(user.second);
      }

      // Otherwise
      if (is_new_channel) {
        kChannels.insert({channel->name, channel});
      }
      break;
    }
  }
}

/**
 * Removes a user from the requested channel.
 *
 * @buffer is the logout_request
 * @request_address is the user's address.
 * @request_port is the user's port.
 */
void HandleLeaveRequest(void *buffer, in_addr_t request_address, unsigned short request_port) {
  std::shared_ptr<Channel> channel;
  std::string current_channel;
  std::list<std::shared_ptr<User>>::const_iterator it;
  bool is_channel;
  struct request_leave leave_request;

  memcpy(&leave_request, buffer, sizeof(struct request_leave));
  current_channel = leave_request.req_channel;

  for (auto user : kUsers) {
    unsigned short current_port = user.second->port;
    in_addr_t current_address = user.second->address;

    if (current_port == request_port && current_address == request_address) {
      is_channel = false;
      for (auto ch : kChannels) {
        if (ch.first == current_channel) {
          is_channel = true;
          break;
        }
      }

      if (is_channel) {
        channel = kChannels[current_channel];

        for (it = channel->users.begin(); it != channel->users.end(); ++it) {
          if ((*it)->name == user.first) {
            break;
          }
        }

        if (it != channel->users.end()) {
          channel->users.remove(*it);
          std::cout << user.first << " leaves channel " << channel->name << std::endl;
          if (channel->users.size() == 0) {
            kChannels.erase(channel->name);
//            delete(channel);
            std::cout << "server: removing empty channel " << channel->name << std::endl;
          }
        }
        break;
      } else {
        std::cout << "server: " << user.first << " trying to leave non-existent channel " << current_channel << std::endl;
      }

    }
  }
}

/**
 * Sends message from a user to the requested channel.
 *
 * @server_socket is the socket to send on.
 * @buffer is the logout_request
 * @request_address is the user's address.
 * @request_port is the user's port.
 */
void HandleSayRequest(int server_socket, void *buffer, in_addr_t request_address, unsigned short request_port) {
  struct request_say say_request;
  memcpy(&say_request, buffer, sizeof(struct request_say));

  for (auto user : kUsers) {
    unsigned short current_port = user.second->port;
    in_addr_t current_address = user.second->address;

    if (current_port == request_port && current_address == request_address) {
      for (auto channel_user : kChannels[say_request.req_channel]->users) {
        struct sockaddr_in client_addr;
        memset(&client_addr, 0, sizeof(struct sockaddr_in));

        struct text_say say;
        memcpy(&say, buffer, sizeof(struct text_say));

        client_addr.sin_family = AF_INET;
        client_addr.sin_port = channel_user->port;
        client_addr.sin_addr.s_addr = channel_user->address;

        // copy message into struct being sent
        strncpy(say.txt_channel, say_request.req_channel, CHANNEL_MAX);
        strncpy(say.txt_text, say_request.req_text, SAY_MAX);
        say.txt_type = TXT_SAY;
        strncpy(say.txt_username, user.second->name.c_str(), USERNAME_MAX);

        size_t message_size = sizeof(struct text_say);

        if (sendto(server_socket, &say, message_size, 0, (struct sockaddr*) &client_addr, sizeof(client_addr)) < 0) {
          Error("server: failed to send say\n");
        }
      }
      std::cout << user.second->name << " sends say message in " << say_request.req_channel << std::endl;
      break;
    }
  }
}

/**
 * Sends a text list packet containing every channel to the requesting user.
 *
 * @server_socket is the socket to send on.
 * @request_address is the address to send to.
 * @request_port is the port to send to.
 */
void HandleListRequest(int server_socket, in_addr_t request_address, unsigned short request_port) {
  struct sockaddr_in client_addr;
  size_t list_size = sizeof(text_list) + (kChannels.size() * sizeof(channel_info));
  struct text_list *list = (text_list *) malloc(list_size);
  memset(list, '\0', list_size);;

  list->txt_type = TXT_LIST;
  list->txt_nchannels = (int) kChannels.size();

  // Fills the packet's channels array.
  int i = 0;
  for (auto ch : kChannels) {
    strncpy(list->txt_channels[i++].ch_channel, ch.first.c_str(), CHANNEL_MAX);
  }

  // TODO Print test
  std::cout << "Channels:" << std::endl;
  for (i = 0; i < (int) kChannels.size(); i++) {
    std::cout << list->txt_channels[i].ch_channel << std::endl;
  }

  // Finds the requesting users address and port and sends the packet.
  for (auto user : kUsers) {
    unsigned short port = user.second->port;
    in_addr_t address = user.second->address;

    if (port == request_port && address == request_address) {
      memset(&client_addr, 0, sizeof(struct sockaddr_in));
      client_addr.sin_family = AF_INET;
      client_addr.sin_port = port;
      client_addr.sin_addr.s_addr = address;

      if (sendto(server_socket, list, list_size, 0, (struct sockaddr*) &client_addr, sizeof(client_addr)) < 0) {
        Error("server: failed to send list\n");
      }

      std::cout << "server: " << user.first << " lists channels" << std::endl;
      break;
    }
  }

  free(list);
}

/**
 * Sends a list of every user on the requested channel.
 *
 * @server_socket is the socket to send on.
 * @request_address is the address to send to.
 * @request_port is the port to send to.
 */
void HandleWhoRequest(int server_socket, in_addr_t request_address, unsigned short request_port) {
  std::cout << "Not implemented yet." << std::endl;
  std::cout << "server_socket: " << server_socket << std::endl;
  std::cout << "request_address: " << request_address << std::endl;
  std::cout << "request_port: " << request_port << std::endl;
}

/**
 * Processes a request.
 *
 * @server_socket is the socket to send on.
 * @buffer is the request
 * @request_address is the address to send to.
 * @request_port is the port to send to.
 */
void ProcessRequest(int server_socket, void *buffer, in_addr_t request_address, unsigned short request_port) {
  struct request current_request;
  memcpy(&current_request, buffer, sizeof(struct request));
  request_t request_type = current_request.req_type;

  switch(request_type) {
    case REQ_LOGIN:
      HandleLoginRequest(buffer, request_address, request_port);
      break;
    case REQ_LOGOUT:
      HandleLogoutRequest(buffer, request_address, request_port);
      break;
    case REQ_JOIN:
      HandleJoinRequest(buffer, request_address, request_port);
      break;
    case REQ_LEAVE:
      HandleLeaveRequest(buffer, request_address, request_port);
      break;
    case REQ_SAY:
      HandleSayRequest(server_socket, buffer, request_address, request_port);
      break;
    case REQ_LIST:
      HandleListRequest(server_socket, request_address, request_port);
      break;
    case REQ_WHO:
      HandleWhoRequest(server_socket, request_address, request_port);
      break;
    default:
      break;
  }
}

int main(int argc, char *argv[]) {
  struct sockaddr_in server_addr;

  int server_socket;
  int receive_len;
  void* buffer[kBufferSize];
  int port;
//  std::string domain;

  if (argc < 3) {
    std::cerr << "Usage: ./server domain_name port_num" << std::endl;
    exit(1);
  }

//  domain = argv[1];
  port = atoi(argv[2]);

  memset((char *) &server_addr, 0, sizeof(server_addr));
  server_addr.sin_family = AF_INET;
  server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  server_addr.sin_port = htons(port);

  if ((server_socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    Error("server: can't open socket\n");
  }

  if (bind(server_socket, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) {
    Error("server: bind failed\n");
  }

  printf("server: waiting on port %d\n", port);
  while (1) {
    struct sockaddr_in client_addr;
    socklen_t client_addr_len = sizeof(client_addr);
    receive_len = recvfrom(server_socket, buffer, kBufferSize, 0, (struct sockaddr *) &client_addr, &client_addr_len);

    if (receive_len > 0) {
      buffer[receive_len] = 0;

      ProcessRequest(server_socket, buffer, client_addr.sin_addr.s_addr, client_addr.sin_port);
    }
  }

//  for (auto user : kUsers) {
//    delete(user.second);
//  }
//  for (auto channel : kChannels) {
//    delete(channel.second);
//  }
}
<|endoftext|>


<commit_before>// Copyright 2014 BVLC and contributors.

#include <cmath>
#include <cstdlib>
#include <cstring>
#include <vector>

#include "cuda_runtime.h"
#include "gtest/gtest.h"
#include "caffe/blob.hpp"
#include "caffe/common.hpp"
#include "caffe/filler.hpp"
#include "caffe/vision_layers.hpp"
#include "caffe/test/test_gradient_check_util.hpp"

#include "caffe/test/test_caffe_main.hpp"

namespace caffe {

extern cudaDeviceProp CAFFE_TEST_CUDA_PROP;

template <typename Dtype>
class HingeLossLayerTest : public ::testing::Test {
 protected:
  HingeLossLayerTest()
      : blob_bottom_data_(new Blob<Dtype>(10, 5, 1, 1)),
        blob_bottom_label_(new Blob<Dtype>(10, 1, 1, 1)) {
    // fill the values
    FillerParameter filler_param;
    filler_param.set_std(10);
    GaussianFiller<Dtype> filler(filler_param);
    filler.Fill(this->blob_bottom_data_);
    blob_bottom_vec_.push_back(blob_bottom_data_);
    for (int i = 0; i < blob_bottom_label_->count(); ++i) {
      blob_bottom_label_->mutable_cpu_data()[i] = caffe_rng_rand() % 5;
    }
    blob_bottom_vec_.push_back(blob_bottom_label_);
  }
  virtual ~HingeLossLayerTest() {
    delete blob_bottom_data_;
    delete blob_bottom_label_;
  }
  Blob<Dtype>* const blob_bottom_data_;
  Blob<Dtype>* const blob_bottom_label_;
  vector<Blob<Dtype>*> blob_bottom_vec_;
  vector<Blob<Dtype>*> blob_top_vec_;
};

typedef ::testing::Types<float, double> Dtypes;
TYPED_TEST_CASE(HingeLossLayerTest, Dtypes);

TYPED_TEST(HingeLossLayerTest, TestGradientCPU) {
  LayerParameter layer_param;
  Caffe::set_mode(Caffe::CPU);
  HingeLossLayer<TypeParam> layer(layer_param);
  layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_);
  GradientChecker<TypeParam> checker(1e-2, 1e-3, 1701, 1, 0.01);
  checker.CheckGradientSingle(&layer, &(this->blob_bottom_vec_),
      &(this->blob_top_vec_), 0, -1, -1);
}

TYPED_TEST(HingeLossLayerTest, TestGradientGPU) {
  LayerParameter layer_param;
  Caffe::set_mode(Caffe::GPU);
  HingeLossLayer<TypeParam> layer(layer_param);
  layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_);
  GradientChecker<TypeParam> checker(1e-2, 1e-3, 1701, 1, 0.01);
  checker.CheckGradientSingle(&layer, &(this->blob_bottom_vec_),
      &(this->blob_top_vec_), 0, -1, -1);
}

TYPED_TEST(HingeLossLayerTest, TestGradientL2CPU) {
  LayerParameter layer_param;
  // Set norm to L2
  HingeLossParameter* hinge_loss_param = layer_param.mutable_hinge_loss_param();
  hinge_loss_param->set_norm(HingeLossParameter_Norm_L2);
  Caffe::set_mode(Caffe::CPU);
  HingeLossLayer<TypeParam> layer(layer_param);
  layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_);
  GradientChecker<TypeParam> checker(1e-2, 2e-3, 1701);
  checker.CheckGradientSingle(&layer, &(this->blob_bottom_vec_),
      &(this->blob_top_vec_), 0, -1, -1);
}

TYPED_TEST(HingeLossLayerTest, TestGradientL2GPU) {
  LayerParameter layer_param;
  // Set norm to L2
  HingeLossParameter* hinge_loss_param = layer_param.mutable_hinge_loss_param();
  hinge_loss_param->set_norm(HingeLossParameter_Norm_L2);
  Caffe::set_mode(Caffe::GPU);
  HingeLossLayer<TypeParam> layer(layer_param);
  layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_);
  GradientChecker<TypeParam> checker(1e-2, 2e-3, 1701);
  checker.CheckGradientSingle(&layer, &(this->blob_bottom_vec_),
      &(this->blob_top_vec_), 0, -1, -1);
}

}  // namespace caffe
<commit_msg>explicitly name L1 hinge test<commit_after>// Copyright 2014 BVLC and contributors.

#include <cmath>
#include <cstdlib>
#include <cstring>
#include <vector>

#include "cuda_runtime.h"
#include "gtest/gtest.h"
#include "caffe/blob.hpp"
#include "caffe/common.hpp"
#include "caffe/filler.hpp"
#include "caffe/vision_layers.hpp"
#include "caffe/test/test_gradient_check_util.hpp"

#include "caffe/test/test_caffe_main.hpp"

namespace caffe {

extern cudaDeviceProp CAFFE_TEST_CUDA_PROP;

template <typename Dtype>
class HingeLossLayerTest : public ::testing::Test {
 protected:
  HingeLossLayerTest()
      : blob_bottom_data_(new Blob<Dtype>(10, 5, 1, 1)),
        blob_bottom_label_(new Blob<Dtype>(10, 1, 1, 1)) {
    // fill the values
    FillerParameter filler_param;
    filler_param.set_std(10);
    GaussianFiller<Dtype> filler(filler_param);
    filler.Fill(this->blob_bottom_data_);
    blob_bottom_vec_.push_back(blob_bottom_data_);
    for (int i = 0; i < blob_bottom_label_->count(); ++i) {
      blob_bottom_label_->mutable_cpu_data()[i] = caffe_rng_rand() % 5;
    }
    blob_bottom_vec_.push_back(blob_bottom_label_);
  }
  virtual ~HingeLossLayerTest() {
    delete blob_bottom_data_;
    delete blob_bottom_label_;
  }
  Blob<Dtype>* const blob_bottom_data_;
  Blob<Dtype>* const blob_bottom_label_;
  vector<Blob<Dtype>*> blob_bottom_vec_;
  vector<Blob<Dtype>*> blob_top_vec_;
};

typedef ::testing::Types<float, double> Dtypes;
TYPED_TEST_CASE(HingeLossLayerTest, Dtypes);

TYPED_TEST(HingeLossLayerTest, TestGradientL1CPU) {
  LayerParameter layer_param;
  Caffe::set_mode(Caffe::CPU);
  HingeLossLayer<TypeParam> layer(layer_param);
  layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_);
  GradientChecker<TypeParam> checker(1e-2, 1e-3, 1701, 1, 0.01);
  checker.CheckGradientSingle(&layer, &(this->blob_bottom_vec_),
      &(this->blob_top_vec_), 0, -1, -1);
}

TYPED_TEST(HingeLossLayerTest, TestGradientL1GPU) {
  LayerParameter layer_param;
  Caffe::set_mode(Caffe::GPU);
  HingeLossLayer<TypeParam> layer(layer_param);
  layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_);
  GradientChecker<TypeParam> checker(1e-2, 1e-3, 1701, 1, 0.01);
  checker.CheckGradientSingle(&layer, &(this->blob_bottom_vec_),
      &(this->blob_top_vec_), 0, -1, -1);
}

TYPED_TEST(HingeLossLayerTest, TestGradientL2CPU) {
  LayerParameter layer_param;
  // Set norm to L2
  HingeLossParameter* hinge_loss_param = layer_param.mutable_hinge_loss_param();
  hinge_loss_param->set_norm(HingeLossParameter_Norm_L2);
  Caffe::set_mode(Caffe::CPU);
  HingeLossLayer<TypeParam> layer(layer_param);
  layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_);
  GradientChecker<TypeParam> checker(1e-2, 2e-3, 1701);
  checker.CheckGradientSingle(&layer, &(this->blob_bottom_vec_),
      &(this->blob_top_vec_), 0, -1, -1);
}

TYPED_TEST(HingeLossLayerTest, TestGradientL2GPU) {
  LayerParameter layer_param;
  // Set norm to L2
  HingeLossParameter* hinge_loss_param = layer_param.mutable_hinge_loss_param();
  hinge_loss_param->set_norm(HingeLossParameter_Norm_L2);
  Caffe::set_mode(Caffe::GPU);
  HingeLossLayer<TypeParam> layer(layer_param);
  layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_);
  GradientChecker<TypeParam> checker(1e-2, 2e-3, 1701);
  checker.CheckGradientSingle(&layer, &(this->blob_bottom_vec_),
      &(this->blob_top_vec_), 0, -1, -1);
}

}  // namespace caffe
<|endoftext|>


<commit_before>//************************************************************************
//*	main.c
//*
//*	Arduino core files for PIC32
//*		Copyright (c) 2010, 2011 by Mark Sproul
//*
//*
//************************************************************************
//*	this code is based on code Copyright (c) 2005-2006 David A. Mellis
//*
//*	This library is free software; you can redistribute it and/or
//*	modify it under the terms of the GNU Lesser General Public
//*	License as published by the Free Software Foundation; either
//*	version 2.1 of the License, or (at your option) any later version.
//*
//*	This library 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
//*	Lesser General Public License for more details.
//*
//*	You should have received a copy of the GNU Lesser General
//*	Public License along with this library; if not, write to the
//*	Free Software Foundation, Inc., 59 Temple Place, Suite 330,
//*	Boston, MA  02111-1307  USA
//*
//*
//************************************************************************
//*	Edit History
//************************************************************************
//*	Oct 12,	2010	Got MPLAB X working on MacOSX 1.6 for the first time
//* Dec 12, 2011 <GeneApperson> added call to _scheduleTask() before call
//*					to loop().
//************************************************************************

#define OPT_SYSTEM_INTERNAL
#include <System_Defs.h>

#if (ARDUINO >= 100)
	#include <Arduino.h>
#else
	#include <WProgram.h>
#endif

extern "C" {
extern void __use_isr_install(void);
__attribute__((section(".comment"))) void (*__use_force_isr_install)(void) = &__use_isr_install;
}

//************************************************************************
int main(void)
{
	init();

	setup();

	while (1)
	{
		_scheduleTask();
		loop();
	}
	return 0;
}

<commit_msg>Added read only comment to main.cpp per isse #356<commit_after>//************************************************************************
//*	main.c
//*
//*	Arduino core files for PIC32
//*		Copyright (c) 2010, 2011 by Mark Sproul
//*
//*
//************************************************************************
//*	this code is based on code Copyright (c) 2005-2006 David A. Mellis
//*
//*	This library is free software; you can redistribute it and/or
//*	modify it under the terms of the GNU Lesser General Public
//*	License as published by the Free Software Foundation; either
//*	version 2.1 of the License, or (at your option) any later version.
//*
//*	This library 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
//*	Lesser General Public License for more details.
//*
//*	You should have received a copy of the GNU Lesser General
//*	Public License along with this library; if not, write to the
//*	Free Software Foundation, Inc., 59 Temple Place, Suite 330,
//*	Boston, MA  02111-1307  USA
//*
//*
//************************************************************************
//*	Edit History
//************************************************************************
//*	Oct 12,	2010	Got MPLAB X working on MacOSX 1.6 for the first time
//* Dec 12, 2011 <GeneApperson> added call to _scheduleTask() before call
//*					to loop().
//************************************************************************

//!!! This section is a read only section !!!

#define OPT_SYSTEM_INTERNAL
#include <System_Defs.h>

#if (ARDUINO >= 100)
	#include <Arduino.h>
#else
	#include <WProgram.h>
#endif

extern "C" {
extern void __use_isr_install(void);
__attribute__((section(".comment"))) void (*__use_force_isr_install)(void) = &__use_isr_install;
}

//************************************************************************
int main(void)
{
	init();

	setup();

	while (1)
	{
		_scheduleTask();
		loop();
	}
	return 0;
}

<|endoftext|>


<commit_before>#include <vector>
#include <iostream>
#include "protocol.hpp"
#include "server.hpp"

// sockets
#if defined(_WIN32)
#define NOMINMAX
#include <winsock2.h>
#include <ws2tcpip.h>
typedef SOCKET SocketType;
typedef int AddressLenType;
const SocketType kInvalidSocket = INVALID_SOCKET;
#else
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
typedef int SocketType;
typedef socklen_t AddressLenType;
const SocketType kInvalidSocket = -1;
#endif

// threads
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
#include <stdlib.h>
#include <pthread.h>
#endif

// time
#if defined(__APPLE__)
#include <stdint.h>
#include <mach/mach_time.h>
#endif
#if !defined(_WIN32)
#include <sys/time.h>
#endif
#include <time.h>

static
long NowTime() {
#if defined(_WIN32)
  __int64 freq = 0;
  if (!QueryPerformanceFrequency((LARGE_INTEGER *) &freq))
    return 0;
  __int64 cur = 0;
  QueryPerformanceCounter((LARGE_INTEGER *) &cur);
  return (long) (cur / freq) * 1000;
#elif defined(__APPLE__)
  mach_timebase_info_data_t time_info;
  mach_timebase_info(&time_info);

  uint64_t cur = mach_absolute_time();
  return (long) ((cur / (time_info.denom * 1000000)) * time_info.numer);
#else
  struct timespec ts;
  clock_gettime(CLOCK_MONOTONIC, &ts);
  return (long) (ts.tv_sec * 1000 + ts.tv_nsec / 1000000);
#endif

  return 0;
}

namespace udpdiscovery {
  namespace impl {
    class ServerWorkingEnv : public ServerWorkingEnvInterface {
     public:
      ServerWorkingEnv() : sock_(kInvalidSocket), exit_(false) {
#if defined(_WIN32)
        InitializeCriticalSection(&critical_section_);
#else
        pthread_mutex_init(&mutex_, 0);
#endif
      }

      ~ServerWorkingEnv() {
        if (sock_ != kInvalidSocket) {
#if defined(_WIN32)
          closesocket(sock_);
#else
          close(sock_);
#endif
        }

#if defined(_WIN32)
        DeleteCriticalSection(&critical_section_);
#else
        pthread_mutex_destroy(&mutex_);
#endif
      }

      bool StartServer(int port) {
#if defined(_WIN32)
        WSADATA wsa_data;
        WSAStartup(MAKEWORD(2, 2), &wsa_data);
#endif

        sock_ = socket(AF_INET, SOCK_DGRAM, 0);
        if (sock_ == kInvalidSocket) {
          std::cerr << "udpdiscovery::Server can't create socket" << std::endl;
          return false;
        }

        int value = 1;
        setsockopt(sock_, SOL_SOCKET, SO_REUSEADDR, (const char *) &value, sizeof(value));

        const int receive_timeout = 500;
#if defined(_WIN32)
        {
          int timeout = receive_timeout;
          setsockopt(sock_, SOL_SOCKET, SO_RCVTIMEO, (const char *) &timeout, sizeof(timeout));
        }
#else
        {
          struct timeval timeout;
          timeout.tv_sec = receive_timeout / 1000;
          timeout.tv_usec = 1000 * (receive_timeout % 1000);
          setsockopt(sock_, SOL_SOCKET, SO_RCVTIMEO, (const char *) &timeout, sizeof(timeout));
        }
#endif

        sockaddr_in addr;
        memset((char *) &addr, 0, sizeof(sockaddr_in));
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        addr.sin_addr.s_addr = htonl(INADDR_ANY);

        if (bind(sock_, (struct sockaddr *) &addr, sizeof(sockaddr_in)) < 0) {
          if (sock_ != kInvalidSocket) {
#if defined(_WIN32)
            closesocket(sock_);
#else
            close(sock_);
#endif
          }

          sock_ = kInvalidSocket;

          std::cerr << "udpdiscovery::Server can't bind socket" << std::endl;
          return false;
        }

        buffer_.resize(kMaxPacketSize);

        return true;
      }

      void Update() {
        sockaddr_in from_addr;
        AddressLenType addr_length = sizeof(sockaddr_in);

        int length = (int) recvfrom(sock_, &buffer_[0], buffer_.size(), 0, (struct sockaddr *) &from_addr, &addr_length);
        if (length <= 0) {
          lock();
          deleteIdle(NowTime());
          unlock();

          return;
        }

        IpPort from;
        from.set_port(ntohs(from_addr.sin_port));
        from.set_ip(ntohl(from_addr.sin_addr.s_addr));

        if (length >= sizeof(PacketHeader)) {
          PacketHeader header;
          if (ParsePacketHeader(buffer_.data(), sizeof(PacketHeader), header)) {
            std::string user_data(
              buffer_.begin() + sizeof(PacketHeader), buffer_.begin() + sizeof(PacketHeader) + header.user_data_size);

            lock();

            std::list<DiscoveredClient>::iterator find_it = discovered_clients_.end();
            for (std::list<DiscoveredClient>::iterator it = discovered_clients_.begin(); it != discovered_clients_.end(); ++it) {
              if (Same((*it).ip_port(), from)) {
                find_it = it;
                break;
              }
            }

            long cur_time = NowTime();

            if (find_it == discovered_clients_.end()) {
              discovered_clients_.push_back(DiscoveredClient());
              discovered_clients_.back().set_ip_port(from);
              discovered_clients_.back().SetUserData(user_data, header.packet_index);
              discovered_clients_.back().set_last_updated(cur_time);
            } else {
              bool new_user_data = false;
              if (header.packet_index_reset) {
                new_user_data = true;
              } else {
                if ((*find_it).last_received_packet() < header.packet_index)
                  new_user_data = true;
              }

              if (new_user_data)
                (*find_it).SetUserData(user_data, header.packet_index);
              (*find_it).set_last_updated(cur_time);
            }

            deleteIdle(cur_time);

            unlock();
          }
        }
      }

      std::list<DiscoveredClient> ListClients() {
        lock();
        std::list<DiscoveredClient> result = discovered_clients_;
        unlock();

        return result;
      }

      void Exit() {
        lock();
        exit_ = true;
        unlock();
      }

      bool CanExit() {
        lock();
        bool result = exit_;
        unlock();

        return result;
      }

     private:
      void deleteIdle(long cur_time) {
        long idle_timeout = 5000;

        std::vector<std::list<DiscoveredClient>::iterator> to_delete;
        for (std::list<DiscoveredClient>::iterator it = discovered_clients_.begin(); it != discovered_clients_.end(); ++it) {
          if (cur_time - (*it).last_updated() > idle_timeout)
            to_delete.push_back(it);
        }

        for (size_t i = 0; i < to_delete.size(); ++i)
          discovered_clients_.erase(to_delete[i]);
      }

     private:
      std::string buffer_;
      SocketType sock_;

      void lock() {
#if defined(_WIN32)
        EnterCriticalSection(&critical_section_);
#else
        pthread_mutex_lock(&mutex_);
#endif
      }

      void unlock() {
#if defined(_WIN32)
        LeaveCriticalSection(&critical_section_);
#else
        pthread_mutex_unlock(&mutex_);
#endif
      }

#if defined(_WIN32)
      CRITICAL_SECTION critical_section_;
#else
      pthread_mutex_t mutex_;
#endif
      bool exit_;
      std::list<DiscoveredClient> discovered_clients_;
    };

    void ServerWorkingFunc(ServerWorkingEnv* working_env) {
      while (!working_env->CanExit()) {
        working_env->Update();
      }

      delete working_env;
    }

#if defined(_WIN32)
    DWORD WINAPI PlatformServerWorkingFunc(void* working_env_typeless) {
      ServerWorkingEnv* working_env = (ServerWorkingEnv*) working_env_typeless;
      ServerWorkingFunc(working_env);

      return 0;
    }
#else
    void* PlatformServerWorkingFunc(void* working_env_typeless) {
      ServerWorkingEnv* working_env = (ServerWorkingEnv*) working_env_typeless;
      ServerWorkingFunc(working_env);

      return 0;
    }
#endif
  };

  Server::Server() : started_(false) {
  }

  Server::~Server() {
    Stop();
  }

  bool Server::Start(int port) {
    Stop();

    impl::ServerWorkingEnv* working_env = new impl::ServerWorkingEnv();
    if (!working_env->StartServer(port)) {
      delete working_env;
      return false;
    }

    working_env_ = working_env;

#if defined(_WIN32)
    HANDLE thread = CreateThread(NULL, 0, impl::PlatformServerWorkingFunc, working_env_, 0, NULL);
    CloseHandle(thread);
#else
    pthread_t thread;
    pthread_create(&thread, 0, impl::PlatformServerWorkingFunc, working_env_);
    pthread_detach(thread);
#endif

    started_ = true;

    return true;
  }

  std::list<DiscoveredClient> Server::ListClients() const {
    std::list<DiscoveredClient> empty_discovered_clients;
    if (!started_)
      return empty_discovered_clients;
    return working_env_->ListClients();
  }

  void Server::Stop() {
    if (!started_)
      return;

    working_env_->Exit();
    working_env_ = 0;

    started_ = false;
  }

  bool Same(const IpPort& lhv, const IpPort& rhv) {
    return lhv == rhv;
  }

  bool Same(const std::list<DiscoveredClient>& lhv, const std::list<DiscoveredClient>& rhv) {
    for (std::list<DiscoveredClient>::const_iterator lhv_it = lhv.begin(); lhv_it != lhv.end(); ++lhv_it) {
      std::list<DiscoveredClient>::const_iterator in_rhv = rhv.end();
      for (std::list<DiscoveredClient>::const_iterator rhv_it = rhv.begin(); rhv_it != rhv.end(); ++rhv_it) {
        if (Same((*lhv_it).ip_port(), (*rhv_it).ip_port())) {
          in_rhv = rhv_it;
          break;
        }
      }

      if (in_rhv == rhv.end())
        return false;
    }

    for (std::list<DiscoveredClient>::const_iterator rhv_it = rhv.begin(); rhv_it != rhv.end(); ++rhv_it) {
      std::list<DiscoveredClient>::const_iterator in_lhv = lhv.end();
      for (std::list<DiscoveredClient>::const_iterator lhv_it = lhv.begin(); lhv_it != lhv.end(); ++lhv_it) {
        if (Same((*rhv_it).ip_port(), (*lhv_it).ip_port())) {
          in_lhv = lhv_it;
          break;
        }
      }

      if (in_lhv == lhv.end())
        return false;
    }

    return true;
  }
};
<commit_msg>Correct time measure on windows<commit_after>#include <vector>
#include <iostream>
#include "protocol.hpp"
#include "server.hpp"

// sockets
#if defined(_WIN32)
#define NOMINMAX
#include <winsock2.h>
#include <ws2tcpip.h>
typedef SOCKET SocketType;
typedef int AddressLenType;
const SocketType kInvalidSocket = INVALID_SOCKET;
#else
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
typedef int SocketType;
typedef socklen_t AddressLenType;
const SocketType kInvalidSocket = -1;
#endif

// threads
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
#include <stdlib.h>
#include <pthread.h>
#endif

// time
#if defined(__APPLE__)
#include <stdint.h>
#include <mach/mach_time.h>
#endif
#if !defined(_WIN32)
#include <sys/time.h>
#endif
#include <time.h>

static
long NowTime() {
#if defined(_WIN32)
  LARGE_INTEGER freq;
  if (!QueryPerformanceFrequency(&freq))
    return 0;
  LARGE_INTEGER cur;
  QueryPerformanceCounter(&cur);
  return (long) (cur.QuadPart * 1000 / freq.QuadPart);
#elif defined(__APPLE__)
  mach_timebase_info_data_t time_info;
  mach_timebase_info(&time_info);

  uint64_t cur = mach_absolute_time();
  return (long) ((cur / (time_info.denom * 1000000)) * time_info.numer);
#else
  struct timespec ts;
  clock_gettime(CLOCK_MONOTONIC, &ts);
  return (long) (ts.tv_sec * 1000 + ts.tv_nsec / 1000000);
#endif

  return 0;
}

namespace udpdiscovery {
  namespace impl {
    class ServerWorkingEnv : public ServerWorkingEnvInterface {
     public:
      ServerWorkingEnv() : sock_(kInvalidSocket), exit_(false) {
#if defined(_WIN32)
        InitializeCriticalSection(&critical_section_);
#else
        pthread_mutex_init(&mutex_, 0);
#endif
      }

      ~ServerWorkingEnv() {
        if (sock_ != kInvalidSocket) {
#if defined(_WIN32)
          closesocket(sock_);
#else
          close(sock_);
#endif
        }

#if defined(_WIN32)
        DeleteCriticalSection(&critical_section_);
#else
        pthread_mutex_destroy(&mutex_);
#endif
      }

      bool StartServer(int port) {
#if defined(_WIN32)
        WSADATA wsa_data;
        WSAStartup(MAKEWORD(2, 2), &wsa_data);
#endif

        sock_ = socket(AF_INET, SOCK_DGRAM, 0);
        if (sock_ == kInvalidSocket) {
          std::cerr << "udpdiscovery::Server can't create socket" << std::endl;
          return false;
        }

        int value = 1;
        setsockopt(sock_, SOL_SOCKET, SO_REUSEADDR, (const char *) &value, sizeof(value));

        const int receive_timeout = 500;
#if defined(_WIN32)
        {
          int timeout = receive_timeout;
          setsockopt(sock_, SOL_SOCKET, SO_RCVTIMEO, (const char *) &timeout, sizeof(timeout));
        }
#else
        {
          struct timeval timeout;
          timeout.tv_sec = receive_timeout / 1000;
          timeout.tv_usec = 1000 * (receive_timeout % 1000);
          setsockopt(sock_, SOL_SOCKET, SO_RCVTIMEO, (const char *) &timeout, sizeof(timeout));
        }
#endif

        sockaddr_in addr;
        memset((char *) &addr, 0, sizeof(sockaddr_in));
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        addr.sin_addr.s_addr = htonl(INADDR_ANY);

        if (bind(sock_, (struct sockaddr *) &addr, sizeof(sockaddr_in)) < 0) {
          if (sock_ != kInvalidSocket) {
#if defined(_WIN32)
            closesocket(sock_);
#else
            close(sock_);
#endif
          }

          sock_ = kInvalidSocket;

          std::cerr << "udpdiscovery::Server can't bind socket" << std::endl;
          return false;
        }

        buffer_.resize(kMaxPacketSize);

        return true;
      }

      void Update() {
        sockaddr_in from_addr;
        AddressLenType addr_length = sizeof(sockaddr_in);

        int length = (int) recvfrom(sock_, &buffer_[0], buffer_.size(), 0, (struct sockaddr *) &from_addr, &addr_length);
        if (length <= 0) {
          lock();
          deleteIdle(NowTime());
          unlock();

          return;
        }

        IpPort from;
        from.set_port(ntohs(from_addr.sin_port));
        from.set_ip(ntohl(from_addr.sin_addr.s_addr));

        if (length >= sizeof(PacketHeader)) {
          PacketHeader header;
          if (ParsePacketHeader(buffer_.data(), sizeof(PacketHeader), header)) {
            std::string user_data(
              buffer_.begin() + sizeof(PacketHeader), buffer_.begin() + sizeof(PacketHeader) + header.user_data_size);

            lock();

            std::list<DiscoveredClient>::iterator find_it = discovered_clients_.end();
            for (std::list<DiscoveredClient>::iterator it = discovered_clients_.begin(); it != discovered_clients_.end(); ++it) {
              if (Same((*it).ip_port(), from)) {
                find_it = it;
                break;
              }
            }

            long cur_time = NowTime();

            if (find_it == discovered_clients_.end()) {
              discovered_clients_.push_back(DiscoveredClient());
              discovered_clients_.back().set_ip_port(from);
              discovered_clients_.back().SetUserData(user_data, header.packet_index);
              discovered_clients_.back().set_last_updated(cur_time);
            } else {
              bool new_user_data = false;
              if (header.packet_index_reset) {
                new_user_data = true;
              } else {
                if ((*find_it).last_received_packet() < header.packet_index)
                  new_user_data = true;
              }

              if (new_user_data)
                (*find_it).SetUserData(user_data, header.packet_index);
              (*find_it).set_last_updated(cur_time);
            }

            deleteIdle(cur_time);

            unlock();
          }
        }
      }

      std::list<DiscoveredClient> ListClients() {
        lock();
        std::list<DiscoveredClient> result = discovered_clients_;
        unlock();

        return result;
      }

      void Exit() {
        lock();
        exit_ = true;
        unlock();
      }

      bool CanExit() {
        lock();
        bool result = exit_;
        unlock();

        return result;
      }

     private:
      void deleteIdle(long cur_time) {
        long idle_timeout = 5000;

        std::vector<std::list<DiscoveredClient>::iterator> to_delete;
        for (std::list<DiscoveredClient>::iterator it = discovered_clients_.begin(); it != discovered_clients_.end(); ++it) {
          if (cur_time - (*it).last_updated() > idle_timeout)
            to_delete.push_back(it);
        }

        for (size_t i = 0; i < to_delete.size(); ++i)
          discovered_clients_.erase(to_delete[i]);
      }

     private:
      std::string buffer_;
      SocketType sock_;

      void lock() {
#if defined(_WIN32)
        EnterCriticalSection(&critical_section_);
#else
        pthread_mutex_lock(&mutex_);
#endif
      }

      void unlock() {
#if defined(_WIN32)
        LeaveCriticalSection(&critical_section_);
#else
        pthread_mutex_unlock(&mutex_);
#endif
      }

#if defined(_WIN32)
      CRITICAL_SECTION critical_section_;
#else
      pthread_mutex_t mutex_;
#endif
      bool exit_;
      std::list<DiscoveredClient> discovered_clients_;
    };

    void ServerWorkingFunc(ServerWorkingEnv* working_env) {
      while (!working_env->CanExit()) {
        working_env->Update();
      }

      delete working_env;
    }

#if defined(_WIN32)
    DWORD WINAPI PlatformServerWorkingFunc(void* working_env_typeless) {
      ServerWorkingEnv* working_env = (ServerWorkingEnv*) working_env_typeless;
      ServerWorkingFunc(working_env);

      return 0;
    }
#else
    void* PlatformServerWorkingFunc(void* working_env_typeless) {
      ServerWorkingEnv* working_env = (ServerWorkingEnv*) working_env_typeless;
      ServerWorkingFunc(working_env);

      return 0;
    }
#endif
  };

  Server::Server() : started_(false) {
  }

  Server::~Server() {
    Stop();
  }

  bool Server::Start(int port) {
    Stop();

    impl::ServerWorkingEnv* working_env = new impl::ServerWorkingEnv();
    if (!working_env->StartServer(port)) {
      delete working_env;
      return false;
    }

    working_env_ = working_env;

#if defined(_WIN32)
    HANDLE thread = CreateThread(NULL, 0, impl::PlatformServerWorkingFunc, working_env_, 0, NULL);
    CloseHandle(thread);
#else
    pthread_t thread;
    pthread_create(&thread, 0, impl::PlatformServerWorkingFunc, working_env_);
    pthread_detach(thread);
#endif

    started_ = true;

    return true;
  }

  std::list<DiscoveredClient> Server::ListClients() const {
    std::list<DiscoveredClient> empty_discovered_clients;
    if (!started_)
      return empty_discovered_clients;
    return working_env_->ListClients();
  }

  void Server::Stop() {
    if (!started_)
      return;

    working_env_->Exit();
    working_env_ = 0;

    started_ = false;
  }

  bool Same(const IpPort& lhv, const IpPort& rhv) {
    return lhv == rhv;
  }

  bool Same(const std::list<DiscoveredClient>& lhv, const std::list<DiscoveredClient>& rhv) {
    for (std::list<DiscoveredClient>::const_iterator lhv_it = lhv.begin(); lhv_it != lhv.end(); ++lhv_it) {
      std::list<DiscoveredClient>::const_iterator in_rhv = rhv.end();
      for (std::list<DiscoveredClient>::const_iterator rhv_it = rhv.begin(); rhv_it != rhv.end(); ++rhv_it) {
        if (Same((*lhv_it).ip_port(), (*rhv_it).ip_port())) {
          in_rhv = rhv_it;
          break;
        }
      }

      if (in_rhv == rhv.end())
        return false;
    }

    for (std::list<DiscoveredClient>::const_iterator rhv_it = rhv.begin(); rhv_it != rhv.end(); ++rhv_it) {
      std::list<DiscoveredClient>::const_iterator in_lhv = lhv.end();
      for (std::list<DiscoveredClient>::const_iterator lhv_it = lhv.begin(); lhv_it != lhv.end(); ++lhv_it) {
        if (Same((*rhv_it).ip_port(), (*lhv_it).ip_port())) {
          in_lhv = lhv_it;
          break;
        }
      }

      if (in_lhv == lhv.end())
        return false;
    }

    return true;
  }
};
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: recently_used_file.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 19:56:10 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef INCLUDED_RECENTLY_USED_FILE_HXX
#define INCLUDED_RECENTLY_USED_FILE_HXX

#include <stdio.h>
#include <unistd.h>

//##################################
// simple wrapper around the recently_used_file

class recently_used_file
{
public:
    //----------------------------
    recently_used_file();

    //----------------------------
    ~recently_used_file();

    //----------------------------
    // set file pointer to the start of file
    void reset() const;

    //----------------------------
    void truncate(off_t length = 0);

    //----------------------------
    void flush();

    //----------------------------
    size_t read(
        char* buffer,
        size_t size) const;

    //----------------------------
    void write(const char* buffer, size_t size) const;

    //----------------------------
    bool eof() const;

private:
    FILE* file_;
};

#endif // INCLUDED_RECENTLY_USED_FILE_HXX
<commit_msg>INTEGRATION: CWS changefileheader (1.3.216); FILE MERGED 2008/03/31 13:17:11 rt 1.3.216.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: recently_used_file.hxx,v $
 * $Revision: 1.4 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef INCLUDED_RECENTLY_USED_FILE_HXX
#define INCLUDED_RECENTLY_USED_FILE_HXX

#include <stdio.h>
#include <unistd.h>

//##################################
// simple wrapper around the recently_used_file

class recently_used_file
{
public:
    //----------------------------
    recently_used_file();

    //----------------------------
    ~recently_used_file();

    //----------------------------
    // set file pointer to the start of file
    void reset() const;

    //----------------------------
    void truncate(off_t length = 0);

    //----------------------------
    void flush();

    //----------------------------
    size_t read(
        char* buffer,
        size_t size) const;

    //----------------------------
    void write(const char* buffer, size_t size) const;

    //----------------------------
    bool eof() const;

private:
    FILE* file_;
};

#endif // INCLUDED_RECENTLY_USED_FILE_HXX
<|endoftext|>