<commit_before>/* bzflag
 * Copyright (c) 1993 - 2008 <NAME>
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* inteface header */
#include "RCLink.h"

/* system implementation headers */
#include <fcntl.h>
#include <errno.h>
#include <stdarg.h>
#ifdef HAVE_SYS_SOCKET_H
#  include <sys/socket.h>
#  include <arpa/inet.h>
#endif 

/* local implementation headers */
#include "Roster.h"
#include "RCRobotPlayer.h"
#include "RCMessage.h"


/**
 * Only valid in member methods.  This is so derived classes calling
 * our method will get their output sent to the right place. :-)
 */
#define SPECIFICLOGGER (*specificLogger)


RCLink::RCLink(std::ostream *logger) :
  status(Disconnected),
  listenfd(-1),
  connfd(-1),
  specificLogger(logger)
{
  isFrontEnd = false;
}

RCLink::~RCLink()
{
}

/* Waits forever for data to come down on connfd. (NOTE: doesn't check listenfd,
 * so only use this if you're ignoring connects.) */
bool RCLink::waitForData()
{
#ifdef _USE_FAKE_NET
  if(isFrontEnd)
    return fakeNetPendingFrontEnd() > 0;
  else
    return fakeNetPendingFrontEnd() > 0;
#else

  if (status != Connected) {
    error = "Not connected!";
    return false;
  }

  fd_set fds;
  int socks;

  FD_ZERO(&fds);
  FD_SET(connfd, &fds);

  while (true) {
    socks = select(connfd + 1, &fds, NULL, NULL, NULL);
    if (socks < 0) {
      status = SocketError;
      error = strerror(errno);
      SPECIFICLOGGER << "RCLink: Write failed. Disconnecting. Error: " << strerror(errno) << std::endl;
      return false;
    } else if (socks > 0) {
      return true;
    }
  }
#endif
}

void RCLink::startListening(int port)
{
#ifdef _USE_FAKE_NET
  return;
#else
  struct sockaddr_in sa;

  if (status != Disconnected) {
    return;
  }

  sa.sin_family = AF_INET;
  sa.sin_port = htons(port);
  //sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  sa.sin_addr.s_addr = htonl(INADDR_ANY);

  listenfd = socket(AF_INET, SOCK_STREAM, 0);
  if (listenfd == -1)
    return;

 /* Used so we can re-bind to our port while a previous connection is
  * still in TIME_WAIT state.
  */
  int reuse_addr = 1;

  setsockopt(connfd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr));

  if (bind(listenfd, (sockaddr*)&sa, sizeof(sa)) == -1) {
    close(listenfd);
    return;
  }

  if (listen(listenfd, 1) == -1) {
    close(listenfd);
    return;
  }

  //BzfNetwork::setNonBlocking(listenfd);
  int flags = fcntl(listenfd, F_GETFL);
  fcntl(listenfd, F_SETFL, flags | O_NONBLOCK);

  status = Listening;
#endif
}

bool RCLink::tryAccept()
{
#ifdef _USE_FAKE_NET
  return fakeNetConnect;
#else

  if (status != Listening) {
    error = "Cannot accept when not listening!";
    return false;
  }
  // O_NONBLOCK is set so we'll probably return immediately.
  connfd = accept(listenfd, NULL, 0);
  if (connfd == -1) {
    error = strerror(errno);
    return false;
  }

  //BzfNetwork::setNonBlocking(connfd);
  int flags = fcntl(connfd, F_GETFL);
  fcntl(connfd, F_SETFL, flags | O_NONBLOCK);

  status = Connecting;
  send_amount = 0;
  recv_amount = 0;
  input_toolong = false;

  SPECIFICLOGGER << "RCLink: Accepted a new connection." << std::endl;

  // Now we wait for them to introduce themselves.
  return true;
#endif
}


bool RCLink::connect(const char *host, int port)
{
#ifndef _USE_FAKE_NET
  status = Disconnected;
  connfd = socket(AF_INET, SOCK_STREAM, 0);
  if (connfd < 0)
    {
      error = strerror(errno);
      return false;
    }

  sockaddr_in remote;
  remote.sin_port = htons(port);
  remote.sin_family = AF_INET;

  hostent *hostdata = gethostbyname(host);
  if (hostdata == NULL)
    {
      error = hstrerror(h_errno);
      return false;
    }
  memcpy(&remote.sin_addr.s_addr, hostdata->h_addr_list[0], hostdata->h_length);

  if (::connect(connfd, (sockaddr *)&remote, sizeof(remote)) < 0)
    {
      error = strerror(errno);
      return false;
    }

  int flags = fcntl(connfd, F_GETFL);
  fcntl(connfd, F_SETFL, flags | O_NONBLOCK);

  status = Connecting;
  send_amount = recv_amount = 0;
  input_toolong = false;

  return true;
#else
  return true;
#endif
}

bool RCLink::send(const char* message)<commit_msg>make sure the connection is not buffered! .. should probably be using more NetHandler calls instead of rolling it up custom<commit_after>/* bzflag
 * Copyright (c) 1993 - 2008 <NAME>
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* inteface header */
#include "RCLink.h"

/* system implementation headers */
#include <fcntl.h>
#include <errno.h>
#include <stdarg.h>
#ifdef HAVE_SYS_SOCKET_H
#  include <sys/socket.h>
#  include <arpa/inet.h>
#endif 

/* common implementation headers */
#include "NetHandler.h"

/* local implementation headers */
#include "Roster.h"
#include "RCRobotPlayer.h"
#include "RCMessage.h"


/**
 * Only valid in member methods.  This is so derived classes calling
 * our method will get their output sent to the right place. :-)
 */
#define SPECIFICLOGGER (*specificLogger)


RCLink::RCLink(std::ostream *logger) :
  status(Disconnected),
  listenfd(-1),
  connfd(-1),
  specificLogger(logger)
{
  isFrontEnd = false;
}

RCLink::~RCLink()
{
}

/* Waits forever for data to come down on connfd. (NOTE: doesn't check listenfd,
 * so only use this if you're ignoring connects.) */
bool RCLink::waitForData()
{
#ifdef _USE_FAKE_NET
  if(isFrontEnd)
    return fakeNetPendingFrontEnd() > 0;
  else
    return fakeNetPendingFrontEnd() > 0;
#else

  if (status != Connected) {
    error = "Not connected!";
    return false;
  }

  fd_set fds;
  int socks;

  FD_ZERO(&fds);
  FD_SET(connfd, &fds);

  while (true) {
    socks = select(connfd + 1, &fds, NULL, NULL, NULL);
    if (socks < 0) {
      status = SocketError;
      error = strerror(errno);
      SPECIFICLOGGER << "RCLink: Write failed. Disconnecting. Error: " << strerror(errno) << std::endl;
      return false;
    } else if (socks > 0) {
      return true;
    }
  }
#endif
}

void RCLink::startListening(int port)
{
#ifdef _USE_FAKE_NET
  return;
#else
  struct sockaddr_in sa;

  if (status != Disconnected) {
    return;
  }

  sa.sin_family = AF_INET;
  sa.sin_port = htons(port);
  //sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  sa.sin_addr.s_addr = htonl(INADDR_ANY);

  listenfd = socket(AF_INET, SOCK_STREAM, 0);
  if (listenfd == -1)
    return;

 /* Used so we can re-bind to our port while a previous connection is
  * still in TIME_WAIT state.
  */
  int reuse_addr = 1;

  setsockopt(connfd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr));

  if (bind(listenfd, (sockaddr*)&sa, sizeof(sa)) == -1) {
    close(listenfd);
    return;
  }

  if (listen(listenfd, 1) == -1) {
    close(listenfd);
    return;
  }

  //BzfNetwork::setNonBlocking(listenfd);
  int flags = fcntl(listenfd, F_GETFL);
  fcntl(listenfd, F_SETFL, flags | O_NONBLOCK);

  status = Listening;
#endif
}

bool RCLink::tryAccept()
{
#ifdef _USE_FAKE_NET
  return fakeNetConnect;
#else

  if (status != Listening) {
    error = "Cannot accept when not listening!";
    return false;
  }
  // O_NONBLOCK is set so we'll probably return immediately.
  connfd = accept(listenfd, NULL, 0);
  if (connfd == -1) {
    error = strerror(errno);
    return false;
  }

  //BzfNetwork::setNonBlocking(connfd);
  int flags = fcntl(connfd, F_GETFL);
  fcntl(connfd, F_SETFL, flags | O_NONBLOCK);

  status = Connecting;
  send_amount = 0;
  recv_amount = 0;
  input_toolong = false;

  SPECIFICLOGGER << "RCLink: Accepted a new connection." << std::endl;

  // Now we wait for them to introduce themselves.
  return true;
#endif
}


bool RCLink::connect(const char *host, int port)
{
#ifndef _USE_FAKE_NET
  status = Disconnected;
  connfd = socket(AF_INET, SOCK_STREAM, 0);
  if (connfd < 0)
    {
      error = strerror(errno);
      return false;
    }

  sockaddr_in remote;
  remote.sin_port = htons(port);
  remote.sin_family = AF_INET;

  hostent *hostdata = gethostbyname(host);
  if (hostdata == NULL)
    {
      error = hstrerror(h_errno);
      return false;
    }
  memcpy(&remote.sin_addr.s_addr, hostdata->h_addr_list[0], hostdata->h_length);

  if (::connect(connfd, (sockaddr *)&remote, sizeof(remote)) < 0)
    {
      error = strerror(errno);
      return false;
    }

  int flags = fcntl(connfd, F_GETFL);
  fcntl(connfd, F_SETFL, flags | O_NONBLOCK);

  // libGame's NetHandler.cxx
  setNoDelay(connfd);

  status = Connecting;
  send_amount = recv_amount = 0;
  input_toolong = false;

  return true;
#else
  return true;
#endif
}

bool RCLink::send(const char* message)
{'fraction_non_alphanumeric': 0.12407648848326815, 'fraction_numerical': 0.00651890482398957, 'mean_word_length': 3.53001968503937, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 25, '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': '5413715', 'n_tokens_mistral': 3390, 'n_tokens_neox': 3277, 'n_words': 900}