00001
00016 #include "OSConfig.h"
00017
00018 #ifdef WIN_
00019 #ifndef _SYS_UNISTD_H
00020 #define _SYS_UNISTD_H
00021 #endif
00022 #include <winsock.h>
00023 #else
00024 #include <sys/socket.h>
00025 #include <arpa/inet.h>
00026 #include <unistd.h>
00027 #include <netdb.h>
00028 #endif
00029
00030
00031
00032 #ifdef min
00033 #undef min
00034 #endif
00035 #ifdef max
00036 #undef max
00037 #endif
00038
00039 #include "OSParameters.h"
00040 #include "OSWSUtil.h"
00041 #include <cstring>
00042 #include <iostream>
00043 #include <sstream>
00044 #include "OSErrorClass.h"
00045 #include "OSResult.h"
00046 #include "OSrLWriter.h"
00047 #include "OSOutput.h"
00048
00049 using std::string;
00050 using std::endl;
00051 using std::ostringstream;
00052
00053
00054 WSUtil::WSUtil()
00055 {
00056 }
00057
00058 WSUtil::~WSUtil()
00059 {
00060 }
00061
00062
00063
00064 string WSUtil::sendSOAPMessage(string theSOAP, string serviceIP, unsigned int servicePortNumber)
00065 {
00066 try
00067 {
00068
00069 unsigned long ResolveName(char *name);
00070 ostringstream ret_message, outStr;
00071 int sock;
00072 struct sockaddr_in httpServAddr;
00073 unsigned short httpServPort = servicePortNumber;
00074 char *servIP = &serviceIP[0];
00075 char httpBuffer[RCVBUFSIZE] = "";
00076 int httpStringLen;
00077 char* message = &theSOAP[0];
00078 #ifndef NDEBUG
00079 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSAgent, ENUM_OUTPUT_LEVEL_trace, "Inside WSUtil::sendSOAPMessage\n");
00080 #endif
00081 #ifdef WIN_
00082 WSADATA wsaData;
00083 if( WSAStartup(MAKEWORD(2, 0), &wsaData) != 0 ) throw ErrorClass( "WSAStartup failed");
00084 #endif
00085
00086 if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) throw ErrorClass( "failure creating socket");
00087
00088 memset(&httpServAddr, 0, sizeof(httpServAddr));
00089 httpServAddr.sin_family = AF_INET;
00090 httpServAddr.sin_addr.s_addr = ResolveName( servIP);
00091 httpServAddr.sin_port = htons(httpServPort);
00092
00093 if (connect(sock, (struct sockaddr *) &httpServAddr, sizeof(httpServAddr)) < 0)
00094 {
00095 string sipadd = &serviceIP[0];
00096 string errormsg = "failure connecting with remote socket at address: " + sipadd ;
00097 throw ErrorClass( errormsg );
00098 }
00099 #ifndef NDEBUG
00100 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSAgent, ENUM_OUTPUT_LEVEL_detailed_trace, "Connection Established\n");
00101 #endif
00102 httpStringLen = strlen( message);
00103 #ifndef NDEBUG
00104 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSAgent, ENUM_OUTPUT_LEVEL_detailed_trace, "HERE IS WHAT WE SEND\n");
00105 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSAgent, ENUM_OUTPUT_LEVEL_detailed_trace, message);
00106 #endif
00107
00108 if (send(sock, message, httpStringLen, 0) != httpStringLen)
00109 throw ErrorClass("send() sent a different number of bytes than expected");
00110 #ifndef NDEBUG
00111 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSAgent, ENUM_OUTPUT_LEVEL_detailed_trace, "OSiL sent to server\n");
00112 #endif
00113 int recvMsgSize = 1;
00114 int n;
00115 #ifndef NDEBUG
00116 int char_val;
00117 #endif
00118 httpBuffer[ RCVBUFSIZE - 1] = '\0';
00119 while (recvMsgSize > 0)
00120 {
00121 #ifndef NDEBUG
00122 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSAgent, ENUM_OUTPUT_LEVEL_detailed_trace, "start to receive\n");
00123 #endif
00124 if ((recvMsgSize = recv(sock, httpBuffer, RCVBUFSIZE-1, 0)) < 0)
00125 throw ErrorClass( "socket error receiving data");
00126 #ifndef NDEBUG
00127 outStr.str("");
00128 outStr.clear();
00129 outStr << "Message size = " << recvMsgSize << endl;
00130 outStr << httpBuffer << endl;
00131 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSAgent, ENUM_OUTPUT_LEVEL_trace, outStr.str());
00132
00133
00134
00135
00136
00137
00138
00139
00140 #endif
00141 ret_message << httpBuffer;
00142
00143 for(n = 0; n < RCVBUFSIZE; n++)
00144 {
00145 httpBuffer[ n] = 0;
00146 }
00147 }
00148 #ifdef WIN_
00149 closesocket( sock);
00150 WSACleanup();
00151 #else
00152 close( sock);
00153 #endif
00154 return ret_message.str();
00155 }
00156 catch(const ErrorClass& eclass)
00157 {
00158 throw ErrorClass( eclass.errormsg);
00159 }
00160 }
00161
00162 std::string WSUtil::createSOAPMessage(int numInputs, string solverAddress, string postURI, string smethod,
00163 string* msInputs, string* msInputNames, string sSoapAction)
00164 {
00165 ostringstream request, body, outStr;
00166 int i;
00167 string mynamespace = "xmlns:ns1=\"http://www.optimizationservices.org\"";
00168 #ifndef NDEBUG
00169 outStr.str("");
00170 outStr.clear();
00171 outStr << "Solver address = " << solverAddress << endl;
00172 outStr << "SOAP action = " << sSoapAction << endl;
00173 outStr << "postURI = " << postURI << endl;
00174 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSAgent, ENUM_OUTPUT_LEVEL_detailed_trace, outStr.str());
00175 #endif
00176 request << "POST " << postURI << " HTTP/1.0" << endl ;
00177 request << "Content-Type: text/xml; charset=UTF-8" << endl;
00178 request << "Host: " ;
00179 request << solverAddress << endl;
00180 request << "Connection: close" << endl;
00181 request << "Accept: application/soap+xml, application/dime, multipart/related, text/*" << endl;
00182 request << "Cache-Control: no-cache" << endl;
00183 request << "Pragma: no-cache" << endl;
00184 request << "SOAPAction: ";
00185 request << "\"" << sSoapAction << "\"" << endl;
00186
00187 body << "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" << endl;
00188 body << "<SOAP-ENV:Body>" << endl;
00189 body << "<ns1:" << smethod << " " << mynamespace << ">" << endl;
00190 for(i = 0; i < numInputs; i++)
00191 {
00192 body << "<" << msInputNames[ i] << " xsi:type=\"xsd:string\"" << ">" ;
00193 body << msInputs[ i] ;
00194 body << "</" << msInputNames[ i] << ">" << endl;
00195 }
00196 body << "</ns1:" << smethod << ">" << endl;
00197 body << "</SOAP-ENV:Body>" << endl;
00198 body << "</SOAP-ENV:Envelope>" << endl;
00199 body << "\n";
00200 request << "Content-Length: " << body.str().length();
00201 request << endl << endl;
00202
00203 request << body.str();
00204 return request.str();
00205 }
00206
00207 std::string WSUtil::createFormDataUpload(std::string solverAddress, std::string postURI,
00208 std::string fileName, std::string theFile, std::string boundaryName)
00209 {
00210 ostringstream request, body, outStr;
00211 #ifndef NDEBUG
00212 outStr.str("");
00213 outStr.clear();
00214 outStr << "Solver address = " << solverAddress << endl;
00215 outStr << "postURI = " << postURI << endl;
00216 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSAgent, ENUM_OUTPUT_LEVEL_detailed_trace, outStr.str());
00217 #endif
00218 request << "POST " << postURI << " HTTP/1.0" << "\r\n";
00219 request << "Host: " ;
00220 request << solverAddress << "\r\n";
00221 request << "Content-Type: multipart/form-data; boundary=" ;
00222 request << boundaryName << "\r\n";
00223 request << "Connection: keep-alive" << "\r\n";
00224
00225 body << "--" ;
00226 body << boundaryName ;
00227 body << "\r\n";
00228 body << "Content-Disposition: form-data; name=\"";
00229 body << "myfile";
00230 body << "\"";
00231 body << ";";
00232 body << " filename=\"";
00233 body << fileName;
00234 body << "\"" << "\r\n";
00235
00236 body << "Content-Type: text/plain" ;
00237 body << "\r\n" ;
00238 body << "\r\n";
00239 body << theFile ;
00240 body << "\r\n";
00241 body << "--" ;
00242 body << boundaryName;
00243 body << "--" ;
00244 body << "\r\n" ;
00245
00246 request << "Content-Length: " << body.str().length();
00247 request << "\r\n";
00248 request << "\r\n";
00249 request << body.str();
00250 return request.str();
00251 }
00252
00253
00254 string WSUtil::SOAPify(std::string inputstring, bool useCDATA)
00255 {
00256
00257
00258
00259 #ifndef NDEBUG
00260 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSAgent, ENUM_OUTPUT_LEVEL_detailed_trace, "prepare the XML for a SOAP envelope\n");
00261 #endif
00262 ostringstream body;
00263 int i = 0;
00264 int loopsize = inputstring.length();
00265 if(useCDATA == true)
00266 {
00267 body << "<![CDATA[";
00268 body << inputstring;
00269 body << "]]>";
00270 }
00271 else
00272 {
00273 while (i < loopsize)
00274 {
00275 switch( inputstring[i])
00276 {
00277 case '<':
00278 body << "<";
00279 break;
00280 case '>':
00281 body << ">";
00282 break;
00283 case '\"':
00284 body << """;
00285 break;
00286 case '\'':
00287 body << """;
00288 break;
00289 default:
00290 body << inputstring[i];
00291 }
00292 i++;
00293 }
00294 }
00295 return body.str();
00296 }
00297
00298 string WSUtil::deSOAPify(std::string inputstring, bool useCDATA)
00299 {
00304 ostringstream body;
00305 int i = 0;
00306 int loopsize = inputstring.length();
00307 if(useCDATA == true)
00308 {
00309 string::size_type pos1 = inputstring.find( "<![CDATA[" );
00310 string::size_type pos2 = inputstring.find( "]]>" );
00311 body << inputstring.substr( pos1 + 1, pos2 - pos1 - 1);
00312
00313
00314
00315 }
00316 else
00317 {
00318 while (i < loopsize)
00319 {
00320 if(inputstring[i] == '&')
00321 {
00322 switch (inputstring[i+1])
00323 {
00324 case 'l':
00325 if (inputstring[i + 2] == 't' && inputstring[i + 3] == ';')
00326 {
00327 body << "<";
00328 }
00329 i = i + 4;
00330 break;
00331 case 'g':
00332 if (inputstring[i + 2] == 't' && inputstring[i + 3] == ';')
00333 {
00334 body << ">";
00335 }
00336 i = i + 4;
00337 break;
00338 case 'q':
00339 if (inputstring[i + 2] == 'u' && inputstring[i + 3] == 'o' && inputstring[i + 4] == 't' && inputstring[i + 5] == ';')
00340 {
00341 body << "\"";
00342 }
00343 i = i + 6;
00344 break;
00345 default:
00346 body << inputstring[i];
00347 i++;
00348 break;
00349 }
00350 }
00351 else
00352 {
00353 body << inputstring[i];
00354 i++;
00355 }
00356 }
00357 }
00358 return body.str();
00359 }
00360
00361 unsigned long ResolveName(char *name)
00362 {
00363 struct hostent *host;
00364 try
00365 {
00366 if ((host = gethostbyname(name)) == NULL)
00367 {
00368 string s1 = &name[0];
00369 string errormsg = "cannot resolve the domain name: " + s1;
00370 throw ErrorClass( errormsg);
00371 }
00372 return *((unsigned long *) host->h_addr_list[0]);
00373 }
00374 catch(const ErrorClass& eclass)
00375 {
00376 throw eclass;
00377 }
00378 }
00379
00380 string WSUtil::getOSxL(string soapstring, string serviceMethod)
00381 {
00382
00383
00384
00385 string result = "";
00386
00387
00388 string::size_type startxml = soapstring.find(serviceMethod+"Return" , 1);
00389 string::size_type pos;
00390 if (startxml == string::npos)
00391 {
00392
00393
00394 OSResult *osresult = NULL;
00395 OSrLWriter *osrlwriter = NULL;
00396 osrlwriter = new OSrLWriter();
00397 osresult = new OSResult();
00398
00399 startxml = soapstring.find("<faultstring>" , 1);
00400 if(startxml == string::npos)
00401 {
00402 osresult->setGeneralMessage( "we had a problem contacting the server which we cannot figure out -- check address of server");
00403 }
00404 else
00405 {
00406 pos = soapstring.find("</faultstring>" , startxml + 1);
00407 std::string tmpString = soapstring.substr(startxml + 13 , pos - startxml - 13);
00408 osresult->setGeneralMessage( "There was a communication problem with server, SOAP error message: " + tmpString);
00409 }
00410
00411 osresult->setGeneralStatusType( "error");
00412 result = osrlwriter->writeOSrL( osresult);
00413 delete osresult;
00414 osresult = NULL;
00415 delete osrlwriter;
00416 osrlwriter = NULL;
00417
00418 return result;
00419 }
00420 else
00421 {
00422 startxml = soapstring.find(">", startxml + 1);
00423 if(startxml == string::npos) return result;
00424
00425 string::size_type endxml = soapstring.find( "</", startxml);
00426
00427
00428 if(endxml == string::npos)
00429 {
00430 return result;
00431 }
00432 else
00433 {
00434
00435 startxml++;
00436 result = soapstring.substr(startxml, endxml - startxml);
00437 return result;
00438 }
00439 }
00440 return result;
00441 }