AREXPORT void ArServerInfoDrawings::netGetDrawingList(ArServerClient *client, ArNetPacket *packet) { ArNetPacket sendingPacket; // TODO: Any need to protect the map by a mutex? for (std::map<std::string, ArDrawingData *, ArStrCaseCmpOp>::iterator it = myDrawingDatas.begin(); it != myDrawingDatas.end(); it++) { sendingPacket.empty(); sendingPacket.strToBuf((*it).first.c_str()); sendingPacket.strToBuf((*it).second->getShape()); sendingPacket.byte4ToBuf((*it).second->getPrimaryColor().colorToByte4()); sendingPacket.byte4ToBuf((*it).second->getSize()); sendingPacket.byte4ToBuf((*it).second->getLayer()); sendingPacket.uByte4ToBuf((*it).second->getDefaultRefreshTime()); sendingPacket.byte4ToBuf((*it).second->getSecondaryColor().colorToByte4()); sendingPacket.strToBuf((*it).second->getVisibility()); client->sendPacketTcp(&sendingPacket); } // end for each drawing sendingPacket.empty(); client->sendPacketTcp(&sendingPacket); }
int main(int argc, char **argv) { Aria::init(); ArClientBase client; std::string host; ArArgumentParser parser(&argc, argv); ArClientSimpleConnector clientConnector(&parser); parser.loadDefaultArguments(); /* Check for -help, and unhandled arguments: */ if (!clientConnector.parseArgs() || !parser.checkHelpAndWarnUnparsed()) { clientConnector.logOptions(); exit(0); } /* Connect our client object to the remote server: */ if (!clientConnector.connectClient(&client)) { if (client.wasRejected()) printf("Server rejected connection, exiting\n"); else printf("Could not connect to server, exiting\n"); exit(1); } client.addHandler("getCameraModeListCam1", new ArGlobalFunctor1<ArNetPacket *>(&getCameraModeList)); client.requestOnce("getCameraModeListCam1"); ArNetPacket sending; // This does the look at goal mode sending.empty(); sending.strToBuf("lookAtGoal"); client.requestOnce("setCameraModeCam1", &sending); // This does the look at point mode (at 0 0); sending.empty(); sending.strToBuf("lookAtPoint"); sending.byte4ToBuf(1157); sending.byte4ToBuf(-15786); client.requestOnce("setCameraModeCam1", &sending); while (Aria::getRunning() && client.isConnected()) { client.loopOnce(); ArUtil::sleep(1000); } Aria::shutdown(); return 0; };
AREXPORT void ArServerHandlerPopup::netPopupList(ArServerClient *client, ArNetPacket *packet) { ArLog::log(ArLog::Normal, "Sending popup list"); std::map<ArTypes::Byte4, PopupData *>::iterator it; ArNetPacket sendingPacket; PopupData *popupData; myDataMutex.lock(); for (it = myMap.begin(); it != myMap.end(); it++) { popupData = (*it).second; sendingPacket.empty(); ArLog::log(ArLog::Normal, "Sending popup %d", popupData->myID); buildPacket(&sendingPacket, popupData); sendingPacket.setCommand(myServer->findCommandFromName("popupCreate")); client->sendPacketTcp(&sendingPacket); } sendingPacket.empty(); client->sendPacketTcp(&sendingPacket); ArLog::log(ArLog::Normal, "Sent popups"); myDataMutex.unlock(); }
AREXPORT void ArServerClient::processAuthPacket(ArNetPacket *packet, struct sockaddr_in *sin) { ArNetPacket retPacket; long authKey; // check the auth key again, just in case authKey = packet->bufToUByte4(); if (authKey != myAuthKey) { ArLog::log(ArLog::Terse, "ArServerClient: authKey given does not match actual authKey, horrible error."); return; } if (mySin.sin_port != sin->sin_port) { ArLog::log(myVerboseLogLevel, "Client says it is using port %u but is using port %u\n", ArSocket::netToHostOrder(mySin.sin_port), ArSocket::netToHostOrder(sin->sin_port)); } myUdpConfirmedFrom = true; mySin.sin_port = sin->sin_port; mySin.sin_addr = sin->sin_addr; ArLog::log(myVerboseLogLevel, "Client connected to server on udp port %u", ArSocket::netToHostOrder(mySin.sin_port)); // TODO put some state info here to note that its fully udp connected retPacket.empty(); retPacket.setCommand(ArServerCommands::UDP_INTRODUCTION); retPacket.byte4ToBuf(myIntroKey); sendPacketUdp(&retPacket); retPacket.empty(); retPacket.setCommand(ArServerCommands::UDP_CONFIRMATION); sendPacketTcp(&retPacket); }
void laserRequest_and_odom(ArServerClient *client, ArNetPacket *packet) { robot.lock(); ArNetPacket sending; sending.empty(); ArLaser* laser = robot.findLaser(1); if(!laser){ printf("Could not connect to Laser... exiting\n"); Aria::exit(1);} laser->lockDevice(); const std::list<ArSensorReading*> *sensorReadings = laser->getRawReadings(); // see ArRangeDevice interface doc sending.byte4ToBuf((ArTypes::Byte4)(sensorReadings->size())); for (std::list<ArSensorReading*>::const_iterator it2= sensorReadings->begin(); it2 != sensorReadings->end(); ++it2){ ArSensorReading* laserRead =*it2; sending.byte4ToBuf((ArTypes::Byte4)(laserRead->getRange())); //printf("%i,%i:",laserRead->getRange(),laserRead->getIgnoreThisReading()); } sending.byte4ToBuf((ArTypes::Byte4)(robot.getX())); sending.byte4ToBuf((ArTypes::Byte4)(robot.getY())); sending.byte4ToBuf((ArTypes::Byte4)(robot.getTh())); sending.byte4ToBuf((ArTypes::Byte4)(robot.getVel())); sending.byte4ToBuf((ArTypes::Byte4)(robot.getRotVel())); //printf("%1f,%1f,%1f\n",robot.getX(),robot.getY(),robot.getTh()); laser->unlockDevice(); robot.unlock(); sending.finalizePacket(); //sending.printHex(); client->sendPacketTcp(&sending); }
// Method called by accessor methods when properties changed. This reconstructs // the myReply packet sent in response to requests from clients void Circle::regenerate() { myMutex.lock(); myReply.empty(); myReply.byte4ToBuf(myNumPoints); double a = 360.0/myNumPoints; for(unsigned int i = 0; i < myNumPoints; ++i) { myReply.byte4ToBuf(ArMath::roundInt(myPos.getX()+ArMath::cos(i*a)*myRadius)); // X myReply.byte4ToBuf(ArMath::roundInt(myPos.getY()+ArMath::sin(i*a)*myRadius)); // Y } myMutex.unlock(); }
AREXPORT void ArServerHandlerPopup::serverCycleCallback(void) { std::map<ArTypes::Byte4, PopupData *>::iterator it; ArNetPacket sendingPacket; PopupData *popupData; int timeout; std::list<ArTypes::Byte4> doneIDs; std::list<PopupData *> donePopups; myDataMutex.lock(); // only check it if we haven't checked it lately if (myLastTimeCheck.mSecSince() > 1000) { myLastTimeCheck.setToNow(); for (it = myMap.begin(); it != myMap.end(); it++) { popupData = (*it).second; if ((timeout = popupData->myPopupInfo->getTimeout()) > 0 && popupData->myStarted.secSince() >= timeout) { sendingPacket.empty(); sendingPacket.byte4ToBuf((*it).first); sendingPacket.strToBuf(popupData->myPopupInfo->getTimeoutString()); myServer->broadcastPacketTcp(&sendingPacket, "popupClose"); doneIDs.push_back((*it).first); donePopups.push_back(popupData); } } } while (doneIDs.begin() != doneIDs.end()) { myMap.erase((*doneIDs.begin())); doneIDs.pop_front(); } myDataMutex.unlock(); std::list<PopupData *>::iterator donePopupIt; while ((donePopupIt = donePopups.begin()) != donePopups.end()) { popupData = (*donePopupIt); if (popupData->myCallback != NULL) popupData->myCallback->invoke(popupData->myID, -1); delete popupData; donePopups.pop_front(); } }
AREXPORT void ArServerHandlerMap::sendMapWithMaxCategory(ArServerClient *client, const char *maxCategory) { ArLog::LogLevel level = ArLog::Verbose; ArLog::log(level, "Starting sending map (%s) to client", maxCategory); if (myMap == NULL) { ArLog::log(level, "ArServerHandlerMap::sendMapWithMaxCategory() NULL map"); writeMapToClient("", client); return; } myMap->lock(); // This functor is used to send the map header and objects in text format. ArFunctor1<const char *> *textFunctor = new ArFunctor2C<ArServerHandlerMap, const char *, ArServerClient *> (this, &ArServerHandlerMap::writeMapToClient, NULL, client); // This functor is used to send the map data lines in binary format (since // it is faster). ArFunctor2<int, std::vector<ArLineSegment> *> *linesFunctor = new ArFunctor3C<ArServerHandlerMap, int, std::vector<ArLineSegment> *, ArServerClient *> (this, &ArServerHandlerMap::writeLinesToClient, 0, NULL, client); // This functor is used to send the map data points in binary format (since // it is faster). ArFunctor2<int, std::vector<ArPose> *> *pointsFunctor = new ArFunctor3C<ArServerHandlerMap, int, std::vector<ArPose> *, ArServerClient *> (this, &ArServerHandlerMap::writePointsToClient, 0, NULL, client); // Send the map up to but not including the DATA tag. myMap->writeObjectsToFunctor(textFunctor, "", false, maxCategory); std::list<std::string> scanTypeList = myMap->getScanTypes(); if (!scanTypeList.empty()) { // see if we want to send the lines and make sure we have lines if (myDataToSend == LINES || myDataToSend == BOTH) { for (std::list<std::string>::iterator iter = scanTypeList.begin(); iter != scanTypeList.end(); iter++) { const char *scanType = (*iter).c_str(); if ((myMap->getLines(scanType) != NULL) && (!myMap->getLines(scanType)->empty())) { myMap->writeLinesToFunctor(linesFunctor, scanType, textFunctor); ArNetPacket sendPacket; sendPacket.empty(); sendPacket.byte4ToBuf(0); client->sendPacketTcp(&sendPacket); } } } if (myDataToSend == POINTS || myDataToSend == BOTH) { // TODO This is different than getMapBinary -- in that DATA is not necessarily // always sent. Is this going to be a problem? for (std::list<std::string>::iterator iter = scanTypeList.begin(); iter != scanTypeList.end(); iter++) { const char *scanType = (*iter).c_str(); if ((myMap->getPoints(scanType) != NULL) && (!myMap->getPoints(scanType)->empty())) { myMap->writePointsToFunctor(pointsFunctor, scanType, textFunctor); ArNetPacket sendPacket; sendPacket.empty(); sendPacket.byte4ToBuf(0); client->sendPacketTcp(&sendPacket); } } } } // end if scan types // send an empty packet to say we're done ArNetPacket emptyPacket; client->sendPacketTcp(&emptyPacket); myMap->unlock(); ArLog::log(level, "Finished sending map (%s) to client", maxCategory); // delete textFunctor; delete textFunctor; textFunctor = NULL; delete linesFunctor; linesFunctor = NULL; delete pointsFunctor; pointsFunctor = NULL; } // end method sendMapWithMaxCategory
AREXPORT void ArServerHandlerMap::serverGetMapBinary(ArServerClient *client, ArNetPacket *packet) { ArLog::log(ArLog::Verbose, "Starting sending map (binary) to client"); if (myMap == NULL) { writeMapToClient("", client); return; } myMap->lock(); // This functor is used to send the map header and objects in text format. ArFunctor1<const char *> *textFunctor = new ArFunctor2C<ArServerHandlerMap, const char *, ArServerClient *> (this, &ArServerHandlerMap::writeMapToClient, NULL, client); // This functor is used to send the map data lines in binary format (since // it is faster). ArFunctor2<int, std::vector<ArLineSegment> *> *linesFunctor = new ArFunctor3C<ArServerHandlerMap, int, std::vector<ArLineSegment> *, ArServerClient *> (this, &ArServerHandlerMap::writeLinesToClient, 0, NULL, client); // This functor is used to send the map data points in binary format (since // it is faster). ArFunctor2<int, std::vector<ArPose> *> *pointsFunctor = new ArFunctor3C<ArServerHandlerMap, int, std::vector<ArPose> *, ArServerClient *> (this, &ArServerHandlerMap::writePointsToClient, 0, NULL, client); // Send the map up to but not including the DATA tag. myMap->writeObjectsToFunctor(textFunctor, "", true, // Only send one scan type ArMapInterface::MAP_CATEGORY_2D); std::list<std::string> scanTypeList = myMap->getScanTypes(); bool isAnyLinesExist = false; for (std::list<std::string>::iterator iter = scanTypeList.begin(); iter != scanTypeList.end(); iter++) { const char *scanType = (*iter).c_str(); if ((myMap->getLines(scanType) != NULL) && (!myMap->getLines(scanType)->empty())) { isAnyLinesExist = true; break; } } // end for each scan type // see if we want to send the lines and make sure we have lines if ((myDataToSend == LINES || myDataToSend == BOTH) && isAnyLinesExist) { writeMapToClient("LINES", client); /*** myMap->writeLinesToFunctor(linesFunctor, NULL, ARMAP_SUMMARY_SCAN_TYPE); ***/ for (std::list<std::string>::iterator iter = scanTypeList.begin(); iter != scanTypeList.end(); iter++) { const char *scanType = (*iter).c_str(); ArLog::log(ArLog::Normal, "ArServerHandlerMap::serverGetMapBinary() sending lines for %s", scanType); myMap->writeLinesToFunctor(linesFunctor, scanType, NULL); } // end for each scan type ArNetPacket sendPacket; sendPacket.empty(); sendPacket.byte4ToBuf(0); client->sendPacketTcp(&sendPacket); /****/ } // Always write the points (even if empty) because this signifies // the end of the map for the client. //if (myMap->getPoints()->begin() != myMap->getPoints()->end()) //{ writeMapToClient("DATA", client); // if we want to send points then send 'em if (myDataToSend == POINTS || myDataToSend == BOTH) { // myMap->writePointsToFunctor(pointsFunctor, NULL, sendScanType); /**/ for (std::list<std::string>::iterator iter = scanTypeList.begin(); iter != scanTypeList.end(); iter++) { const char *scanType = (*iter).c_str(); ArLog::log(ArLog::Normal, "ArServerHandlerMap::serverGetMapBinary() sending points for %s", scanType); myMap->writePointsToFunctor(pointsFunctor, scanType, NULL); } // end for each scan type /**/ ArNetPacket sendPacket; sendPacket.empty(); sendPacket.byte4ToBuf(0); client->sendPacketTcp(&sendPacket); } // if not just say we're done else writeMapToClient("", client); //} // send an empty packet to say we're done ArNetPacket emptyPacket; client->sendPacketTcp(&emptyPacket); myMap->unlock(); ArLog::log(ArLog::Verbose, "Finished sending map (binary) to client"); // delete textFunctor; delete textFunctor; textFunctor = NULL; delete linesFunctor; linesFunctor = NULL; delete pointsFunctor; pointsFunctor = NULL; }
/** @internal */ AREXPORT void ArServerHandlerMap::writeLinesToClient( int lineCount, std::vector<ArLineSegment> *lines, ArServerClient *client) { ArNetPacket sendPacket; // Should never happen... if (lines == NULL) { // Send 0 points just so the client doesn't hang sendPacket.byte4ToBuf(0); client->sendPacketTcp(&sendPacket); return; } ArLog::log(ArLog::Verbose, "ArServerHandlerMap::writeLinesToClient() pointCount = %i, vector size = %i", lineCount, (int) lines->size()); // Neither should this, but just in case... if (lineCount > (int) lines->size()) { lineCount = lines->size(); } int maxInPacketCount = 1000; // Maximum number of points sent in a packet int currentCount = 0; // Number put into the current packet int remainingCount = lineCount; // Total number of points remaining to be sent bool isStartPacket = true; // Whether a new packet is being started int totalCount = 0; for (std::vector<ArLineSegment>::iterator lineIt = lines->begin(); lineIt != lines->end(); lineIt++) { // Start a new packet if the previous one was sent (or there is no // previous one) if (isStartPacket) { isStartPacket = false; sendPacket.empty(); currentCount = 0; // Leftover points... if (maxInPacketCount > remainingCount) { maxInPacketCount = remainingCount; } // The first item in the packet is the number of points contained sendPacket.byte4ToBuf(maxInPacketCount); } // end if starting a new packet // Add the current point to the packet (think that the test should // always be true) if (currentCount < maxInPacketCount) { currentCount++; remainingCount--; sendPacket.byte4ToBuf( ArMath::roundInt((*lineIt).getX1())); sendPacket.byte4ToBuf( ArMath::roundInt((*lineIt).getY1())); sendPacket.byte4ToBuf( ArMath::roundInt((*lineIt).getX2())); sendPacket.byte4ToBuf( ArMath::roundInt((*lineIt).getY2())); } // If the packet is full, send it and then start a new one if (currentCount == maxInPacketCount) { totalCount += currentCount; client->sendPacketTcp(&sendPacket); //ArUtil::sleep(1); isStartPacket = true; } } // end for each point ArLog::log(ArLog::Verbose, "ArServerHandlerMap::writePointsToClient() totalCount = %i", totalCount); // Send 0 points to indicate that all have been sent if (false) { sendPacket.empty(); sendPacket.byte4ToBuf(0); client->sendPacketTcp(&sendPacket); } } // end writePointsToClient
/** * @param client the ArServerClient * to which to send the config * @param packet the ArNetPacket * which accompanied the client's request * @param isMultiplePackets a bool set to true if the server should send a * packet for each config section followed by the empty packet; false if * the server should send the entire config in one packet (i.e. the old style) * @param lastPriority the last ArPriority::Priority that should be sent * to the client (this is the greatest numerical value and the least * semantic priority). **/ AREXPORT void ArServerHandlerConfig::handleGetConfig(ArServerClient *client, ArNetPacket *packet, bool isMultiplePackets, ArPriority::Priority lastPriority) { ArConfigArg param; // The multiple packets method also sends display hints with the parameters; // the old single packet method does not. ArClientArg clientArg(isMultiplePackets, lastPriority); std::set<std::string> sent; ArNetPacket sending; ArLog::log(ArLog::Normal, "Config requested."); std::list<ArConfigSection *> *sections = myConfig->getSections(); for (std::list<ArConfigSection *>::iterator sIt = sections->begin(); sIt != sections->end(); sIt++) { // Clear the packet... if (isMultiplePackets) { sending.empty(); } // clear out the sent list between sections sent.clear(); ArConfigSection *section = (*sIt); if (section == NULL) { continue; } sending.byteToBuf('S'); sending.strToBuf(section->getName()); sending.strToBuf(section->getComment()); ArLog::log(ArLog::Verbose, "Sending config section %s...", section->getName()); //printf("S %s %s\n", section->getName(), section->getComment()); std::list<ArConfigArg> *params = section->getParams(); for (std::list<ArConfigArg>::iterator pIt = params->begin(); pIt != params->end(); pIt++) { param = (*pIt); bool isCheckableName = (param.getType() != ArConfigArg::DESCRIPTION_HOLDER && param.getType() != ArConfigArg::SEPARATOR && param.getType() != ArConfigArg::STRING_HOLDER); // if we've already sent it don't send it again if (isCheckableName && sent.find(param.getName()) != sent.end()) { continue; } else if (isCheckableName) { sent.insert(param.getName()); } if (clientArg.isSendableParamType(param)) { sending.byteToBuf('P'); bool isSuccess = clientArg.createPacket(param, &sending); } } // end for each parameter if (!sending.isValid()) { ArLog::log(ArLog::Terse, "Config section %s cannot be sent; packet size exceeded", section->getName()); } // end if length exceeded... else if (isMultiplePackets) { client->sendPacketTcp(&sending); } // end else send in chunks... } // end for each section // If sending each section in individual packets, then send an empty packet // to indicate the end of the config data. if (isMultiplePackets) { sending.empty(); client->sendPacketTcp(&sending); } else { // send the entire config in one packet // If the config is too big to fit in the packet, then just send an empty // packet (to try to prevent an older client from crashing) // TODO: Is there any better way to notify the user of an error.... if (!sending.isValid()) { ArLog::log(ArLog::Terse, "Error sending config; packet size exceeded"); sending.empty(); } client->sendPacketTcp(&sending); } // end else send the entire packet } // end method getConfigBySections
AREXPORT ArServerClient::ArServerClient( ArSocket *tcpSocket, unsigned int udpPort, long authKey, long introKey, ArRetFunctor2<bool, ArNetPacket *, struct sockaddr_in *> *sendUdpCallback, std::map<unsigned int, ArServerData *> *dataMap, const char *passwordKey, const char *serverKey, const ArServerUserInfo *userInfo, int rejecting, const char *rejectingString, bool debugLogging, const char *serverClientName, bool logPasswordFailureVerbosely, bool allowSlowPackets, bool allowIdlePackets) : myProcessPacketCB(this, &ArServerClient::processPacket, NULL, true) { ArNetPacket packet; // set our default to no command pushCommand(0); myAuthKey = authKey; myIntroKey = introKey; myTcpSocket.transfer(tcpSocket); myTcpSocket.setCloseCallback(tcpSocket->getCloseCallback()); myTcpSocket.setNonBlock(); myTcpReceiver.setSocket(&myTcpSocket); myTcpReceiver.setProcessPacketCB(&myProcessPacketCB); myTcpSender.setSocket(&myTcpSocket); mySendUdpCB = sendUdpCallback; myDataMap = dataMap; if (udpPort == 0) myTcpOnly = true; else myTcpOnly = false; mySentTcpOnly = myTcpOnly; myUserInfo = userInfo; myPasswordKey = passwordKey; myServerKey = serverKey; myRejecting = rejecting; if (rejectingString != NULL) myRejectingString = rejectingString; myDebugLogging = debugLogging; if (myDebugLogging) myVerboseLogLevel = ArLog::Normal; else myVerboseLogLevel = ArLog::Verbose; myTcpSender.setDebugLogging(myDebugLogging); myLogPrefix = serverClientName; myLogPrefix += ": "; myTcpSender.setLoggingPrefix(myLogPrefix.c_str()); myTcpReceiver.setLoggingPrefix(myLogPrefix.c_str()); myLogPasswordFailureVerbosely = logPasswordFailureVerbosely; mySlowPacketsMutex.setLogName("ArServerClient::mySlowPacketsMutex"); myIdlePacketsMutex.setLogName("ArServerClient::myIdlePacketsMutex"); myAllowSlowPackets = allowSlowPackets; myAllowIdlePackets = allowIdlePackets; setIdentifier(ArServerClientIdentifier()); internalSwitchState(STATE_SENT_INTRO); packet.empty(); packet.setCommand(ArServerCommands::INTRODUCTION); packet.strToBuf("alpha"); packet.uByte2ToBuf(udpPort); packet.uByte4ToBuf(myAuthKey); packet.uByte4ToBuf(myIntroKey); packet.strToBuf(myPasswordKey.c_str()); sendPacketTcp(&packet); mySlowIdleThread = NULL; myHaveSlowPackets = false; myHaveIdlePackets = false; myCreationTime.setToNow(); resetTracking(); }
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); } }
void ArServerClient::sendListPacket(void) { ArNetPacket packet; std::map<unsigned int, ArServerData *>::iterator it; unsigned int count; unsigned int shortLen; unsigned int longLen; ArServerData *serverData; // First we send a list of numbers, names and descriptions packet.setCommand(ArServerCommands::LIST); // number of entries (we'll overwrite it later with the right number) shortLen = packet.getLength(); packet.uByte2ToBuf(0); // loop through the data to build the packet for (it = myDataMap->begin(), count = 0; it != myDataMap->end(); it++) { serverData = (*it).second; if (myUserInfo == NULL || serverData->getCommandGroup() == NULL || serverData->getCommandGroup()[0] == '\0' || myGroups.count(serverData->getCommandGroup()) != 0 || myGroups.count("all") != 0) { count++; packet.uByte2ToBuf(serverData->getCommand()); packet.strToBuf(serverData->getName()); packet.strToBuf(serverData->getDescription()); } } // put the real number of entries in the right spot longLen = packet.getLength(); packet.setLength(shortLen); packet.uByte2ToBuf(count); packet.setLength(longLen); sendPacketTcp(&packet); // then we send a list of the arguments and returns... they aren't // combined so that the packet structure doesn't need to change packet.empty(); packet.setCommand(ArServerCommands::LISTARGRET); // number of entries (we'll overwrite it later with the right number) shortLen = packet.getLength(); packet.uByte2ToBuf(0); // loop through the data to build the packet for (it = myDataMap->begin(), count = 0; it != myDataMap->end(); it++) { serverData = (*it).second; if (myUserInfo == NULL || serverData->getCommandGroup() == NULL || serverData->getCommandGroup()[0] == '\0' || myGroups.count(serverData->getCommandGroup()) != 0 || myGroups.count("all") != 0) { count++; packet.uByte2ToBuf(serverData->getCommand()); packet.strToBuf(serverData->getArgumentDescription()); packet.strToBuf(serverData->getReturnDescription()); } } // put the real number of entries in the right spot longLen = packet.getLength(); packet.setLength(shortLen); packet.uByte2ToBuf(count); packet.setLength(longLen); sendPacketTcp(&packet); // then we send a list of command groups... they aren't // combined so that the packet structure doesn't need to change packet.empty(); packet.setCommand(ArServerCommands::LISTGROUPANDFLAGS); // number of entries (we'll overwrite it later with the right number) shortLen = packet.getLength(); packet.uByte2ToBuf(0); // loop through the data to build the packet for (it = myDataMap->begin(), count = 0; it != myDataMap->end(); it++) { serverData = (*it).second; if (myUserInfo == NULL || serverData->getCommandGroup() == NULL || serverData->getCommandGroup()[0] == '\0' || myGroups.count(serverData->getCommandGroup()) != 0 || myGroups.count("all") != 0) { count++; packet.uByte2ToBuf(serverData->getCommand()); packet.strToBuf(serverData->getCommandGroup()); packet.strToBuf(serverData->getDataFlagsString()); } } // put the real number of entries in the right spot longLen = packet.getLength(); packet.setLength(shortLen); packet.uByte2ToBuf(count); packet.setLength(longLen); sendPacketTcp(&packet); }
void putFile(char *fileName, char *asFileName) { ArNetPacket sendPacket; size_t ui; size_t len; FILE *file; if ((file = ArUtil::fopen(fileName, "r")) == NULL) { ArLog::log(ArLog::Normal, "putFile: can't open file '%s'", fileName); return; } // tell the server we're sending sendPacket.empty(); sendPacket.uByte2ToBuf(0); sendPacket.strToBuf(asFileName); client.requestOnce("putFile", &sendPacket); printf("Starting send of file %s\n", fileName); char buf[30000]; size_t ret; // now send the file while ((ret = fread(buf, 1, sizeof(buf), file)) == sizeof(buf)) { sendPacket.empty(); sendPacket.uByte2ToBuf(1); sendPacket.strToBuf(asFileName); sendPacket.uByte4ToBuf(ret); sendPacket.dataToBuf(buf, ret); client.requestOnce("putFile", &sendPacket); printf("Sent packet with %d\n", ret); } if (ferror(file)) { ArLog::log(ArLog::Normal, "ArServerFileToClient: Error sending file %s", fileName); sendPacket.empty(); sendPacket.uByte2ToBuf(3); sendPacket.strToBuf(asFileName); client.requestOnce("putFile", &sendPacket); return; } sendPacket.empty(); sendPacket.uByte2ToBuf(1); sendPacket.strToBuf(asFileName); sendPacket.uByte4ToBuf(ret); sendPacket.dataToBuf(buf, ret); client.requestOnce("putFile", &sendPacket); printf("Sent packet with %d\n", ret); sendPacket.empty(); sendPacket.uByte2ToBuf(2); sendPacket.strToBuf(asFileName); client.requestOnce("putFile", &sendPacket); if (feof(file)) { ArLog::log(ArLog::Normal, "ArServerFileToClient: Sent file %s", fileName); } fclose(file); }