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