/* ------------------------------------------------------------------------------------------------ * The server was initialized and this plug-in must initialize as well. */ static uint8_t OnServerInitialise(void) { // Obtain the server settings. We only need the port number _Func->GetServerSettings(&g_Settings); // Obtain the server version. This doesn't change much g_ServerVersion = _Func->GetServerVersion(); // Attempt to generate the update payload for (unsigned n = 0; n < g_Servers.size();) { // Attempt to generate the payload g_Servers[n].Generate(); // See if any failures occurred if (g_Servers[n].GetData()[0] == 0) { // Erase the server completely g_Servers.erase(g_Servers.begin() + n); } // Move to the next server else { ++n; } } // See if any servers are left if (g_Servers.empty()) { // We don't want to receive events anymore _Clbk->OnServerInitialise = nullptr; _Clbk->OnServerShutdown = nullptr; _Clbk->OnServerFrame = nullptr; } else { // Enable the announce thread to run if there are servers g_Announce = true; // Create the announce thread g_Thread = std::thread(AnnounceThread, std::move(g_Servers)); // Notify that the plug-in was successfully initialized VerboseMessage("Announce plug-in was successfully initialized"); } // Allow the server to continue return 1; }
/* --------------------------------------------------------------------------------------------- * Generate the payload message. */ void Generate() { char body[32]; // Generate the post data if (snprintf(body, sizeof(body), "port=%d", g_Settings.port) < 0) { VerboseError("Unable to generate the post data for '%s'", m_Addr.Host()); // Make sure the data is null terminated m_Data[0] = '\0'; // Make sure this is marked as invalid m_Valid = false; } // Generate the payload message sent with each message else if (snprintf(m_Data, sizeof(m_Data), "POST %s HTTP/1.1\r\n" "Host: %s\r\n" "Connection: close\r\n" "User-Agent: VCMP/0.4\r\n" "VCMP-Version: %u\r\n" "Content-Type: application/x-www-form-urlencoded\r\n" "Content-Length: %u\r\n" "\r\n" /* ... */ "%s" , m_Addr.Path(), m_Addr.Host() , g_ServerVersion, strlen(body), body) < 0) { VerboseError("Unable to generate the payload message for '%s'", m_Addr.Host()); // Make sure the data is null terminated m_Data[0] = '\0'; // Make sure this is marked as invalid m_Valid = false; } else { VerboseMessage("Payload for master-server '%s' is:\n%s", m_Addr.Host(), m_Data); // Make sure this is marked as valid MakeValid(); } }
/* ========================================================================= */ int run_as_sender(struct optbase *ob) { /* This used to be char junkbuf[0]; but the compiler complained. junkbuf is a pointer to the top of the auto variables. The point is to have a pointer to some data - but nothing of particular value. */ int junk; char *junkbuf = (char *)&junk; struct roundtrip *rt; struct pc_comm *pcomm = NULL; int go; /* Used multiple times for "event loops" */ char child_message[80]; char mirror_address[MAX_VALUE_SIZE]; char mirror_protocol[MAX_VALUE_SIZE]; char mirror_port[MAX_VALUE_SIZE]; unsigned long multiplier; unsigned short optimal_block; unsigned long run_seconds; char sink_address[MAX_VALUE_SIZE]; char sink_protocol[MAX_VALUE_SIZE]; char sink_port[MAX_VALUE_SIZE]; time_t time_started; /* Really about reporting. */ time_t time_now; /* The most recent time. */ time_t time_stop; /* Do some basic validation of the expected values */ if ( IsInvalidOption(ob, "MIRROR_ADDRESS", IVO_EXISTS) ) { ErrorMessage("ERROR: MIRROR_ADDRESS option is missing or invalid.\n"); return(1); } if ( IsInvalidOption(ob, "MIRROR_PROTOCOL", IVO_EXISTS) ) { ErrorMessage("ERROR: MIRROR_PROTOCOL option is missing or invalid.\n"); return(1); } if ( IsInvalidOption(ob, "MIRROR_PORT", IVO_EXISTS) ) { ErrorMessage("ERROR: MIRROR_PORT option is missing or invalid.\n"); return(1); } if ( IsInvalidOption(ob, "RETURN_MULTIPLIER", IVO_NNNUMERIC) ) { ErrorMessage("ERROR: RETURN_MULTIPLIER option is missing or invalid.\n"); return(1); } if ( IsInvalidOption(ob, "OPTIMAL_BLOCK", IVO_EXISTS) ) { optimal_block = DEFAULT_OPTIMAL_BLOCK; } else { if ( GetUSValue(ob, &optimal_block, "OPTIMAL_BLOCK", 0, 65535) ) { ErrorMessage("ERROR: Problems parsing OPTIMAL_BLOCK value.\n"); return(1); } } if ( IsInvalidOption(ob, "RUN_FOR", IVO_EXISTS) ) { run_seconds = 0; } else { if ( GetTimeValue(ob, &run_seconds, "RUN_FOR", 0, ULONG_MAX) ) { ErrorMessage("ERROR: Problems parsing RUN_FOR value.\n"); return(1); } } if ( GetULValue(ob, &multiplier, "RETURN_MULTIPLIER", 0, ULONG_MAX) ) { ErrorMessage("ERROR: Problems parsing RETURN_MULTIPLIER value.\n"); return(1); } if ( multiplier > 0 ) { /* This *could* be derived - it should not be *required* */ if ( IsInvalidOption(ob, "SINK_ADDRESS", IVO_EXISTS) ) { ErrorMessage("ERROR: SINK_ADDRESS option is missing or invalid.\n"); return(1); } if ( IsInvalidOption(ob, "SINK_PORT", IVO_EXISTS) ) { ErrorMessage("ERROR: SINK_PORT option is missing or invalid.\n"); return(1); } if ( IsInvalidOption(ob, "SINK_PROTOCOL", IVO_EXISTS) ) { ErrorMessage("ERROR: SINK_PROTOCOL option is missing or invalid.\n"); return(1); } } if ( GetStrValue(ob, mirror_address, "MIRROR_ADDRESS", 4, MAX_VALUE_SIZE) ) { ErrorMessage("ERROR: Problems parsing MIRROR_ADDRESS value.\n"); return(1); } if ( GetSTRValue(ob, mirror_protocol, "MIRROR_PROTOCOL", 2, 4) ) { ErrorMessage("ERROR: Problems parsing MIRROR_PROTOCOL value.\n"); return(1); } if ( GetStrValue(ob, mirror_port, "MIRROR_PORT", 2, 5) ) { ErrorMessage("ERROR: Problems parsing MIRROR_PORT value.\n"); return(1); } if ( multiplier > 0 ) { if ( GetStrValue(ob, sink_address, "SINK_ADDRESS", 4, MAX_VALUE_SIZE) ) { ErrorMessage("ERROR: Problems parsing SINK_ADDRESS value.\n"); return(1); } if ( GetSTRValue(ob, sink_protocol, "SINK_PROTOCOL", 2, 4) ) { ErrorMessage("ERROR: Problems parsing SINK_PROTOCOL value.\n"); return(1); } if ( GetStrValue(ob, sink_port, "SINK_PORT", 2, 5) ) { ErrorMessage("ERROR: Problems parsing SINK_PORT value.\n"); return(1); } } ReportStart("netmirror", NULL, "A module to bounce packets across the network."); /* Register signal handlers */ /* signal(SIGTERM, capture_signal); signal(SIGQUIT, capture_signal); signal(SIGINT, capture_signal); signal(SIGHUP, NULL); */ if ( NULL == ( rt = InitRoundTrip() ) ) return(1); if ( InitSender(rt, mirror_address, mirror_protocol, mirror_port) ) return(1); if ( InitReceiver(rt, sink_address, sink_protocol, sink_port, multiplier) ) return(1); DebugMessage("Round trip multiplier is %lu.\n", multiplier); DebugMessage("Run time (in seconds) is: %lu.\n", run_seconds); if ( multiplier > 0 ) { if (NULL == (pcomm = LaunchAsSink("ADDR", "PROTO", "PORT"))) return(1); } /* Check for message from the sink (if we started it). */ if (pcomm) { if(CheckForChildMessages(pcomm->outof, 250, child_message) > 0) VerboseMessage("Sink: %s\n", child_message); /* A sink is present */ } rt->opt_block = optimal_block; rt->run_seconds = run_seconds; /* Start up the sender and send the opening packets */ if(StartSender(rt)) return(1); /* Take time here - use it or not */ time(&time_started); time_stop = time_started + run_seconds; /* Send packets - handle sink messages */ go = 1; while(go) { //DebugMessage("Sending data..."); send(rt->sd, junkbuf, optimal_block, 0); //DebugMessage("Done.\n"); /* NOTE: This is an oppurtunity to put a delay in the sender. It can be done here with the CheckForChildMessages() API. In cases where there is no sink, then that code will not run, so some other blocking mechanisim might be required to insert the (optional) delay. */ if (pcomm) { /* A sink is present */ if(CheckForChildMessages(pcomm->outof, 0, child_message) > 0) VerboseMessage("Sink: %s\n", child_message); } /* Now time becomes conditional */ if ( run_seconds > 0 ) { time(&time_now); if ( time_now >= time_stop ) go = 0; } } DebugMessage("Shutting down the connection..."); close(rt->sd); /* An actual shutdown() is not relevant. */ DebugMessage("Done.\n"); /* There should be a several second pause between shutting down outbound traffic and sending the stop to the sink. */ DebugMessage("Sending stop to sink process"); go = 3; while(go) { DebugMessage("."); sleep(1); go--; } SendStopSink(pcomm->into); DebugMessage("Done.\n"); go = 10; while ( go ) { if(CheckForChildMessages(pcomm->outof, 500, child_message) > 0) { if ( child_message[0] == '.' ) { VerboseMessage("Sink exited. Sender exiting now.\n"); return(0); } } go--; } ErrorMessage("ERROR: Sink process never exited. Sender exiting.\n"); return(1); }
int main(int argc, char *argv[]) { /* int err; <------ Unused. Commenting out */ int N; //number of cycles int ping_cpu=0; //cpu number to pin the ping process int pong_cpu=1; //cpu number to pin the pong process int pingbusy = 0; int pongbusy = 0; int ncpus=0; struct optbase *ob; if(NULL == (ob = ReadOptions(argc, argv))) return(1); ncpus=sysconf( _SC_NPROCESSORS_ONLN ); if ( ncpus > 2) { VerboseMessage ("number of cpu on the box %d\n",ncpus); } else{ ErrorMessage ("Not enough cpus to run the test\n"); return -1; } /* The cpu_set_t data structure represents a set of CPUs. CPU sets are used by sched_setaffinity(2) and similar interfaces. cpu_set_t data type is implemented as a bitset. mask should have only the total number of max cpu */ cpu_set_t mask[128]; /* inizialize mask with all 0 */ memset(mask, 0, sizeof(mask)); /* work the test options it must be update */ int min_cpu=0; int max_cpu=ncpus-1; int busy=1; int nobusy=0; GetOptionValue(ob, "PING_CPU", GOV_INT16, &ping_cpu, &min_cpu, &max_cpu, NULL); GetOptionValue(ob, "PONG_CPU", GOV_INT16, &pong_cpu, &min_cpu, &max_cpu, NULL); GetOptionValue(ob, "N", GOV_INT16, &N, NULL, NULL, NULL); GetOptionValue(ob, "PING_BUSY", GOV_INT16, &pingbusy,&nobusy,&busy,NULL); GetOptionValue(ob, "PONG_BUSY", GOV_INT16, &pongbusy,&nobusy,&busy,NULL); EvalOptions(ob); if (1<0){ if(argc < 4) { usage(argv[0]); return -1; } ping_cpu = atoi(argv[1]); pong_cpu = atoi(argv[2]); N = atoi(argv[3]); if(argc > 4) { if(strcmp(argv[4], "pongbusy") == 0) pongbusy = 1; else if(strcmp(argv[4], "pingbusy") == 0) pingbusy = 1; } if(argc > 5) { if(strcmp(argv[5], "pongbusy") == 0) pongbusy = 1; else if(strcmp(argv[5], "pingbusy") == 0) pingbusy = 1; } } /* Let's create sem_open the two semaphore oflag is O_CREATE, mode is mode is 0600 S_IRUSR | S_IWUSR from umask */ semInit(&g_semPing, g_pingName); semInit(&g_semPong, g_pongName); if(fork() == 0) { /* child CPU_SET Add CPU cpu to set. */ VerboseMessage("run child\n"); CPU_SET(pong_cpu, mask); sched_setaffinity(0, 128, mask); // If pid is zero, then the calling process is used. if(pongbusy) pong_busy(N); else pong(N); TRY(sem_close(g_semPong), -1); TRY(sem_unlink(g_pongName), -1); VerboseMessage ("wrap child\n"); } else { /* parent */ time_type start, finish; /* time_type start_one, finish_one; <---- Unused. Commenting out */ VerboseMessage ("run parent\n"); CPU_SET(ping_cpu, mask); sched_setaffinity(0, 128, mask); getTime(&start); if(pingbusy) ping_busy(N); else ping(N); VerboseMessage("wrapping parent\n"); getTime(&finish); const long int elapsed = timeDiff(&start, &finish); printf("avg RTT = %.1f nsec.\n", (elapsed * 1.0) / N); TRY(sem_close(g_semPing), -1); TRY(sem_unlink(g_pingName), -1); } return 0; }
/* ========================================================================= */ static void semInit(sem_t** _sem, const char* _name) { VerboseMessage("Initializing %s...\n", _name); TRY(*_sem = sem_open(_name, O_CREAT, S_IRUSR | S_IWUSR, 0), SEM_FAILED); VerboseMessage("Value of %s = %d\n", _name, semGet(*_sem)); }