My Project
OSWSUtil.cpp
Go to the documentation of this file.
1/* $Id$ */
15#include "OSConfig.h"
16
17#ifdef WIN_
18#ifndef _SYS_UNISTD_H
19#define _SYS_UNISTD_H
20#endif
21#include <winsock.h>
22#else
23#include <sys/socket.h>
24#include <arpa/inet.h>
25#include <unistd.h>
26#include <netdb.h>
27#endif
28
29// need to include OSParameters.h after winsock.h, because it may include unistd.h,
30// which needs to know that winsock.h has already been included
31// unfortunately, the windows stuff defines a macro named "max",
32// and maybe also "min"? so undefine these first
33#ifdef min
34#undef min
35#endif
36#ifdef max
37#undef max
38#endif
39
40#include "OSParameters.h"
41#include "OSWSUtil.h"
42#include <cstring>
43#include <iostream>
44#include <sstream>
45#include "OSErrorClass.h"
46#include "OSResult.h"
47#include "OSrLWriter.h"
48#include "OSOutput.h"
49
50using std::string;
51using std::endl;
52using std::ostringstream;
53
54
58
62
63
64
65string WSUtil::sendSOAPMessage(string theSOAP, string serviceIP, unsigned int servicePortNumber)
66{
67 try
68 {
69 /* code taken from "TCP/IP Sockets in C" by Donahoo and Calvert */
70 unsigned long ResolveName(char *name);
71 ostringstream ret_message, outStr;
72 int sock;
73 struct sockaddr_in httpServAddr;
74 unsigned short httpServPort = servicePortNumber;
75 char *servIP = &serviceIP[0];
76 char httpBuffer[RCVBUFSIZE] = "";
77 int httpStringLen;
78 char* message = &theSOAP[0];
79#ifndef NDEBUG
80 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSAgent, ENUM_OUTPUT_LEVEL_trace, "Inside WSUtil::sendSOAPMessage\n");
81#endif
82#ifdef WIN_
83 WSADATA wsaData;
84 if( WSAStartup(MAKEWORD(2, 0), &wsaData) != 0 ) throw ErrorClass( "WSAStartup failed");
85#endif
86 /* Create a reliable, stream socket using TCP */
87 if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) throw ErrorClass( "failure creating socket");
88 /* Construct the server address structure */
89 memset(&httpServAddr, 0, sizeof(httpServAddr)); /* Zero out structure */
90 httpServAddr.sin_family = AF_INET; /* Internet address family */
91 httpServAddr.sin_addr.s_addr = ResolveName( servIP); /* Server IP address */
92 httpServAddr.sin_port = htons(httpServPort); /* Server port */
93 /* Establish the connection to the http server */
94 if (connect(sock, (struct sockaddr *) &httpServAddr, sizeof(httpServAddr)) < 0)
95 {
96 string sipadd = &serviceIP[0];
97 string errormsg = "failure connecting with remote socket at address: " + sipadd ;
98 throw ErrorClass( errormsg );
99 }
100#ifndef NDEBUG
101 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSAgent, ENUM_OUTPUT_LEVEL_detailed_trace, "Connection Established\n");
102#endif
103 httpStringLen = strlen( message);
104#ifndef NDEBUG
105 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSAgent, ENUM_OUTPUT_LEVEL_detailed_trace, "HERE IS WHAT WE SEND\n");
107#endif
108 /* Send the string to the server */
109 if (send(sock, message, httpStringLen, 0) != httpStringLen)
110 throw ErrorClass("send() sent a different number of bytes than expected");
111#ifndef NDEBUG
112 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSAgent, ENUM_OUTPUT_LEVEL_detailed_trace, "OSiL sent to server\n");
113#endif
114 int recvMsgSize = 1;
115 int n;
116#ifndef NDEBUG
117 int char_val;
118#endif
119 httpBuffer[ RCVBUFSIZE - 1] = '\0';
120 while (recvMsgSize > 0)
121 {
122#ifndef NDEBUG
124#endif
125 if ((recvMsgSize = recv(sock, httpBuffer, RCVBUFSIZE-1, 0)) < 0)
126 throw ErrorClass( "socket error receiving data");
127#ifndef NDEBUG
128 outStr.str("");
129 outStr.clear();
130 outStr << "Message size = " << recvMsgSize << endl;
131 outStr << httpBuffer << endl;
133#endif
134 ret_message << httpBuffer;
135 // clear the buffer
136 for(n = 0; n < RCVBUFSIZE; n++)
137 {
138 httpBuffer[ n] = 0;
139 }
140 }
141#ifdef WIN_
142 closesocket( sock);
143 WSACleanup();
144#else
145 close( sock);
146#endif
147 return ret_message.str();
148 }
149 catch(const ErrorClass& eclass)
150 {
151 throw ErrorClass( eclass.errormsg);
152 }
153}
154
155std::string WSUtil::createSOAPMessage(int numInputs, string solverAddress, string postURI, string smethod,
156 string* msInputs, string* msInputNames, string sSoapAction)
157{
158 ostringstream request, body, outStr;
159 int i;
160 string mynamespace = "xmlns:ns1=\"http://www.optimizationservices.org\"";
161#ifndef NDEBUG
162 outStr.str("");
163 outStr.clear();
164 outStr << "Solver address = " << solverAddress << endl;
165 outStr << "SOAP action = " << sSoapAction << endl;
166 outStr << "postURI = " << postURI << endl;
168#endif
169 request << "POST " << postURI << " HTTP/1.0" << endl ;
170 request << "Content-Type: text/xml; charset=UTF-8" << endl;
171 request << "Host: " ;
172 request << solverAddress << endl;
173 request << "Connection: close" << endl;
174 request << "Accept: application/soap+xml, application/dime, multipart/related, text/*" << endl;
175 request << "Cache-Control: no-cache" << endl;
176 request << "Pragma: no-cache" << endl;
177 request << "SOAPAction: ";
178 request << "\"" << sSoapAction << "\"" << endl;
179 //body << "<?xml version='1.0' encoding='utf-8' ?>" << endl;
180 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;
181 body << "<SOAP-ENV:Body>" << endl;
182 body << "<ns1:" << smethod << " " << mynamespace << ">" << endl;
183 for(i = 0; i < numInputs; i++)
184 {
185 body << "<" << msInputNames[ i] << " xsi:type=\"xsd:string\"" << ">" ;
186 body << msInputs[ i] ;
187 body << "</" << msInputNames[ i] << ">" << endl;
188 }
189 body << "</ns1:" << smethod << ">" << endl;
190 body << "</SOAP-ENV:Body>" << endl;
191 body << "</SOAP-ENV:Envelope>" << endl;
192 body << "\n";
193 request << "Content-Length: " << body.str().length();
194 request << endl << endl;
195
196 request << body.str();
197 return request.str();
198}// end createSOAPMessage
199
200std::string WSUtil::createFormDataUpload(std::string solverAddress, std::string postURI,
201 std::string fileName, std::string theFile, std::string boundaryName)
202{
203 ostringstream request, body, outStr;
204#ifndef NDEBUG
205 outStr.str("");
206 outStr.clear();
207 outStr << "Solver address = " << solverAddress << endl;
208 outStr << "postURI = " << postURI << endl;
210#endif
211 request << "POST " << postURI << " HTTP/1.0" << "\r\n";
212 request << "Host: " ;
213 request << solverAddress << "\r\n";
214 request << "Content-Type: multipart/form-data; boundary=" ;
215 request << boundaryName << "\r\n";
216 request << "Connection: keep-alive" << "\r\n";
217 //request << "Referer: /servlets-examples/fileupload.html" << endl;
218 body << "--" ;
219 body << boundaryName ;
220 body << "\r\n";
221 body << "Content-Disposition: form-data; name=\"";
222 body << "myfile";
223 body << "\"";
224 body << ";";
225 body << " filename=\"";
226 body << fileName;
227 body << "\"" << "\r\n";
228
229 body << "Content-Type: text/plain" ;
230 body << "\r\n" ;
231 body << "\r\n";
232 body << theFile ;
233 body << "\r\n";
234 body << "--" ;
235 body << boundaryName;
236 body << "--" ;
237 body << "\r\n" ;
238
239 request << "Content-Length: " << body.str().length();
240 request << "\r\n";
241 request << "\r\n";
242 request << body.str();
243 return request.str();
244}// end createFromDataUpload
245
246
247string WSUtil::SOAPify(std::string inputstring, bool useCDATA)
248{
253#ifndef NDEBUG
254 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSAgent, ENUM_OUTPUT_LEVEL_detailed_trace, "prepare the XML for a SOAP envelope\n");
255#endif
256 ostringstream body;
257 int i = 0;
258 int loopsize = inputstring.length();
259 if(useCDATA == true)
260 {
261 body << "<![CDATA[";
262 body << inputstring;
263 body << "]]>";
264 }
265 else
266 {
267 while (i < loopsize)
268 {
269 switch( inputstring[i])
270 {
271 case '<':
272 body << "&lt;";
273 break;
274 case '>':
275 body << "&gt;";
276 break;
277 case '\"':
278 body << "&quot;";
279 break;
280 case '\'':
281 body << "&quot;";
282 break;
283 default:
284 body << inputstring[i];
285 }
286 i++;
287 }//end while
288 }
289 return body.str();
290}
291
292string WSUtil::deSOAPify(std::string inputstring, bool useCDATA)
293{
298 ostringstream body;
299 int i = 0;
300 int loopsize = inputstring.length();
301 if(useCDATA == true)
302 {
303 string::size_type pos1 = inputstring.find( "<![CDATA[" );
304 string::size_type pos2 = inputstring.find( "]]>" );
305 body << inputstring.substr( pos1 + 1, pos2 - pos1 - 1);
306
307 //kipp -- put in error checking
308
309 }
310 else
311 {
312 while (i < loopsize)
313 {
314 if(inputstring[i] == '&')
315 {
316 switch (inputstring[i+1])
317 {
318 case 'l':
319 if (inputstring[i + 2] == 't' && inputstring[i + 3] == ';')
320 {
321 body << "<";
322 }
323 i = i + 4;
324 break;
325 case 'g':
326 if (inputstring[i + 2] == 't' && inputstring[i + 3] == ';')
327 {
328 body << ">";
329 }
330 i = i + 4;
331 break;
332 case 'q':
333 if (inputstring[i + 2] == 'u' && inputstring[i + 3] == 'o' && inputstring[i + 4] == 't' && inputstring[i + 5] == ';')
334 {
335 body << "\"";
336 }
337 i = i + 6;
338 break;
339 default:
340 body << inputstring[i];
341 i++;
342 break;
343 } //end switch
344 } // end if'&"
345 else
346 {
347 body << inputstring[i];
348 i++;
349 }
350 }// end while
351 }
352 return body.str();
353}
354
355unsigned long ResolveName(char *name)
356{
357 struct hostent *host;
358 try
359 {
360 if ((host = gethostbyname(name)) == NULL)
361 {
362 string s1 = &name[0];
363 string errormsg = "cannot resolve the domain name: " + s1;
364 throw ErrorClass( errormsg);
365 }
366 return *((unsigned long *) host->h_addr_list[0]);
367 }
368 catch(const ErrorClass& eclass)
369 {
370 throw eclass;
371 }
372}
373
374string WSUtil::getOSxL(string soapstring, string serviceMethod)
375{
379 string result = "";
380 // strip off the return header information
381 // find start of XML information
382 string::size_type startxml = soapstring.find(serviceMethod+"Return" , 1);
383 string::size_type pos;
384 if (startxml == string::npos)
385 {
386 //something went wrong, perhaps we had an error in service location
387
388 OSResult *osresult = NULL;
389 OSrLWriter *osrlwriter = NULL;
390 osrlwriter = new OSrLWriter();
391 osresult = new OSResult();
392 // see if the SOAP contains <faultstring> -- if so use it
393 startxml = soapstring.find("<faultstring>" , 1);
394 if(startxml == string::npos)
395 {
396 osresult->setGeneralMessage( "we had a problem contacting the server which we cannot figure out -- check address of server");
397 }
398 else
399 {
400 pos = soapstring.find("</faultstring>" , startxml + 1);
401 std::string tmpString = soapstring.substr(startxml + 13 , pos - startxml - 13);
402 osresult->setGeneralMessage( "There was a communication problem with server, SOAP error message: " + tmpString);
403 }
404
406 result = osrlwriter->writeOSrL( osresult);
407 delete osresult;
408 osresult = NULL;
409 delete osrlwriter;
410 osrlwriter = NULL;
411 //
412 return result;
413 }
414 else
415 {
416 startxml = soapstring.find(">", startxml + 1);
417 if(startxml == string::npos) return result;
418 // find the end of the string
419 string::size_type endxml = soapstring.find( "</", startxml);
420 // now go back for the </
421
422 if(endxml == string::npos)
423 {
424 return result;
425 }
426 else
427 {
428 // now get the substring
429 startxml++;
430 result = soapstring.substr(startxml, endxml - startxml);
431 return result;
432 }
433 }
434 return result;
435}
void send(OSCommandLine *oscommandline, OSnl2OS *osnl2os)
const OSSmartPtr< OSOutput > osoutput
Definition OSOutput.cpp:39
unsigned long ResolveName(char *name)
Definition OSWSUtil.cpp:355
#define RCVBUFSIZE
Definition OSWSUtil.h:25
used for throwing exceptions.
std::string errormsg
errormsg is the error that is causing the exception to be thrown
The Result Class.
Definition OSResult.h:2549
bool setGeneralMessage(std::string message)
Set the general message.
bool setGeneralStatusType(std::string type)
Set the general status type, which can be: success, error, warning.
Take an OSResult object and write a string that validates against OSrL.
Definition OSrLWriter.h:31
std::string writeOSrL(OSResult *theosresult)
create an osrl string from an OSResult object
static std::string deSOAPify(std::string theXmlString, bool useCDATA)
take the XML from a SOAP envelop and replace < with < replace > with > replace &quot with ";
Definition OSWSUtil.cpp:292
static std::string createSOAPMessage(int numInputs, std::string solverAddress, std::string postURI, std::string smethod, std::string *msInputs, std::string *msInputNames, std::string sSoapAction)
create the SOAP message that is send to the solver Web Service
Definition OSWSUtil.cpp:155
static std::string createFormDataUpload(std::string solverAddress, std::string postURI, std::string fileName, std::string theFile, std::string boundaryName)
create the SOAP message that is sent to the solver Web Service
Definition OSWSUtil.cpp:200
static std::string sendSOAPMessage(std::string theSOAP, std::string serviceIP, unsigned int servicePortNumber)
open a socket and send a SOAP message to the solver Web Service
Definition OSWSUtil.cpp:65
static std::string getOSxL(std::string soapstring, std::string serviceMethod)
extract the appropriate OSxL protocol from the SOAP envelop
Definition OSWSUtil.cpp:374
WSUtil()
Default constructor.
Definition OSWSUtil.cpp:55
static std::string SOAPify(std::string theXmlString, bool useCDATA)
prepare XML to be put into a SOAP envelop, replace < with < replace > with > replace " and ' with &quote;
Definition OSWSUtil.cpp:247
~WSUtil()
Class destructor.
Definition OSWSUtil.cpp:59
@ ENUM_OUTPUT_LEVEL_detailed_trace
@ ENUM_OUTPUT_LEVEL_trace
@ ENUM_OUTPUT_AREA_OSAgent
OSResult * osresult