<commit_before>/*
 * File:   SDFLoader.cpp
 * Author: Benedikt Vogler
 *
 * Created on 8. Juli 2014, 18:52
 */

#include <algorithm>
#include "SDFloader.hpp"
#include "Camera.hpp"
#include "Box.hpp"
#include "Sphere.hpp"
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include "Material.hpp"
#include "LightPoint.hpp"
#include "Composite.hpp"

using namespace std;

/**
 * Loads a scene file and reacts to the commands in it
 * @param scenefile the string to the file
 * @return
 */
Scene SDFLoader::load(std::string const& scenefile) {
    cout << "Loading file: " << scenefile << endl;
    Scene scene = Scene();

    std::map<std::string, Material> mMap;
    std::map<std::string, LightPoint> lMap;
    std::map<std::string, RenderObject*> roMap;

    string line;
    ifstream file(scenefile);
    stringstream ss;
    //file.open(scenefile, ios::in);
    if (file.is_open()) {
        while (getline (file,line)){//get line
            ss = stringstream(line);//fill the line into stringstream
            string firstWord;
            ss >> firstWord;
            //is first string define?
            if (firstWord=="define"){
                cout << "defininig: ";

                ss >> firstWord;
                if (firstWord=="material"){
                    cout << "a material: "<<endl;
                    //extract name
                    string name;
                    ss>>name;

                    //extract color
                    float red, green, blue;
                    ss >> red;
                    ss >> green;
                    ss >> blue;
                    Color ca(red, green, blue);
                    ss >> red;
                    ss >> green;
                    ss >> blue;
                    Color cd(red, green, blue);
                    ss >> red;
                    ss >> green;
                    ss >> blue;
                    Color cs(red, green, blue);
                    float m;
                    ss >> m;
                    Material mat(ca, cd, cs,m, name);
                    cout << "Material specs: "<<endl<<mat;
                    mMap[name]=mat;
                } else if (firstWord=="camera"){
                    string cameraname;
                    ss >> cameraname;
                    int fovX;
                    ss >> fovX;
                    scene.camera = Camera(cameraname,fovX);
                    cout << "camera: "<<cameraname<<"("<<fovX<<")"<<endl;
                } else if (firstWord=="light"){
                    string type;
                    ss>>type;

                    if (type=="diffuse") {
                        string name;
                        ss >> name;

                        glm::vec3 pos;
                        ss >> pos.x;
                        ss >> pos.y;
                        ss >> pos.z;

                        float red, green, blue;
                        ss >> red;
                        ss >> green;
                        ss >> blue;
                        Color diff(red, green, blue);

                        LightPoint light = LightPoint(name, pos, diff);
                        cout << "light point: "<<name<<"("<<pos.x<<","<<pos.y<<","<<pos.z<<","<<diff<<")"<<endl;
                        lMap[name] = light;
                    }else if (type=="ambient") {
                        string lightname;
                        ss >> lightname;//name get's ignored

                        float red, green, blue;
                        ss >> red;
                        ss >> green;
                        ss >> blue;
                        Color amb(red, green, blue);

                        scene.amb = amb;
                        cout << "ambient light "<<amb<<endl;
                    } else {
                        cout << "type not supported yet."<<endl;
                    }
                } else if (firstWord=="shape"){
                    string classname;
                    ss >> classname;
                    cout << "Shape \""<< classname << "\"."<<endl;
                    transform(classname.begin(), classname.end(),classname.begin(), ::toupper);

                    string name;
                    ss >> name;

                    RenderObject* rObject = nullptr;
                    if (classname=="BOX"){
                        int edge1x, edge1y, edge1z;
                        ss>> edge1x;
                        ss>> edge1y;
                        ss>> edge1z;

                        int edge2x, edge2y, edge2z;
                        ss>> edge2x;
                        ss>> edge2y;
                        ss>> edge2z;

                        string materialName;
                        ss>>materialName;
                        Material material = mMap[materialName];

                        rObject = new Box(
                                name,
                                glm::vec3(edge1x, edge1y, edge1z),
                                glm::vec3(edge2x, edge2y, edge2z),
                                material
                                );
                    } else if (classname=="SPHERE") {
                        int posX, posY, posZ;
                        ss>> posX;
                        ss>> posY;
                        ss>> posZ;
                        float radius;
                        ss>>radius;

                        string materialString;
                        ss>>materialString;

                        rObject = new Sphere(
                            name,
                            glm::vec3(posX, posY, posZ),
                            radius,
                            mMap[materialString]
                        );
                        cout << "Sphere \""<< name << "\" aus Material "<<materialString<<" mit Radius: "<<radius<<"@("<<posX<<","<<posY<<","<<posZ<<")"<<endl;
                    } else if(classname=="COMPOSITE") {
                        rObject = new Composite(name);
                        cout << "Composite \""<< name << "\" (" ;
                        string objectString;
                        while (!ss.eof()){
                            ss>>objectString;
                            auto linkedObject = roMap.find(objectString);
                            if (linkedObject == roMap.end()){
                                cout << "Error: "<<objectString <<" not found!";
                            } else {
                                ((Composite*)rObject)->add_child(linkedObject->second);
                                cout<<", "<<objectString;
                            }
                        }
                        cout<<")"<<endl;
                    } else cout << "ERROR: Shape \""<< classname << "\" not defined."<<endl;

                    if (rObject != nullptr)
                        roMap[name] = rObject;
                } else
                    cout << "object to define not implemented:"<<ss.str() <<endl;
            } else if (firstWord=="render"){
                ss >> scene.camname;
                ss >> scene.outputFile;
                ss >> scene.resX;
                ss >> scene.resY;
                ss >> scene.antialiase;

                //set default if not set
                if (scene.resX<=0) scene.resX=480;
                if (scene.resY<=0) scene.resY=320;
                cout << "Scene should be rendered from "<< scene.camname << " at resolution "<<scene.resX<<"x"<< scene.resY<<"with "<< scene.antialiase<<"x SSAA to "<<scene.outputFile<<endl;
            } else if (firstWord=="#" || firstWord.substr(0,1)=="#"){
                cout << line << endl;//just print comment lines

			}
			else if (firstWord == "transform"){

				string name, transform;
				double X, Y, Z;
				RenderObject* object;

				ss >> name;
				ss >> transform;

				auto linkedObject = roMap.find(name);
				if (linkedObject == roMap.end()){
					cout << "Error: " << name << " not found!";
				}
				else {
					object = linkedObject->second;
					if (transform == "scale")
					{

						ss >> X;
						ss >> Y;
						ss >> Z;

						glm::vec3 coords(X, Y, Z);
						object->scale(coords);
					}
					else if (transform == "roatate")
					{
						double angle;

						ss >> angle;
						ss >> X;
						ss >> Y;
						ss >> Z;

						glm::vec3 coords(X, Y, Z);
						object->rotate(angle,coords);

					}
					else if (transform == "translate")
					{
						ss >> X;
						ss >> Y;
						ss >> Z;

						glm::vec3 coords(X, Y, Z);
						object->translate(coords);

					}
					else
					{
						cout << "Error in SDF file. Please check the structure." << endl;
					}
				}

			}

			else
                cout << "???:"<<line <<endl;
        }
        file.close();
    }else cout << "Unable to open file";

    //save collected data in scene
    scene.materials = mMap;
    scene.renderObjects = roMap;
    scene.lights = lMap;
    return scene;
}<commit_msg>INdent<commit_after>/*
 * File:   SDFLoader.cpp
 * Author: Benedikt Vogler
 *
 * Created on 8. Juli 2014, 18:52
 */

#include <algorithm>
#include "SDFloader.hpp"
#include "Camera.hpp"
#include "Box.hpp"
#include "Sphere.hpp"
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include "Material.hpp"
#include "LightPoint.hpp"
#include "Composite.hpp"

using namespace std;

/**
 * Loads a scene file and reacts to the commands in it
 * @param scenefile the string to the file
 * @return
 */
Scene SDFLoader::load(std::string const& scenefile) {
    cout << "Loading file: " << scenefile << endl;
    Scene scene = Scene();

    std::map<std::string, Material> mMap;
    std::map<std::string, LightPoint> lMap;
    std::map<std::string, RenderObject*> roMap;

    string line;
    ifstream file(scenefile);
    stringstream ss;
    //file.open(scenefile, ios::in);
    if (file.is_open()) {
        while (getline (file,line)){//get line
            ss = stringstream(line);//fill the line into stringstream
            string firstWord;
            ss >> firstWord;
            //is first string define?
            if (firstWord=="define"){
                cout << "defininig: ";

                ss >> firstWord;
                if (firstWord=="material"){
                    cout << "a material: "<<endl;
                    //extract name
                    string name;
                    ss>>name;

                    //extract color
                    float red, green, blue;
                    ss >> red;
                    ss >> green;
                    ss >> blue;
                    Color ca(red, green, blue);
                    ss >> red;
                    ss >> green;
                    ss >> blue;
                    Color cd(red, green, blue);
                    ss >> red;
                    ss >> green;
                    ss >> blue;
                    Color cs(red, green, blue);
                    float m;
                    ss >> m;
                    Material mat(ca, cd, cs,m, name);
                    cout << "Material specs: "<<endl<<mat;
                    mMap[name]=mat;
                } else if (firstWord=="camera"){
                    string cameraname;
                    ss >> cameraname;
                    int fovX;
                    ss >> fovX;
                    scene.camera = Camera(cameraname,fovX);
                    cout << "camera: "<<cameraname<<"("<<fovX<<")"<<endl;
                } else if (firstWord=="light"){
                    string type;
                    ss>>type;

                    if (type=="diffuse") {
                        string name;
                        ss >> name;

                        glm::vec3 pos;
                        ss >> pos.x;
                        ss >> pos.y;
                        ss >> pos.z;

                        float red, green, blue;
                        ss >> red;
                        ss >> green;
                        ss >> blue;
                        Color diff(red, green, blue);

                        LightPoint light = LightPoint(name, pos, diff);
                        cout << "light point: "<<name<<"("<<pos.x<<","<<pos.y<<","<<pos.z<<","<<diff<<")"<<endl;
                        lMap[name] = light;
                    }else if (type=="ambient") {
                        string lightname;
                        ss >> lightname;//name get's ignored

                        float red, green, blue;
                        ss >> red;
                        ss >> green;
                        ss >> blue;
                        Color amb(red, green, blue);

                        scene.amb = amb;
                        cout << "ambient light "<<amb<<endl;
                    } else {
                        cout << "type not supported yet."<<endl;
                    }
                } else if (firstWord=="shape"){
                    string classname;
                    ss >> classname;
                    cout << "Shape \""<< classname << "\"."<<endl;
                    transform(classname.begin(), classname.end(),classname.begin(), ::toupper);

                    string name;
                    ss >> name;

                    RenderObject* rObject = nullptr;
                    if (classname=="BOX"){
                        int edge1x, edge1y, edge1z;
                        ss>> edge1x;
                        ss>> edge1y;
                        ss>> edge1z;

                        int edge2x, edge2y, edge2z;
                        ss>> edge2x;
                        ss>> edge2y;
                        ss>> edge2z;

                        string materialName;
                        ss>>materialName;
                        Material material = mMap[materialName];

                        rObject = new Box(
                                name,
                                glm::vec3(edge1x, edge1y, edge1z),
                                glm::vec3(edge2x, edge2y, edge2z),
                                material
                                );
                    } else if (classname=="SPHERE") {
                        int posX, posY, posZ;
                        ss>> posX;
                        ss>> posY;
                        ss>> posZ;
                        float radius;
                        ss>>radius;

                        string materialString;
                        ss>>materialString;

                        rObject = new Sphere(
                            name,
                            glm::vec3(posX, posY, posZ),
                            radius,
                            mMap[materialString]
                        );
                        cout << "Sphere \""<< name << "\" aus Material "<<materialString<<" mit Radius: "<<radius<<"@("<<posX<<","<<posY<<","<<posZ<<")"<<endl;
                    } else if(classname=="COMPOSITE") {
                        rObject = new Composite(name);
                        cout << "Composite \""<< name << "\" (" ;
                        string objectString;
                        while (!ss.eof()){
                            ss>>objectString;
                            auto linkedObject = roMap.find(objectString);
                            if (linkedObject == roMap.end()){
                                cout << "Error: "<<objectString <<" not found!";
                            } else {
                                ((Composite*)rObject)->add_child(linkedObject->second);
                                cout<<", "<<objectString;
                            }
                        }
                        cout<<")"<<endl;
                    } else cout << "ERROR: Shape \""<< classname << "\" not defined."<<endl;

                    if (rObject != nullptr)
                        roMap[name] = rObject;
                } else
                    cout << "object to define not implemented:"<<ss.str() <<endl;
            } else if (firstWord=="render"){
                ss >> scene.camname;
                ss >> scene.outputFile;
                ss >> scene.resX;
                ss >> scene.resY;
                ss >> scene.antialiase;

                //set default if not set
                if (scene.resX<=0) scene.resX=480;
                if (scene.resY<=0) scene.resY=320;
                cout << "Scene should be rendered from "<< scene.camname << " at resolution "<<scene.resX<<"x"<< scene.resY<<"with "<< scene.antialiase<<"x SSAA to "<<scene.outputFile<<endl;
            } else if (firstWord=="#" || firstWord.substr(0,1)=="#"){
                cout << line << endl;//just print comment lines

            } else if (firstWord == "transform"){
                string name, transform;
                double X, Y, Z;
                RenderObject* object;

                ss >> name;
                ss >> transform;

                auto linkedObject = roMap.find(name);
                if (linkedObject == roMap.end()){
                        cout << "Error: " << name << " not found!";
                } else {
                    object = linkedObject->second;
                    if (transform == "scale") {

                            ss >> X;
                            ss >> Y;
                            ss >> Z;

                            glm::vec3 coords(X, Y, Z);
                            object->scale(coords);
                    } else if (transform == "roatate") {
                            double angle;

                            ss >> angle;
                            ss >> X;
                            ss >> Y;
                            ss >> Z;

                            glm::vec3 coords(X, Y, Z);
                            object->rotate(angle,coords);

                    } else if (transform == "translate"){
                            ss >> X;
                            ss >> Y;
                            ss >> Z;

                            glm::vec3 coords(X, Y, Z);
                            object->translate(coords);

                    } else {
                            cout << "Error in SDF file. Please check the structure." << endl;
                    }
                }
            } else cout << "???:"<<line <<endl;//prinkt uknown lines
        }
        file.close();
    }else cout << "Unable to open file";

    //save collected data in scene
    scene.materials = mMap;
    scene.renderObjects = roMap;
    scene.lights = lMap;
    return scene;
}<|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 "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.

class Channel {
public:
  std::string name;
  std::list<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, User *> kUsers;
std::map<std::string, Channel *> kChannels;

void Error(const char *msg) {
  perror(msg);
  exit(1);
}

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);
        break;
      }
    }
  }
  for(auto current_user : kUsers){
    if(current_user.second->name == user->name){
      kUsers.erase(user->name);
    }
  }
}

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;
}

void ProcessRequest(int server_socket, void *buffer, in_addr_t request_address, unsigned short request_port) {
  struct request current_request;
  User *current_user;
  Channel *channel;
  std::string current_channel;
  std::list<User *>::const_iterator it;
  std::map<std::string, User *>::const_iterator map_it;
  bool is_new_channel;
  bool is_channel;
  bool is_channel_user;
  int i;

//  channel_info *channel_list;

  memcpy(&current_request, buffer, sizeof(struct request));
//  std::cout << "request type: " << current_request.req_type << std::endl;
  request_t request_type = current_request.req_type;

  switch(request_type) {
    case REQ_LOGIN:
      struct request_login login_request;
      memcpy(&login_request, buffer, sizeof(struct request_login));

      current_user = new 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;
      break;

    case REQ_LOGOUT:
      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);
          break;
        }
      }
      break;

    case REQ_LEAVE:
      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){
              std::cout << "channel found" << std::endl;
              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);
                std::cout << "server: removing empty channel " << channel->name << std::endl;
              }
            }
            for (auto u : channel->users) {
              std::cout << "user: " << u->name << std::endl;
            }
            break;
          } else {
            std::cout << "server: " << user.first << " trying to leave non-existent channel " << channel->name << std::endl;
          }

        }
      }
      break;
    case REQ_JOIN:
      struct request_join join_request;
      memcpy(&join_request, buffer, sizeof(struct request_join));
      is_new_channel = true;

      // 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 a new channel
      if (is_new_channel) {
        channel = new Channel(join_request.req_channel);
      }

      for (auto user : kUsers) {
        unsigned short current_port = user.second->port;
        in_addr_t current_address = user.second->address;
//        std::cout << std::endl;
//        std::cout << "port: " << current_port << " address "<< current_address << std::endl;
//        std::cout << "port: " << request_port << " address "<< request_address << std::endl;
//        std::cout << std::endl;
        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});
          }

          // Test print
          for (auto u : channel->users) {
            std::cout << "user: " << u->name << std::endl;
          }
          break;
        }

      }
      break;
    case REQ_SAY:
      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) {
          current_user = user.second;
          for(auto channel_user : kChannels[say_request.req_channel]->users){
            struct sockaddr_in client_addr;
            struct text_say say;
            memcpy(&say, buffer, sizeof(struct text_say));

//        client_addr = CreateSockAddr(user->port, user->address);
            memset(&client_addr, 0, sizeof(struct sockaddr_in));
            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, current_user->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 << current_user->name << " sends say message in " << say_request.req_channel << std::endl;
          break;
        }
      }

      break;

    case REQ_LIST:
//      struct sockaddr_in client_addr;
      struct text_list list;

      list.txt_type = TXT_LIST;
      list.txt_nchannels = (int) kChannels.size();
//      channel_list = new channel_info[list.txt_nchannels];
      i = 0;
      for(auto ch : kChannels){
        struct channel_info new_info;
        strncpy(new_info.ch_channel, ch.second->name.c_str(), CHANNEL_MAX);
        memcpy(&list.txt_channels[i].ch_channel, &new_info.ch_channel, sizeof(struct channel_info));
//        std::cout << "channel name: " << channel_list[i].ch_channel << std::endl;
        i++;
      }
//      memcpy(&list.txt_channels->ch_channel, &channel_list->ch_channel, sizeof(channel_list));
      std::cout << "first channel name: " << list.txt_channels[0].ch_channel << std::endl;

//      std::cout << "size of array: " << sizeof(list.txt_channels) / sizeof(struct channel_info) << std::endl;

//      std::cout << "length of list nchannels : " << list.txt_nchannels << std::endl;
//      memset(list.txt_channels, 0, list.txt_nchannels * sizeof(struct channel_info));
//      i = 0;
//      for(auto ch : kChannels){
//        struct channel_info new_channel;
//        memset(new_channel.ch_channel, 0, CHANNEL_MAX);
//        strncpy(new_channel.ch_channel, ch.second->name.c_str(), CHANNEL_MAX);
//        std::cout << "channel: " << new_channel.ch_channel << std::endl;
////        std::cout << "size of array: " << sizeof(list.txt_channels) / sizeof(struct channel_info) << std::endl;
////        list.txt_channels[i++] = new_channel;
//        memcpy(&list.txt_channels[i++], &new_channel, sizeof(new_channel));
//      }
//      for (auto user : kUsers) {
//        std::cout << "user loop" << std::endl;
//        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 << " lists channels" << std::endl;
//          current_user = user.second;
//          memset(&client_addr, 0, sizeof(struct sockaddr_in));
//          client_addr.sin_family = AF_INET;
//          client_addr.sin_port = current_user->port;
//          client_addr.sin_addr.s_addr = current_user->address;
//          size_t message_size = sizeof(struct text_list);
//
//          if (sendto(server_socket, &list, message_size, 0, (struct sockaddr*) &client_addr, sizeof(client_addr)) < 0) {
//            Error("server: failed to send say\n");
//          }
//          break;
//        }
//      }

      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);
    }
  }
}
<commit_msg>changed size<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 "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.

class Channel {
public:
  std::string name;
  std::list<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, User *> kUsers;
std::map<std::string, Channel *> kChannels;

void Error(const char *msg) {
  perror(msg);
  exit(1);
}

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);
        break;
      }
    }
  }
  for(auto current_user : kUsers){
    if(current_user.second->name == user->name){
      kUsers.erase(user->name);
    }
  }
}

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;
}

void ProcessRequest(int server_socket, void *buffer, in_addr_t request_address, unsigned short request_port) {
  struct request current_request;
  User *current_user;
  Channel *channel;
  std::string current_channel;
  std::list<User *>::const_iterator it;
  std::map<std::string, User *>::const_iterator map_it;
  bool is_new_channel;
  bool is_channel;
  bool is_channel_user;
  int i;

//  channel_info *channel_list;

  memcpy(&current_request, buffer, sizeof(struct request));
//  std::cout << "request type: " << current_request.req_type << std::endl;
  request_t request_type = current_request.req_type;

  switch(request_type) {
    case REQ_LOGIN:
      struct request_login login_request;
      memcpy(&login_request, buffer, sizeof(struct request_login));

      current_user = new 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;
      break;

    case REQ_LOGOUT:
      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);
          break;
        }
      }
      break;

    case REQ_LEAVE:
      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){
              std::cout << "channel found" << std::endl;
              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);
                std::cout << "server: removing empty channel " << channel->name << std::endl;
              }
            }
            for (auto u : channel->users) {
              std::cout << "user: " << u->name << std::endl;
            }
            break;
          } else {
            std::cout << "server: " << user.first << " trying to leave non-existent channel " << channel->name << std::endl;
          }

        }
      }
      break;
    case REQ_JOIN:
      struct request_join join_request;
      memcpy(&join_request, buffer, sizeof(struct request_join));
      is_new_channel = true;

      // 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 a new channel
      if (is_new_channel) {
        channel = new Channel(join_request.req_channel);
      }

      for (auto user : kUsers) {
        unsigned short current_port = user.second->port;
        in_addr_t current_address = user.second->address;
//        std::cout << std::endl;
//        std::cout << "port: " << current_port << " address "<< current_address << std::endl;
//        std::cout << "port: " << request_port << " address "<< request_address << std::endl;
//        std::cout << std::endl;
        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});
          }

          // Test print
          for (auto u : channel->users) {
            std::cout << "user: " << u->name << std::endl;
          }
          break;
        }

      }
      break;
    case REQ_SAY:
      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) {
          current_user = user.second;
          for(auto channel_user : kChannels[say_request.req_channel]->users){
            struct sockaddr_in client_addr;
            struct text_say say;
            memcpy(&say, buffer, sizeof(struct text_say));

//        client_addr = CreateSockAddr(user->port, user->address);
            memset(&client_addr, 0, sizeof(struct sockaddr_in));
            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, current_user->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 << current_user->name << " sends say message in " << say_request.req_channel << std::endl;
          break;
        }
      }

      break;

    case REQ_LIST:
//      struct sockaddr_in client_addr;
      struct text_list list;

      list.txt_type = TXT_LIST;
      list.txt_nchannels = (int) kChannels.size();
//      channel_list = new channel_info[list.txt_nchannels];
      i = 0;
      for(auto ch : kChannels){
        struct channel_info new_info;
        strncpy(new_info.ch_channel, ch.second->name.c_str(), CHANNEL_MAX);
        memcpy(&list.txt_channels[i].ch_channel, &new_info.ch_channel, CHANNEL_MAX);
//        std::cout << "channel name: " << channel_list[i].ch_channel << std::endl;
        i++;
      }
//      memcpy(&list.txt_channels->ch_channel, &channel_list->ch_channel, sizeof(channel_list));
      std::cout << "first channel name: " << list.txt_channels[0].ch_channel << std::endl;

//      std::cout << "size of array: " << sizeof(list.txt_channels) / sizeof(struct channel_info) << std::endl;

//      std::cout << "length of list nchannels : " << list.txt_nchannels << std::endl;
//      memset(list.txt_channels, 0, list.txt_nchannels * sizeof(struct channel_info));
//      i = 0;
//      for(auto ch : kChannels){
//        struct channel_info new_channel;
//        memset(new_channel.ch_channel, 0, CHANNEL_MAX);
//        strncpy(new_channel.ch_channel, ch.second->name.c_str(), CHANNEL_MAX);
//        std::cout << "channel: " << new_channel.ch_channel << std::endl;
////        std::cout << "size of array: " << sizeof(list.txt_channels) / sizeof(struct channel_info) << std::endl;
////        list.txt_channels[i++] = new_channel;
//        memcpy(&list.txt_channels[i++], &new_channel, sizeof(new_channel));
//      }
//      for (auto user : kUsers) {
//        std::cout << "user loop" << std::endl;
//        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 << " lists channels" << std::endl;
//          current_user = user.second;
//          memset(&client_addr, 0, sizeof(struct sockaddr_in));
//          client_addr.sin_family = AF_INET;
//          client_addr.sin_port = current_user->port;
//          client_addr.sin_addr.s_addr = current_user->address;
//          size_t message_size = sizeof(struct text_list);
//
//          if (sendto(server_socket, &list, message_size, 0, (struct sockaddr*) &client_addr, sizeof(client_addr)) < 0) {
//            Error("server: failed to send say\n");
//          }
//          break;
//        }
//      }

      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);
    }
  }
}
<|endoftext|>


<commit_before>#include <glbinding/GetProcAddress.h>

#ifdef WIN32
    #include <string>
    #include <windows.h>
#elif __APPLE__
    #include <string>
    #include <mach-o/dyld.h>
#else
    #include <GL/glx.h>
#endif

namespace gl {

ProcAddress GetProcAddress(const char * name)
{
#ifdef WIN32

    typedef void (__stdcall * PROCADDRESS)();
    PROCADDRESS procAddress = reinterpret_cast<PROCADDRESS>(wglGetProcAddress(name));

    if(nullptr == procAddress)
    {
        static HMODULE module = LoadLibrary(L"OPENGL32.DLL");
        procAddress = reinterpret_cast<PROCADDRESS>(::GetProcAddress(module, name));
    }

#elif __APPLE__

    typedef void * PROCADDRESS;

    std::string string(name);
    string = "_" + string;

    NSSymbol symbol(nullptr);

    if (NSIsSymbolNameDefined(string.c_str()))
        symbol = NSLookupAndBindSymbol(string.c_str());

    PROCADDRESS procAddress = reinterpret_cast<PROCADDRESS>(symbol ? NSAddressOfSymbol(symbol) : nullptr);

#else

    typedef void (* PROCADDRESS)();
    PROCADDRESS procAddress = reinterpret_cast<PROCADDRESS>(glXGetProcAddress(reinterpret_cast<const unsigned char*>(name)));

#endif

    return reinterpret_cast<ProcAddress>(procAddress);
}

} // namespace gl
<commit_msg>Replace deprecated Mac code.<commit_after>#include <glbinding/GetProcAddress.h>
#include <cassert>

#ifdef WIN32
    #include <string>
    #include <windows.h>
#elif __APPLE__
    #include <string>
//    #include <mach-o/dyld.h>
    #include <dlfcn.h>
#else
    #include <GL/glx.h>
#endif

namespace gl {

ProcAddress GetProcAddress(const char * name)
{
#ifdef WIN32

    typedef void (__stdcall * PROCADDRESS)();
    PROCADDRESS procAddress = reinterpret_cast<PROCADDRESS>(wglGetProcAddress(name));

    if(nullptr == procAddress)
    {
        static HMODULE module = LoadLibrary(L"OPENGL32.DLL");
        procAddress = reinterpret_cast<PROCADDRESS>(::GetProcAddress(module, name));
    }

#elif __APPLE__

    typedef void * PROCADDRESS;

    void* library = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY);
    assert(library != nullptr);

    void* symbol = dlsym(library, name);

    PROCADDRESS procAddress = reinterpret_cast<PROCADDRESS>(symbol);

#else

    typedef void (* PROCADDRESS)();
    PROCADDRESS procAddress = reinterpret_cast<PROCADDRESS>(glXGetProcAddress(reinterpret_cast<const unsigned char*>(name)));

#endif

    return reinterpret_cast<ProcAddress>(procAddress);
}

} // namespace gl
<|endoftext|>


<commit_before>
#include "fetchURL.h"

/*
    Publicity: private
    Return type: int
    Name/Type: callExtensionArgs()
    Description: default request function.
*/
int FetchURL::CallExtensionArgs(char *output, int outputSize, const char *function, const char **args, int argsCnt)
{
    if (argsCnt <= 0)
        return 200;

    if (strcmp(function, "RQST") == 0)
    {
        std::stringstream str_stream;
        str_stream << AddRequestToQueue(args, argsCnt) << '\0';
        strncpy(output, str_stream.str().c_str(), outputSize);
        return 200;
    }
    else if (strcmp(function, "STAT") == 0)
    {
        //TODO: Find a more convenient way to convert the int to a string with an ending line.
        std::stringstream str_stream;
        str_stream << GetStatus(atoi(args[0])) << '\0';
        strncpy(output, str_stream.str().c_str(), outputSize);
        return 300;
    }
    else if (strcmp(function, "RECV") == 0)
    {
        //TODO: Find a more convenient way to convert the int to a string with an ending line.
        std::stringstream str_stream;
        str_stream << GetResult(atoi(args[0])) << '\0';
        strncpy(output, str_stream.str().c_str(), outputSize);
        return 400;
    }

    return 0;
};

/*
    Publicity: private
    Return type: std::map<std::string, std::string>
    Name/Type: parseRequestArgs()
    Description: Converts input **args to a map<std::string, std::string>.
*/
std::map<std::string, std::string> FetchURL::parseRequestArgs(const char **args, int argsCnt)
{
    std::map<std::string, std::string> params;

    for (int x = 0; x < argsCnt; x++)
    {
        std::string param(args[x]);

        if (param.size() > 0)
        {
            if (param.compare(param.size() - 1, 1, "\"") == 0)
                param.erase(param.size() - 1);

            if (param.compare(0, 1, "\"") == 0)
                param.erase(0, 1);

            size_t i = param.find(*paramSep);

            if (i != std::string::npos)
            {
                params[param.substr(0, i)] = param.substr(i+1, param.length() - i);
            }
        }
    }

    return params;
};

/*
    Publicity: private
    Return type: int
    Name/Type: addResultToQueue()
    Description: This function adds a result to a special queue for later usage.
*/
int FetchURL::addResultToQueue()
{
    int key = -1;
    int i = 0;

    resList_mutex.lock();
    while (key == -1)
    {
        if (resList.find(i) == resList.end())
            key = i;
        i++;
    }

    FetchURL::FetchResult fres;
    fres.status = 0;
    fres.result = std::string("");
    resList.insert(std::pair<int, FetchURL::FetchResult>(key, fres));
    resList_mutex.unlock();

    return key;
};

/*
    Publicity: public
    Return type: int
    Name/Type: AddRequestToQueue()
    Description: Adds a full request to the queue(s).
*/
int FetchURL::AddRequestToQueue(const char **args, int argsCnt)
{
    /*
    Initialization of Windows worker Threads. Otherwise the .dll crashes.
    */
    #ifdef _MSC_VER
    InitializeThreads();
    #endif

    int key = addResultToQueue();

    FetchURL::FetchQueueItem qItem;
    qItem.key = key;
    qItem.params = parseRequestArgs(args, argsCnt);

    queue_mutex.lock();
    queue.push(qItem);
    queue_mutex.unlock();

    return key;
};

/*
    Publicity: public
    Return type: void
    Name/Type: InitializeThreads()
    Description: Setups worker threads for url fetching.
*/
void FetchURL::InitializeThreads()
{
    if (!workerInitialized)
    {
        workerInitialized = true;
        int cnt_thr = 2; //(std::thread::hardware_concurrency() / 2);
        if (cnt_thr == 0)
            cnt_thr = 1;

        for (int i = 0; i < cnt_thr; i++)
        {
            /*
            Create a thread and immediately detach it.
            */
            std::thread myThread(&FetchURL::QueueWorkerThread, this);
            myThread.detach();
        }
    }
};

/*
    Publicity: public
    Return type: void
    Name/Type: QueueWorkerThread()
    Description: Worker thread loop: processes incoming requests asyncroniously to ArmA 3.
*/
void FetchURL::QueueWorkerThread()
{
    while (true) {
        if (!queue.empty())
        {
            queue_mutex.lock();
            if (queue.empty())
            {
                queue_mutex.unlock();
            }
            else
            {
                FetchURL::FetchQueueItem qItem;
                qItem = queue.front();
                queue.pop();
                queue_mutex.unlock();

                std::string action = qItem.params["#method"];

                if (
                    action.compare(actionGET) == 0 ||
                    action.compare(actionPOST) == 0 ||
                    action.compare(actionPUT) == 0 ||
                    action.compare(actionPATCH) == 0 ||
                    action.compare(actionDELETE) == 0 ||
                    action.compare(actionTRACE) == 0
                )
                {
                    fetchResult(&qItem);
                }
                else
                {
                    resList_mutex.lock();
                    FetchURL::FetchResult fres;
                    fres = resList[qItem.key];
                    fres.status = 2;
                    resList[qItem.key] = fres;
                    resList_mutex.unlock();
                };
            }
        }
    }
};

/*
    Publicity: public/static
    Return type: size_t
    Name/Type: FetchURLCallbackWriter()
    Description: Writes incoming data from curl to a string/buffer.
*/
static size_t FetchURLCallbackWriter(void *contents, size_t size, size_t nmemb, void *buf)
{
    ((std::string *)buf)->append((char *)contents, size * nmemb);
    return size * nmemb;
};

/*
    Publicity: private
    Return type: void
    Name/Type: fetchResult()
    Description: processes a single url request.
*/
void FetchURL::fetchResult(FetchURL::FetchQueueItem * qItem)
{
    FetchURL::FetchResult fres;

    int key = qItem->key;
    std::string url = qItem->params["#url"];
    std::string method = qItem->params["#method"];
    //std::string mime = qItem.params["#mime"]; currently unused

    if (resList.empty())
        return;

    fres = resList[key];
    fres.status = 3;

    CURL *curl;
    CURLcode res;

    curl = curl_easy_init();

    if (qItem->params.size() > 0)
        url.append("?");

    bool fBind = false;
    for (std::map<std::string, std::string>::iterator iter = qItem->params.begin(); iter != qItem->params.end(); ++iter)
    {
        if (
            iter->first.compare(cmdUrl) != 0 &&
            iter->first.compare(cmdMethod) != 0 &&
            iter->first.compare(cmdJSONDec) != 0
        )
        {
            if (fBind) {
                url.append("&");
            } else {
                fBind = true;
            }

            char * encVal = curl_easy_escape(curl, iter->second.c_str(), 0);
            char * encKey = curl_easy_escape(curl, iter->first.c_str(), 0);
            url.append(encKey);
            url.append("=");
            url.append(encVal);
        }
    }

    std::string str;
    struct curl_slist *headers = NULL;

    if (curl)
    {
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method.c_str());
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &str);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, FetchURLCallbackWriter);
        res = curl_easy_perform(curl);

        if (res == CURLE_OK)
        {
            char *ct;
            res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct);

            if ((CURLE_OK == res) && ct)
            {
                if (str.size() > 10240)
                    str.resize(10240);

                fres.result = str;
                fres.status = 1;
            }
        }
    }

    if (qItem->params["#jsonToArray"].compare("true") == 0)
    {
        fres.result = JsonToArray(str);
    }

    resList_mutex.lock();
    resList[key] = fres;
    resList_mutex.unlock();
};

/*
    Publicity: public
    Return type: int
    Name/Type: GetStatus()
    Description: returns the status of an result queue item.
*/
int FetchURL::GetStatus(int key)
{
    if (resList.empty() || resList.find(key) == resList.end())
        return 0;

    FetchURL::FetchResult fres;
    fres = resList[key];

    return fres.status;
};

/*
    Publicity: public
    Return type: std::string
    Name/Type: GetResult()
    Description: returns the result of an request. If a request finished successful or errored the selected item is removed after the request.
*/
std::string FetchURL::GetResult(int key)
{
    if (resList.empty()/* || resList.find(key) == resList.end()*/)
        return std::string();

    FetchURL::FetchResult fres;
    fres = resList[key];

    if (fres.status != 0) {
        resList_mutex.lock();
        resList.erase(key);
        resList_mutex.unlock();
    }

    return fres.result;
};

/*
    Publicity: private
    Return type: std::string
    Name/Type: jsonToArray_object()
    Description: subfunction of JsonToArray() and jsonToArray_array() for object iterations.
*/
std::string FetchURL::jsonToArray_object(nlohmann::json j)
{
    std::stringstream res;

    res << "[";
    for (nlohmann::json::iterator it = j.begin(); it != j.end(); ++it)
    {
        if (it != j.begin())
            res << ",";

        if (it.value().is_number() || it.value().is_boolean() || it.value().is_string())
        {
            res << "[\"" << it.key() << "\"," << it.value() << "]";
        }
        else if (it.value().is_null())
        {
            res << "[\"" << it.key() << ",null]";
        }
        else if (it.value().is_object())
        {
            res << "[\"" << it.key() << "\",[\"object\"," << jsonToArray_object(it.value()) << "]]";
        }
        else if (it.value().is_array())
        {
            res << "[\"" << it.key() << "\",[\"array\"," << jsonToArray_array(it.value()) << "]]";
        }
    }
    res << "]";

    return res.str();
};

/*
    Publicity: private
    Return type: std::string
    Name/Type: jsonToArray_array()
    Description: subfunction of JsonToArray() and jsonToArray_object() for array iterations.
*/
std::string FetchURL::jsonToArray_array(nlohmann::json j)
{
    std::stringstream res;

    res << "[";
    for (int i = 0; i < j.size(); i++)
    {
        if (i != 0)
            res << ",";

        if (j[i].is_number() || j[i].is_boolean() || j[i].is_string())
        {
            res << j[i];
        }
        else if (j[i].is_null())
        {
            res << "null";
        }
        else if (j[i].is_object())
        {
            res << "[\"object\"," << jsonToArray_object(j[i]) << "]";
        }
        else if (j[i].is_array())
        {
            res << "[\"array\"," << jsonToArray_array(j[i]) << "]";
        }
    }
    res << "]";

    return res.str();
};

/*
    Publicity: private
    Return type: std::string
    Name/Type: jsonToArray()
    Description: Parses a JSON input to an ArmA 3 friendly array.
*/
std::string FetchURL::JsonToArray(std::string jsonStr)
{
    nlohmann::json j = nlohmann::json::parse(jsonStr);
    std::stringstream res;

    if (j.is_array()) {
        res << "[\"array\"," << jsonToArray_array(j) << "]";
    }
    else if (j.is_object())
    {
        res << "[\"object\"," << jsonToArray_object(j) << "]";
    }

    return res.str();
};
<commit_msg>increase key start value to 1<commit_after>
#include "fetchURL.h"

/*
    Publicity: private
    Return type: int
    Name/Type: callExtensionArgs()
    Description: default request function.
*/
int FetchURL::CallExtensionArgs(char *output, int outputSize, const char *function, const char **args, int argsCnt)
{
    if (argsCnt <= 0)
        return 200;

    if (strcmp(function, "RQST") == 0)
    {
        std::stringstream str_stream;
        str_stream << AddRequestToQueue(args, argsCnt) << '\0';
        strncpy(output, str_stream.str().c_str(), outputSize);
        return 200;
    }
    else if (strcmp(function, "STAT") == 0)
    {
        //TODO: Find a more convenient way to convert the int to a string with an ending line.
        std::stringstream str_stream;
        str_stream << GetStatus(atoi(args[0])) << '\0';
        strncpy(output, str_stream.str().c_str(), outputSize);
        return 300;
    }
    else if (strcmp(function, "RECV") == 0)
    {
        //TODO: Find a more convenient way to convert the int to a string with an ending line.
        std::stringstream str_stream;
        str_stream << GetResult(atoi(args[0])) << '\0';
        strncpy(output, str_stream.str().c_str(), outputSize);
        return 400;
    }

    return 0;
};

/*
    Publicity: private
    Return type: std::map<std::string, std::string>
    Name/Type: parseRequestArgs()
    Description: Converts input **args to a map<std::string, std::string>.
*/
std::map<std::string, std::string> FetchURL::parseRequestArgs(const char **args, int argsCnt)
{
    std::map<std::string, std::string> params;

    for (int x = 0; x < argsCnt; x++)
    {
        std::string param(args[x]);

        if (param.size() > 0)
        {
            if (param.compare(param.size() - 1, 1, "\"") == 0)
                param.erase(param.size() - 1);

            if (param.compare(0, 1, "\"") == 0)
                param.erase(0, 1);

            size_t i = param.find(*paramSep);

            if (i != std::string::npos)
            {
                params[param.substr(0, i)] = param.substr(i+1, param.length() - i);
            }
        }
    }

    return params;
};

/*
    Publicity: private
    Return type: int
    Name/Type: addResultToQueue()
    Description: This function adds a result to a special queue for later usage.
*/
int FetchURL::addResultToQueue()
{
    int key = -1;
    int i = 1;

    resList_mutex.lock();
    while (key == -1)
    {
        if (resList.find(i) == resList.end())
            key = i;
        i++;
    }

    FetchURL::FetchResult fres;
    fres.status = 0;
    fres.result = std::string("");
    resList.insert(std::pair<int, FetchURL::FetchResult>(key, fres));
    resList_mutex.unlock();

    return key;
};

/*
    Publicity: public
    Return type: int
    Name/Type: AddRequestToQueue()
    Description: Adds a full request to the queue(s).
*/
int FetchURL::AddRequestToQueue(const char **args, int argsCnt)
{
    /*
    Initialization of Windows worker Threads. Otherwise the .dll crashes.
    */
    #ifdef _MSC_VER
    InitializeThreads();
    #endif

    int key = addResultToQueue();

    FetchURL::FetchQueueItem qItem;
    qItem.key = key;
    qItem.params = parseRequestArgs(args, argsCnt);

    queue_mutex.lock();
    queue.push(qItem);
    queue_mutex.unlock();

    return key;
};

/*
    Publicity: public
    Return type: void
    Name/Type: InitializeThreads()
    Description: Setups worker threads for url fetching.
*/
void FetchURL::InitializeThreads()
{
    if (!workerInitialized)
    {
        workerInitialized = true;
        int cnt_thr = 2; //(std::thread::hardware_concurrency() / 2);
        if (cnt_thr == 0)
            cnt_thr = 1;

        for (int i = 0; i < cnt_thr; i++)
        {
            /*
            Create a thread and immediately detach it.
            */
            std::thread myThread(&FetchURL::QueueWorkerThread, this);
            myThread.detach();
        }
    }
};

/*
    Publicity: public
    Return type: void
    Name/Type: QueueWorkerThread()
    Description: Worker thread loop: processes incoming requests asyncroniously to ArmA 3.
*/
void FetchURL::QueueWorkerThread()
{
    while (true) {
        if (!queue.empty())
        {
            queue_mutex.lock();
            if (queue.empty())
            {
                queue_mutex.unlock();
            }
            else
            {
                FetchURL::FetchQueueItem qItem;
                qItem = queue.front();
                queue.pop();
                queue_mutex.unlock();

                std::string action = qItem.params["#method"];

                if (
                    action.compare(actionGET) == 0 ||
                    action.compare(actionPOST) == 0 ||
                    action.compare(actionPUT) == 0 ||
                    action.compare(actionPATCH) == 0 ||
                    action.compare(actionDELETE) == 0 ||
                    action.compare(actionTRACE) == 0
                )
                {
                    fetchResult(&qItem);
                }
                else
                {
                    resList_mutex.lock();
                    FetchURL::FetchResult fres;
                    fres = resList[qItem.key];
                    fres.status = 2;
                    resList[qItem.key] = fres;
                    resList_mutex.unlock();
                };
            }
        }
    }
};

/*
    Publicity: public/static
    Return type: size_t
    Name/Type: FetchURLCallbackWriter()
    Description: Writes incoming data from curl to a string/buffer.
*/
static size_t FetchURLCallbackWriter(void *contents, size_t size, size_t nmemb, void *buf)
{
    ((std::string *)buf)->append((char *)contents, size * nmemb);
    return size * nmemb;
};

/*
    Publicity: private
    Return type: void
    Name/Type: fetchResult()
    Description: processes a single url request.
*/
void FetchURL::fetchResult(FetchURL::FetchQueueItem * qItem)
{
    FetchURL::FetchResult fres;

    int key = qItem->key;
    std::string url = qItem->params["#url"];
    std::string method = qItem->params["#method"];
    //std::string mime = qItem.params["#mime"]; currently unused

    if (resList.empty())
        return;

    fres = resList[key];
    fres.status = 3;

    CURL *curl;
    CURLcode res;

    curl = curl_easy_init();

    if (qItem->params.size() > 0)
        url.append("?");

    bool fBind = false;
    for (std::map<std::string, std::string>::iterator iter = qItem->params.begin(); iter != qItem->params.end(); ++iter)
    {
        if (
            iter->first.compare(cmdUrl) != 0 &&
            iter->first.compare(cmdMethod) != 0 &&
            iter->first.compare(cmdJSONDec) != 0
        )
        {
            if (fBind) {
                url.append("&");
            } else {
                fBind = true;
            }

            char * encVal = curl_easy_escape(curl, iter->second.c_str(), 0);
            char * encKey = curl_easy_escape(curl, iter->first.c_str(), 0);
            url.append(encKey);
            url.append("=");
            url.append(encVal);
        }
    }

    std::string str;
    struct curl_slist *headers = NULL;

    if (curl)
    {
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method.c_str());
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &str);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, FetchURLCallbackWriter);
        res = curl_easy_perform(curl);

        if (res == CURLE_OK)
        {
            char *ct;
            res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct);

            if ((CURLE_OK == res) && ct)
            {
                if (str.size() > 10240)
                    str.resize(10240);

                fres.result = str;
                fres.status = 1;
            }
        }
    }

    if (qItem->params["#jsonToArray"].compare("true") == 0)
    {
        fres.result = JsonToArray(str);
    }

    resList_mutex.lock();
    resList[key] = fres;
    resList_mutex.unlock();
};

/*
    Publicity: public
    Return type: int
    Name/Type: GetStatus()
    Description: returns the status of an result queue item.
*/
int FetchURL::GetStatus(int key)
{
    if (resList.empty() || resList.find(key) == resList.end())
        return 0;

    FetchURL::FetchResult fres;
    fres = resList[key];

    return fres.status;
};

/*
    Publicity: public
    Return type: std::string
    Name/Type: GetResult()
    Description: returns the result of an request. If a request finished successful or errored the selected item is removed after the request.
*/
std::string FetchURL::GetResult(int key)
{
    if (resList.empty()/* || resList.find(key) == resList.end()*/)
        return std::string();

    FetchURL::FetchResult fres;
    fres = resList[key];

    if (fres.status != 0) {
        resList_mutex.lock();
        resList.erase(key);
        resList_mutex.unlock();
    }

    return fres.result;
};

/*
    Publicity: private
    Return type: std::string
    Name/Type: jsonToArray_object()
    Description: subfunction of JsonToArray() and jsonToArray_array() for object iterations.
*/
std::string FetchURL::jsonToArray_object(nlohmann::json j)
{
    std::stringstream res;

    res << "[";
    for (nlohmann::json::iterator it = j.begin(); it != j.end(); ++it)
    {
        if (it != j.begin())
            res << ",";

        if (it.value().is_number() || it.value().is_boolean() || it.value().is_string())
        {
            res << "[\"" << it.key() << "\"," << it.value() << "]";
        }
        else if (it.value().is_null())
        {
            res << "[\"" << it.key() << ",null]";
        }
        else if (it.value().is_object())
        {
            res << "[\"" << it.key() << "\",[\"object\"," << jsonToArray_object(it.value()) << "]]";
        }
        else if (it.value().is_array())
        {
            res << "[\"" << it.key() << "\",[\"array\"," << jsonToArray_array(it.value()) << "]]";
        }
    }
    res << "]";

    return res.str();
};

/*
    Publicity: private
    Return type: std::string
    Name/Type: jsonToArray_array()
    Description: subfunction of JsonToArray() and jsonToArray_object() for array iterations.
*/
std::string FetchURL::jsonToArray_array(nlohmann::json j)
{
    std::stringstream res;

    res << "[";
    for (int i = 0; i < j.size(); i++)
    {
        if (i != 0)
            res << ",";

        if (j[i].is_number() || j[i].is_boolean() || j[i].is_string())
        {
            res << j[i];
        }
        else if (j[i].is_null())
        {
            res << "null";
        }
        else if (j[i].is_object())
        {
            res << "[\"object\"," << jsonToArray_object(j[i]) << "]";
        }
        else if (j[i].is_array())
        {
            res << "[\"array\"," << jsonToArray_array(j[i]) << "]";
        }
    }
    res << "]";

    return res.str();
};

/*
    Publicity: private
    Return type: std::string
    Name/Type: jsonToArray()
    Description: Parses a JSON input to an ArmA 3 friendly array.
*/
std::string FetchURL::JsonToArray(std::string jsonStr)
{
    nlohmann::json j = nlohmann::json::parse(jsonStr);
    std::stringstream res;

    if (j.is_array()) {
        res << "[\"array\"," << jsonToArray_array(j) << "]";
    }
    else if (j.is_object())
    {
        res << "[\"object\"," << jsonToArray_object(j) << "]";
    }

    return res.str();
};
<|endoftext|>


<commit_before>#include "adian_rtable.h"

//--------------- routing table functions ---------------------

// constructor
Adian_rtable::Adian_rtable() { }

//The print() function will dump the contents of the node’s routing table to the trace file.
void Adian_rtable::print(Trace* out) {

	sprintf(out->pt_->buffer(), "A\tdest\tnext_hop\tnn");
	out->pt_->dump();

	// Iterate over through the _nexthop_ map
	rtable_nexthop_t::iterator it_hop;

	for (it_hop = rt_nexthop_.begin(),; it_hop != rt_nexthop_.end(); it_hop++) {

  		// foreach destination -> (*it_hop).first, find the corrosponding number of nodes
  		rtable_nn_t::iterator it_nn = rt_nn_.find((*it_hop).first);
  		if (it_nn == rt_nn_.end()) {
  			// number of nodes entry not exists for destination node
  			// that means inconsistent data
  			sprintf(stderr, "Inconsistent Data, number of nodes entry not exists for %d node\n", (*it_hop).first);
  		}
  		else {
  			//found all data, dump it
   			sprintf(out->pt_->buffer(), "A\t%d\t%d\t%d",(*it_hop).first,(*it_hop).second,(*it_nn).second);
   			out->pt_->dump();
  		}
  	}
 }

//function removes all entries in routing table
void Adian_rtable::clear() {
 	rt_nexthop_.clear();
 	rt_nn_.clear();
}

//function removes entry given the destination address
void Adian_rtable::rm_entry(nsaddr_t dest) {
	rt_nexthop_.erase(dest);
	rt_nn_.erase(dest);
}

//function adds a new entry in the routing table given its destination,next hop address and nn
void Adian_rtable::add_entry(nsaddr_t dest, nsaddr_t next, u_int8_t nn) {
	rt_nexthop_[dest] = next;
	rt_nn_[dest] = nn;
}

//function updates the next_hop and number of nodes corrosponding to dest entry
void Adian_rtable::update_entry(nsaddr_t dest, nsaddr_t nexthop, u_int8_t nn) {
	//update operation
	rt_nexthop_[dest] = nexthop;
	rt_nn_[dest] = nn;
}

//function returns rtable_t object containing the next hop address and number of nodes
//if there exists an entry for destination in the routing table
rtable_entry Adian_rtable::lookup(nsaddr_t dest) {

	// to return the result
	rtable_entry result;
	result.daddr = dest;

	rtable_nexthop_t::iterator it_hop = rt_nexthop_.find(dest);
	if (it_hop == rt_nexthop_.end()) {
		result.next_hop = IP_BROADCAST;
		result.nn = 0;
 		return result;
	}
 	else {
  		rtable_nn_t::iterator it_nn = rt_nn_.find(dest);
  		if(it_nn == rt_nn_.end()) {
  			result.next_hop = IP_BROADCAST;
			result.nn = 0;
	 		return result;
  		}
  		else {
  			result.next_hop = (*it_hop).second;
  			result.nn = (*it_nn).second;
  		}
 	}
 }
<commit_msg>add definition to neighbourhood table function in adian_rtable.cc<commit_after>#include "adian_rtable.h"
#include <vector>

//--------------- routing table functions ---------------------

// constructor
Adian_rtable::Adian_rtable() { }

//The print() function will dump the contents of the node’s routing table to the trace file.
void Adian_rtable::print(Trace* out) {

	sprintf(out->pt_->buffer(), "A\tdest\tnext_hop\tnn");
	out->pt_->dump();

	// Iterate over through the _nexthop_ map
	rtable_nexthop_t::iterator it_hop;

	for (it_hop = rt_nexthop_.begin(); it_hop != rt_nexthop_.end(); it_hop++) {

  		// foreach destination -> (*it_hop).first, find the corrosponding number of nodes
  		rtable_nn_t::iterator it_nn = rt_nn_.find((*it_hop).first);
  		if (it_nn == rt_nn_.end()) {
  			// number of nodes entry not exists for destination node
  			// that means inconsistent data
  			sprintf(stderr, "Inconsistent Data, number of nodes entry not exists for %d node\n", (*it_hop).first);
  		}
  		else {
  			//found all data, dump it
   			sprintf(out->pt_->buffer(), "A\t%d\t%d\t%d",(*it_hop).first,(*it_hop).second,(*it_nn).second);
   			out->pt_->dump();
  		}
  	}
 }

//function removes all entries in routing table
void Adian_rtable::clear() {
 	rt_nexthop_.clear();
 	rt_nn_.clear();
}

//function removes entry given the destination address
void Adian_rtable::rm_entry(nsaddr_t dest) {
	rt_nexthop_.erase(dest);
	rt_nn_.erase(dest);
}

//function adds a new entry in the routing table given its destination,next hop address and nn
void Adian_rtable::add_entry(nsaddr_t dest, nsaddr_t next, u_int8_t nn) {
	rt_nexthop_[dest] = next;
	rt_nn_[dest] = nn;
}

//function updates the next_hop and number of nodes corrosponding to dest entry
void Adian_rtable::update_entry(nsaddr_t dest, nsaddr_t nexthop, u_int8_t nn) {
	//update operation
	rt_nexthop_[dest] = nexthop;
	rt_nn_[dest] = nn;
}

//function returns rtable_t object containing the next hop address and number of nodes
//if there exists an entry for destination in the routing table
rtable_entry Adian_rtable::lookup(nsaddr_t dest) {

	// to return the result
	rtable_entry result;
	result.daddr = dest;

	rtable_nexthop_t::iterator it_hop = rt_nexthop_.find(dest);
	if (it_hop == rt_nexthop_.end()) {
		result.next_hop = IP_BROADCAST;
		result.nn = 0;
 		return result;
	}
 	else {
  		rtable_nn_t::iterator it_nn = rt_nn_.find(dest);
  		if(it_nn == rt_nn_.end()) {
  			result.next_hop = IP_BROADCAST;
			result.nn = 0;
	 		return result;
  		}
  		else {
  			result.next_hop = (*it_hop).second;
  			result.nn = (*it_nn).second;
  		}
 	}
 }

//------------------------neighbourhood table------------------------------

 //constructor
Adian_nbtable::Adian_nbtable(){ }

//print function will dump all enteries of  its neighbouring table to trace file
void Adian_nbtable::print(Trace* out) {
	sprintf(out->pt_->buffer(),"a\tnode\n");
	out->pt_->dump();

	//Iterate over through the _nb_ list
	nbtable_t::iterator it_nb;

	for(it_nb = nb_.begin(); it_nb != nb_.end(); it_nb++ ) {
		sprintf(out->pt_->buffer(), "A\t%d",*it_nb);
   		out->pt_->dump();
	}
}

// remove all the enteries in neighbourhood table
void Adian_nbtable::clear(){
	nb_.clear();
}

// remove a particular entry in neighbourhood table
void Adian_nbtable::rm_entry(nsaddr_t neighbour){
	nb_.erase(dest);
}

// add a new node to the neighbourhood
void Adian_nbtable::add_entry(nsaddr_t neighbour){
	nb_.push_back(neighbour);// adds a entry from back of the list
}

//to get all the neighbour nodes from neighbourhood table
nsaddr_t* Adian_nbtable::get_neighbours(){
	std::vector<nsaddr_t*> neighbours_{std::begin(nb_),std::end(nb_)};//copies all the list to vector "neighbours_"
	return neighbours_;
}<|endoftext|>


<commit_before>/**
 * \file
 * \brief RawMessageQueue class implementation
 *
 * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2015-01-17
 */

#include "distortos/RawMessageQueue.hpp"

#include "distortos/synchronization/SemaphoreWaitFunctor.hpp"

#include <cstring>
#include <cerrno>

namespace distortos
{

namespace
{

/*---------------------------------------------------------------------------------------------------------------------+
| local types
+---------------------------------------------------------------------------------------------------------------------*/

/// PushFunctor is a functor used for pushing of data to the RawMessageQueue
class PushFunctor : public synchronization::MessageQueueBase::Functor
{
public:

	/**
	 * \brief PushFunctor's constructor
	 *
	 * \param [in] data is a pointer to data that will be pushed to RawMessageQueue
	 * \param [in] size is the size of \a data, bytes
	 */

	constexpr PushFunctor(const void* const data, const size_t size) :
			data_{data},
			size_{size}
	{

	}

	/**
	 * \brief Copies the data to RawMessageQueue's storage (with memcpy()).
	 *
	 * \param [in,out] storage is a pointer to storage for element
	 */

	virtual void operator()(void* const storage) const override
	{
		memcpy(storage, data_, size_);
	}

private:

	/// pointer to data that will be pushed to RawMessageQueue
	const void* const data_;

	/// size of \a data_, bytes
	const size_t size_;
};

}	// namespace

/*---------------------------------------------------------------------------------------------------------------------+
| public functions
+---------------------------------------------------------------------------------------------------------------------*/

int RawMessageQueue::push(const uint8_t priority, const void* const data, const size_t size)
{
	const synchronization::SemaphoreWaitFunctor semaphoreWaitFunctor;
	return pushInternal(semaphoreWaitFunctor, priority, data, size);
}

/*---------------------------------------------------------------------------------------------------------------------+
| private functions
+---------------------------------------------------------------------------------------------------------------------*/

int RawMessageQueue::pushInternal(const synchronization::SemaphoreFunctor& waitSemaphoreFunctor, const uint8_t priority,
		const void* const data, const size_t size)
{
	if (size != elementSize_)
		return EMSGSIZE;

	const PushFunctor pushFunctor {data, size};
	return messageQueueBase_.push(waitSemaphoreFunctor, priority, pushFunctor);
}

}	// namespace distortos
<commit_msg>RawMessageQueue: add local PopFunctor class<commit_after>/**
 * \file
 * \brief RawMessageQueue class implementation
 *
 * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2015-01-17
 */

#include "distortos/RawMessageQueue.hpp"

#include "distortos/synchronization/SemaphoreWaitFunctor.hpp"

#include <cstring>
#include <cerrno>

namespace distortos
{

namespace
{

/*---------------------------------------------------------------------------------------------------------------------+
| local types
+---------------------------------------------------------------------------------------------------------------------*/

/// PopFunctor is a functor used for popping of data from the RawMessageQueue
class PopFunctor : public synchronization::MessageQueueBase::Functor
{
public:

	/**
	 * \brief PopFunctor's constructor
	 *
	 * \param [out] buffer is a pointer to buffer for popped element
	 * \param [in] size is the size of \a buffer, bytes
	 */

	constexpr PopFunctor(void* const buffer, const size_t size) :
			buffer_{buffer},
			size_{size}
	{

	}

	/**
	 * \brief Copies the data from RawMessageQueue's storage (with memcpy()).
	 *
	 * \param [in,out] storage is a pointer to storage for element
	 */

	virtual void operator()(void* const storage) const override
	{
		memcpy(buffer_, storage, size_);
	}

private:

	/// pointer to buffer for popped element
	void* const buffer_;

	/// size of \a buffer_, bytes
	const size_t size_;
};

/// PushFunctor is a functor used for pushing of data to the RawMessageQueue
class PushFunctor : public synchronization::MessageQueueBase::Functor
{
public:

	/**
	 * \brief PushFunctor's constructor
	 *
	 * \param [in] data is a pointer to data that will be pushed to RawMessageQueue
	 * \param [in] size is the size of \a data, bytes
	 */

	constexpr PushFunctor(const void* const data, const size_t size) :
			data_{data},
			size_{size}
	{

	}

	/**
	 * \brief Copies the data to RawMessageQueue's storage (with memcpy()).
	 *
	 * \param [in,out] storage is a pointer to storage for element
	 */

	virtual void operator()(void* const storage) const override
	{
		memcpy(storage, data_, size_);
	}

private:

	/// pointer to data that will be pushed to RawMessageQueue
	const void* const data_;

	/// size of \a data_, bytes
	const size_t size_;
};

}	// namespace

/*---------------------------------------------------------------------------------------------------------------------+
| public functions
+---------------------------------------------------------------------------------------------------------------------*/

int RawMessageQueue::push(const uint8_t priority, const void* const data, const size_t size)
{
	const synchronization::SemaphoreWaitFunctor semaphoreWaitFunctor;
	return pushInternal(semaphoreWaitFunctor, priority, data, size);
}

/*---------------------------------------------------------------------------------------------------------------------+
| private functions
+---------------------------------------------------------------------------------------------------------------------*/

int RawMessageQueue::pushInternal(const synchronization::SemaphoreFunctor& waitSemaphoreFunctor, const uint8_t priority,
		const void* const data, const size_t size)
{
	if (size != elementSize_)
		return EMSGSIZE;

	const PushFunctor pushFunctor {data, size};
	return messageQueueBase_.push(waitSemaphoreFunctor, priority, pushFunctor);
}

}	// namespace distortos
<|endoftext|>


<commit_before>#include "libtxc_dxtn.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "s2tc_compressor.h"

void fetch_2d_texel_rgb_dxt1(GLint srcRowStride, const GLubyte *pixdata,
			     GLint i, GLint j, GLvoid *texel)
{
	// fetches a single texel (i,j) into pixdata (RGB)
	GLubyte *t = (GLubyte *) texel;
	const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8);
	unsigned int c  = blksrc[0] + 256*blksrc[1];
	unsigned int c1 = blksrc[2] + 256*blksrc[3];
	int b = (blksrc[4 + (j % 4)] >> (2 * (i % 4))) & 0x03;
	switch(b)
	{
		case 0:                         break;
		case 1:  c = c1;                break;
		case 3:  if(c1 > c) { c = 0;    break; }
		default: if(rand() & 1) c = c1; break;
	}
	t[0] = ((c >> 11) & 0x1F); t[0] = (t[0] << 3) | (t[0] >> 2);
	t[1] = ((c >>  5) & 0x3F); t[1] = (t[1] << 2) | (t[1] >> 4);
	t[2] = ((c      ) & 0x1F); t[2] = (t[2] << 3) | (t[2] >> 2);
}

void fetch_2d_texel_rgba_dxt1(GLint srcRowStride, const GLubyte *pixdata,
			     GLint i, GLint j, GLvoid *texel)
{
	// fetches a single texel (i,j) into pixdata (RGBA)
	GLubyte *t = (GLubyte *) texel;
	const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8);
	unsigned int c  = blksrc[0] + 256*blksrc[1];
	unsigned int c1 = blksrc[2] + 256*blksrc[3];
	int b = (blksrc[4 + (j % 4)] >> (2 * (i % 4))) & 0x03;
	switch(b)
	{
		case 0:                         t[3] = 255; break;
		case 1:  c = c1;                t[3] = 255; break;
		case 3:  if(c1 > c) { c = 0;    t[3] =   0; break; }
		default: if(rand() & 1) c = c1; t[3] = 255; break;
	}
	t[0] = ((c >> 11) & 0x1F); t[0] = (t[0] << 3) | (t[0] >> 2);
	t[1] = ((c >>  5) & 0x3F); t[1] = (t[1] << 2) | (t[1] >> 4);
	t[2] = ((c      ) & 0x1F); t[2] = (t[2] << 3) | (t[2] >> 2);
}

void fetch_2d_texel_rgba_dxt3(GLint srcRowStride, const GLubyte *pixdata,
			     GLint i, GLint j, GLvoid *texel)
{
	// fetches a single texel (i,j) into pixdata (RGBA)
	GLubyte *t = (GLubyte *) texel;
	const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8);
	unsigned int c  = blksrc[8] + 256*blksrc[9];
	unsigned int c1 = blksrc[10] + 256*blksrc[11];
	int b = (blksrc[12 + (j % 4)] >> (2 * (i % 4))) & 0x03;
	switch(b)
	{
		case 0:                         break;
		case 1:  c = c1;                break;
		default: if(rand() & 1) c = c1; break;
	}
	t[0] = ((c >> 11) & 0x1F); t[0] = (t[0] << 3) | (t[0] >> 2);
	t[1] = ((c >>  5) & 0x3F); t[1] = (t[1] << 2) | (t[1] >> 4);
	t[2] = ((c      ) & 0x1F); t[2] = (t[2] << 3) | (t[2] >> 2);
	int a = (blksrc[(j % 4) * 2 + (i % 4) / 2] >> (4 * (i % 4) % 2)) & 0x0F;
	t[3] = a | (a << 4);
}

void fetch_2d_texel_rgba_dxt5(GLint srcRowStride, const GLubyte *pixdata,
			     GLint i, GLint j, GLvoid *texel)
{
	// fetches a single texel (i,j) into pixdata (RGBA)
	GLubyte *t = (GLubyte *) texel;
	const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8);
	unsigned int c  = blksrc[8] + 256*blksrc[9];
	unsigned int c1 = blksrc[10] + 256*blksrc[11];
	int b = (blksrc[12 + (j % 4)] >> (2 * (i % 4))) & 0x03;
	switch(b)
	{
		case 0:                         break;
		case 1:  c = c1;                break;
		default: if(rand() & 1) c = c1; break;
	}
	t[0] = ((c >> 11) & 0x1F); t[0] = (t[0] << 3) | (t[0] >> 2);
	t[1] = ((c >>  5) & 0x3F); t[1] = (t[1] << 2) | (t[1] >> 4);
	t[2] = ((c      ) & 0x1F); t[2] = (t[2] << 3) | (t[2] >> 2);

	unsigned int a  = blksrc[0];
	unsigned int a1 = blksrc[1];
	int abit = ((j % 4) * 4 + (i % 4)) * 3;
	int ab = 0;
	if(blksrc[(abit / 8)] & (1 << (abit % 8)))
		ab |= 1;
	++abit;
	if(blksrc[(abit / 8)] & (1 << (abit % 8)))
		ab |= 2;
	++abit;
	if(blksrc[(abit / 8)] & (1 << (abit % 8)))
		ab |= 4;
	switch(ab)
	{
		case 0:                         break;
		case 1:  a = a1;                break;
		case 6:  a = 0;                 break;
		case 7:  a = 255;               break;
		default: if(rand() & 1) a = a1; break;
	}
	t[3] = a;
}

void tx_compress_dxtn(GLint srccomps, GLint width, GLint height,
		      const GLubyte *srcPixData, GLenum destFormat,
		      GLubyte *dest, GLint dstRowStride)
{
	// compresses width*height pixels (RGB or RGBA depending on srccomps) at srcPixData (packed) to destformat (dest, dstRowStride)

	GLubyte *blkaddr = dest;
	GLint numxpixels, numypixels;
	GLint i, j;
	GLint dstRowDiff;
	unsigned char *rgba = (unsigned char *) malloc(width * height * 4);
	unsigned char *srcaddr;
	DxtMode dxt;

	switch (destFormat) {
		case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
		case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
			dxt = DXT1;
			rgb565_image(rgba, srcPixData, width, height, srccomps, 0, 1);
			break;
		case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
			dxt = DXT3;
			rgb565_image(rgba, srcPixData, width, height, srccomps, 0, 4);
			break;
		case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
			dxt = DXT5;
			rgb565_image(rgba, srcPixData, width, height, srccomps, 0, 8);
			break;
		default:
			free(rgba);
			fprintf(stderr, "libdxtn: Bad dstFormat %d in tx_compress_dxtn\n", destFormat);
			return;
	}

	ColorDistMode cd = WAVG;
	int nrandom = -1;
	{
		const char *v = getenv("S2TC_COLORDIST_MODE");
		if(v)
		{
			if(!strcasecmp(v, "RGB"))
				cd = RGB;
			else if(!strcasecmp(v, "YUV"))
				cd = YUV;
			else if(!strcasecmp(v, "SRGB"))
				cd = SRGB;
			else if(!strcasecmp(v, "SRGB_MIXED"))
				cd = SRGB_MIXED;
			else if(!strcasecmp(v, "LAB"))
				cd = LAB;
			else if(!strcasecmp(v, "AVG"))
				cd = AVG;
			else if(!strcasecmp(v, "WAVG"))
				cd = WAVG;
			else if(!strcasecmp(v, "NORMALMAP"))
				cd = NORMALMAP;
			else
				fprintf(stderr, "Invalid color dist mode: %s\n", v);
		}
	}
	{
		const char *v = getenv("S2TC_RANDOM_COLORS");
		if(v)
			nrandom = atoi(v);
	}

	s2tc_encode_block_func_t encode_block = s2tc_encode_block_func(dxt, cd, nrandom);
	switch (destFormat) {
		case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
		case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
			/* hmm we used to get called without dstRowStride... */
			dstRowDiff = dstRowStride >= (width * 2) ? dstRowStride - (((width + 3) & ~3) * 2) : 0;
			/*      fprintf(stderr, "dxt1 tex width %d tex height %d dstRowStride %d\n",
				width, height, dstRowStride); */
			for (j = 0; j < height; j += 4) {
				if (height > j + 3) numypixels = 4;
				else numypixels = height - j;
				srcaddr = rgba + j * width * 4;
				for (i = 0; i < width; i += 4) {
					if (width > i + 3) numxpixels = 4;
					else numxpixels = width - i;
					encode_block(blkaddr, srcaddr, width, numxpixels, numypixels, nrandom);
					srcaddr += 4 * numxpixels;
					blkaddr += 8;
				}
				blkaddr += dstRowDiff;
			}
			break;
		case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
			dstRowDiff = dstRowStride >= (width * 4) ? dstRowStride - (((width + 3) & ~3) * 4) : 0;
			/*      fprintf(stderr, "dxt3 tex width %d tex height %d dstRowStride %d\n",
				width, height, dstRowStride); */
			for (j = 0; j < height; j += 4) {
				if (height > j + 3) numypixels = 4;
				else numypixels = height - j;
				srcaddr = rgba + j * width * 4;
				for (i = 0; i < width; i += 4) {
					if (width > i + 3) numxpixels = 4;
					else numxpixels = width - i;
					encode_block(blkaddr, srcaddr, width, numxpixels, numypixels, nrandom);
					srcaddr += 4 * numxpixels;
					blkaddr += 16;
				}
				blkaddr += dstRowDiff;
			}
			break;
		case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
			dstRowDiff = dstRowStride >= (width * 4) ? dstRowStride - (((width + 3) & ~3) * 4) : 0;
			/*      fprintf(stderr, "dxt5 tex width %d tex height %d dstRowStride %d\n",
				width, height, dstRowStride); */
			for (j = 0; j < height; j += 4) {
				if (height > j + 3) numypixels = 4;
				else numypixels = height - j;
				srcaddr = rgba + j * width * 4;
				for (i = 0; i < width; i += 4) {
					if (width > i + 3) numxpixels = 4;
					else numxpixels = width - i;
					encode_block(blkaddr, srcaddr, width, numxpixels, numypixels, nrandom);
					srcaddr += 4 * numxpixels;
					blkaddr += 16;
				}
				blkaddr += dstRowDiff;
			}
			break;
	}

	free(rgba);
}
<commit_msg>make decoding deterministic<commit_after>#include "libtxc_dxtn.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "s2tc_compressor.h"

void fetch_2d_texel_rgb_dxt1(GLint srcRowStride, const GLubyte *pixdata,
			     GLint i, GLint j, GLvoid *texel)
{
	// fetches a single texel (i,j) into pixdata (RGB)
	GLubyte *t = (GLubyte *) texel;
	const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8);
	unsigned int c  = blksrc[0] + 256*blksrc[1];
	unsigned int c1 = blksrc[2] + 256*blksrc[3];
	int b = (blksrc[4 + (j % 4)] >> (2 * (i % 4))) & 0x03;
	switch(b)
	{
		case 0:                        break;
		case 1:  c = c1;               break;
		case 3:  if(c1 > c) { c = 0;   break; }
		default: if((i^j) & 1) c = c1; break;
	}
	t[0] = ((c >> 11) & 0x1F); t[0] = (t[0] << 3) | (t[0] >> 2);
	t[1] = ((c >>  5) & 0x3F); t[1] = (t[1] << 2) | (t[1] >> 4);
	t[2] = ((c      ) & 0x1F); t[2] = (t[2] << 3) | (t[2] >> 2);
}

void fetch_2d_texel_rgba_dxt1(GLint srcRowStride, const GLubyte *pixdata,
			     GLint i, GLint j, GLvoid *texel)
{
	// fetches a single texel (i,j) into pixdata (RGBA)
	GLubyte *t = (GLubyte *) texel;
	const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8);
	unsigned int c  = blksrc[0] + 256*blksrc[1];
	unsigned int c1 = blksrc[2] + 256*blksrc[3];
	int b = (blksrc[4 + (j % 4)] >> (2 * (i % 4))) & 0x03;
	switch(b)
	{
		case 0:                        t[3] = 255; break;
		case 1:  c = c1;               t[3] = 255; break;
		case 3:  if(c1 > c) { c = 0;   t[3] =   0; break; }
		default: if((i^j) & 1) c = c1; t[3] = 255; break;
	}
	t[0] = ((c >> 11) & 0x1F); t[0] = (t[0] << 3) | (t[0] >> 2);
	t[1] = ((c >>  5) & 0x3F); t[1] = (t[1] << 2) | (t[1] >> 4);
	t[2] = ((c      ) & 0x1F); t[2] = (t[2] << 3) | (t[2] >> 2);
}

void fetch_2d_texel_rgba_dxt3(GLint srcRowStride, const GLubyte *pixdata,
			     GLint i, GLint j, GLvoid *texel)
{
	// fetches a single texel (i,j) into pixdata (RGBA)
	GLubyte *t = (GLubyte *) texel;
	const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8);
	unsigned int c  = blksrc[8] + 256*blksrc[9];
	unsigned int c1 = blksrc[10] + 256*blksrc[11];
	int b = (blksrc[12 + (j % 4)] >> (2 * (i % 4))) & 0x03;
	switch(b)
	{
		case 0:                        break;
		case 1:  c = c1;               break;
		default: if((i^j) & 1) c = c1; break;
	}
	t[0] = ((c >> 11) & 0x1F); t[0] = (t[0] << 3) | (t[0] >> 2);
	t[1] = ((c >>  5) & 0x3F); t[1] = (t[1] << 2) | (t[1] >> 4);
	t[2] = ((c      ) & 0x1F); t[2] = (t[2] << 3) | (t[2] >> 2);
	int a = (blksrc[(j % 4) * 2 + (i % 4) / 2] >> (4 * (i % 4) % 2)) & 0x0F;
	t[3] = a | (a << 4);
}

void fetch_2d_texel_rgba_dxt5(GLint srcRowStride, const GLubyte *pixdata,
			     GLint i, GLint j, GLvoid *texel)
{
	// fetches a single texel (i,j) into pixdata (RGBA)
	GLubyte *t = (GLubyte *) texel;
	const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8);
	unsigned int c  = blksrc[8] + 256*blksrc[9];
	unsigned int c1 = blksrc[10] + 256*blksrc[11];
	int b = (blksrc[12 + (j % 4)] >> (2 * (i % 4))) & 0x03;
	switch(b)
	{
		case 0:                        break;
		case 1:  c = c1;               break;
		default: if((i^j) & 1) c = c1; break;
	}
	t[0] = ((c >> 11) & 0x1F); t[0] = (t[0] << 3) | (t[0] >> 2);
	t[1] = ((c >>  5) & 0x3F); t[1] = (t[1] << 2) | (t[1] >> 4);
	t[2] = ((c      ) & 0x1F); t[2] = (t[2] << 3) | (t[2] >> 2);

	unsigned int a  = blksrc[0];
	unsigned int a1 = blksrc[1];
	int abit = ((j % 4) * 4 + (i % 4)) * 3;
	int ab = 0;
	if(blksrc[(abit / 8)] & (1 << (abit % 8)))
		ab |= 1;
	++abit;
	if(blksrc[(abit / 8)] & (1 << (abit % 8)))
		ab |= 2;
	++abit;
	if(blksrc[(abit / 8)] & (1 << (abit % 8)))
		ab |= 4;
	switch(ab)
	{
		case 0:                        break;
		case 1:  a = a1;               break;
		case 6:  a = 0;                break;
		case 7:  a = 255;              break;
		default: if((i^j) & 1) a = a1; break;
	}
	t[3] = a;
}

void tx_compress_dxtn(GLint srccomps, GLint width, GLint height,
		      const GLubyte *srcPixData, GLenum destFormat,
		      GLubyte *dest, GLint dstRowStride)
{
	// compresses width*height pixels (RGB or RGBA depending on srccomps) at srcPixData (packed) to destformat (dest, dstRowStride)

	GLubyte *blkaddr = dest;
	GLint numxpixels, numypixels;
	GLint i, j;
	GLint dstRowDiff;
	unsigned char *rgba = (unsigned char *) malloc(width * height * 4);
	unsigned char *srcaddr;
	DxtMode dxt;

	switch (destFormat) {
		case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
		case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
			dxt = DXT1;
			rgb565_image(rgba, srcPixData, width, height, srccomps, 0, 1);
			break;
		case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
			dxt = DXT3;
			rgb565_image(rgba, srcPixData, width, height, srccomps, 0, 4);
			break;
		case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
			dxt = DXT5;
			rgb565_image(rgba, srcPixData, width, height, srccomps, 0, 8);
			break;
		default:
			free(rgba);
			fprintf(stderr, "libdxtn: Bad dstFormat %d in tx_compress_dxtn\n", destFormat);
			return;
	}

	ColorDistMode cd = WAVG;
	int nrandom = -1;
	{
		const char *v = getenv("S2TC_COLORDIST_MODE");
		if(v)
		{
			if(!strcasecmp(v, "RGB"))
				cd = RGB;
			else if(!strcasecmp(v, "YUV"))
				cd = YUV;
			else if(!strcasecmp(v, "SRGB"))
				cd = SRGB;
			else if(!strcasecmp(v, "SRGB_MIXED"))
				cd = SRGB_MIXED;
			else if(!strcasecmp(v, "LAB"))
				cd = LAB;
			else if(!strcasecmp(v, "AVG"))
				cd = AVG;
			else if(!strcasecmp(v, "WAVG"))
				cd = WAVG;
			else if(!strcasecmp(v, "NORMALMAP"))
				cd = NORMALMAP;
			else
				fprintf(stderr, "Invalid color dist mode: %s\n", v);
		}
	}
	{
		const char *v = getenv("S2TC_RANDOM_COLORS");
		if(v)
			nrandom = atoi(v);
	}

	s2tc_encode_block_func_t encode_block = s2tc_encode_block_func(dxt, cd, nrandom);
	switch (destFormat) {
		case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
		case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
			/* hmm we used to get called without dstRowStride... */
			dstRowDiff = dstRowStride >= (width * 2) ? dstRowStride - (((width + 3) & ~3) * 2) : 0;
			/*      fprintf(stderr, "dxt1 tex width %d tex height %d dstRowStride %d\n",
				width, height, dstRowStride); */
			for (j = 0; j < height; j += 4) {
				if (height > j + 3) numypixels = 4;
				else numypixels = height - j;
				srcaddr = rgba + j * width * 4;
				for (i = 0; i < width; i += 4) {
					if (width > i + 3) numxpixels = 4;
					else numxpixels = width - i;
					encode_block(blkaddr, srcaddr, width, numxpixels, numypixels, nrandom);
					srcaddr += 4 * numxpixels;
					blkaddr += 8;
				}
				blkaddr += dstRowDiff;
			}
			break;
		case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
			dstRowDiff = dstRowStride >= (width * 4) ? dstRowStride - (((width + 3) & ~3) * 4) : 0;
			/*      fprintf(stderr, "dxt3 tex width %d tex height %d dstRowStride %d\n",
				width, height, dstRowStride); */
			for (j = 0; j < height; j += 4) {
				if (height > j + 3) numypixels = 4;
				else numypixels = height - j;
				srcaddr = rgba + j * width * 4;
				for (i = 0; i < width; i += 4) {
					if (width > i + 3) numxpixels = 4;
					else numxpixels = width - i;
					encode_block(blkaddr, srcaddr, width, numxpixels, numypixels, nrandom);
					srcaddr += 4 * numxpixels;
					blkaddr += 16;
				}
				blkaddr += dstRowDiff;
			}
			break;
		case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
			dstRowDiff = dstRowStride >= (width * 4) ? dstRowStride - (((width + 3) & ~3) * 4) : 0;
			/*      fprintf(stderr, "dxt5 tex width %d tex height %d dstRowStride %d\n",
				width, height, dstRowStride); */
			for (j = 0; j < height; j += 4) {
				if (height > j + 3) numypixels = 4;
				else numypixels = height - j;
				srcaddr = rgba + j * width * 4;
				for (i = 0; i < width; i += 4) {
					if (width > i + 3) numxpixels = 4;
					else numxpixels = width - i;
					encode_block(blkaddr, srcaddr, width, numxpixels, numypixels, nrandom);
					srcaddr += 4 * numxpixels;
					blkaddr += 16;
				}
				blkaddr += dstRowDiff;
			}
			break;
	}

	free(rgba);
}
<|endoftext|>


<commit_before><commit_msg>LRU cache cleanup strategy.<commit_after><|endoftext|>