<commit_before>//
// Created by mabaiming on 16-12-20.
//

#ifndef TCP_TUNNEL_EVENT_MANAGER_H
#define TCP_TUNNEL_EVENT_MANAGER_H

#include "buffer.hpp"
#include "logger.h"
#include "frame.h"

#include <arpa/inet.h>
#include <fcntl.h>
#include <errno.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <unistd.h>

#include <map>
#include <memory>

using namespace std;

class EventManager {
public:
  EventManager() {
    epollFd = epoll_create1(0);
    if(epollFd < 0) {
      log_error << "failed to epoll_create1";
      exit(EXIT_FAILURE);
    }
  }
 ~EventManager() {
    // program exits, and all fds are clean up, so we have to do nothing
  }
  virtual void onBufferCreated(shared_ptr<Buffer> buffer) = 0;
  virtual bool exchangeData() = 0;
  virtual int idle() = 0;

  static const int FD_TYPE_TUNNEL = 1;
  static const int FD_TYPE_TRAFFIC = 2;
  static const int FD_TYPE_MONITOR = 3;

  map<int, shared_ptr<Buffer>> bufferMap;
  map<int, int> acceptFdMap;

  void listen(const string& ip, int port, int connectionCount, int type) {
    int fd = socket(PF_INET, SOCK_STREAM, 0);
    if(fd < 0) {
      log_error << "failed to create socket!";
      exit(EXIT_FAILURE);
    }
    int v;
    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(v)) < 0) {
      log_error << "failed to setsockopt: " << SO_REUSEADDR;
      close(fd);
      exit(EXIT_FAILURE);
    }

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(ip.c_str());
    addr.sin_port = htons(port);
    int result = ::bind(fd, (struct sockaddr *)&addr, sizeof(sockaddr));
    if (result < 0) {
      log_error << "failed to bind, port: " << port;
      exit(EXIT_FAILURE);
    }
    result = ::listen(fd, connectionCount);
    if (result < 0) {
      log_error << "failed to listen, port: " << port;
      exit(EXIT_FAILURE);
    }

    if (registerFd(fd) < 0) {
      log_error << "failed to registerFd: " <<  fd;
      exit(EXIT_FAILURE);
    }
    acceptFdMap[fd] = type;
  }

  bool accept(int eventFd, int events) {
    map<int, int>::iterator it = acceptFdMap.find(eventFd);
    if (it == acceptFdMap.end()) {
      return false;
    }
    struct sockaddr_in addr;
    socklen_t sin_size = sizeof(addr);
    int clientFd = ::accept(eventFd, (struct sockaddr *) &addr, &sin_size);
    if (clientFd < 0) {
      log_error << "failed to accept client: " << FdToAddr(clientFd, false);
      exit(EXIT_FAILURE);
    } else {
      log_info << "success accept client: " << FdToAddr(clientFd, false);
    }
    registerFd(clientFd);
    shared_ptr<Buffer> buffer(new Buffer(it->second, clientFd));
    bufferMap[clientFd] = buffer;
    shared_ptr<Buffer> buffer2(new Buffer(buffer->reverse()));
    onBufferCreated(buffer2);
    return true;
  }

  shared_ptr<Buffer> connect(const string& ip, int port, int type) {
    int fd = socket(PF_INET, SOCK_STREAM, 0);
    if (fd < 0) {
      log_error << "failed to socket";
      return shared_ptr<Buffer>(NULL);
    }
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(ip.c_str());
    addr.sin_port = htons(port);
    int result = ::connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr));
    shared_ptr<Buffer> buffer(new Buffer(type, fd));
    if(result < 0) {
      log_error << "failed to connect " << ip << ":" << port;
      buffer->close();
    } else {
      registerFd(fd);
      bufferMap[fd] = buffer;
    }
    return shared_ptr<Buffer>(new Buffer(buffer->reverse()));
  }

  bool handleEvent(int eventFd, int events) {
    map<int, shared_ptr<Buffer>>::iterator it = bufferMap.find(eventFd);
    if (it == bufferMap.end()) {
      return false;
    }
    shared_ptr<Buffer> buffer = it->second;
    if ((events & EPOLLRDHUP) || (events & EPOLLERR)) {
      buffer->close();
      return true;
    }<commit_msg>make code compatible for shared_ptr<commit_after>//
// Created by mabaiming on 16-12-20.
//

#ifndef TCP_TUNNEL_EVENT_MANAGER_H
#define TCP_TUNNEL_EVENT_MANAGER_H

#include "buffer.hpp"
#include "logger.h"
#include "frame.h"

#include <arpa/inet.h>
#include <fcntl.h>
#include <errno.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <unistd.h>

#include <map>
#include <memory>

using namespace std;

class EventManager {
public:
  EventManager() {
    epollFd = epoll_create1(0);
    if(epollFd < 0) {
      log_error << "failed to epoll_create1";
      exit(EXIT_FAILURE);
    }
  }
 ~EventManager() {
    // program exits, and all fds are clean up, so we have to do nothing
  }
  virtual void onBufferCreated(shared_ptr<Buffer> buffer) = 0;
  virtual bool exchangeData() = 0;
  virtual int idle() = 0;

  static const int FD_TYPE_TUNNEL = 1;
  static const int FD_TYPE_TRAFFIC = 2;
  static const int FD_TYPE_MONITOR = 3;

  map<int, shared_ptr<Buffer>> bufferMap;
  map<int, int> acceptFdMap;

  void listen(const string& ip, int port, int connectionCount, int type) {
    int fd = socket(PF_INET, SOCK_STREAM, 0);
    if(fd < 0) {
      log_error << "failed to create socket!";
      exit(EXIT_FAILURE);
    }
    int v;
    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(v)) < 0) {
      log_error << "failed to setsockopt: " << SO_REUSEADDR;
      close(fd);
      exit(EXIT_FAILURE);
    }

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(ip.c_str());
    addr.sin_port = htons(port);
    int result = ::bind(fd, (struct sockaddr *)&addr, sizeof(sockaddr));
    if (result < 0) {
      log_error << "failed to bind, port: " << port;
      exit(EXIT_FAILURE);
    }
    result = ::listen(fd, connectionCount);
    if (result < 0) {
      log_error << "failed to listen, port: " << port;
      exit(EXIT_FAILURE);
    }

    if (registerFd(fd) < 0) {
      log_error << "failed to registerFd: " <<  fd;
      exit(EXIT_FAILURE);
    }
    acceptFdMap[fd] = type;
  }

  bool accept(int eventFd, int events) {
    map<int, int>::iterator it = acceptFdMap.find(eventFd);
    if (it == acceptFdMap.end()) {
      return false;
    }
    struct sockaddr_in addr;
    socklen_t sin_size = sizeof(addr);
    int clientFd = ::accept(eventFd, (struct sockaddr *) &addr, &sin_size);
    if (clientFd < 0) {
      log_error << "failed to accept client: " << FdToAddr(clientFd, false);
      exit(EXIT_FAILURE);
    } else {
      log_info << "success accept client: " << FdToAddr(clientFd, false);
    }
    registerFd(clientFd);
    shared_ptr<Buffer> buffer(new Buffer(it->second, clientFd));
    bufferMap[clientFd] = buffer;
    shared_ptr<Buffer> buffer2(new Buffer(buffer->reverse()));
    onBufferCreated(buffer2);
    return true;
  }

  shared_ptr<Buffer> connect(const string& ip, int port, int type) {
    int fd = socket(PF_INET, SOCK_STREAM, 0);
    if (fd < 0) {
      log_error << "failed to socket";
      return shared_ptr<Buffer>();
    }
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(ip.c_str());
    addr.sin_port = htons(port);
    int result = ::connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr));
    shared_ptr<Buffer> buffer(new Buffer(type, fd));
    if(result < 0) {
      log_error << "failed to connect " << ip << ":" << port;
      buffer->close();
    } else {
      registerFd(fd);
      bufferMap[fd] = buffer;
    }
    return shared_ptr<Buffer>(new Buffer(buffer->reverse()));
  }

  bool handleEvent(int eventFd, int events) {
    map<int, shared_ptr<Buffer>>::iterator it = bufferMap.find(eventFd);
    if (it == bufferMap.end()) {
      return false;
    }
    shared_ptr<Buffer> buffer = it->second;
    if ((events & EPOLLRDHUP) || (events & EPOLLERR)) {
      buffer->close();
      return true;
    }
{'fraction_non_alphanumeric': 0.14364364364364365, 'fraction_numerical': 0.0075075075075075074, 'mean_word_length': 3.235824059353471, 'pattern_counts': {'":': 2, '<': 147, '<?xml version=': 0, '>': 65, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3699770', 'n_tokens_mistral': 2929, 'n_tokens_neox': 2891, 'n_words': 684}