OSWSUtil.cpp
Go to the documentation of this file.
1 /* $Id: OSWSUtil.cpp 5284 2017-12-08 13:52:50Z stefan $ */
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 
50 using std::string;
51 using std::endl;
52 using std::ostringstream;
53 
54 
56 {
57 }
58 
60 {
61 }
62 
63 
64 
65 string 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
123  osoutput->OSPrint(ENUM_OUTPUT_AREA_OSAgent, ENUM_OUTPUT_LEVEL_detailed_trace, "start to receive\n");
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 
155 std::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 
200 std::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 
247 string 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 
292 string 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 
355 unsigned 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 
374 string 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 
405  osresult->setGeneralStatusType( "error");
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 }
unsigned long ResolveName(char *name)
Definition: OSWSUtil.cpp:355
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
void send(OSCommandLine *oscommandline, OSnl2OS *osnl2os)
const OSSmartPtr< OSOutput > osoutput
Definition: OSOutput.cpp:39
pos
position where the operator should be printed when printing the expression
static std::string getOSxL(std::string soapstring, std::string serviceMethod)
extract the appropriate OSxL protocol from the SOAP envelop
Definition: OSWSUtil.cpp:374
std::string errormsg
errormsg is the error that is causing the exception to be thrown
Definition: OSErrorClass.h:42
The Result Class.
Definition: OSResult.h:2548
Take an OSResult object and write a string that validates against OSrL.
Definition: OSrLWriter.h:30
#define RCVBUFSIZE
Definition: OSWSUtil.h:25
std::string writeOSrL(OSResult *theosresult)
create an osrl string from an OSResult object
Definition: OSrLWriter.cpp:45
CONST unsigned char * s1
Definition: OSdtoa.cpp:1814
WSUtil()
Default constructor.
Definition: OSWSUtil.cpp:55
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
OSResult * osresult
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.
static std::string deSOAPify(std::string theXmlString, bool useCDATA)
take the XML from a SOAP envelop and replace &lt; with &lt; replace &gt; with &gt; replace &amp;quot with "; ...
Definition: OSWSUtil.cpp:292
~WSUtil()
Class destructor.
Definition: OSWSUtil.cpp:59
static std::string SOAPify(std::string theXmlString, bool useCDATA)
prepare XML to be put into a SOAP envelop, replace &lt; with &lt; replace &gt; with &gt; replace " and &#39; with ...
Definition: OSWSUtil.cpp:247
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
used for throwing exceptions.
Definition: OSErrorClass.h:31
void fint * n