📄 httppipe.h
字号:
#ifndef _httppipe_h_
#define _httppipe_h_
#include "BrewString.h"
#include "AEEStdlib.h"
#include "AEENet.h"
#include "AEEAppGen.h"
#include "AEE.h"
#include "CbkDispatcher.h"
//Port address to connect to.
#define TIMESERVER_PORT 80
#define TIMESERVER_HOST "216.18.119.195" // IP address in a.b.c.d dot-notation
#define WEB_ERROR_PROTOCOL AEE_NET_EBADAPP
// Invalid Address
#define DOTADDR_NONE 0xFFFFFFFF
typedef enum {NO_DATA_TYPE, TEXT_DATA_TYPE, IMAGE_DATA_TYPE} DATA_TYPE;
//A few utility macros; We shall eventually move this into the AEE Services.
#define ISDIGIT(c) ( (unsigned) ((c) - '0') < 10)
#define ISALPHA(c) ( (unsigned) ( ((c)|32) - 'a') < 26 )
#define ISALNUM(c) ( ISDIGIT(c) || ISALPHA(c) )
#define HTTP_REQUEST_TAIL " HTTP/1.0 \r\n\r\n"
#define HTTP_HEADER_TAIL "\r\n\r\n"
struct HDS: public IRelease
{
static void createHTTPDataStruct(HDS*& ds)
{
if (ds==0)
ds = new HDS();
}
virtual void releaseResource( )
{
delete this;
}
virtual int getUID( )
{
return 100;
}
static int getID()
{
return 100;
}
template <class R>
static HDS* initDataStruct(R* rr, char* address, const String& params )
{
HDS* ds=static_cast<HDS*>(rr->getRegistered(HDS::getID()));
HDS::createHTTPDataStruct(ds);
ds->address = address;
ds->parameters = params;
if (!ds->data.isEmpty())
ds->data="";
rr->registerResource(ds);
return ds;
}
char* address;
String parameters;
String data;
int error;
DATA_TYPE dataType;
UINT bufSize;
private:
HDS() : bufSize(128)
{}
HDS( const HDS &Value );
const HDS &operator = ( const HDS &Rhs );
};
template <class Y, class F>
struct pkCBK;
class HTTPpipe
{
public:
HTTPpipe(IShell* shell, IExecute* pp, HDS* ds) :
shell_(shell),
processPolicy_(pp),
piSock_(0),
piNet_(0),
isHeaderProcessed_(false),
buf_(new char[ds->bufSize+1]),
ds_(ds)
{
}
~HTTPpipe();
int init();
int initConnection();
void reset();
private:
void connect( int err);
static void connectStatic(HTTPpipe* app, int err);
void write();
void read();
int readHeader();
void onError( int errorCode) ;
void onData( ) ;
void releaseResources();
void releaseResource();
private:
IShell* shell_;
INetMgr *piNet_;
ISocket *piSock_;
IExecute* processPolicy_;
String command_;
bool isHeaderProcessed_;
char* buf_;
typedef pkCBK0<HTTPpipe, void (HTTPpipe::*)()> P;
P p_;
typedef pkCBK1<HTTPpipe, void (HTTPpipe::*)(int)> PI;
PI pi_;
HDS* ds_;
private:
HTTPpipe( const HTTPpipe &Value );
const HTTPpipe &operator = ( const HTTPpipe &Rhs );
};
static INAddr xConvertToINAddr(char *psz)
{
INAddr ul = 0;
int nByte = 0;
char c;
if(!psz)
return 0;
while (ISDIGIT(*psz)) {
int n = 0;
while ( ISDIGIT(c=*psz)) {
n = n*10 + (c - '0');
++psz;
}
((char*)&ul)[nByte++] = n;
if (nByte == 4 || *psz != '.')
break;
++psz;
}
if (nByte < 4 || ISALNUM(*psz))
ul = DOTADDR_NONE;
return ul;
}
HTTPpipe::~HTTPpipe()
{
releaseResources();
}
void HTTPpipe::releaseResource()
{
if (piSock_)
{
ISOCKET_Cancel(piSock_, 0, 0);
ISOCKET_Release(piSock_);
piSock_ = 0;
}
}
void HTTPpipe::reset()
{
releaseResource();
isHeaderProcessed_ = false;
command_ = "";
}
void HTTPpipe::releaseResources()
{
releaseResource();
if (piNet_)
{
INETMGR_Release(piNet_);
piNet_ = 0;
}
delete[] buf_;
buf_ = 0;
}
int HTTPpipe::init()
{
int err;
if ((err = ISHELL_CreateInstance(shell_, AEECLSID_NET, (void**)(&piNet_))) != SUCCESS)
{
return err;
}
if (!piNet_)
{
return EFAILED;
}
// INETMGR_SetLinger(piNet_, 0);
return SUCCESS;
}
int HTTPpipe::initConnection()
{
if (piSock_)
{
return SUCCESS; //safe approach if a connection is tried
//before ending the previous one - isReusable==true
}
int err;
// DBGPRINTF("initConnection");
piSock_ = INETMGR_OpenSocket(piNet_, AEE_SOCK_STREAM);
if (!piSock_)
{
err = INETMGR_GetLastError(piNet_);
return err;
}
INAddr nodeINAddr = xConvertToINAddr(ds_->address);
command_ = "GET " + ds_->parameters + HTTP_REQUEST_TAIL;
pi_.setCallback(this, &HTTPpipe::connect);
if ((err = ISOCKET_Connect (piSock_, nodeINAddr, AEE_htons(TIMESERVER_PORT),
(PFNCONNECTCB)PI::callbackHandler, &pi_)) != AEE_NET_SUCCESS)
{
return ISOCKET_GetLastError(piSock_);
}
return SUCCESS;
}
void HTTPpipe::connectStatic(HTTPpipe* app, int err)
{
app->connect(err);
}
void HTTPpipe::connect(int err)
{
if (err)
{
DBGPRINTF("error connect");
onError(err) ;
return;
}
p_.setCallback(this, &HTTPpipe::write);
write();
return;
}
void HTTPpipe::write ()
{
const char *psz = command_.toCharArray();
int cbWrite = command_.length();
while (cbWrite > 0) {
int rv = ISOCKET_Write(piSock_,
(byte *)psz, (uint16)cbWrite);
if (rv == AEE_NET_WOULDBLOCK) {
command_.partialString(command_.length()- cbWrite, command_.length());
ISOCKET_Writeable(piSock_, (PFNNOTIFY)P::callbackHandler, &p_);
return;
}
else if (rv == AEE_NET_ERROR)
{
onError(ISOCKET_GetLastError(piSock_)) ;
return;
}
cbWrite -= rv;
psz += rv;
}
p_.setCallback(this,&HTTPpipe::read);
read();
return;
}
void HTTPpipe::read ()
{
if (!piSock_)
{
DBGPRINTF("piSock == 0 in read");
onError(EFAILED);
return;
}
int32 rv = ISOCKET_Read(piSock_, buf_, ds_->bufSize);
if (rv == AEE_NET_WOULDBLOCK)
{
ISOCKET_Readable(piSock_, (PFNNOTIFY)P::callbackHandler, &p_);
return;
}
else if (rv == AEE_NET_ERROR)
{
onError(ISOCKET_GetLastError(piSock_)) ;
return;
}
else if (rv > 0)
{
buf_[rv] = 0;
ds_->data += buf_;
if (!isHeaderProcessed_)
{
int err = readHeader();
if (err == SUCCESS)
{
isHeaderProcessed_ = true;
}
else if (err == WEB_ERROR_PROTOCOL)
{
onError(err) ;
return;
}
}
ISOCKET_Readable(piSock_, (PFNNOTIFY)P::callbackHandler, &p_);
return;
}
else if (rv == 0)
{
onData();
return;
}
}
int HTTPpipe::readHeader()
{
int contentIndex = ds_->data.indexOf(HTTP_HEADER_TAIL);
if (contentIndex == -1)
{
return EFAILED;
}
contentIndex += 4;
// String content = "Content-Type:";
// String cLength = "Content-Length:";
int statusIndexStart = ds_->data.indexOf("HTTP/");
statusIndexStart = ds_->data.indexOf(" ", statusIndexStart + 1);
int statusIndexEnd = ds_->data.indexOf(" ", statusIndexStart + 1);
int status = ATOI((ds_->data.substring(statusIndexStart, statusIndexEnd)).toCharArray())/100;
if (status != 2)
{
return WEB_ERROR_PROTOCOL;
}
ds_->dataType = (ds_->data.indexOf("image/") > -1) ? IMAGE_DATA_TYPE : TEXT_DATA_TYPE;
ds_->data.partialString(contentIndex, ds_->data.length());
return SUCCESS;
}
void HTTPpipe::onError( int errorCode) {
ds_->error = errorCode;
ds_->data = "";
ds_->dataType = NO_DATA_TYPE;
processPolicy_->onCbk() ;
}
void HTTPpipe::onData( ) {
ds_->error = SUCCESS;
processPolicy_->onCbk() ;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -