<commit_before>/*******************************************************************************
Name: <NAME>, <NAME>, and <NAME>
Date Created: 11-25-2015
Filename: bank.cpp
Description: Bank server that services requests from the ATM 
             using the Boost library. Compile using the following:
             g++ -std=c++11 bank.cpp -lboost_system -lboost_thread -lboost_regex
             -o bank.out 
*******************************************************************************/

#include <iostream>
#include <string>
//#include <memory>
//#include <utility>
#include <vector>
#include <unordered_map>
#include <boost/thread.hpp>
#include <boost/asio.hpp>
#include "validate.h"
#include <mutex>

using boost::asio::ip::tcp;

class User{
public:
    User(std::string name, long long balance): name(name), balance(balance){}         
    void addMoney(long long money){balance += money;}
    void removeMoney(long long money){balance -= money;}
    long long getBalance(){return balance;}
    int getPin(){return pin;}
private:
    std::string name;
    long long balance;
    int pin;
};

class Bank{
public:
    Bank(){}
    bool login(std::string user, int pin){
        data_m.lock();

        if(users.count(user)!=1){
            data_m.unlock();
            return false;
        }
        if(users[user]->getPin() != pin){
            data_m.unlock();
            return false;
        }
        
        loggedin[user]=true;

        data_m.unlock();
        return true;
    }
    bool balance(std::string user, long long &retBal){
        data_m.lock();

        if(!loggedin[user]){
            data_m.unlock();
            return false;
        }
        retBal = users[user]->getBalance();

        data_m.unlock();
        return true;
    }
    bool withdraw(std::string user, long long amount){
        data_m.lock();

        if(!loggedin[user]){
            data_m.unlock();
            return false;
        }
        if(amount<=0){
            data_m.unlock();
            return false;
        }
        if(users[user]->getBalance()<amount){
            data_m.unlock();
            return false;
        }
        users[user]->removeMoney(amount);

        data_m.unlock();
        return true;
    }
    bool transfer(std::string user1, std::string user2, long long amount){
        data_m.lock();

        if(!loggedin[user1]){
            data_m.unlock();
            return false;
        }
        if(users[user1]->getBalance()<amount){
            data_m.unlock();
            return false;
        }
        if(amount<=0){
            data_m.unlock();
            return false;
        }
        if(users.count(user2)!=1){
            data_m.unlock();
            return false;
        }
        
        users[user1]->removeMoney(amount);
        users[user2]->addMoney(amount);

        data_m.unlock();
        return true;
    }
    bool logout(std::string user){
        data_m.lock();
        
        if(!loggedin[user]){
            data_m.unlock();
            return false;
        }
        
        loggedin[user]=false;
        
        data_m.unlock();
        return true;
    }
private:
    std::unordered_map<std::string, bool> loggedin;
    std::unordered_map<std::string, User*> users;
    std::mutex data_m;
};


/*******************************************************************************
 @DESC: The Session class is responsible for reading from the ATM socket and
        to the Bank socket.
 @ARGS: N/A
 @RTN:  N/A
*******************************************************************************/
class Session : public std::enable_shared_from_this<Session> {
    public:
        Session(tcp::socket Socket1) 
            : bank_socket_(std::move(Socket1)) {}
        void Start() {
            DoRead();
        }
    private:
        //Read from the listen socket (ATM socket)
        void DoRead() {
            auto Self(shared_from_this());    
            bank_socket_.async_read_some(boost::asio::buffer(data_, max_length),
            [this, Self](boost::system::error_code EC, std::size_t Length) {
                if (!EC) {
		    std::cout << "Message received: " << data_ << std::endl;
                    //instead of directly writing, perform the correct operation
                    if(std::string(data_).find("login") == 0){
                        sprintf(data_, "successful write to socket");
                    }            
                    DoWrite(Length);
                }
            });
        }
        //Write to the bank socket 
        void DoWrite(std::size_t Length) {
            auto Self(shared_from_this());
            boost::asio::async_write(bank_socket_, 
                                            boost::asio::buffer(data_, Length),
                        [this, Self](boost::system::error_code EC, std::size_t){
                if (!EC) {
                    DoRead();
                }
            });
        }
        tcp::socket bank_socket_;
        //Max length of messages passed through the proxy
        enum {max_length = 1024};
        //Array to hold the incoming message<commit_msg>Add end of message delimeter<commit_after>/*******************************************************************************
Name: <NAME>, <NAME>, and <NAME>
Date Created: 11-25-2015
Filename: bank.cpp
Description: Bank server that services requests from the ATM 
             using the Boost library. Compile using the following:
             g++ -std=c++11 bank.cpp -lboost_system -lboost_thread -lboost_regex
             -o bank.out 
*******************************************************************************/

#include <iostream>
#include <string>
//#include <memory>
//#include <utility>
#include <vector>
#include <unordered_map>
#include <boost/thread.hpp>
#include <boost/asio.hpp>
#include "validate.h"
#include <mutex>

using boost::asio::ip::tcp;

class User{
public:
    User(std::string name, long long balance): name(name), balance(balance){}         
    void addMoney(long long money){balance += money;}
    void removeMoney(long long money){balance -= money;}
    long long getBalance(){return balance;}
    int getPin(){return pin;}
private:
    std::string name;
    long long balance;
    int pin;
};

class Bank{
public:
    Bank(){}
    bool login(std::string user, int pin){
        data_m.lock();

        if(users.count(user)!=1){
            data_m.unlock();
            return false;
        }
        if(users[user]->getPin() != pin){
            data_m.unlock();
            return false;
        }
        
        loggedin[user]=true;

        data_m.unlock();
        return true;
    }
    bool balance(std::string user, long long &retBal){
        data_m.lock();

        if(!loggedin[user]){
            data_m.unlock();
            return false;
        }
        retBal = users[user]->getBalance();

        data_m.unlock();
        return true;
    }
    bool withdraw(std::string user, long long amount){
        data_m.lock();

        if(!loggedin[user]){
            data_m.unlock();
            return false;
        }
        if(amount<=0){
            data_m.unlock();
            return false;
        }
        if(users[user]->getBalance()<amount){
            data_m.unlock();
            return false;
        }
        users[user]->removeMoney(amount);

        data_m.unlock();
        return true;
    }
    bool transfer(std::string user1, std::string user2, long long amount){
        data_m.lock();

        if(!loggedin[user1]){
            data_m.unlock();
            return false;
        }
        if(users[user1]->getBalance()<amount){
            data_m.unlock();
            return false;
        }
        if(amount<=0){
            data_m.unlock();
            return false;
        }
        if(users.count(user2)!=1){
            data_m.unlock();
            return false;
        }
        
        users[user1]->removeMoney(amount);
        users[user2]->addMoney(amount);

        data_m.unlock();
        return true;
    }
    bool logout(std::string user){
        data_m.lock();
        
        if(!loggedin[user]){
            data_m.unlock();
            return false;
        }
        
        loggedin[user]=false;
        
        data_m.unlock();
        return true;
    }
private:
    std::unordered_map<std::string, bool> loggedin;
    std::unordered_map<std::string, User*> users;
    std::mutex data_m;
};


/*******************************************************************************
 @DESC: The Session class is responsible for reading from the ATM socket and
        to the Bank socket.
 @ARGS: N/A
 @RTN:  N/A
*******************************************************************************/
class Session : public std::enable_shared_from_this<Session> {
    public:
        Session(tcp::socket Socket1) 
            : bank_socket_(std::move(Socket1)) {}
        void Start() {
            DoRead();
        }
    private:
        //Read from the listen socket (ATM socket)
        void DoRead() {
            auto Self(shared_from_this());    
            bank_socket_.async_read_some(boost::asio::buffer(data_, max_length),
            [this, Self](boost::system::error_code EC, std::size_t Length) {
                if (!EC) {
                    data_[Length] = '\0';
		    std::cout << "Message received: " << data_ << std::endl;
                    //instead of directly writing, perform the correct operation
                    //if(std::string(data_).find("login") == 0){
                    //    sprintf(data_, "successful write to socket");
                    //}            
                    DoWrite(Length);
                }
            });
        }
        //Write to the bank socket 
        void DoWrite(std::size_t Length) {
            auto Self(shared_from_this());
            boost::asio::async_write(bank_socket_, 
                                    boost::asio::buffer(data_, Length),
                        [this, Self](boost::system::error_code EC, std::size_t){
                if (!EC) {
                    DoRead();
                }
            });
        }
        tcp::socket bank_socket_;
        //Max length of messages passed through the proxy
        enum {max_length = 1024};
        //Array to hold the incoming message
{'fraction_non_alphanumeric': 0.1812785832441374, 'fraction_numerical': 0.0055463656709156366, 'mean_word_length': 1.905852417302799, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 47, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1228507', 'n_tokens_mistral': 2862, 'n_tokens_neox': 2743, 'n_words': 643}