AREXPORT bool ArServerClient::tcpCallback(void)
{
  if (myState == STATE_REJECTED)
  {
    myTcpSender.sendData();
    ArUtil::sleep(10);
    return false;
  }

  if (myState == STATE_DISCONNECTED && (myHaveSlowPackets || 
					myHaveIdlePackets))
    return true;

  if (myState == STATE_DISCONNECTED)
    return false;

  if (myState == STATE_SENT_INTRO && myStateStart.secSince() >= 60)
  {
    ArLog::log(myVerboseLogLevel, "%sTook too long for %s to connect",
	       myLogPrefix.c_str(), getIPString());
    return false;
  }

  if (myTcpOnly && !mySentTcpOnly)
  {
    mySentTcpOnly = true;
    ArNetPacket sending;
    sending.setCommand(ArServerCommands::TCP_ONLY);
    sendPacketTcp(&sending);
  }

  if (!myTcpReceiver.readData())
  {
    ArLog::log(myVerboseLogLevel, "%sTrouble receiving tcp data from %s",
	       myLogPrefix.c_str(), getIPString());
    internalSwitchState(STATE_DISCONNECTED);
    return tcpCallback();
    //return false; 
  }
  if (!myTcpSender.sendData())
  {
    ArLog::log(myVerboseLogLevel, "%sTrouble sending tcp data to %s", 
	       myLogPrefix.c_str(), getIPString());
    internalSwitchState(STATE_DISCONNECTED);
    return tcpCallback();
    //return false;
  }

  return true;
}
AREXPORT void ArServerClient::forceDisconnect(bool quiet)
{
  if (!quiet)
    ArLog::log(ArLog::Normal, "Client from %s has been forcibly disconnected.",
	       getIPString());
  internalSwitchState(STATE_DISCONNECTED);
}
Example #3
0
/*
   This cannot write more than 512 number of bytes
   @param str the string to write to the socket
   @return number of bytes written
**/
AREXPORT int ArSocket::writeString(const char *str, ...)
{
  char buf[1200];
  int len;
  int ret;
  myWriteStringMutex.lock();
  va_list ptr;
  va_start(ptr, str);
  vsnprintf(buf, sizeof(buf), str, ptr);
  va_end(ptr);
  len = strlen(buf);
  if (myStringWrongEndChars)
  {
    buf[len] = '\n';
    len++;
    buf[len] = '\r';
    len++;
  }
  else
  {
    buf[len] = '\r';
    len++;
    buf[len] = '\n';
    len++;
  }
  ret = write(buf, len);
  buf[len] = '\0';
  len++;
  if (ret <= 0)
  {
    if (ret < 0)
      ArLog::log(ArLog::Normal, "Problem sending (ret %d errno %d) to %s: %s",
		 ret, errno, getIPString(), buf);
    else 
      ArLog::log(ArLog::Normal, "Problem sending (backed up) to %s: %s",
		 getIPString(), buf);
  }
  else if (myLogWriteStrings)
    ArLog::log(ArLog::Normal, "Sent to %s: %s", getIPString(), buf);

  myWriteStringMutex.unlock();
  return ret;
}
AREXPORT void ArServerClient::setIdentifier(
	ArServerClientIdentifier identifier)
{
  std::string oldIPString = myIPString;
  
  myIdentifier = identifier;
  myIPString = myTcpSocket.getRawIPString();
  if (myIdentifier.getIDString() != 0 && 
      myIdentifier.getIDString()[0] != '\0')
  {
    myIPString += " ";
    myIPString += myIdentifier.getIDString(); 
  }
  
  if (!oldIPString.empty() && oldIPString != myIPString)
    ArLog::log(ArLog::Normal, "%s%s changed to %s", myLogPrefix.c_str(),
	       oldIPString.c_str(), getIPString());
  myTcpSocket.setIPString(getIPString());
}
Example #5
0
/*
   This cannot write more than 512 number of bytes
   @param str the string to write to the socket
   @return number of bytes written
**/
AREXPORT int ArSocket::writeString(const char *str, ...)
{
  char buf[1200];
  int len;
  int ret;
  myWriteStringMutex.lock();
  va_list ptr;
  va_start(ptr, str);
  vsnprintf(buf, sizeof(buf), str, ptr);
  va_end(ptr);
  if (myLogWriteStrings)
    ArLog::log(ArLog::Normal, "Sent to %s: %s", getIPString(), buf);
  len = strlen(buf);
  buf[len] = '\n';
  len++;
  buf[len] = '\r';
  len++;
  ret = write(buf, len);
  myWriteStringMutex.unlock();
  return ret;
}
Example #6
0
AREXPORT char *ArSocket::readString(unsigned int msWait)
{
  size_t i;
  int n;

  myReadStringMutex.lock();
  myStringBufEmpty[0] = '\0';
  
  // read one byte at a time
  for (i = myStringPos; i < sizeof(myStringBuf); i++)
  {
    
    n = read(&myStringBuf[i], 1, msWait);
    if (n > 0)
    {
      if (i == 0 && myStringBuf[i] < 0)
      {
	myStringGotEscapeChars = true;
      }
      if (myStringIgnoreReturn && myStringBuf[i] == '\r')
      {
	i--;
	continue;
      }

      if (myStringBuf[i] == '\n' || myStringBuf[i] == '\r')
      {
	if (i != 0)
	  myStringGotComplete = true;
	myStringBuf[i] = '\0';
	myStringPos = 0;
	myStringPosLast = 0;
	// if we have leading escape characters get rid of them
	if (myStringBuf[0] < 0)
	{
	  int ei;
	  myStringGotEscapeChars = true;
	  // increment out the escape chars
	  for (ei = 0; 
	       myStringBuf[ei] < 0 || (ei > 0 && myStringBuf[ei - 1] < 0); 
	       ei++);
	  // okay now return the good stuff
	  doStringEcho();
	  myLastStringReadTime.setToNow();
	  myReadStringMutex.unlock();
	  return &myStringBuf[ei];
	}
	// if we don't return what we got
	doStringEcho();
	myLastStringReadTime.setToNow();
	myReadStringMutex.unlock();
	return myStringBuf;
      }
      // if its not an ending character but was good keep going
      else
	continue;
    }
    // failed
    else if (n == 0)
    {
      myStringPos = i;
      myStringBuf[myStringPos] = '\0';
      myReadStringMutex.unlock();
      return NULL;
    }
    else // which means (n < 0)
    {
#ifdef WIN32
      if (WSAGetLastError() == WSAEWOULDBLOCK)
      {
	myStringPos = i;
	doStringEcho();
	myReadStringMutex.unlock();
	return myStringBufEmpty;
      }
#endif
#ifndef WIN32
      if (errno == EAGAIN)
      {
	myStringPos = i;
	doStringEcho();
	myReadStringMutex.unlock();
	return myStringBufEmpty;
      }
#endif
      perror("Error in reading from network");
      myReadStringMutex.unlock();
      return NULL;
    }
  }
  // if they want a 0 length string
  ArLog::log(ArLog::Normal, "Some trouble in ArSocket::readString to %s (cannot fit string into buffer?)", getIPString());
  writeString("String too long");
  myReadStringMutex.unlock();
  return NULL;
}
AREXPORT void ArServerClient::processPacket(ArNetPacket *packet, bool tcp)
{
  std::string str;
  struct sockaddr_in sin;
  unsigned int clientUdpPort;
  ArNetPacket retPacket;

  //printf("Command number %d\n", packet->getCommand());
  // if we're in intro mode and received back the intro
  if (myState == STATE_SENT_INTRO && 
      packet->getCommand() == ArClientCommands::INTRODUCTION)
  {
    char user[512];
    unsigned char password[16];
    clientUdpPort = packet->bufToUByte2();
    packet->bufToStr(user, sizeof(user));
    packet->bufToData((char *)password, 16);

    if (myRejecting != 0)
    {
      retPacket.empty();
      retPacket.setCommand(ArServerCommands::REJECTED);
      retPacket.byte2ToBuf(myRejecting);
      retPacket.strToBuf(myRejectingString.c_str());
      sendPacketTcp(&retPacket);
      if (myRejecting == 2)
	ArLog::log(ArLog::Normal, 
   "%sRejected connection from %s since we're using a central server at %s",
		   myLogPrefix.c_str(), getIPString(), 
		   myRejectingString.c_str());
      internalSwitchState(STATE_REJECTED);
      return;
    }

    // if user info is NULL we're not checking passwords
    if (myUserInfo != NULL && 
	!myUserInfo->matchUserPassword(user, password, myPasswordKey.c_str(),
				       myServerKey.c_str(),
				       myLogPasswordFailureVerbosely))
    {
      retPacket.empty();
      retPacket.setCommand(ArServerCommands::REJECTED);
      retPacket.byte2ToBuf(1);
      retPacket.strToBuf("");
      sendPacketTcp(&retPacket);
      ArLog::log(ArLog::Normal, "%sRejected user '%s' or password from %s",
		 myLogPrefix.c_str(), user, getIPString());
      internalSwitchState(STATE_REJECTED);
      return;
    }
    if (myUserInfo != NULL)
      myGroups = myUserInfo->getUsersGroups(user);
    else
      myGroups.clear();
    sin.sin_family = AF_INET;
    sin.sin_addr = *myTcpSocket.inAddr();
    sin.sin_port = ArSocket::hostToNetOrder(clientUdpPort);
    if (myUserInfo != NULL)
      ArLog::log(ArLog::Normal, 
		 "%sClient connected from %s with user %s", 
		 myLogPrefix.c_str(), getIPString(), user);
    else
      ArLog::log(ArLog::Normal, 
		 "%sClient connected from %s", myLogPrefix.c_str(), 
		 getIPString());

    setUdpAddress(&sin);
    // send that we've connected
    retPacket.empty();
    retPacket.setCommand(ArServerCommands::CONNECTED);
    sendPacketTcp(&retPacket);
    // note that we're connected
    internalSwitchState(STATE_CONNECTED);

    // send them the list
    sendListPacket();
    // send the udp introduction if we're using udp
    if (!myTcpOnly)
    {
      retPacket.empty();
      retPacket.setCommand(ArServerCommands::UDP_INTRODUCTION);
      retPacket.byte4ToBuf(myIntroKey);
      sendPacketUdp(&retPacket);
    }
  }
  // if we aren't in intro mode and got an intro somethings wrong
  else if (packet->getCommand() == ArClientCommands::INTRODUCTION)
  {
    ArLog::log(ArLog::Terse, 
	       "%sReceived introduction when not in intro mode",
	       myLogPrefix.c_str());
    return;
  }
  // if we got this over tcp then they only want tcp
  else if (packet->getCommand() == ArClientCommands::UDP_INTRODUCTION)
  {
    if (!myTcpOnly)
    {
      ArLog::log(ArLog::Normal, "%sGot UDP introduction over tcp, assuming client only wants tcp data.", myLogPrefix.c_str());
      myTcpOnly = true;
    }
    return;
  }
  // if we're connected and got a udp confirmation
  else if ((myState == STATE_CONNECTED || 
	    myState == STATE_SENT_INTRO) && 
	   packet->getCommand() == ArClientCommands::UDP_CONFIRMATION)
  {
    myUdpConfirmedTo = true;
    ArLog::log(myVerboseLogLevel, 
	       "%s: udp connection to client confirmed.", myLogPrefix.c_str());
    return;
  }
  // if we're not connected (or close) and got a confirmation
  else if (packet->getCommand() == ArClientCommands::UDP_CONFIRMATION)
  {
    ArLog::log(ArLog::Normal, 
	       "%sReceived udp confirmation when not connected.",
	       myLogPrefix.c_str());
    return;
  }
  else if (packet->getCommand() == ArClientCommands::TCP_ONLY)
  {
    ArLog::log(myVerboseLogLevel, "%sClient only wants tcp data.", myLogPrefix.c_str());
    myTcpOnly = true;
    return;
  }
  else if (packet->getCommand() == ArClientCommands::SHUTDOWN)
  {
    ArLog::log(ArLog::Normal, "%sClient from %s has disconnected.",
	       myLogPrefix.c_str(), getIPString());
    internalSwitchState(STATE_DISCONNECTED);
    return;
  }
  // if we're connected its a request, then set all that up
  else if (myState == STATE_CONNECTED && 
	   packet->getCommand() == ArClientCommands::REQUEST)
  {
    std::list<ArServerClientData *>::iterator it;
    ArServerClientData *data;
    ArServerData *serverData;
    unsigned int command;
    long mSec;
    // see which one they requested
    command = packet->bufToUByte2();
    mSec = packet->bufToByte4();

    // first we see if we already have this one
    for (it = myRequested.begin(); it != myRequested.end(); ++it)
    {
      data = (*it);
      serverData = data->getServerData();
      if (serverData->getCommand() == command)
      {
	trackPacketReceived(packet, command);
	data->setMSec(mSec);
	data->setPacket(packet);
	data->getPacket()->setCommand(command);
	serverData->callRequestChangedFunctor();
	ArLog::log(myVerboseLogLevel, 
	   "%sRevised request for command %s to %d mSec with new argument", 
		   myLogPrefix.c_str(), 
		   findCommandName(serverData->getCommand()), mSec);
	return;
      }
    }
    // we didn't have it, so make a new one
    std::map<unsigned int, ArServerData *>::iterator sdit;
    if ((sdit = myDataMap->find(command)) == myDataMap->end())
    {
      ArLog::log(ArLog::Terse, 
  	      "%sGot request for command %d which doesn't exist", 
		 myLogPrefix.c_str(), command);
      return;
    }
    serverData = (*sdit).second;
    if (serverData == NULL) 
    {
      ArLog::log(ArLog::Terse, 
		 "%sprocessPackets request handler has NULL serverData", 
		 myLogPrefix.c_str());
    }
    if (myUserInfo != NULL && 
	serverData->getCommandGroup() != NULL &&
	serverData->getCommandGroup()[0] != '\0' &&
	myGroups.count(serverData->getCommandGroup()) == 0 &&
	myGroups.count("all") == 0)
    {
      ArLog::log(ArLog::Normal, 
		 "%s%s tried to request command '%s' but it doesn't have access to that command", 
		 myLogPrefix.c_str(), getIPString(), 
		 serverData->getName());
      return;
    }
    trackPacketReceived(packet, command);
    data = new ArServerClientData(serverData, mSec, packet);
    data->getPacket()->setCommand(command);
    ArLog::log(myVerboseLogLevel, 
	       "%sadded request for command %s every %d mSec", 
	       myLogPrefix.c_str(), serverData->getName(), mSec);
    if (mSec == 0)
      ArLog::log(ArLog::Normal, "%sClient from %s requested command %s every at 0 msec", myLogPrefix.c_str(), 
		 getIPString(), serverData->getName());
    myRequested.push_front(data);
    serverData->callRequestChangedFunctor();
    pushCommand(command);
    pushForceTcpFlag(false);
    if (serverData->getFunctor() != NULL)
      serverData->getFunctor()->invoke(this, data->getPacket());
    popCommand();
    popForceTcpFlag();
    return;
  }
  // if we got a request when we're not connected
  else if (packet->getCommand() == ArClientCommands::REQUEST)
  {
    ArLog::log(ArLog::Normal, 
	       "Got a request while not connected.",
	       myLogPrefix.c_str());
    return;
  }
  // if we're connected its a requestStop, then set all that up
  else if (myState == STATE_CONNECTED && 
	   packet->getCommand() == ArClientCommands::REQUESTSTOP)
  {
    std::list<ArServerClientData *>::iterator it;
    ArServerClientData *data;
    ArServerData *serverData;
    unsigned int command;
    // see which one they requested
    command = packet->bufToUByte2();

    // first we see if we have this one
    for (it = myRequested.begin(); it != myRequested.end(); ++it)
    {
      data = (*it);
      serverData = data->getServerData();
      // we have a match, so set the new params then return
      if (data->getServerData()->getCommand() == command)
      {
	trackPacketReceived(packet, command);
	myRequested.erase(it);
	ArLog::log(myVerboseLogLevel, "%sStopped request for command %s", 
		   myLogPrefix.c_str(), 
		   findCommandName(serverData->getCommand()));
	delete data;
	serverData->callRequestChangedFunctor();
	return;
      }
    }
    // if we don't have it... that means that it wasn't here
    
    // find out what to call it
    std::map<unsigned int, ArServerData *>::iterator sdit;
    if ((sdit = myDataMap->find(command)) == myDataMap->end())
    {
      ArLog::log(ArLog::Terse, 
		 "%sGot a requeststop for command %d which doesn't exist", 
		 myLogPrefix.c_str(), command);
      return;
    }
    trackPacketReceived(packet, command);
    serverData = (*sdit).second;
    if (serverData == NULL) 
      ArLog::log(ArLog::Terse, 
		 "%srequeststop handler has NULL serverData on back command %d", 
		 myLogPrefix.c_str(), command);
    else
      ArLog::log(ArLog::Normal, "%s: Got a stop request for command %s that isn't requested", myLogPrefix.c_str(), serverData->getName());
    return;
  }
  // if we got a requestStop when we're not connected
  else if (packet->getCommand() == ArClientCommands::REQUESTSTOP)
  {
    ArLog::log(ArLog::Normal, 
	       "%sGot a requeststop while not connected.", 
	       myLogPrefix.c_str());
    return;
  }
  // if we're connected and its a command to execute just once
  else if (myState == STATE_CONNECTED)
  {
    unsigned int command;
    std::map<unsigned int, ArServerData *>::iterator it;
    ArServerData *serverData;

    command = packet->getCommand();
    if ((it = myDataMap->find(command)) == myDataMap->end())
    {
      ArLog::log(ArLog::Terse, 
  	      "%sArServerClient got request for command %d which doesn't exist", 
		 myLogPrefix.c_str(), command);
      return;
    }
    serverData = (*it).second;
    if (myUserInfo != NULL && 
	serverData->getCommandGroup() != NULL &&
	serverData->getCommandGroup()[0] != '\0' &&
	myGroups.count(serverData->getCommandGroup()) == 0 &&
	myGroups.count("all") == 0)
    {
      ArLog::log(ArLog::Normal, 
		 "%s%s tried to request command '%s' once but it doesn't have access to that command", myLogPrefix.c_str(),
		 getIPString(), 
		 serverData->getName());
      return;
    }
    trackPacketReceived(packet, command);

    // copy it out and return if its an idle packet
    if (myAllowIdlePackets && serverData->isIdlePacket())
    {
      myHaveIdlePackets = true;
      if (command <= 255)
	ArLog::log(myVerboseLogLevel, "%sStoring idle command %d", 
		   myLogPrefix.c_str(), command);
      else
	ArLog::log(myVerboseLogLevel, "%sStoring idle command %s", 
		   myLogPrefix.c_str(), serverData->getName());
      myIdlePacketsMutex.lock();
      ArNetPacket *idlePacket = new ArNetPacket(packet->getLength() + 5);
      idlePacket->duplicatePacket(packet);
      myIdlePackets.push_back(idlePacket);
      myIdlePacketsMutex.unlock();
      return;
    }
    // If its a slow or an idle packet (and we're not allowing the
    // idle behavior) and we allow slow packets then copy it
    else if (myAllowSlowPackets && (serverData->isSlowPacket() || 
				    serverData->isIdlePacket()))
    {
      myHaveSlowPackets = true;
      if (command <= 255)
	ArLog::log(myVerboseLogLevel, "%sStoring slow command %d", 
		   myLogPrefix.c_str(), command);
      else
	ArLog::log(myVerboseLogLevel, "%sStoring slow command %s", 
		   myLogPrefix.c_str(), serverData->getName());
      mySlowPacketsMutex.lock();
      ArNetPacket *slowPacket = new ArNetPacket(packet->getLength() + 5);
      slowPacket->duplicatePacket(packet);
      mySlowPackets.push_back(slowPacket);
      mySlowPacketsMutex.unlock();
      return;
    }


    if (command <= 255)
      ArLog::log(myVerboseLogLevel, "%sGot command %s", 
		 myLogPrefix.c_str(), serverData->getName());
    else
      ArLog::log(ArLog::Verbose, "%sGot command %s", 
		 myLogPrefix.c_str(), serverData->getName());
    pushCommand(command);
    pushForceTcpFlag(tcp);
    if (serverData->getFunctor() != NULL)
      serverData->getFunctor()->invoke(this, packet);
    if (serverData->getRequestOnceFunctor() != NULL)
      serverData->getRequestOnceFunctor()->invoke(this, packet);
    popCommand();
    popForceTcpFlag();
    return;
  }
  else
  {
    ArLog::log(ArLog::Terse, 
	       "%sRogue packet command %s in state %d", myLogPrefix.c_str(),
	       findCommandName(packet->getCommand()), myState);
  }
}
AREXPORT void ArServerClient::logTracking(bool terse)
{
  std::map<ArTypes::UByte2, Tracker *>::iterator it;

  ArTypes::UByte2 command;
  Tracker *tracker = NULL;
  long seconds;

  seconds = myTrackingStarted.secSince();
  if (seconds == 0)
    seconds = 1;

  char name[512];

  long packetsReceivedTcp = 0;
  long bytesReceivedTcp = 0;
  long packetsReceivedUdp = 0;
  long bytesReceivedUdp = 0;

  ArLog::log(ArLog::Terse, "");
  ArLog::log(ArLog::Terse, "Received tracking for %s (active %d seconds):", 
	     getIPString(), seconds);
  for (it = myTrackingReceivedMap.begin(); it != myTrackingReceivedMap.end(); it++)
  {
    command = (*it).first;
    tracker = (*it).second;

    packetsReceivedTcp += tracker->myPacketsTcp;
    bytesReceivedTcp += tracker->myBytesTcp;
    packetsReceivedUdp += tracker->myPacketsUdp;
    bytesReceivedUdp += tracker->myBytesUdp;

    std::map<unsigned int, ArServerData *>::iterator nameIt;
    if ((nameIt = myDataMap->find(command)) != myDataMap->end())
      snprintf(name, sizeof(name), "%s", (*nameIt).second->getName());
    // if we're command 255 or less and there's no name its probably
    // one of the server commands we don't really need to track
    else if (command <= 255)
      continue;
    // we should know what the name of everything other then the
    // server command is, but print if we don't, just in case
    else
      snprintf(name, sizeof(name), "#%d", command);
    if (terse)
    {
      ArLog::log(ArLog::Terse, 
		 "%35s %7ld pkts %10ld B %7ld B/sec", 
		 name, tracker->myPacketsTcp + tracker->myPacketsUdp, 
		 tracker->myBytesTcp + tracker->myBytesUdp,
		 ((tracker->myBytesTcp + tracker->myBytesUdp)/
		  seconds));
    }
    else
    {
      ArLog::log(ArLog::Terse, 
	 "%35s %7ld tcp pkts %10ld tcp B %7ld tcp B/S %7ld udp pkts %10ld udp B %7ld udp B/s ", 
		 name, tracker->myPacketsTcp, tracker->myBytesTcp, 
		 tracker->myBytesTcp/seconds,
		 tracker->myPacketsUdp, tracker->myBytesUdp,
		 tracker->myBytesUdp/seconds);
    }
  }
  
  ArLog::log(ArLog::Terse, "");
  if (terse)
  {
    ArLog::log(ArLog::Terse, "%-35s %7ld pkts %10ld B %7ld B/sec", 
	       "Total Received", packetsReceivedTcp + packetsReceivedUdp, 
	       bytesReceivedTcp + bytesReceivedUdp,
	       (bytesReceivedTcp + bytesReceivedUdp) / seconds);
  }
  else
  {
    ArLog::log(ArLog::Terse, "%-35s %7ld tcp pkts %10ld tcp B %7ld tcp B/S %7ld udp pkts %10ld udp B %7ld udp B/sec",  
	       "Total Received", packetsReceivedTcp, bytesReceivedTcp, 
	       bytesReceivedTcp/seconds, packetsReceivedUdp, bytesReceivedUdp, 
	       bytesReceivedUdp/seconds);
    ArLog::log(ArLog::Terse, "%-35s %7ld tcp rcvs %10ld tcp B %7ld tcp B/S",
	       "Low level TCP Received", myTcpSocket.getRecvs(), 
	       myTcpSocket.getBytesRecvd(), 
	       myTcpSocket.getBytesRecvd()/seconds);
  }

  long packetsSentTcp = 0;
  long bytesSentTcp = 0;
  long packetsSentUdp = 0;
  long bytesSentUdp = 0;

  ArLog::log(ArLog::Terse, "");
  ArLog::log(ArLog::Terse, "Sent tracking for %s (active %d seconds):", 
	     getIPString(), seconds);
  for (it = myTrackingSentMap.begin(); it != myTrackingSentMap.end(); it++)
  {
    command = (*it).first;
    tracker = (*it).second;

    packetsSentTcp += tracker->myPacketsTcp;
    bytesSentTcp += tracker->myBytesTcp;
    packetsSentUdp += tracker->myPacketsUdp;
    bytesSentUdp += tracker->myBytesUdp;

    std::map<unsigned int, ArServerData *>::iterator nameIt;
    if ((nameIt = myDataMap->find(command)) != myDataMap->end())
      snprintf(name, sizeof(name), "%s", (*nameIt).second->getName());
    // if we're command 255 or less and there's no name its probably
    // one of the server commands we don't really need to track
    else if (command <= 255)
      continue;
    // we should know what the name of everything other then the
    // server command is, but print if we don't, just in case
    else
      snprintf(name, sizeof(name), "#%d", command);
    if (terse)
    {
      ArLog::log(ArLog::Terse, 
		 "%35s %7ld pkts %10ld B %7ld B/sec", 
		 name, tracker->myPacketsTcp + tracker->myPacketsUdp, 
		 tracker->myBytesTcp + tracker->myBytesUdp,
		 ((tracker->myBytesTcp + tracker->myBytesUdp)/
		  seconds));
    }
    else
    {
      ArLog::log(ArLog::Terse, 
	 "%35s %7ld tcp pkts %10ld tcp B %7ld tcp B/S %7ld udp pkts %10ld udp B %7ld udp B/s ", 
		 name, tracker->myPacketsTcp, tracker->myBytesTcp, 
		 tracker->myBytesTcp/seconds,
		 tracker->myPacketsUdp, tracker->myBytesUdp,
		 tracker->myBytesUdp/seconds);
    }
  }

  ArLog::log(ArLog::Terse, "");
  if (terse)
  {
    ArLog::log(ArLog::Terse, "%-35s %7ld pkts %10ld B %7ld B/sec", 
	       "Total Sent", packetsSentTcp + packetsSentUdp, 
	       bytesSentTcp + bytesSentUdp,
	       (bytesSentTcp + bytesSentUdp) / seconds);    
    ArLog::log(ArLog::Terse, "");
    ArLog::log(ArLog::Terse, "%-35s %7ld pkts %10ld B %7ld B/sec", 
	       "Total Sent and Received", 
	       (packetsSentTcp + packetsSentUdp + 
		packetsReceivedTcp + packetsReceivedUdp),
	       (bytesSentTcp + bytesSentUdp + 
		bytesReceivedTcp + bytesReceivedUdp),
	       (bytesSentTcp + bytesSentUdp + 
		bytesReceivedTcp + bytesReceivedUdp) / seconds);
  }
  else
  {
    ArLog::log(ArLog::Terse, "%-35s %7ld tcp pkts %10ld tcp B %7ld tcp B/S %7ld udp pkts %10ld udp B %7ld udp B/sec",  
	       "Total Sent", packetsSentTcp, bytesSentTcp, 
	       bytesSentTcp / seconds,
	       packetsSentUdp, bytesSentUdp, bytesSentUdp / seconds);
    ArLog::log(ArLog::Terse, "%-35s %7ld tcp snds %10ld tcp B %7ld tcp B/S",
	       "Low level TCP Sent", myTcpSocket.getSends(), 
	       myTcpSocket.getBytesSent(), 
	       myTcpSocket.getBytesSent() / seconds);

    ArLog::log(ArLog::Terse, "");
    ArLog::log(ArLog::Terse, "%-35s %7ld tcp pkts %10ld tcp B %7ld tcp B/S %7ld udp pkts %10ld udp B %7ld udp B/sec",  
	       "Total Sent and Received", packetsSentTcp = packetsReceivedTcp, 
	       bytesSentTcp + bytesReceivedTcp, 
	       (bytesSentTcp + bytesReceivedTcp) / seconds,
	       packetsSentUdp + packetsReceivedUdp, 
	       bytesSentUdp + bytesReceivedUdp, 
	       (bytesSentUdp + bytesReceivedUdp) / seconds);
  }

  ArLog::log(ArLog::Terse, "");
}
Example #9
0
/*
 * Case of a server with two sockets:
 * function trying to create and set up all (ipv4 and ipv6) available server sockets of
 * the host. When one socket is IPv6, the IPV6_V6ONLY socket option is set.
 * The list of sockets is passed as a parameter to be completed.
 */
void createAndSetUpAllTCPServerSockets(int *nb_sockets, int *tb_sockets,
                                int port, int max_connections)
{
	int server_socket;
	struct addrinfo hints, *address_list, *paddress;
	int on = 1;
	char ip[IP_MAX_CHARS];
	char port_string[PORT_MAX_DIGITS];

	*nb_sockets = 0;
	
	/* getaddrinfo parameters */
	memset(&hints, 0, sizeof(hints));	/* init */
	hints.ai_flags |= AI_PASSIVE;		/* server behaviour: accept connection on any network address */
	hints.ai_family = AF_UNSPEC;		/* find both ipv4 and ipv6 addresses */
	hints.ai_socktype = SOCK_STREAM;	/* type of socket */

	sprintf (port_string, "%d", port);
	getaddrinfo(NULL, port_string, &hints, &address_list);

	paddress = address_list;
	while (paddress)
	{
		/* create the socket */
		server_socket = socket(paddress->ai_family, paddress->ai_socktype, paddress->ai_protocol);
		if (server_socket == -1)
		{
			/* try next address */
			paddress = paddress->ai_next;
			continue;
		}

		/* set SO_REUSEADDR option */
		setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
		
        /* we must set IPV6_V6ONLY in order to allow an IPv4 socket on the same port number. */
		if (paddress->ai_family == AF_INET6)
		{	
			setsockopt(server_socket, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on, sizeof(on));
		}

		/* bind and listen */
		if (	(bind(server_socket, paddress->ai_addr, paddress->ai_addrlen)	== -1) ||
			(listen(server_socket, max_connections)	 			== -1))
		{
			close(server_socket);
            /* try next address */
			paddress = paddress->ai_next;
			continue;
		}

		/* get the ip string, display it with the port number  */
		getIPString(paddress->ai_addr, ip, IP_MAX_CHARS);
		printf("Server socket now listening on %s port %d\n", ip, port);
		
		tb_sockets[*nb_sockets] = server_socket;
		*nb_sockets += 1;
		paddress = paddress->ai_next;
	}

	/* free the list */
	freeaddrinfo(address_list);
}
Example #10
0
/*
 * Case of a server with one socket:
 * function trying to create a server socket using all available addresses of the host
 * until one is successfully created. If the socket is IPv6, the IPV6_V6ONLY
 * socket option is unset.
 * Then the socket is returned, or -1 in case of failure.
 */
int createAndSetUpATCPServerSocket(int port, int max_connections)
{
	int server_socket;
	struct addrinfo hints, *address_list, *paddress;
	int on = 1, off = 0;
	char ip[IP_MAX_CHARS];
	char port_string[PORT_MAX_DIGITS];

	server_socket = -1;

    scar_log(1, "Try address...\n");
	
	/* getaddrinfo parameters */
	memset(&hints, 0, sizeof(hints));	/* init */
	hints.ai_flags |= AI_PASSIVE;		/* server behaviour: accept connection on any network address */
	hints.ai_family = AF_UNSPEC;		/* find both ipv4 and ipv6 addresses */
	hints.ai_socktype = SOCK_STREAM;	/* type of socket */

	sprintf (port_string, "%d", port);
	getaddrinfo(NULL, port_string, &hints, &address_list);

	paddress = address_list;
	while (paddress)
	{
		/* create the socket */
		server_socket = socket(paddress->ai_family, paddress->ai_socktype, paddress->ai_protocol);
		if (server_socket == -1)
		{
            /* try next address */
			paddress = paddress->ai_next;
			continue;
		}

		/* set SO_REUSEADDR option */
		setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
		
        /* we must unset IPV6_V6ONLY in order to allow IPv4 client to connect to the IPv6 socket */
		if (paddress->ai_family == AF_INET6)
		{	
			setsockopt(server_socket, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&off, sizeof(off));
		}

        /* Make the master socket non-blocking */
        if (fcntl (server_socket, 
                   F_SETFL, 
                   fcntl(server_socket, F_GETFL)|O_NONBLOCK) == -1)
        {
            net_printErrNo (errno, __func__);
            return -1;
        }

		/* bind and listen */
		if ((bind (server_socket, paddress->ai_addr, paddress->ai_addrlen) == -1) ||
            (listen (server_socket, max_connections) == -1))
		{
			close(server_socket); 
            server_socket = -1;

            /* try next address */
			paddress = paddress->ai_next;
			continue;
		}

		/* get the ip string, display it with the port number  */
		getIPString(paddress->ai_addr, ip, IP_MAX_CHARS);
		scar_log (1, "Server socket now listening on %s port %d (socket fd %d)\n", 
                     ip, 
                     port, 
                     server_socket);
		
        /* break if no error */
		break;
	}

	/* free the list */
	freeaddrinfo(address_list);

	/* return the server socket */
	return server_socket;
}
Example #11
0
int main(int argc, char * argv[])
{
	struct sockaddr_in sockname, client;
	struct sigaction sa;
	char *ep, *inbuff, *tmp;
	char outbuff[256];

	int clientlen, sd;

	u_short port;
	u_long p;
	pid_t pid;
	
		/* daemonize */
#ifndef DEBUG
	/* don't daemonize if we compile with -DDEBUG */
	if (daemon(1,1) == -1)
		err(1, "daemon() failed");
#endif

	/* check params */
	if (argc != 4)
		usage();

	errno = 0;
	p = strtoul(argv[1], &ep, 10);
	if (&argv[1] == '\0' || *ep != '\0'){
		/* parameter wasn't a number, or was empty */
		fprintf(stderr, "%s - not a number\n", argv[1]);
		usage();
	}
	if ((errno == ERANGE && p == ULONG_MAX) || (p > USHRT_MAX)) {
		/* It's a number, but it either can't fit in an unsigned
		 * long, or it is too big for an unsigned short */
		fprintf(stderr, "%s - value out of range\n", argv[1]);
		usage();
	}
	
	/* Ensure argv[2] is a valid directory */
	
	if (chdir(argv[2]) == -1)
		err(1, "chdir failed");
		
	/* TODO : Ensure argv[3] is a valid file */
	LOG_FILE = argv[3];

	/* now safe to do this */
	port = p;

	memset(&sockname, 0, sizeof(sockname));
	sockname.sin_family = AF_INET;
	sockname.sin_port = htons(port);
	sockname.sin_addr.s_addr = htonl(INADDR_ANY);
	sd = socket(AF_INET, SOCK_STREAM, 0);

	if (sd == -1)
		err(1, "socket failed");
	if (bind(sd, (struct sockaddr *) &sockname, sizeof(sockname)) == -1)
		err(1, "bind failed");
	if (listen(sd, 3) == -1)
		err(1, "listen failed");

	/* We are now bound and listening for connections on "sd" */

	/* Catch SIGCHLD to stop zombie children wandering around */
	sa.sa_handler = kidhandler;
	sigemptyset(&sa.sa_mask);

	/* allow system calls (accept) to restart if interrupted by SIGCHLD */
	sa.sa_flags = SA_RESTART;
	if (sigaction(SIGCHLD, &sa, NULL) == -1)
		err(1, "sigaction failed");

	/* main loop. Accept connections and do stuff */
	for(;;) {
		int clientsd;
		ssize_t written, w;
	
		clientlen = sizeof(&client);
		clientsd = accept(sd, (struct sockaddr *)&client, &clientlen);
		if (clientsd == -1)
			err(1, "accept failed");
		
		/* fork child to deal with each connection */
		pid = fork();
		if (pid == -1)
			internalError((struct sockaddr *)&client, 
				"fork failed", NULL);		

		if (pid == 0) {
			char * getLine, *fName;
			int valid, written;
			long lSize;
			FILE * fp;
			
			/* Parse GET */
			inbuff = malloc(12800*sizeof(char));
			fName = malloc(256*sizeof(char));
			if (inbuff == NULL || fName == NULL)
				internalError(&client, "malloc failed", NULL);

			readSocket(clientsd, inbuff, 12800);

			getLine = malloc(256*sizeof(char));
			if (getLine == NULL)
				internalError(&client, "malloc failed", NULL);
			
			valid = checkGET(inbuff, fName, getLine);
			fName++;


			if (valid == 0) {
				/* BAD REQUEST */
				sendBadRequestError(clientsd);
				logBadRequest(getIPString(&client), getLine);
			} else {
				/* GET is good. Try reading file & sending */

				fp = fopen(fName, "r");
				if (fp == NULL) {
					if (errno == ENOENT) {
						sendNotFoundError(clientsd);
						logNotFound(
							getIPString(&client),
							 getLine);
					} else if (errno == EACCES) {
						sendForbiddenError(clientsd);
						logForbidden(
							getIPString(&client), 
							getLine);
					} else 
						internalError(&client, 
							"fopen failed", 
							getLine);
				} else {
					
					/* get file size */
					fseek(fp, sizeof(char), SEEK_END);
					lSize = ftell(fp);
					rewind(fp);
					/* send OK and file */
				
					sendOK(clientsd, lSize);
					written = sendFile(fp, clientsd);
					logOK(getIPString(&client), getLine, 
						written, lSize-1);
				}		
				fclose(fp);
			}

			/* Clean up */
			fName--;
			free(getLine);
			free(inbuff);
			free(fName);
			fName = NULL;
			getLine = NULL;
			inbuff = NULL;

			exit(0);
		}
		close(clientsd);
	}
}
/////////////////////////////////////////////////////////////////////////////
// handle leaving
/////////////////////////////////////////////////////////////////////////////
void CNetworkConnectorSetupDialog::OnOK() 
{
	CString str;

	UpdateData();

	//update the max players allowed
	m_MaxStatic.GetWindowText(str);
	GAME->m_nMaxPlayers = atoi(str);

	//update quit cutoff percent
	m_CutoffStatic.GetWindowText(str);
	GAME->m_nQuitCutoff = atoi(str);

	//set the ladder value
	GAME->m_bLadder = m_LadderCheck.GetCheck();

	//set the team value
	GAME->m_bTeam = m_TeamCheck.GetCheck();

	//set some variants automatically if playing in team
	if(TRUE == GAME->m_bTeam)
	{
		VARIANTS->m_iVariants |= (VARIANT_TRADE_ZERO | VARIANT_TRADE_AFTER_BUILD);
	}

	//remove any |'s from the game name
	m_strName.Remove('|');

	if(TRUE == CONNECTOR->isPortForwarding())
	{
		//see if we need to get the IP
		if(FALSE == m_IPAddress.IsBlank())
		{
			//get the IP address
			str = getIPString();

			//now set it in the connector
			CONNECTOR->setIP(str);
		}

		//write it
		WritePrivateProfileString(INI_NETWORK, INI_PORTFOR_IP, str, INI_FILE);
		str.Empty();

		//see if we need to set the port
		if(FALSE == m_strPort.IsEmpty())
		{
			//set the value
			str = m_strPort;

			CONNECTOR->setPort(atoi(str));
		}
		else
		{
			str.Format("%d", PORT);
		}		

		//write it
		WritePrivateProfileString(INI_NETWORK, INI_PORTFOR_PORT, str, INI_FILE);
	}
	
	CHelpDialog::OnOK();
}