![]() |
|
|
Generated: 18 Jul 2008 |
00001 00006 /* 00007 * ApMon - Application Monitoring Tool 00008 * Version: 2.2.0 00009 * 00010 * Copyright (C) 2006 California Institute of Technology 00011 * 00012 * Permission is hereby granted, free of charge, to use, copy and modify 00013 * this software and its documentation (the "Software") for any 00014 * purpose, provided that existing copyright notices are retained in 00015 * all copies and that this notice is included verbatim in any distributions 00016 * or substantial portions of the Software. 00017 * This software is a part of the MonALISA framework (http://monalisa.cacr.caltech.edu). 00018 * Users of the Software are asked to feed back problems, benefits, 00019 * and/or suggestions about the software to the MonALISA Development Team 00020 * (developers@monalisa.cern.ch). Support for this software - fixing of bugs, 00021 * incorporation of new features - is done on a best effort basis. All bug 00022 * fixes and enhancements will be made available under the same terms and 00023 * conditions as the original software, 00024 00025 * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR 00026 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT 00027 * OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, 00028 * EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00029 00030 * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, 00031 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 00032 * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS 00033 * PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO 00034 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR 00035 * MODIFICATIONS. 00036 */ 00037 00038 #include "utils.h" 00039 #include "ApMon.h" 00040 00041 00042 bool apmon_utils::urlModified(char *url, char *lastModified) throw(runtime_error) { 00043 char temp_filename[300]; 00044 FILE *tmp_file; 00045 bool lineFound; 00046 char line[MAX_STRING_LEN1]; 00047 00048 #ifndef WIN32 00049 long mypid = getpid(); 00050 #else 00051 long mypid = _getpid(); 00052 #endif 00053 00054 char str1[100], str2[100]; 00055 #ifndef WIN32 00056 sprintf(temp_filename, "/tmp/apmon_http%ld", mypid); 00057 #else 00058 char *tmp = getenv("TEMP"); 00059 if(tmp == NULL) 00060 tmp = getenv("TMP"); 00061 if(tmp == NULL) 00062 tmp = "c:"; 00063 sprintf(temp_filename, "%s\\apmon_http%ld", tmp, mypid); 00064 #endif 00065 /* get the HTTP header and put it in a temporary file */ 00066 httpRequest(url, (char*)"HEAD", temp_filename); 00067 00068 /* read the header from the temporary file */ 00069 tmp_file = fopen(temp_filename, "rt"); 00070 if (tmp_file == NULL) 00071 throw runtime_error("[ urlModified() ] Error getting the configuration web page"); 00072 00073 //line = (char*)malloc(MAX_STRING_LEN * sizeof(char)); 00074 00075 //check if we got the page correctly 00076 fgets(line, MAX_STRING_LEN, tmp_file); 00077 sscanf(line, "%s %s", str1, str2); 00078 if (atoi(str2) != 200) { 00079 fclose(tmp_file); 00080 unlink(temp_filename); 00081 free(line); 00082 throw runtime_error("[ urlModified() ] Error getting the configuration web page"); 00083 } 00084 00085 // look for the "Last-Modified" line 00086 lineFound = false; 00087 while (fgets(line, MAX_STRING_LEN, tmp_file) != NULL) { 00088 if (strstr(line, "Last-Modified") == line) { 00089 lineFound = true; 00090 break; 00091 } 00092 } 00093 00094 fclose(tmp_file); 00095 unlink(temp_filename); 00096 if (lineFound) { 00097 if (strcmp(line, lastModified) != 0) { 00098 return true; 00099 } 00100 else 00101 return false; 00102 } else 00103 // if the line was not found we must assume the page was modified 00104 return true; 00105 00106 } 00107 00108 int apmon_utils::httpRequest(char *url, char *reqType, char *temp_filename) 00109 throw(runtime_error) { 00110 // the server from which we get the configuration file 00111 char hostname[MAX_STRING_LEN]; 00112 // the name of the remote file 00113 char filename[MAX_STRING_LEN]; 00114 // the port on which the server listens (by default 80) 00115 int port; 00116 char msg[MAX_STRING_LEN]; 00117 00118 int sd, rc; 00119 struct sockaddr_in localAddr, servAddr; 00120 struct hostent *h; 00121 struct timeval optval; 00122 00123 char *request; // the HTTP request 00124 00125 char buffer[MAX_STRING_LEN]; // for reading from the socket 00126 int totalSize; // the size of the remote file 00127 FILE *tmp_file; 00128 00129 parse_URL(url, hostname, &port, filename); 00130 00131 sprintf(msg, "Sending HTTP %s request to: \n Hostname: %s , Port: %d , Filename: %s", 00132 reqType, hostname, port, filename); 00133 logger(INFO, msg); 00134 00135 request = (char *)malloc(MAX_STRING_LEN * sizeof(char)); 00136 strcpy(request, reqType); 00137 strcat(request, " "); 00138 00139 request = (char *)strcat( request, filename); 00140 request = (char *)strcat( request, " HTTP/1.0\r\nHOST: "); 00141 request = (char *)strcat( request, hostname); 00142 request = (char *)strcat( request, "\r\n\r\n"); 00143 00144 h = gethostbyname(hostname); 00145 if(h==NULL) { 00146 free(request); 00147 sprintf(msg,"[ httpRequest() ] Unknown host: %s ", hostname); 00148 throw runtime_error(msg); 00149 } 00150 00151 servAddr.sin_family = h->h_addrtype; 00152 memcpy((char *) &servAddr.sin_addr.s_addr, h->h_addr_list[0], h->h_length); 00153 servAddr.sin_port = htons(port);//(LOCAL_SERVER_PORT); 00154 00155 sd = socket(AF_INET, SOCK_STREAM, 0); 00156 if(sd<0) { 00157 free(request); 00158 throw runtime_error(" [ httpRequest() ] Cannot open socket "); 00159 } 00160 00161 /* set connection timeout */ 00162 00163 optval.tv_sec = 10; 00164 optval.tv_usec = 0; 00165 //setsockopt(sd, SOL_SOCKET, SO_SNDTIMEO, (char *) &optval, 00166 // sizeof(optval)); 00167 setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char *) &optval, 00168 sizeof(optval)); 00169 00170 localAddr.sin_family = AF_INET; 00171 localAddr.sin_addr.s_addr = htonl(INADDR_ANY); 00172 localAddr.sin_port = htons(0); 00173 00174 /* 00175 rc = bind(sd, (struct sockaddr *) &localAddr, sizeof(localAddr)); 00176 if(rc<0) { 00177 free(request); 00178 close(sd); 00179 sprintf(msg, "%s: cannot bind port TCP %u", url,port); 00180 throw runtime_error(msg); 00181 } 00182 */ 00183 00184 // connect to the server 00185 rc = connect(sd, (struct sockaddr *) &servAddr, sizeof(servAddr)); 00186 if(rc<0) { 00187 free(request); 00188 #ifndef WIN32 00189 close(sd); 00190 #else 00191 closesocket(sd); 00192 #endif 00193 throw runtime_error("[ httpRequest() ] Cannot connect to http server"); 00194 } 00195 00196 // send the request 00197 rc = send(sd, request, strlen(request), 0); 00198 if(rc<0) { 00199 #ifndef WIN32 00200 close(sd); 00201 #else 00202 closesocket(sd); 00203 #endif 00204 free(request); 00205 throw runtime_error("[ httpRequest() ] Cannot send the request to the http server"); 00206 } 00207 00208 free(request); 00209 00210 /* read the response and put it in a temporary file */ 00211 tmp_file = fopen(temp_filename, "wb"); 00212 if (tmp_file == NULL) { 00213 #ifndef WIN32 00214 close(sd); 00215 #else 00216 closesocket(sd); 00217 #endif 00218 throw runtime_error("[ httpRequest() ] Unable to open for writing temporary file"); 00219 } 00220 00221 rc = 0, totalSize = 0; 00222 do { 00223 memset(buffer,0x0,MAX_STRING_LEN); // init line 00224 rc = recv(sd, buffer, MAX_STRING_LEN, 0); 00225 if( rc > 0) { 00226 fwrite(buffer, rc, 1, tmp_file); 00227 totalSize +=rc; 00228 } 00229 }while(rc>0); 00230 00231 sprintf(msg, "Received response from %s, response size is %d bytes", 00232 hostname, totalSize); 00233 logger(INFO, msg); 00234 00235 #ifndef WIN32 00236 close(sd); 00237 #else 00238 closesocket(sd); 00239 #endif 00240 fclose(tmp_file); 00241 return totalSize; 00242 } 00243 00244 char *apmon_utils::findIP(char *address) throw(runtime_error) { 00245 int isIP = 1; 00246 char *destIP, *s; 00247 struct in_addr addr; 00248 unsigned int j; 00249 bool ipFound; 00250 00251 for (j = 0; j < strlen(address); j++) 00252 if (isalpha(address[j])) { 00253 // if we found a letter, this is not an IP address 00254 isIP = 0; 00255 break; 00256 } 00257 00258 if (!isIP) { // the user provided a hostname, find the IP 00259 struct hostent *he = gethostbyname(address); 00260 if (he == NULL) { 00261 char tmp_msg[40]; 00262 sprintf(tmp_msg, "[ findIP() ] Invalid destination address %s", address); 00263 throw runtime_error(tmp_msg); 00264 } 00265 j = 0; 00266 /* get from the list the first IP address 00267 (which is not a loopback one) */ 00268 ipFound = false; 00269 while ((he -> h_addr_list)[j] != NULL) { 00270 memcpy(&(addr.s_addr), (he -> h_addr_list)[j], 4); 00271 s = inet_ntoa(addr); 00272 if (strcmp(s, "127.0.0.1") != 0) { 00273 destIP = strdup(s); 00274 ipFound = true; 00275 break; 00276 } 00277 j++; 00278 } 00279 if (!ipFound) { 00280 destIP = strdup("127.0.0.1"); 00281 fprintf(stderr, "The destination for datagrams is localhost\n"); 00282 } 00283 00284 } else // the string was an IP address 00285 destIP = strdup(address); 00286 00287 return destIP; 00288 } 00289 00290 00291 void apmon_utils::parse_URL(char *url, char *hostname, int *port, char *identifier) 00292 throw(runtime_error) { 00293 char protocol[MAX_STRING_LEN], scratch[MAX_STRING_LEN], *ptr=0, *nptr=0; 00294 char msg[MAX_STRING_LEN]; 00295 00296 strcpy(scratch, url); 00297 ptr = (char *)strchr(scratch, ':'); 00298 if (!ptr) 00299 throw runtime_error("[ parse_URL() ] Wrong url: no protocol specified"); 00300 00301 strcpy(ptr, "\0"); 00302 strcpy(protocol, scratch); 00303 if (strcmp(protocol, "http")) { 00304 sprintf(msg, "[ parse_URL() ] Wrong protocol in URL: %s", protocol); 00305 throw runtime_error(msg); 00306 } 00307 00308 strcpy(scratch, url); 00309 ptr = (char *)strstr(scratch, "//"); 00310 if (!ptr) { 00311 throw runtime_error("[ parse_URL() ] Wrong url: no server specified"); 00312 } 00313 ptr += 2; 00314 00315 strcpy(hostname, ptr); 00316 nptr = (char *)strchr(ptr, ':'); 00317 if (!nptr) { 00318 *port = 80; /* use the default HTTP port number */ 00319 nptr = (char *)strchr(hostname, '/'); 00320 } else { 00321 sscanf(nptr, ":%d", port); 00322 nptr = (char *)strchr(hostname, ':'); 00323 } 00324 00325 if (nptr) 00326 *nptr = '\0'; 00327 00328 nptr = (char *)strchr(ptr, '/'); 00329 if (!nptr) { 00330 throw runtime_error("[ parse_URL() ] Wrong url: no file specified"); 00331 } 00332 strcpy(identifier, nptr); 00333 } 00334 00335 00336 void apmon_utils::freeMat(char **mat, int nRows) { 00337 int i; 00338 for (i = 0; i < nRows; i++) 00339 free(mat[i]); 00340 free(mat); 00341 } 00342 00343 char *apmon_utils::trimString(char *s) { 00344 unsigned int i, j, firstpos, lastpos; 00345 char *ret = (char *)malloc((strlen(s) + 1) * sizeof(char)); 00346 j = 0; 00347 00348 // find the position of the first non-space character in the string 00349 for (i = 0; i < strlen(s); i++) 00350 if (!isspace(s[i])) 00351 break; 00352 firstpos = i; 00353 00354 if (firstpos == strlen(s)) { 00355 ret[0] = 0; 00356 return ret; 00357 } 00358 00359 // find the position of the last non-space character in the string 00360 for (i = strlen(s) ; i > 0; i--) 00361 if (!isspace(s[i-1])) 00362 break; 00363 lastpos = i; 00364 00365 for (i = firstpos; i <= lastpos; i++) 00366 ret[j++] = s[i]; 00367 00368 ret[j++] = 0; 00369 return ret; 00370 } 00371 00372 int apmon_utils::xdrSize(int type, char *value) { 00373 int size; 00374 00375 switch (type) { 00376 // case XDR_INT16: (not supported) 00377 case XDR_INT32: 00378 case XDR_REAL32: 00379 return 4; 00380 // case XDR_INT64: (not supported) 00381 case XDR_REAL64: 00382 return 8; 00383 case XDR_STRING: 00384 /* XDR adds 4 bytes to hold the length of the string */ 00385 //size = (strlen(value) + 1) + 4; 00386 if (value == NULL) { 00387 logger(WARNING, "[ xdrSize() ] null string argument"); 00388 size = 4; 00389 } else { 00390 size = strlen(value) + 4; 00391 /* the length of the XDR representation must be a multiple of 4, 00392 so there might be some extra bytes added*/ 00393 if (size % 4 != 0) 00394 size += (4 - size % 4); 00395 return size; 00396 } 00397 } 00398 00399 return RET_ERROR; 00400 } 00401 00402 int apmon_utils::sizeEval(int type, char *value) { 00403 00404 switch (type) { 00405 // case XDR_INT16: 00406 case XDR_INT32: 00407 case XDR_REAL32: 00408 return 4; 00409 // case XDR_INT64: 00410 case XDR_REAL64: 00411 return 8; 00412 case XDR_STRING: 00413 return (strlen(value) + 1); 00414 } 00415 00416 return RET_ERROR; 00417 } 00418 00419 00420 00421 void apmon_utils::logParameters(int level, int nParams, char **paramNames, 00422 int *valueTypes, char **paramValues) { 00423 int i; 00424 char typeNames[][15] = {"XDR_STRING", "", "XDR_INT32", "", "XDR_REAL32", 00425 "XDR_REAL64"}; 00426 char logmsg[200], val[100]; 00427 00428 for (i = 0; i < nParams; i++) { 00429 if (paramNames[i] == NULL || (valueTypes[i] == XDR_STRING && 00430 paramValues[i] == NULL)) 00431 continue; 00432 sprintf(logmsg, "%s (%s) ", paramNames[i], typeNames[valueTypes[i]]); 00433 //printf("%s () ", paramNames[i]); 00434 switch(valueTypes[i]) { 00435 case XDR_STRING: 00436 sprintf(val, "%s", paramValues[i]); 00437 break; 00438 case XDR_INT32: 00439 sprintf(val, "%d", *(int *)paramValues[i]); 00440 break; 00441 case XDR_REAL32: 00442 sprintf(val, "%f", *(float *)paramValues[i]); 00443 break; 00444 case XDR_REAL64: 00445 sprintf(val, "%f", *(double *)(paramValues[i])); 00446 break; 00447 } 00448 strcat(logmsg, val); 00449 logger(level, logmsg); 00450 } 00451 } 00452 00453 00454 bool apmon_utils::isPrivateAddress(char *addr) { 00455 char *s1, *s2; 00456 int n1, n2; 00457 char tmp[MAX_STRING_LEN]; 00458 // char buf[MAX_STRING_LEN]; 00459 // char *pbuf = buf; 00460 00461 strcpy(tmp, addr); 00462 s1 = strtok/*_r*/(tmp,".");//, &pbuf); 00463 n1 = atoi(s1); 00464 00465 s2 = strtok/*_r*/(NULL, ".");//, &pbuf); 00466 n2 = atoi(s2); 00467 00468 if (n1 == 10) 00469 return true; 00470 if (n1 == 172 && n2 >= 16 && n2 <= 31) 00471 return true; 00472 if (n1 == 192 && n2 == 168) 00473 return true; 00474 00475 return false; 00476 } 00477 00478 int apmon_utils::getVectIndex(char *item, char **vect, int vectDim) { 00479 int i; 00480 00481 for (i = 0; i < vectDim; i++) 00482 if (strcmp(item, vect[i]) == 0) 00483 return i; 00484 return -1; 00485 } 00486 00487 void apmon_utils::logger(int msgLevel, const char *msg, int newLevel) { 00488 char time_s[30]; 00489 int len; 00490 long crtTime = time(NULL); 00491 char *levels[5] = {(char*)"FATAL", 00492 (char*)"WARNING", 00493 (char*)"INFO", 00494 (char*)"FINE", 00495 (char*)"DEBUG"}; 00496 static int loglevel = INFO; 00497 #ifndef WIN32 00498 static pthread_mutex_t logger_mutex; 00499 #else 00500 static HANDLE logger_mutex; 00501 #endif 00502 static bool firstTime = true; 00503 00504 if (firstTime) { 00505 #ifndef WIN32 00506 pthread_mutex_init(&logger_mutex, NULL); 00507 #else 00508 logger_mutex = CreateMutex(NULL, FALSE, NULL); 00509 #endif 00510 firstTime = false; 00511 } 00512 00513 pthread_mutex_lock(&logger_mutex); 00514 00515 #ifndef WIN32 00516 char cbuf[50]; 00517 strcpy(time_s, ctime_r(&crtTime, cbuf)); 00518 #else 00519 strcpy(time_s, ctime(&crtTime)); 00520 #endif 00521 len = strlen(time_s); time_s[len - 1] = 0; 00522 00523 if (newLevel >= 0 && newLevel <=4) { 00524 loglevel = newLevel; 00525 if (loglevel>=2) 00526 printf("[TIME: %s] Changed the logging level to %s\n", time_s, levels[newLevel]); 00527 } else { 00528 if (msgLevel >= 0 && msgLevel <= 4) { 00529 if (msgLevel <= loglevel) 00530 printf("[TIME: %s] [%s] %s\n",time_s, levels[msgLevel], msg); 00531 } else 00532 printf("[WARNING] Invalid logging level %d!\n", msgLevel); 00533 } 00534 pthread_mutex_unlock(&logger_mutex); 00535 }