void MessageProcessor::run() { for (;;) { // timeout is the time left until the next cron should execute. int64_t timeout = server_->computeTimeout(); if (timeout <= 0) { server_->ProcessCron(); continue; } // wait for incoming message or up to timeout, // i.e. stop polling in time for the next cron execution. if (zpoller_wait(zmqPoller_, timeout)) { processSocket(); continue; } if (zpoller_terminated(zmqPoller_)) { otErr << __FUNCTION__ << ": zpoller_terminated - process interrupted or" << " parent context destroyed\n"; break; } if (!zpoller_expired(zmqPoller_)) { otErr << __FUNCTION__ << ": zpoller_wait error\n"; // we do not want busy loop if something goes wrong Log::SleepMilliseconds(100); } } }
void Server::run() { if (m_wordList.size() == 0) return; cpp3ds::Clock pingClock; if (m_listener.listen(m_port) == cpp3ds::Socket::Done) { m_selector.add(m_listener); std::cout << "Started DrawAttack server on port " << m_port << "..." << std::endl; m_running = true; while (m_running) { // Make the selector wait for data on any socket if (m_selector.wait(cpp3ds::milliseconds(1000))) { if (m_selector.isReady(m_listener)) { cpp3ds::TcpSocket* socket = new cpp3ds::TcpSocket; if (m_listener.accept(*socket) == cpp3ds::Socket::Done) { std::cout << "client connected" << std::endl; // Add the new client to the clients list sendPlayerData(socket); socket->send(m_drawDataPacket); m_pingResponses[socket] = true; m_sockets.emplace_back(socket); m_selector.add(*socket); } else { delete socket; } } else { for (auto& socket : m_sockets) { if (m_selector.isReady(*socket)) { processSocket(socket); } } } } // Ping clients and check for previous response if (pingClock.getElapsedTime() >= cpp3ds::seconds(PING_TIMEOUT)) { cpp3ds::Packet packet; packet << NetworkEvent::Ping; for (auto i = m_sockets.begin(); i != m_sockets.end();) { if (m_pingResponses[*i]) { (*i)->send(packet); m_pingResponses[*i] = false; i++; } else { // Timed out socket std::cout << "A socket timed out." << std::endl; removeSocket(*i); } } pingClock.restart(); } if (m_mode == Play) { if (m_roundClock.getElapsedTime() >= cpp3ds::seconds(ROUND_DURATION)) { // Round time ended, nobody won cpp3ds::Packet packet; packet << NetworkEvent::RoundWord << m_currentWord << NetworkEvent::RoundFail; sendToAllSockets(packet); m_roundClock.restart(); m_mode = Wait; } if (m_roundTimeoutClock.getElapsedTime() >= cpp3ds::seconds(ROUND_TIMEOUT)) { // Drawer hasn't been active, so end round cpp3ds::Packet packet; packet << NetworkEvent::RoundWord << m_currentWord << NetworkEvent::RoundTimeout; sendToAllSockets(packet); m_roundClock.restart(); m_mode = Wait; } } else if (m_mode == Wait) { if (m_players.size() >= MIN_PLAYERS) { if (m_roundClock.getElapsedTime() >= cpp3ds::seconds(ROUND_INTERMISSION)) { Player drawer = getNextDrawer(); startRound(drawer, getNextWord(), ROUND_DURATION); } } } } } else { cpp3ds::err() << "Failed to listen on port " << m_port << std::endl; } }
int main(int argc, char *argv[]) // arg1: controller number { int nolog = 0; struct sockaddr_in serv_addr; struct hostent *server; char buffer[256]; int run = 1; // set to 0 to stop main loop fd_set readfd; int numfds; int interval = 60; int tmout = 90; // seconds to wait in select() int saveInterval = 600; // Save to NVRAM every 10 mins int logerror = 0; int option; int delay = 1000; // usec to sleep (but it rounds up to 20mSec anyway time_t update = 0, now; pthread_t tid; time_t nextSave; // Command line arguments opterr = 0; while ((option = getopt(argc, argv, "di:slVZ1:2:")) != -1) { switch (option) { case 's': noserver = 1; break; case 'l': nolog = 1; break; case '?': usage(); exit(1); case 'i': interval = atoi(optarg); break; case 'd': debug++; break; case '1': rate1 = rate2 = atof(optarg); break; case '2': rate2 = atof(optarg); break; case 'V': printf("Version %s %s\n", getversion(), id); exit(0); case 'Z': decode("(b+#Gjv~z`mcx-@ndd`rxbwcl9Vox=,/\x10\x17\x0e\x11\x14\x15\x11\x0b\x1a" "\x19\x1a\x13\x0cx@NEEZ\\F\\ER\\\x19YTLDWQ'a-1d()#!/#(-9' >q\"!;=?51-??r"); exit(0); } } DEBUG printf("Debug %d. optind %d argc %d\n", debug, optind, argc); if (optind < argc) controllernum = atoi(argv[optind]); // get optional controller number: parameter 1 sprintf(buffer, LOGFILE, controllernum); if (!nolog) if ((logfp = fopen(buffer, "a")) == NULL) logerror = errno; // There is no point in logging the failure to open the logfile // to the logfile, and the socket is not yet open. sprintf(buffer, "STARTED %s as %d interval %d %s", argv[0], controllernum, interval, nolog ? "nolog" : ""); logmsg(INFO, buffer); // Set up socket if (!noserver) { sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) logmsg(FATAL, "FATAL " PROGNAME " Creating socket"); server = gethostbyname("localhost"); if (server == NULL) { logmsg(FATAL, "FATAL " PROGNAME " Cannot resolve localhost"); } bzero((char *) &serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length); serv_addr.sin_port = htons(PORTNO); if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) { sockfd = 0; logmsg(ERROR, "ERROR " PROGNAME " Connecting to socket"); } if (flock(fileno(logfp), LOCK_EX | LOCK_NB) == -1) { logmsg(FATAL, "FATAL " PROGNAME " is already running, cannot start another one"); } // Logon to server as meter sprintf(buffer, "logon " progname " %s %d %d", getversion(), getpid(), controllernum); sockSend(buffer); } else sockfd = 1; // noserver: use stdout // If we failed to open the logfile and were NOT called with nolog, warn server // Obviously don't use logmsg! if (logfp == NULL && nolog == 0) { sprintf(buffer, "event WARN " PROGNAME " %d could not open logfile %s: %s", controllernum, LOGFILE, strerror(logerror)); sockSend(buffer); } // Set up hardware int mem = open("/dev/mem", O_RDWR); unsigned char * start = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, mem, 0x80840000); pbdata = (unsigned int*)(start + 0x04); pbddr = (unsigned int *)(start + 0x14); // All inputs *pbddr = DIO4 | DIO5; // DIO 4/5 outputs. *pbdata = 0xff; // set to all 1's numfds = sockfd + 1; // nfds parameter to select. One more than highest descriptor // Main Loop count1 = count2 = 0; readCMOS(); DEBUG fprintf(stderr, "Got values from NVRAM: %d %d (%f %f)\n", count1, count2, (count1 / rate1), (count2 / rate2)); // Start count thread if (pthread_create(&tid, NULL, count_pulses, NULL) < 0) perror("count_pulse"); DEBUG fprintf(stderr, "Thread started as %d (0x%x)\n", tid, tid); FD_ZERO(&readfd); update = timeMod(interval); nextSave = timeMod(saveInterval); while(run) { struct timeval tv1; now = time(NULL); if (now > nextSave) { DEBUG fprintf(stderr, "Saving to NVRAM "); writeCMOS(); nextSave = timeMod(saveInterval); DEBUG { struct tm * t; t = localtime(&nextSave); strftime(buffer, sizeof(buffer), "%F %T", t); fprintf(stderr, "Next save at %s\n", buffer); } } if (now > update) { // message time. Will always send out 0 0 at startup. int fd; sprintf(buffer, "meter 2 %.1f %.1f", (count1 / rate1), (count2 / rate2)); sockSend(buffer); update = timeMod(interval); // Write to /tmp/pulse fd = open("/tmp/pulse", O_RDWR | O_CREAT | O_TRUNC); if (fd < 0) perror("/tmp/pulse"); if (fd > 0) { strcat(buffer, "\n"); write(fd, buffer, strlen(buffer)); close(fd); } } FD_SET(sockfd, &readfd); tv1.tv_sec = 0; tv1.tv_usec = tmout; if (select(sockfd + 1, &readfd, NULL, NULL, &tv1) && sockfd > 1) // anything from server? run = processSocket(); // the server may request a shutdown by setting run to 0 usleep(delay); }
int main(int argc, char **argv) { in_port_t port = DEFAULT_PORT; long baud = DEFAULT_BAUD; char dv3000tty[MAXPATHLEN] = DEFAULT_TTY; fd_set fds; int serialFd; int sockFd; int topFd; int c; #ifdef __CYGWIN__ int commnum; #endif char reset = 0; char daemon = 0; setvbuf(stdout, NULL, _IOLBF, 0); setvbuf(stderr, NULL, _IOLBF, 0); #ifdef __CYGWIN__ while ((c = getopt(argc, argv, "dp:s:c:vxrh")) != -1) { #else while ((c = getopt(argc, argv, "dp:s:i:vxrh")) != -1) { #endif switch (c) { case 'd': daemon = 1; break; case 'p': errno = 0; port = strtol(optarg, NULL, 10); if(errno != 0 || port == 0) { fprintf(stderr, "Invalid port number: %s\n", optarg); usage(); } break; case 's': errno = 0; baud = strtol(optarg, NULL, 10); if(errno != 0 || baud == 0) { fprintf(stderr, "Invalid baud rate: %s\n", optarg); usage(); } break; #ifdef __CYGWIN__ case 'c': commnum = strtol(optarg, NULL, 10); sprintf(dv3000tty,"/dev/ttyS%d",commnum - 1); break; #else case 'i': strncpy(dv3000tty, optarg, sizeof(dv3000tty)); break; #endif case 'v': fprintf(stdout, "AMBEserver: version " DV3000_VERSION "\n"); return 0; case 'x': debug = 1; break; case 'r': reset = 1; break; case 'h': default: usage(); break; } } if (strlen(dv3000tty) < 1) { fprintf(stderr, "An input tty filename (-i /dev/ttyXXX) must be set.\n"); return 1; } if (daemon) { pid_t pid = fork(); if (pid < 0) { fprintf(stderr, "AMBEserver: error in fork(), exiting\n"); exit(1); } // If this is the parent, exit if (pid > 0) exit(0); // We are the child from here onwards setsid(); umask(0); } fprintf(stdout, "AMBEserver: Starting...\n"); serialFd = openSerial(dv3000tty, baud); if (serialFd < 0) exit(1); fprintf(stdout, "AMBEserver: Opened serial port %s at %ld bps.\n", dv3000tty, baud); if(initDV3K(serialFd, reset) == 0) { fprintf(stderr, "AMBEserver: Could not initialize the DV3K!\n"); exit(1); } sockFd = openSocket(port); if (sockFd < 0) exit(1); fprintf(stdout, "AMBEserver: Listening for connections on UDP port %d.\n", port); topFd = (sockFd > serialFd ? sockFd : serialFd ) + 1; for (;;) { FD_ZERO(&fds); FD_SET(sockFd, &fds); FD_SET(serialFd, &fds); if (select(topFd, &fds, NULL, NULL, NULL) < 0) { fprintf(stderr, "AMBEserver: error from select: %s\n", strerror(errno)); exit(1); } if(FD_ISSET(sockFd, &fds)) if (!processSocket(sockFd, serialFd)) exit(1); if(FD_ISSET(serialFd, &fds)) if (!processSerial(sockFd, serialFd)) exit(1); } exit(0); }