HTTPpipe.h
上传用户:smh666999
上传日期:2007-01-14
资源大小:553k
文件大小:7k
源码类别:

BREW编程

开发平台:

Visual C++

  1. #ifndef _httppipe_h_
  2. #define _httppipe_h_
  3. #include "BrewString.h"
  4. #include "AEEStdlib.h"
  5. #include "AEENet.h"
  6. #include "AEEAppGen.h"
  7. #include "AEE.h"
  8. #include "CbkDispatcher.h"
  9. //Port address to connect to.
  10. #define  TIMESERVER_PORT      80
  11. #define  TIMESERVER_HOST      "216.18.119.195"   // IP address in a.b.c.d dot-notation
  12. #define WEB_ERROR_PROTOCOL AEE_NET_EBADAPP
  13. // Invalid Address
  14. #define DOTADDR_NONE  0xFFFFFFFF
  15. typedef enum {NO_DATA_TYPE, TEXT_DATA_TYPE, IMAGE_DATA_TYPE} DATA_TYPE;
  16. //A few utility macros; We shall eventually move this into the AEE Services.
  17. #define ISDIGIT(c)  ( (unsigned) ((c) - '0') < 10)
  18. #define ISALPHA(c)  ( (unsigned) ( ((c)|32) - 'a') < 26 )
  19. #define ISALNUM(c)  ( ISDIGIT(c) || ISALPHA(c) )
  20. #define HTTP_REQUEST_TAIL " HTTP/1.0 rnrn"
  21. #define HTTP_HEADER_TAIL "rnrn"
  22. struct HDS: public IRelease
  23. {
  24. static void createHTTPDataStruct(HDS*& ds)
  25. {
  26. if (ds==0)
  27. ds = new HDS();
  28. }
  29. virtual void releaseResource( ) 
  30. {
  31. delete this;
  32. }
  33. virtual int getUID( ) 
  34. {
  35. return 100;
  36. }
  37. static int getID()
  38. {
  39. return 100;
  40. }
  41. template <class R>
  42. static HDS* initDataStruct(R* rr, char* address, const String& params )
  43. {
  44. HDS* ds=static_cast<HDS*>(rr->getRegistered(HDS::getID()));
  45. HDS::createHTTPDataStruct(ds);
  46. ds->address = address;
  47. ds->parameters = params;
  48. if (!ds->data.isEmpty())
  49. ds->data="";
  50. rr->registerResource(ds);
  51. return ds;
  52. }
  53. char* address;
  54. String parameters;
  55. String data;
  56. int error;
  57. DATA_TYPE dataType;
  58. UINT bufSize;
  59. private:
  60. HDS() :  bufSize(128)
  61. {}
  62. HDS( const HDS &Value );
  63. const HDS &operator = ( const HDS &Rhs );
  64. };
  65. template <class Y, class F>
  66. struct pkCBK;
  67. class HTTPpipe 
  68. {
  69. public:
  70. HTTPpipe(IShell* shell,  IExecute* pp, HDS* ds) :
  71. shell_(shell),
  72. processPolicy_(pp), 
  73. piSock_(0),
  74. piNet_(0),
  75. isHeaderProcessed_(false),
  76. buf_(new char[ds->bufSize+1]),
  77. ds_(ds)
  78. {
  79. }
  80. ~HTTPpipe();
  81. int init();
  82. int initConnection();
  83. void reset();
  84. private:
  85. void connect( int err);
  86. static void connectStatic(HTTPpipe* app, int err);
  87. void write();
  88. void read();
  89. int readHeader();
  90. void onError( int errorCode) ;
  91. void onData( ) ;
  92. void releaseResources();
  93. void releaseResource();
  94. private:
  95. IShell* shell_;
  96. INetMgr *piNet_;
  97. ISocket *piSock_;
  98. IExecute* processPolicy_; 
  99. String  command_;
  100. bool isHeaderProcessed_;
  101. char* buf_;
  102. typedef pkCBK0<HTTPpipe, void (HTTPpipe::*)()> P;
  103. P p_;
  104. typedef pkCBK1<HTTPpipe, void (HTTPpipe::*)(int)> PI;
  105. PI pi_;
  106. HDS* ds_;
  107. private:
  108. HTTPpipe( const HTTPpipe &Value );
  109. const HTTPpipe &operator = ( const HTTPpipe &Rhs );
  110. };
  111. static INAddr xConvertToINAddr(char *psz)
  112. {
  113. INAddr ul = 0;
  114. int nByte = 0;
  115. char c;
  116. if(!psz)
  117. return 0;
  118. while (ISDIGIT(*psz)) {
  119. int n = 0;
  120. while ( ISDIGIT(c=*psz)) {
  121. n = n*10 + (c - '0');
  122. ++psz;
  123. }
  124. ((char*)&ul)[nByte++] = n;
  125. if (nByte == 4 || *psz != '.')
  126. break;
  127. ++psz;
  128. }
  129. if (nByte < 4 || ISALNUM(*psz))
  130. ul = DOTADDR_NONE;
  131. return ul;
  132. }
  133. HTTPpipe::~HTTPpipe()
  134. {
  135. releaseResources();
  136. }
  137. void HTTPpipe::releaseResource()
  138. {
  139. if (piSock_) 
  140. {
  141. ISOCKET_Cancel(piSock_, 0, 0);
  142. ISOCKET_Release(piSock_);
  143. piSock_ = 0;
  144. }
  145. }
  146. void HTTPpipe::reset()
  147. {
  148. releaseResource();
  149. isHeaderProcessed_ = false;
  150. command_ = "";
  151. }
  152. void HTTPpipe::releaseResources()
  153. {
  154. releaseResource();
  155. if (piNet_)
  156. {
  157. INETMGR_Release(piNet_);
  158. piNet_ = 0;
  159. }
  160. delete[] buf_;
  161. buf_ = 0;
  162. }
  163. int HTTPpipe::init()
  164. int err;
  165. if ((err = ISHELL_CreateInstance(shell_, AEECLSID_NET, (void**)(&piNet_))) != SUCCESS) 
  166. {
  167. return err; 
  168. }
  169. if (!piNet_)
  170. {
  171. return EFAILED;
  172. }
  173.    // INETMGR_SetLinger(piNet_, 0);
  174. return SUCCESS;
  175. }
  176. int HTTPpipe::initConnection()
  177. {
  178. if (piSock_)
  179. {
  180. return SUCCESS; //safe approach if a connection is tried 
  181. //before ending the previous one - isReusable==true
  182. }
  183. int err;
  184. // DBGPRINTF("initConnection");
  185. piSock_ = INETMGR_OpenSocket(piNet_, AEE_SOCK_STREAM);
  186. if (!piSock_) 
  187. {
  188. err = INETMGR_GetLastError(piNet_);
  189. return err;
  190. }
  191. INAddr nodeINAddr = xConvertToINAddr(ds_->address);
  192. command_ = "GET " + ds_->parameters + HTTP_REQUEST_TAIL;
  193. pi_.setCallback(this, &HTTPpipe::connect);
  194. if ((err = ISOCKET_Connect (piSock_, nodeINAddr, AEE_htons(TIMESERVER_PORT), 
  195. (PFNCONNECTCB)PI::callbackHandler, &pi_))  != AEE_NET_SUCCESS)
  196. {
  197. return ISOCKET_GetLastError(piSock_);
  198. }
  199. return SUCCESS;
  200. }
  201. void HTTPpipe::connectStatic(HTTPpipe* app, int err)
  202. {
  203. app->connect(err);
  204. }
  205. void HTTPpipe::connect(int err)
  206. {
  207. if (err) 
  208. {
  209. DBGPRINTF("error connect");
  210. onError(err) ;
  211. return;
  212. }
  213. p_.setCallback(this, &HTTPpipe::write);
  214. write();
  215. return;
  216. }
  217. void HTTPpipe::write ()
  218. {
  219. const char *psz = command_.toCharArray();
  220. int  cbWrite = command_.length();
  221. while (cbWrite > 0) {
  222. int rv = ISOCKET_Write(piSock_, 
  223. (byte *)psz, (uint16)cbWrite);
  224. if (rv == AEE_NET_WOULDBLOCK) {
  225. command_.partialString(command_.length()- cbWrite, command_.length());
  226. ISOCKET_Writeable(piSock_, (PFNNOTIFY)P::callbackHandler, &p_);
  227. return;
  228. else if (rv == AEE_NET_ERROR) 
  229. {
  230. onError(ISOCKET_GetLastError(piSock_)) ;
  231. return;
  232. }
  233. cbWrite -= rv;
  234. psz += rv;
  235. }
  236. p_.setCallback(this,&HTTPpipe::read);
  237. read();
  238. return;
  239. }
  240. void HTTPpipe::read ()
  241. {
  242. if (!piSock_)
  243. {
  244. DBGPRINTF("piSock == 0 in read");
  245. onError(EFAILED);
  246. return;
  247. }
  248. int32 rv = ISOCKET_Read(piSock_, buf_, ds_->bufSize);
  249. if  (rv == AEE_NET_WOULDBLOCK) 
  250. {
  251. ISOCKET_Readable(piSock_, (PFNNOTIFY)P::callbackHandler, &p_);
  252. return;
  253. else if (rv == AEE_NET_ERROR)  
  254. {
  255. onError(ISOCKET_GetLastError(piSock_)) ;
  256. return;
  257. }
  258. else if (rv > 0) 
  259. {
  260. buf_[rv] = 0;
  261. ds_->data += buf_;
  262. if (!isHeaderProcessed_)
  263. {
  264. int err = readHeader();
  265. if (err == SUCCESS)
  266. {
  267. isHeaderProcessed_ = true;
  268. }
  269. else  if (err == WEB_ERROR_PROTOCOL)
  270. {
  271. onError(err) ;
  272. return;
  273. }
  274. }
  275. ISOCKET_Readable(piSock_, (PFNNOTIFY)P::callbackHandler, &p_);
  276. return;
  277. }
  278. else if (rv == 0) 
  279. {
  280. onData();
  281. return;
  282. }
  283. }
  284. int HTTPpipe::readHeader() 
  285. {
  286. int contentIndex = ds_->data.indexOf(HTTP_HEADER_TAIL);
  287. if (contentIndex == -1)
  288. {
  289. return EFAILED;
  290. }
  291. contentIndex += 4;
  292. // String content = "Content-Type:";
  293. // String cLength = "Content-Length:";
  294. int statusIndexStart = ds_->data.indexOf("HTTP/");
  295. statusIndexStart = ds_->data.indexOf(" ", statusIndexStart + 1);
  296. int statusIndexEnd = ds_->data.indexOf(" ", statusIndexStart + 1);
  297. int status = ATOI((ds_->data.substring(statusIndexStart, statusIndexEnd)).toCharArray())/100;
  298. if (status != 2) 
  299. {
  300. return WEB_ERROR_PROTOCOL;
  301. }
  302. ds_->dataType = (ds_->data.indexOf("image/") > -1) ? IMAGE_DATA_TYPE : TEXT_DATA_TYPE;
  303. ds_->data.partialString(contentIndex, ds_->data.length());
  304. return SUCCESS;
  305. }
  306. void HTTPpipe::onError( int errorCode) {
  307. ds_->error = errorCode;
  308. ds_->data = "";
  309. ds_->dataType = NO_DATA_TYPE;
  310. processPolicy_->onCbk() ;
  311. }
  312. void HTTPpipe::onData( ) {
  313. ds_->error = SUCCESS;
  314. processPolicy_->onCbk() ;
  315. }
  316. #endif