Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

SBCGI.cpp

Go to the documentation of this file.
00001 
00005 /* --------------------------------------------------------------
00006 Copyright (C) 2001 LifeLine Networks BV <soap2corba@lifeline.nl>
00007 
00008 This program is free software; you can redistribute it and/or
00009 modify it under the terms of the GNU General Public License
00010 as published by the Free Software Foundation; either
00011 version 2 of the License, or (at your option) any later
00012 version.
00013 
00014 This program is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 GNU General Public License for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with this program; if not, write to the Free Software
00021 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00022 -------------------------------------------------------------- */
00023 
00024 #include "OB/CORBA.h"
00025 #include "OB/CosNaming.h"
00026 #include "SoapBridge.h"
00027 
00028 #ifndef __WIN32__
00029 #define stricmp strcasecmp
00030 #endif
00031 
00032 void Fault (const char *msg)
00033 {
00034     puts ("Content-type: text/xml");
00035     puts ("");
00036     puts ("<SOAP-ENV:Envelope ");
00037     puts ("xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\" ");
00038     puts ("xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\" ");
00039     puts ("xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" ");
00040     puts ("SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">");
00041     puts ("<SOAP-ENV:Body>");
00042     puts ("<SOAP-ENV:Fault><faultcode>");
00043     puts ("Server.SoapBridgeCgiFailed");
00044     puts ("</faultcode><faultstring>");
00045     puts (msg);
00046     puts ("</faultstring>");
00047     puts ("</SOAP-ENV:Fault>");
00048     puts ("</SOAP-ENV:Body>");
00049     puts ("</SOAP-ENV:Envelope>\n");
00050     exit (1);
00051 }
00052 
00053 int main (int argc, char *argv[])
00054 {
00055     char *soapHeaderAct = getenv ("HTTP_SOAPACTION");
00056     char *contentLength = getenv ("CONTENT_LENGTH");
00057     int cntLen = 0;
00058     if (contentLength) {
00059         cntLen = atoi (contentLength);
00060     }
00061     if (!cntLen) {
00062         Fault ("No content length found in HTTP header");
00063     }
00064     if (cntLen < 0 || cntLen > 256000) {
00065         Fault ("Content length in HTTP header is out of bounds");
00066     }
00067     // it seems an reasonable enough request to warrant
00068     // reading our configuration and initializing the ORB
00069 
00070     int myArgc = 1;
00071     char *myArgv[20];
00072     myArgv[0] = strdup (argv[0]);
00073     CORBA::String_var sbIOR;
00074     bool haveSbIOR = false;
00075     CORBA::String_var objIOR;
00076     bool haveObjIOR = false;
00077     CORBA::String_var soapAct;
00078     bool haveSoapAct = false;
00079     FILE *f = fopen ("sbcgi.cfg", "rt");
00080     if (f) {
00081         char st[200];
00082         while (fgets (st, 195, f)) {
00083             char toks[300];
00084             strcpy (toks, st);
00085             char *p1 = strtok (toks, " \n");
00086             if (!stricmp (p1, "SoapBridgeIOR")) {
00087                 char *p2 = strtok (NULL, " \n");
00088                 if (!p2) {
00089                     Fault ("No argument for SoapBridgeIOR in sbcgi.cfg");
00090                 } else {
00091                     haveSbIOR = true;
00092                     sbIOR = CORBA::string_dup (p2);
00093                 }
00094             } else if (!stricmp (p1, "ObjectIOR")) {
00095                 char *p2 = strtok (NULL, " \n");
00096                 if (!p2) {
00097                     Fault ("No argument for ObjectIOR in sbcgi.cfg");
00098                 } else {
00099                     haveObjIOR = true;
00100                     objIOR = CORBA::string_dup (p2);
00101                 }
00102             } else if (!stricmp (p1, "OverrideSoapAction")) {
00103                 char *p2 = strtok (NULL, " \n");
00104                 if (!p2) {
00105                     Fault ("No argument for OverrideSoapAction in sbcgi.cfg");
00106                 } else {
00107                     haveSoapAct = true;
00108                     soapAct = CORBA::string_dup (p2);
00109                     if (soapHeaderAct && strcmp (soapAct, soapHeaderAct)) {
00110                         Fault ("SOAP Action supplied in SOAP request does not match with sbcgi.cfg:OverrideSoapAction");
00111                     }
00112                 }
00113             } else {
00114                 if (myArgc == 20) {
00115                     sprintf (toks, "Too many args at '%s' in sbcgi.cfg", st);
00116                     Fault (toks);
00117                 } else {
00118                     myArgv[myArgc++] = strdup (strtok (st, "\n"));
00119                 }
00120             }
00121         }
00122         fclose (f);
00123     }
00124     if (!haveSoapAct) {
00125         if (soapHeaderAct) {
00126             soapAct = CORBA::string_dup (soapHeaderAct);
00127         } else {
00128             soapAct = CORBA::string_dup ("No_SOAPACTION_in_HTTP_header");
00129         }
00130     }
00131     CORBA::ORB_var orb = CORBA::ORB_init (myArgc, myArgv);
00132 
00133     // Orb is initialized, lets grab the actual request from stdin
00134     CORBA::Octet * pBuf = SOAPBridge::SOAPCall::XMLData::allocbuf (cntLen);
00135     memset (pBuf, 0, cntLen);
00136     // Under a sensible OS we could require that the number of bytes
00137     // read equals the specified content length. Unfortunately, due
00138     // to CRLF to LF mappings, this could differ so we ignore the
00139     // return value of fread().
00140     fread (pBuf, cntLen, 1, stdin);
00141 
00142     SOAPBridge::SOAPCall_var spCall;
00143     if (haveSbIOR) {
00144         try {
00145             CORBA::Object_var obj;
00146             obj = orb->string_to_object (sbIOR);
00147             spCall = SOAPBridge::SOAPCall::_narrow (obj);
00148         }
00149         catch (...) {
00150             // Recover from any failures by requerying the NameService
00151             haveSbIOR = false;
00152         }
00153     }
00154     bool doneLookup = false;
00155     if (!haveSbIOR) {
00156         try {
00157             CORBA::Object_var obj;
00158             obj = orb->resolve_initial_references ("NameService");
00159             CosNaming::NamingContext_var inc;
00160             inc = CosNaming::NamingContext::_narrow (obj);
00161             CosNaming::Name name;
00162             name.length (2);
00163             name[0].id = CORBA::string_dup ("SOAPBridge");
00164             name[1].id = CORBA::string_dup ("SOAPCall");
00165             obj = inc->resolve (name);
00166             if (CORBA::is_nil (obj)) {
00167                 Fault ("Could not contact SoapBridge");
00168             }
00169             spCall = SOAPBridge::SOAPCall::_narrow (obj);
00170             doneLookup = true;
00171         }
00172         catch (...) {
00173             Fault ("Could not contact NameService");
00174         }
00175     }
00176     SOAPBridge::SOAPCall::XMLData * pXmlOut = NULL;
00177     if (!haveObjIOR) {
00178         try {
00179             SOAPBridge::SOAPCall::XMLData spReq (cntLen, cntLen, pBuf, 0);
00180             pXmlOut = spCall->invokeAction (soapAct, spReq);
00181         }
00182         catch (...) {
00183         }
00184     } else {
00185         try {
00186             SOAPBridge::SOAPCall::XMLData * pXmlOut;
00187             SOAPBridge::SOAPCall::XMLData spReq (cntLen, cntLen, pBuf, 0);
00188             CORBA::Object_var obj;
00189             obj = orb->string_to_object (objIOR);
00190             pXmlOut = spCall->invokeInstance (obj, soapAct, spReq);
00191         }
00192         catch (...) {
00193         }
00194     }
00195     if (!pXmlOut && !doneLookup) {
00196         // Last resort, attempt to lookup the SOAPCall IOR in case the bridge was restarted
00197         try {
00198             CORBA::Object_var obj;
00199             obj = orb->resolve_initial_references ("NameService");
00200             CosNaming::NamingContext_var inc;
00201             inc = CosNaming::NamingContext::_narrow (obj);
00202             CosNaming::Name name;
00203             name.length (2);
00204             name[0].id = CORBA::string_dup ("SOAPBridge");
00205             name[1].id = CORBA::string_dup ("SOAPCall");
00206             obj = inc->resolve (name);
00207             if (CORBA::is_nil (obj)) {
00208                 Fault ("Could not contact SoapBridge");
00209             }
00210             spCall = SOAPBridge::SOAPCall::_narrow (obj);
00211             doneLookup = true;
00212         }
00213         catch (...) {
00214             Fault ("Could not contact NameService either after first SOAPCall already failed.");
00215         }
00216         if (!haveObjIOR) {
00217             try {
00218                 SOAPBridge::SOAPCall::XMLData spReq (cntLen, cntLen, pBuf, 0);
00219                 pXmlOut = spCall->invokeAction (soapAct, spReq);
00220             }
00221             catch (...) {
00222             }
00223         } else {
00224             try {
00225                 SOAPBridge::SOAPCall::XMLData * pXmlOut;
00226                 SOAPBridge::SOAPCall::XMLData spReq (cntLen, cntLen, pBuf, 0);
00227                 CORBA::Object_var obj;
00228                 obj = orb->string_to_object (objIOR);
00229                 pXmlOut = spCall->invokeInstance (obj, soapAct, spReq);
00230             }
00231             catch (...) {
00232             }
00233         }
00234     }
00235     SOAPBridge::SOAPCall::XMLData::freebuf (pBuf);
00236     if (!pXmlOut) {
00237         Fault ("Cannot reach SoapBridge, even after requering NameService");
00238     } else {
00239         puts ("Content-Type: text/xml");
00240         puts ("");
00241         fwrite (pXmlOut->get_buffer (), pXmlOut->length (), 1, stdout);
00242         delete pXmlOut;
00243     }
00244     if (doneLookup && !CORBA::is_nil (spCall)) {
00245         f = fopen ("sbcgi.recover", "wt");
00246         if (f) {
00247             int i;
00248             for (i = 1; i < myArgc; i++) {
00249                 fprintf (f, "%s\n", myArgv[i]);
00250             }
00251             CORBA::String_var sior = orb->object_to_string (spCall);
00252             fprintf (f, "SoapBridgeIOR %s\n", (char *) sior);
00253             if (haveObjIOR) {
00254                 fprintf (f, "ObjectIOR %s\n", (char *) objIOR);
00255             }
00256             fclose (f);
00257             // Note: This only works reliably if your OS guarantees rename() to be atomic!
00258             rename ("sbcgi.recover", "sbcgi.cfg");
00259         }
00260     }
00261     orb->shutdown (true);
00262     orb->destroy ();
00263     while (myArgc > 0) {
00264         myArgc--;
00265         free (myArgv[myArgc]);
00266     }
00267 
00268     return 0;
00269 }
00270 

This documentation is part of the "SOAP to CORBA bridge" project
Copyright © 2000 by Lifeline Networks bv.
All rights are reserved.