⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sbinethttpstream.cpp

📁 Open VXI. This is a open source.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/****************License************************************************ * * Copyright 2001.  SpeechWorks International, Inc. * * Use of this software is subject to notices and obligations set forth * in the SpeechWorks Public License - Software Version 1.1 which is * included with this software. *  * SpeechWorks is a registered trademark, and SpeechWorks Here,  * DialogModules and the SpeechWorks logo are trademarks of SpeechWorks  * International, Inc. in the United States and other countries.  *  *********************************************************************** * * SBinetHttpStream Implementation * * $Id: SBinetHttpStream.cpp,v 1.38.2.1.2.9 2001/11/14 16:35:04 ddeac Exp $ * ***********************************************************************/#ifndef _SB_USE_STD_NAMESPACE#define _SB_USE_STD_NAMESPACE#endif#ifdef WIN32#ifndef UNICODE#define UNICODE#endif#ifndef _UNICODE#define _UNICODE#endif#undef HTTP_VERSION#define WIN32_LEAN_AND_MEAN#include <windows.h>#endif#include <sys/timeb.h>                  // for _ftime( )/ftime( )#include <WWWLib.h>#include <WWWHTTP.h>#include <WWWInit.h>#ifdef EINVAL// Conflicts with OS definition#undef EINVAL#endif#include "VXIvalue.h"#include "VXIinet.h"#include "VXItrd.h"#include "SBinetLog.h"#include "SBinetURL.h"#include "SBinetStream.h"#include "SBinetChannel.h"#include "SBinetValidator.h"#include "SBinetCacheLock.h"#include "HTCache.h"					 /* Implemented here */#include "HTAncMan.h"#include "HTAnchor.h"#include "HTReq.h"#include "HTReqMan.h"#ifdef WIN32/* Suppress/disable warnings */#pragma warning(4 : 4706) /* Assignment within conditional expression			     (for Libwww HTList_[...]( ) macros) */#endif#define INET_INFO_HTTP_STATUS L"inet.httpStatus"extern "C" {#include "SBHTStream.h"}#ifndef WIN32#define Sleep(x) usleep(1000*(x))#endif #define MAX_CHUNK_SIZE (10 * 1024 * 1024)HTChunk*SBinetHttpStream::Get(SBinetURL*       url,		      VXIint32                  flags,		      const VXIMap             *properties,		      VXIMap                   *streamInfo){  /* Setup to read to chunk for now. Non-optimal in that chunk is size      limited Also, we must wait for entire download to happen. Can we      get a callback when header is complete??      Note: This performs Web transaction in this thread until      something would block, then returns, and rest of download is      done in event thread. Since we are waiting here anyway, we could      actually use blocking IO, but we hope to fix all in future.      Tried to make a Stream class that would return WOULD_BLOCK when      full (instead of failing as Chunks do). However, there seems to      be no mechanism in libwww for dealing with this.  The result was      deadlock as the system ceased to get events, behavior is worse      if the doc was in cache. For now we are just going to use the      libww chunk class and live with the size limitation. Also, as a      consequence, Open will not return until the entire doc is      downloaded into memory...bogus, but that seems to be the way      libwww works.  */  HTRequest_setMethod(m_request,METHOD_GET);  url->AppendQueryArgs(m_queryArgs);  const char* absolute_url = url->GetAbsoluteNarrow();  HTAnchor* anchor = HTAnchor_findAddress(absolute_url);  // Need to do this for CacheValid  HTRequest_setAnchor(m_request,anchor);  /*   * get lock for anchor    */  m_lock = SBinetCacheLockTable::FindCacheLock(anchor);  if(m_lock == NULL){   // Should never fail    Error (217, NULL);    return(NULL);  }  /*   * lock anchor -- Must unlock libwww while waiting to avoid deadlock   */  SBinetInterface::UnlockLibwww( );  m_lock->GetReadLock(m_request);  SBinetInterface::LockLibwww( );  /*   * This test used to be part of ill-fated multiple-reader scheme, now only informative   *  Note: Change printfs to Log when satisfied.  if(CacheValid(m_request)){    printf("Request in cache");  }  else{   printf("Request NOT in cache\n");  }   */  /*   * The actual call   */  m_chunk = NULL;  HTStream * target = SBHTStream(m_request, &m_chunk, MAX_CHUNK_SIZE);  HTRequest_setOutputStream(m_request, target);  if(HTLoadAnchor((HTAnchor*)anchor, m_request) != YES){    HTChunk_delete(m_chunk);    m_chunk =  NULL;  }  return(m_chunk);}/* * POST simple form data. Don't know how to combine Form data  * and audio in multipart POST */HTChunk*SBinetHttpStream::PostMulti(SBinetURL*       url,		      VXIint32                  flags,		      const VXIMap             *properties,		      VXIMap                   *streamInfo){  /* Get an anchor object for the URI */  const char* absolute_url = url->GetAbsoluteNarrow();  HTAnchor* anchor = HTAnchor_findAddress(absolute_url);  /*   * get lock for anchor    */  m_lock = SBinetCacheLockTable::FindCacheLock(anchor);  if(m_lock == NULL){   // Should never fail    Error (217, NULL);    return(NULL);  }  /*   * lock anchor -- Must unlock libwww while waiting to avoid deadlock   */  SBinetInterface::UnlockLibwww( );  m_lock->GetReadLock(m_request);  SBinetInterface::LockLibwww( );  /*   * Set up Post (copied from HTPostFormAnchorToChunk   */  // get doc for query args  VXIulong doclen = 0;  const char* doc = url->QueryArgsToMultipart(m_queryArgs,&doclen);  HTUserProfile * up = HTRequest_userProfile(m_request);  char * tmpfile = HTGetTmpFileName(HTUserProfile_tmp(up));  char * tmpurl = HTParse(tmpfile, "file:", PARSE_ALL);	    /*	    **  Now create a new anchor for the post data and set up	    **  the rest of the metainformation we know about this anchor. The	    **  tmp anchor may actually already exist from previous postings.	    */  HTParentAnchor* postanchor = (HTParentAnchor *) HTAnchor_findAddress(tmpurl);  HTAnchor_clearHeader(postanchor);    // Who frees doc???  HTAnchor_setDocument(postanchor, (void *) doc);  HTAnchor_setLength(postanchor, doclen);  HTAnchor_setFormat(postanchor, HTAtom_for(SB_MULTIPART));  HTStream * target = SBHTStream(m_request, &m_chunk, MAX_CHUNK_SIZE);  HTRequest_setOutputStream(m_request, target);  // I think this does the right thing  if(HTPostAnchor(postanchor,anchor,m_request) == YES){    HT_FREE(tmpfile);    HT_FREE(tmpurl);  }  else{    HTChunk_delete(m_chunk);    m_chunk = NULL;  }  return(m_chunk);}/* * POST simple form data. Don't know how to combine Form data and audio in multipart POST */HTChunk*SBinetHttpStream::Post(SBinetURL*       url,		      VXIint32                  flags,		      const VXIMap             *properties,		      VXIMap                   *streamInfo){  /* Get an anchor object for the URI */  const char* absolute_url = url->GetAbsoluteNarrow();  HTAnchor* anchor = HTAnchor_findAddress(absolute_url);  //  HTRequest_setOutputFormat( m_request, HTAtom_for( m_submitMimeType ));  // If we are a multipart MIME (ie sending audio) branch to special POST  if(url->NeedMultipart(m_queryArgs)){    return(PostMulti(url,flags,properties,streamInfo));  }  HTAssocList* arglist = url->QueryArgsToHtList(m_queryArgs);  /*   * get lock for anchor    */  m_lock = SBinetCacheLockTable::FindCacheLock(anchor);  if(m_lock == NULL){   // Should never fail    Error (217, NULL);    return(NULL);  }  /*   * lock anchor -- Must unlock libwww while waiting to avoid deadlock   */  SBinetInterface::UnlockLibwww( );  m_lock->GetReadLock(m_request);  SBinetInterface::LockLibwww( );  /* Post the data and get the result in a chunk */  m_chunk = NULL;  HTStream * target = SBHTStream(m_request, &m_chunk, MAX_CHUNK_SIZE);  HTRequest_setOutputStream(m_request, target);  if(arglist == NULL){     // NULL arglist, converting to GET    // PostFormAnchor will bomb, use LoadAnchor instead    if(HTLoadAnchor(anchor, m_request) == NO){      HTChunk_delete(m_chunk);      m_chunk =  NULL;    }  }  else{    if(HTPostFormAnchor(arglist, anchor, m_request) == NULL){      HTChunk_delete(m_chunk);      m_chunk =  NULL;    }    HTAssocList_delete(arglist);  }  return(m_chunk);}int SBinetHttpStream::getTime(time_t *timestamp,			  VXIunsigned *timestampMsec){#ifdef WIN32  struct _timeb tbuf;  _ftime(&tbuf);  *timestamp = tbuf.time;  *timestampMsec = (VXIunsigned) tbuf.millitm;#else  struct timeb tbuf;  ftime(&tbuf);  *timestamp = tbuf.time;  *timestampMsec = (VXIunsigned) tbuf.millitm;#endif  return 0;}intSBinetHttpStream::checkTimeout(){  time_t currentTime;  VXIunsigned currentTimeMsec;  getTime( &currentTime, &currentTimeMsec );   long elapsedMillis = ( currentTime - m_ReferenceTime ) * 1000L +     currentTimeMsec - m_ReferenceTimeMsec;  if(elapsedMillis >= m_nTimeoutOpen){    return(1);  }  return(0);}intSBinetHttpStream::terminate_handler (HTRequest * request, 				     HTResponse * response,				     void * param, int status) {    /* Check for status */  SBinetHttpStream* str =   (SBinetHttpStream*)param;  HTParentAnchor* anc = HTRequest_anchor(request);  /* we're not handling other requests */  if(str && !str->m_Done && (status != 301) && (status != 302)){    str->m_Done = 1;    str->m_HttpStatus = status;  }  /* stop here */  return HT_OK;}VXIinetResultSBinetHttpStream::Open(VXIint32                  flags,		       const VXIMap             *properties,		       VXIMap                   *streamInfo){  // Set up  properties instance  SetProperties((VXIMap*)properties);  // Determine if this is a conditional open with a validator,  // irrelevant if caching is disabled  const VXIValue* validatorVal = NULL;  if (m_iMaxAge != 0) {    validatorVal = VXIMapGetProperty( properties, INET_OPEN_IF_MODIFIED );    if (validatorVal != NULL) {      SBinetValidator validator(GetLog(), GetDiagBase());      if (validator.Create(validatorVal) == VXIinet_RESULT_SUCCESS) {	validator.Log(MODULE_SBINET_STREAM_TAGID, L"SBinetHttpStream::Open");		// No need to fetch this if it has not expired, however still	// have to return the validator in streamInfo	if (! validator.Expired()) {	  if (streamInfo) {	    if (VXIMapSetProperty(streamInfo, INET_INFO_VALIDATOR,				  VXIValueClone(validatorVal)) !=		VXIvalue_RESULT_SUCCESS) {	      Error(103, NULL);	      return VXIinet_RESULT_OUT_OF_MEMORY;	    }	  }	  return VXIinet_RESULT_NOT_MODIFIED;	}      }    }  }  // Set up request  SBinetInterface::LockLibwww( );  getTime( &m_ReferenceTime, &m_ReferenceTimeMsec );   m_request = HTRequest_new();  m_Done = 0;  m_HttpStatus = -1234;  /* Store pointer so we can get at it later in callbacks */  HTRequest_setContext(m_request,(void*) this);  /* We want user output: no headers or strange length stuff */  HTRequest_setOutputFormat(m_request, WWW_SOURCE);  /* Close connection immediately */  HTRequest_addConnection(m_request, "close", "");  /* Add our own filter to handle termination */  HTRequest_addAfter(m_request, SBinetHttpStream::terminate_handler, NULL, this, 		     HT_ALL, HT_FILTER_LAST,NO);  SetCachingMode();  // Start request - get or post  if(m_method == GET_METHOD){    m_chunk = Get(m_url,flags,properties,streamInfo);  }  else if(m_method == POST_METHOD){    m_chunk = Post(m_url,flags,properties,streamInfo);  }  SBinetInterface::UnlockLibwww( );  if(!m_chunk){    Error(218, L"%s%s%s%s", L"URL", m_url->GetAbsolute(),         L"Method", (m_method == GET_METHOD) ? L"GET" : L"POST");    // clean up    Close();    return(VXIinet_RESULT_FAILURE);  }  // Wait for completion -- common  //  Really should sleep on timer and wait for wakeup? Actually depends on cost of sleep/wakeup vs  //    a little gratuitous spinning.  int sleepTime = 1;  while(!m_Done){    if(checkTimeout()) {      Error(228, L"%s%s%s%s%s%i", L"URL", m_url->GetAbsolute(),         L"Method", (m_method == GET_METHOD) ? L"GET" : L"POST",        L"Delay", m_nTimeoutOpen);      Close();      return( VXIinet_RESULT_FETCH_TIMEOUT );    }    Sleep(sleepTime);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -