mirror of https://github.com/axmolengine/axmol.git
add CCHttpRequest and related tests to repository
This commit is contained in:
parent
dc35596ce9
commit
24136dc575
|
@ -0,0 +1,576 @@
|
||||||
|
/****************************************************************************
|
||||||
|
Copyright (c) 2010-2012 cocos2d-x.org
|
||||||
|
Copyright (c) 2012 greathqy
|
||||||
|
|
||||||
|
http://www.cocos2d-x.org
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "CCHttpRequest.h"
|
||||||
|
#include <queue>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <semaphore.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include "platform/CCThread.h"
|
||||||
|
#include "curl/curl.h"
|
||||||
|
|
||||||
|
NS_CC_EXT_BEGIN
|
||||||
|
|
||||||
|
static pthread_t s_requestThread;
|
||||||
|
static pthread_mutex_t s_requestQueueMutex;
|
||||||
|
static pthread_mutex_t s_responseQueueMutex;
|
||||||
|
static sem_t * s_pSem = NULL;
|
||||||
|
static unsigned long s_asyncRequestCount = 0;
|
||||||
|
|
||||||
|
#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS
|
||||||
|
#define CC_ASYNC_HTTPREQUEST_USE_NAMED_SEMAPHORE 1
|
||||||
|
#else
|
||||||
|
#define CC_ASYNC_HTTPREQUEST_USE_NAMED_SEMAPHORE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CC_ASYNC_HTTPREQUEST_USE_NAMED_SEMAPHORE
|
||||||
|
#define CC_ASYNC_HTTPREQUEST_SEMAPHORE "ccHttpAsync"
|
||||||
|
#else
|
||||||
|
static sem_t s_sem;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static bool need_quit = false;
|
||||||
|
|
||||||
|
static std::queue<HttpRequestPacket *> *s_requestQueue = NULL;
|
||||||
|
static std::queue<HttpResponsePacket *> *s_responseQueue = NULL;
|
||||||
|
|
||||||
|
static CCHttpRequest *_g_singleton_httprequest = NULL;
|
||||||
|
|
||||||
|
static char errorBuffer[CURL_ERROR_SIZE];
|
||||||
|
typedef size_t (*write_callback)(void *ptr, size_t size, size_t nmemb, void *stream);
|
||||||
|
|
||||||
|
//Callback function used by libcurl for save file
|
||||||
|
size_t writeFile(void *ptr, size_t size, size_t nmemb, void *stream)
|
||||||
|
{
|
||||||
|
int written = fwrite(ptr, size, nmemb, (FILE *)stream);
|
||||||
|
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Callback function used by libcurl for collect response data
|
||||||
|
size_t writeData(void *ptr, size_t size, size_t nmemb, void *stream)
|
||||||
|
{
|
||||||
|
std::string *str = (std::string *)stream;
|
||||||
|
|
||||||
|
size_t sizes = size * nmemb;
|
||||||
|
str->append((char *)ptr, sizes);
|
||||||
|
|
||||||
|
return sizes;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Prototypes
|
||||||
|
void releaseRequestQueue();
|
||||||
|
bool configureCURL(CURL *handle);
|
||||||
|
int processGetTask(HttpRequestPacket *task, write_callback callback, void *stream, int32_t *responseCode);
|
||||||
|
int processPostTask(HttpRequestPacket *task, write_callback callback, void *stream, int32_t *responseCode);
|
||||||
|
int processDownloadTask(HttpRequestPacket *task, write_callback callback, void *stream, int32_t *responseCode);
|
||||||
|
|
||||||
|
void CCHttpRequest::purgeSharedHttpRequest()
|
||||||
|
{
|
||||||
|
CC_SAFE_RELEASE_NULL(_g_singleton_httprequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
CCHttpRequest *CCHttpRequest::sharedHttpRequest()
|
||||||
|
{
|
||||||
|
if (_g_singleton_httprequest == NULL) {
|
||||||
|
_g_singleton_httprequest = new CCHttpRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
return _g_singleton_httprequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Worker thread
|
||||||
|
static void *requestThread(void *data)
|
||||||
|
{
|
||||||
|
CCThread thread;
|
||||||
|
thread.createAutoreleasePool();
|
||||||
|
|
||||||
|
HttpRequestPacket *req = NULL;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
//Wait for http request tasks from main thread
|
||||||
|
int semWaitRet = sem_wait(s_pSem);
|
||||||
|
if (semWaitRet < 0) {
|
||||||
|
CCLog("HttpRequest async thread semaphore error: %s\n", strerror(errno));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::queue<HttpRequestPacket *> *pQueue = s_requestQueue;
|
||||||
|
pthread_mutex_lock(&s_requestQueueMutex); //Get request task from queue
|
||||||
|
if (pQueue->empty()) {
|
||||||
|
pthread_mutex_unlock(&s_requestQueueMutex);
|
||||||
|
|
||||||
|
if (need_quit) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (need_quit) {
|
||||||
|
pthread_mutex_unlock(&s_requestQueueMutex);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
req = pQueue->front();
|
||||||
|
pQueue->pop();
|
||||||
|
pthread_mutex_unlock(&s_requestQueueMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Create a response packet and assume it will successed
|
||||||
|
HttpResponsePacket *responsePacket = new HttpResponsePacket();
|
||||||
|
responsePacket->request = req;
|
||||||
|
responsePacket->succeed = true;
|
||||||
|
|
||||||
|
//Process the request
|
||||||
|
if (req->reqType == kHttpRequestGet) { //Get Request
|
||||||
|
int32_t ret = processGetTask(req, writeData, &responsePacket->responseData, &responsePacket->responseCode);
|
||||||
|
if (ret != 0) {
|
||||||
|
responsePacket->succeed = false;
|
||||||
|
responsePacket->responseData = errorBuffer;
|
||||||
|
}
|
||||||
|
} else if (req->reqType == kHttpRequestPost) { //Post Request
|
||||||
|
int32_t ret = processPostTask(req, writeData, &responsePacket->responseData, &responsePacket->responseCode);
|
||||||
|
if (ret != 0) {
|
||||||
|
responsePacket->succeed = false;
|
||||||
|
responsePacket->responseData = errorBuffer;
|
||||||
|
}
|
||||||
|
} else if (req->reqType == kHttpRequestDownloadFile) { //Download File Request
|
||||||
|
bool fullyDownloaded = true;
|
||||||
|
std::vector<std::string>::iterator iter;
|
||||||
|
std::string saveFileName;
|
||||||
|
std::string needDownload;
|
||||||
|
|
||||||
|
for (iter = req->files.begin(); iter != req->files.end(); ++iter) {
|
||||||
|
needDownload = *iter;
|
||||||
|
std::string::size_type pos = needDownload.rfind("/");
|
||||||
|
|
||||||
|
if (pos != std::string::npos) {
|
||||||
|
saveFileName = needDownload.substr(pos + 1);
|
||||||
|
} else {
|
||||||
|
saveFileName = needDownload;
|
||||||
|
}
|
||||||
|
|
||||||
|
//If the download url is http://www.xxx.com/yyy.html
|
||||||
|
//The saved file name must be yyy.html
|
||||||
|
saveFileName = CCFileUtils::sharedFileUtils()->getWriteablePath() + saveFileName;
|
||||||
|
FILE *handle = fopen(saveFileName.c_str(), "w+");
|
||||||
|
if (!handle) {
|
||||||
|
fullyDownloaded = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
req->url = needDownload;
|
||||||
|
int32_t ret = processDownloadTask(req, writeFile, handle, &responsePacket->responseCode);
|
||||||
|
if (handle) {
|
||||||
|
fclose(handle);
|
||||||
|
}
|
||||||
|
if (ret != 0) {
|
||||||
|
fullyDownloaded = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Only consider download task successfully when all the files downloaded
|
||||||
|
if (!fullyDownloaded) {
|
||||||
|
responsePacket->succeed = false;
|
||||||
|
responsePacket->responseData = errorBuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock(&s_responseQueueMutex);
|
||||||
|
s_responseQueue->push(responsePacket);
|
||||||
|
pthread_mutex_unlock(&s_responseQueueMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
//If worker thread received quit signal, clean up un-completed request queue
|
||||||
|
releaseRequestQueue();
|
||||||
|
|
||||||
|
if (s_pSem != NULL) {
|
||||||
|
#if CC_ASYNC_HTTPREQUEST_USE_NAMED_SEMAPHORE
|
||||||
|
sem_unlink(CC_ASYNC_HTTPREQUEST_SEMAPHORE);
|
||||||
|
sem_close(s_pSem);
|
||||||
|
#else
|
||||||
|
sem_destroy(s_pSem);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
s_pSem = NULL;
|
||||||
|
|
||||||
|
pthread_mutex_destroy(&s_requestQueueMutex);
|
||||||
|
pthread_mutex_destroy(&s_responseQueueMutex);
|
||||||
|
|
||||||
|
delete s_requestQueue;
|
||||||
|
delete s_responseQueue;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_exit(NULL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Release Http request task queue
|
||||||
|
void releaseRequestQueue()
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&s_requestQueueMutex);
|
||||||
|
|
||||||
|
int32_t requestQueueSize = s_requestQueue->size();
|
||||||
|
if (requestQueueSize > 0) {
|
||||||
|
for (int32_t i = 0; i < requestQueueSize; ++i) {
|
||||||
|
HttpRequestPacket *packet = s_requestQueue->front();
|
||||||
|
s_requestQueue->pop();
|
||||||
|
|
||||||
|
delete packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
s_asyncRequestCount -= requestQueueSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&s_requestQueueMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Configure curl's timeout property
|
||||||
|
bool configureCURL(CURL *handle)
|
||||||
|
{
|
||||||
|
if (!handle) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t code;
|
||||||
|
code = curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, errorBuffer);
|
||||||
|
if (code != CURLE_OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
code = curl_easy_setopt(handle, CURLOPT_TIMEOUT, CCHttpRequest::sharedHttpRequest()->getDownloadTimeout());
|
||||||
|
if (code != CURLE_OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
code = curl_easy_setopt(handle, CURLOPT_CONNECTTIMEOUT, CCHttpRequest::sharedHttpRequest()->getConnectTimeout());
|
||||||
|
if (code != CURLE_OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Process Get Request
|
||||||
|
int processGetTask(HttpRequestPacket *task, write_callback callback, void *stream, int32_t *responseCode)
|
||||||
|
{
|
||||||
|
CURLcode code = CURL_LAST;
|
||||||
|
CURL *curl = curl_easy_init();
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (!configureCURL(curl)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
code = curl_easy_setopt(curl, CURLOPT_URL, task->url.c_str());
|
||||||
|
if (code != CURLE_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
code = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback);
|
||||||
|
if (code != CURLE_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
code = curl_easy_setopt(curl, CURLOPT_WRITEDATA, stream);
|
||||||
|
if (code != CURLE_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
code = curl_easy_perform(curl);
|
||||||
|
if (code != CURLE_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
code = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, responseCode);
|
||||||
|
if (code != CURLE_OK || *responseCode / 100 != 2) {
|
||||||
|
code = CURLE_HTTP_RETURNED_ERROR;
|
||||||
|
}
|
||||||
|
} while (0);
|
||||||
|
if (curl) {
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (code == CURLE_OK ? 0 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Process POST Request
|
||||||
|
int processPostTask(HttpRequestPacket *task, write_callback callback, void *stream, int32_t *responseCode)
|
||||||
|
{
|
||||||
|
CURLcode code = CURL_LAST;
|
||||||
|
CURL *curl = curl_easy_init();
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (!configureCURL(curl)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
code = curl_easy_setopt(curl, CURLOPT_URL, task->url.c_str());
|
||||||
|
if (code != CURLE_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
code = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback);
|
||||||
|
if (code != CURLE_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
code = curl_easy_setopt(curl, CURLOPT_WRITEDATA, stream);
|
||||||
|
if (code != CURLE_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
code = curl_easy_setopt(curl, CURLOPT_POST, 1);
|
||||||
|
if (code != CURLE_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
code = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, task->reqData.data());
|
||||||
|
if (code != CURLE_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
code = curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, task->reqData.size());
|
||||||
|
if (code != CURLE_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
code = curl_easy_perform(curl);
|
||||||
|
if (code != CURLE_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
code = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, responseCode);
|
||||||
|
if (code != CURLE_OK || *responseCode / 100 != 2) {
|
||||||
|
code = CURLE_HTTP_RETURNED_ERROR;
|
||||||
|
}
|
||||||
|
} while (0);
|
||||||
|
if (curl) {
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (code == CURLE_OK ? 0 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Process Download Request
|
||||||
|
int processDownloadTask(HttpRequestPacket *task, write_callback callback, void *stream, int32_t *responseCode)
|
||||||
|
{
|
||||||
|
return processGetTask(task, callback, stream, responseCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
CCHttpRequest::CCHttpRequest()
|
||||||
|
{
|
||||||
|
m_timeout = 60;
|
||||||
|
m_connectTimeout = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
CCHttpRequest::~CCHttpRequest()
|
||||||
|
{
|
||||||
|
need_quit = true;
|
||||||
|
|
||||||
|
if (s_pSem != NULL) {
|
||||||
|
sem_post(s_pSem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Lazy create semaphore & mutex & thread
|
||||||
|
bool CCHttpRequest::lazyInitThreadSemphore()
|
||||||
|
{
|
||||||
|
if (s_pSem != NULL) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
#if CC_ASYNC_HTTPREQUEST_USE_NAMED_SEMAPHORE
|
||||||
|
s_pSem = sem_open(CC_ASYNC_HTTPREQUEST_SEMAPHORE, O_CREAT, 0644, 0);
|
||||||
|
if (s_pSem == SEM_FAILED) {
|
||||||
|
CCLog("Open HttpRequest Semaphore failed");
|
||||||
|
s_pSem = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int semRet = sem_init(&s_sem, 0, 0);
|
||||||
|
if (semRet < 0) {
|
||||||
|
CCLog("Init HttpRequest Semaphore failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
s_pSem = &s_sem;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
s_requestQueue = new std::queue<HttpRequestPacket *>();
|
||||||
|
s_responseQueue = new std::queue<HttpResponsePacket *>();
|
||||||
|
|
||||||
|
pthread_mutex_init(&s_requestQueueMutex, NULL);
|
||||||
|
pthread_mutex_init(&s_responseQueueMutex, NULL);
|
||||||
|
|
||||||
|
pthread_create(&s_requestThread, NULL, requestThread, NULL);
|
||||||
|
pthread_detach(s_requestThread);
|
||||||
|
|
||||||
|
need_quit = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add a get task to queue
|
||||||
|
void CCHttpRequest::addGetTask(std::string url, cocos2d::CCObject *pTarget, SEL_CallFuncND pSelector)
|
||||||
|
{
|
||||||
|
bool inited = lazyInitThreadSemphore();
|
||||||
|
if (!inited) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == s_asyncRequestCount) {
|
||||||
|
CCDirector::sharedDirector()->getScheduler()->scheduleSelector(schedule_selector(CCHttpRequest::dispatchResponseCallbacks), this, 0, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
++s_asyncRequestCount;
|
||||||
|
if (pTarget) {
|
||||||
|
pTarget->retain();
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpRequestPacket *packet = new HttpRequestPacket();
|
||||||
|
packet->reqType = kHttpRequestGet;
|
||||||
|
packet->reqId = this->reqId;
|
||||||
|
packet->url = url;
|
||||||
|
packet->pTarget = pTarget;
|
||||||
|
packet->pSelector = pSelector;
|
||||||
|
|
||||||
|
this->reqId.clear();
|
||||||
|
|
||||||
|
pthread_mutex_lock(&s_requestQueueMutex);
|
||||||
|
s_requestQueue->push(packet);
|
||||||
|
pthread_mutex_unlock(&s_requestQueueMutex);
|
||||||
|
|
||||||
|
//Notify thread start to work
|
||||||
|
sem_post(s_pSem);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add a post task to queue
|
||||||
|
void CCHttpRequest::addPostTask(std::string &url, std::string &postData, CCObject *pTarget, SEL_CallFuncND pSelector)
|
||||||
|
{
|
||||||
|
bool inited = lazyInitThreadSemphore();
|
||||||
|
if (!inited) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == s_asyncRequestCount) {
|
||||||
|
CCDirector::sharedDirector()->getScheduler()->scheduleSelector(schedule_selector(CCHttpRequest::dispatchResponseCallbacks), this, 0, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
++s_asyncRequestCount;
|
||||||
|
if (pTarget) {
|
||||||
|
pTarget->retain();
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpRequestPacket *packet = new HttpRequestPacket();
|
||||||
|
packet->reqType = kHttpRequestPost;
|
||||||
|
packet->reqId = this->reqId;
|
||||||
|
packet->url = url;
|
||||||
|
packet->reqData = postData;
|
||||||
|
packet->pTarget = pTarget;
|
||||||
|
packet->pSelector = pSelector;
|
||||||
|
|
||||||
|
this->reqId.clear();
|
||||||
|
|
||||||
|
pthread_mutex_lock(&s_requestQueueMutex);
|
||||||
|
s_requestQueue->push(packet);
|
||||||
|
pthread_mutex_unlock(&s_requestQueueMutex);
|
||||||
|
|
||||||
|
//Notify thread start to work
|
||||||
|
sem_post(s_pSem);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add post task to queue, data binary safe
|
||||||
|
void CCHttpRequest::addPostTask(std::string &url, std::vector<char> &buffer, cocos2d::CCObject *pTarget, SEL_CallFuncND pSelector)
|
||||||
|
{
|
||||||
|
std::string postData = std::string((const char *)&buffer.front(), buffer.size());
|
||||||
|
addPostTask(url, postData, pTarget, pSelector);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Convert const char* to string and call the matched addPostTask method
|
||||||
|
void CCHttpRequest::addPostTask(std::string &url, const char *buffer, int32_t bufferLen, cocos2d::CCObject *pTarget, SEL_CallFuncND pSelector)
|
||||||
|
{
|
||||||
|
std::string postData = std::string(buffer, bufferLen);
|
||||||
|
addPostTask(url, postData, pTarget, pSelector);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add a download task to queue
|
||||||
|
void CCHttpRequest::addDownloadTask(std::vector<std::string> &urls, CCObject *pTarget, SEL_CallFuncND pSelector)
|
||||||
|
{
|
||||||
|
bool init = lazyInitThreadSemphore();
|
||||||
|
if (!init) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == s_asyncRequestCount) {
|
||||||
|
CCDirector::sharedDirector()->getScheduler()->scheduleSelector(schedule_selector(CCHttpRequest::dispatchResponseCallbacks), this, 0, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
++s_asyncRequestCount;
|
||||||
|
if (pTarget) {
|
||||||
|
pTarget->retain();
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpRequestPacket *packet = new HttpRequestPacket();
|
||||||
|
packet->reqType = kHttpRequestDownloadFile;
|
||||||
|
packet->reqId = this->reqId;
|
||||||
|
packet->files = urls;
|
||||||
|
packet->pTarget = pTarget;
|
||||||
|
packet->pSelector = pSelector;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&s_requestQueueMutex);
|
||||||
|
s_requestQueue->push(packet);
|
||||||
|
pthread_mutex_unlock(&s_requestQueueMutex);
|
||||||
|
|
||||||
|
sem_post(s_pSem);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Poll and notify main thread if responses exists in queue
|
||||||
|
void CCHttpRequest::dispatchResponseCallbacks(float delta)
|
||||||
|
{
|
||||||
|
std::queue<HttpResponsePacket *> *pQueue = s_responseQueue;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&s_responseQueueMutex);
|
||||||
|
if (pQueue->empty()) {
|
||||||
|
pthread_mutex_unlock(&s_responseQueueMutex);
|
||||||
|
} else {
|
||||||
|
HttpResponsePacket *packet = pQueue->front();
|
||||||
|
pQueue->pop();
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&s_responseQueueMutex);
|
||||||
|
|
||||||
|
--s_asyncRequestCount;
|
||||||
|
if (0 == s_asyncRequestCount) {
|
||||||
|
CCDirector::sharedDirector()->getScheduler()->unscheduleSelector(schedule_selector(CCHttpRequest::dispatchResponseCallbacks), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpRequestPacket *orgRequest = packet->request;
|
||||||
|
CCObject *pTarget = orgRequest->pTarget;
|
||||||
|
SEL_CallFuncND pSelector = orgRequest->pSelector;
|
||||||
|
|
||||||
|
if (pTarget && pSelector) {
|
||||||
|
(pTarget->*pSelector)((CCNode *)this, packet);
|
||||||
|
|
||||||
|
pTarget->release();
|
||||||
|
}
|
||||||
|
|
||||||
|
delete orgRequest;
|
||||||
|
delete packet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_CC_EXT_END
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,185 @@
|
||||||
|
/****************************************************************************
|
||||||
|
Copyright (c) 2010-2012 cocos2d-x.org
|
||||||
|
Copyright (c) 2012 greathqy
|
||||||
|
|
||||||
|
http://www.cocos2d-x.org
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __CCHTTPREQUEST_H__
|
||||||
|
#define __CCHTTPREQUEST_H__
|
||||||
|
|
||||||
|
#include "cocos2d.h"
|
||||||
|
#include "ExtensionMacros.h"
|
||||||
|
|
||||||
|
NS_CC_EXT_BEGIN
|
||||||
|
|
||||||
|
//Http request type
|
||||||
|
typedef enum {
|
||||||
|
kHttpRequestGet,
|
||||||
|
kHttpRequestPost,
|
||||||
|
kHttpRequestDownloadFile,
|
||||||
|
} HttpRequestType;
|
||||||
|
|
||||||
|
//Request structure
|
||||||
|
typedef struct {
|
||||||
|
HttpRequestType reqType;
|
||||||
|
std::string url;
|
||||||
|
std::string reqData;
|
||||||
|
std::vector<std::string> files;
|
||||||
|
std::string reqId;
|
||||||
|
cocos2d::CCObject *pTarget;
|
||||||
|
cocos2d::SEL_CallFuncND pSelector;
|
||||||
|
} HttpRequestPacket;
|
||||||
|
|
||||||
|
//Response structure
|
||||||
|
typedef struct {
|
||||||
|
HttpRequestPacket *request;
|
||||||
|
std::string responseData;
|
||||||
|
int32_t responseCode;
|
||||||
|
bool succeed;
|
||||||
|
} HttpResponsePacket;
|
||||||
|
|
||||||
|
/** @brief Singleton that handles asynchrounous http requests
|
||||||
|
* Once the request completed, a callback will issued in main thread when it provided during make request
|
||||||
|
*/
|
||||||
|
class CC_DLL CCHttpRequest : public cocos2d::CCObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/** Return the shared instance **/
|
||||||
|
static CCHttpRequest *sharedHttpRequest();
|
||||||
|
|
||||||
|
/** Relase the shared instance **/
|
||||||
|
static void purgeSharedHttpRequest();
|
||||||
|
|
||||||
|
CCHttpRequest();
|
||||||
|
virtual ~CCHttpRequest();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a get request to task queue
|
||||||
|
* @param url url want to get
|
||||||
|
* @param pTarget callback target
|
||||||
|
* @param pSelector callback selector
|
||||||
|
* @return NULL
|
||||||
|
*/
|
||||||
|
void addGetTask(std::string url, cocos2d::CCObject *pTarget, cocos2d::SEL_CallFuncND pSelector);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a post request to task queue
|
||||||
|
* @param url the post destination url
|
||||||
|
* @param postData data want to post
|
||||||
|
* @param pTarget callback target
|
||||||
|
* @param pSelector callback selector
|
||||||
|
* @return NULL
|
||||||
|
*/
|
||||||
|
void addPostTask(std::string &url, std::string &postData, cocos2d::CCObject *pTarget, cocos2d::SEL_CallFuncND pSelector);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a post request to task queue, binary data supported
|
||||||
|
* @param url the post destination url
|
||||||
|
* @param buffer the data want to post
|
||||||
|
* @param pTarget callback target
|
||||||
|
* @param pSelector callback selector
|
||||||
|
* @return NULL
|
||||||
|
*/
|
||||||
|
void addPostTask(std::string &url, std::vector<char> &buffer, cocos2d::CCObject *pTarget, cocos2d::SEL_CallFuncND pSelector);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a post request to task queue, binary data supported
|
||||||
|
* @param url the post destination url
|
||||||
|
* @param buffer the data want to post
|
||||||
|
* @param buffer the data's length
|
||||||
|
* @param pTarget callback target
|
||||||
|
* @param pSelector callback selector
|
||||||
|
* @return NULL
|
||||||
|
*/
|
||||||
|
void addPostTask(std::string &url, const char *buffer, int32_t bufferLen, cocos2d::CCObject *pTarget, cocos2d::SEL_CallFuncND pSelector);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a download request to task queue
|
||||||
|
* @param url urls want to download
|
||||||
|
* @param pTarget callback target
|
||||||
|
* @param pSelector callback selector
|
||||||
|
* @return NULL
|
||||||
|
*/
|
||||||
|
void addDownloadTask(std::vector<std::string> &urls, cocos2d::CCObject *pTarget, cocos2d::SEL_CallFuncND pSelector);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Change the connect timeout
|
||||||
|
* @param timeout
|
||||||
|
* @return NULL
|
||||||
|
*/
|
||||||
|
inline void setConnectTimeout(int32_t timeout) {m_connectTimeout = timeout;};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get connect timeout
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
inline int32_t getConnectTimeout() {return m_connectTimeout;}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change the download timeout
|
||||||
|
* @param timeout
|
||||||
|
* @return NULL
|
||||||
|
*/
|
||||||
|
inline void setDownloadTimeout(int32_t timeout) {m_timeout = timeout;};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get download timeout
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
inline int32_t getDownloadTimeout() {return m_timeout;}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set request Id
|
||||||
|
* Used to distinguish multple requests if you don't want to provide different callbacks for each request
|
||||||
|
* @param reqId request identifier
|
||||||
|
* @return NULL
|
||||||
|
*/
|
||||||
|
inline void setReqId(const std::string reqId) {this->reqId = reqId;}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get request id
|
||||||
|
* @return NULL
|
||||||
|
*/
|
||||||
|
inline const std::string& getReqId() {return this->reqId;};
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Init pthread mutex, semaphore, and create new thread for http requests
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
bool lazyInitThreadSemphore();
|
||||||
|
/** Poll function called from main thread to dispatch callbacks when http requests finished **/
|
||||||
|
void dispatchResponseCallbacks(float delta);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int32_t m_connectTimeout;
|
||||||
|
int32_t m_timeout;
|
||||||
|
|
||||||
|
std::string reqId;
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_CC_EXT_END
|
||||||
|
|
||||||
|
#endif //__CCHTTPREQUEST_H__
|
|
@ -28,5 +28,7 @@
|
||||||
#include "GUI/CCControlExtension/CCControlExtensions.h"
|
#include "GUI/CCControlExtension/CCControlExtensions.h"
|
||||||
#include "GUI/CCScrollView/CCScrollView.h"
|
#include "GUI/CCScrollView/CCScrollView.h"
|
||||||
|
|
||||||
|
#include "Network/CCHttpRequest/CCHttpRequest.h"
|
||||||
|
|
||||||
#endif /* __COCOS2D_EXT_H__ */
|
#endif /* __COCOS2D_EXT_H__ */
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "NotificationCenterTest/NotificationCenterTest.h"
|
#include "NotificationCenterTest/NotificationCenterTest.h"
|
||||||
#include "ControlExtensionTest/CCControlSceneManager.h"
|
#include "ControlExtensionTest/CCControlSceneManager.h"
|
||||||
#include "CocosBuilderTest/CocosBuilderTest.h"
|
#include "CocosBuilderTest/CocosBuilderTest.h"
|
||||||
|
#include "HttpRequestTest/HttpRequestTest.h"
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -15,6 +16,7 @@ enum
|
||||||
TEST_NOTIFICATIONCENTER = 0,
|
TEST_NOTIFICATIONCENTER = 0,
|
||||||
TEST_CCCONTROLBUTTON,
|
TEST_CCCONTROLBUTTON,
|
||||||
TEST_COCOSBUILDER,
|
TEST_COCOSBUILDER,
|
||||||
|
TEST_HTTPREQUEST,
|
||||||
TEST_MAX_COUNT,
|
TEST_MAX_COUNT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -23,6 +25,7 @@ static const std::string testsName[TEST_MAX_COUNT] =
|
||||||
"NotificationCenterTest",
|
"NotificationCenterTest",
|
||||||
"CCControlButtonTest",
|
"CCControlButtonTest",
|
||||||
"CocosBuilderTest",
|
"CocosBuilderTest",
|
||||||
|
"HttpRequestTest",
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////
|
||||||
|
@ -80,6 +83,10 @@ void ExtensionsMainLayer::menuCallback(CCObject* pSender)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case TEST_HTTPREQUEST:
|
||||||
|
{
|
||||||
|
runHttpRequestTest();
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,148 @@
|
||||||
//
|
#include "HttpRequestTest.h"
|
||||||
// HttpRequestTest.cpp
|
#include "../ExtensionsTest.h"
|
||||||
// TestCpp
|
|
||||||
//
|
#define GETURL "http://www.google.com"
|
||||||
// Created by qingyun on 12-8-4.
|
#define POSTURL "http://www.replacewithyours.com/post.php"
|
||||||
// Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
|
#define DOWNLOADURL "http://www.google.com/index.html"
|
||||||
//
|
|
||||||
|
USING_NS_CC;
|
||||||
|
USING_NS_CC_EXT;
|
||||||
|
|
||||||
|
HttpRequestTest::HttpRequestTest() : m_labelStatusCode(NULL)
|
||||||
|
{
|
||||||
|
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
|
||||||
|
|
||||||
|
CCLabelTTF *label = CCLabelTTF::create("Http Request Test", "Arial", 28);
|
||||||
|
label->setPosition(ccp(winSize.width / 2, winSize.height - 50));
|
||||||
|
addChild(label, 0);
|
||||||
|
|
||||||
|
CCMenu *menuRequest = CCMenu::create();
|
||||||
|
menuRequest->setPosition(CCPointZero);
|
||||||
|
addChild(menuRequest);
|
||||||
|
|
||||||
|
//Get
|
||||||
|
CCLabelTTF *labelGet = CCLabelTTF::create("Test Get", "Arial", 15);
|
||||||
|
CCMenuItemLabel *itemGet = CCMenuItemLabel::create(labelGet, this, menu_selector(HttpRequestTest::onLabelGetTestClicked));
|
||||||
|
itemGet->setPosition(ccp(winSize.width / 2, winSize.height - 100));
|
||||||
|
menuRequest->addChild(itemGet);
|
||||||
|
|
||||||
|
//Post
|
||||||
|
CCLabelTTF *labelPost = CCLabelTTF::create("Test Post", "Arial", 15);
|
||||||
|
CCMenuItemLabel *itemPost = CCMenuItemLabel::create(labelPost, this, menu_selector(HttpRequestTest::onLabelPostTestClicked));
|
||||||
|
itemPost->setPosition(ccp(winSize.width / 2, winSize.height - 130));
|
||||||
|
menuRequest->addChild(itemPost);
|
||||||
|
|
||||||
|
//Post Binary
|
||||||
|
CCLabelTTF *labelPostBinary = CCLabelTTF::create("Test Post Binary", "Arial", 15);
|
||||||
|
CCMenuItemLabel *itemPostBinary = CCMenuItemLabel::create(labelPostBinary, this, menu_selector(HttpRequestTest::onLabelPostBinaryTestClicked));
|
||||||
|
itemPostBinary->setPosition(ccp(winSize.width / 2, winSize.height - 160));
|
||||||
|
menuRequest->addChild(itemPostBinary);
|
||||||
|
|
||||||
|
//Download File
|
||||||
|
CCLabelTTF *labelDownload = CCLabelTTF::create("Test Download", "Arial", 15);
|
||||||
|
CCMenuItemLabel *itemDownload = CCMenuItemLabel::create(labelDownload, this, menu_selector(HttpRequestTest::onLabelDownloadTestClicked));
|
||||||
|
itemDownload->setPosition(ccp(winSize.width / 2, winSize.height - 190));
|
||||||
|
menuRequest->addChild(itemDownload);
|
||||||
|
|
||||||
|
//Response Code Label
|
||||||
|
CCLabelTTF *labelStatus = CCLabelTTF::create("Notice: Replace Post Url With Your Own", "Marker Felt", 20);
|
||||||
|
labelStatus->setPosition(ccp(winSize.width / 2, winSize.height - 250));
|
||||||
|
addChild(labelStatus);
|
||||||
|
setLabelStatusCode(labelStatus);
|
||||||
|
|
||||||
|
//Back Menu
|
||||||
|
CCMenuItemFont *itemBack = CCMenuItemFont::create("Back", this, menu_selector(HttpRequestTest::toExtensionsMainLayer));
|
||||||
|
itemBack->setPosition(ccp(winSize.width - 50, 25));
|
||||||
|
CCMenu *menuBack = CCMenu::create(itemBack, NULL);
|
||||||
|
menuBack->setPosition(CCPointZero);
|
||||||
|
addChild(menuBack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpRequestTest::onLabelGetTestClicked(cocos2d::CCObject *sender)
|
||||||
|
{
|
||||||
|
string url = GETURL;
|
||||||
|
|
||||||
|
CCHttpRequest *requestor = CCHttpRequest::sharedHttpRequest();
|
||||||
|
requestor->addGetTask(url, this, callfuncND_selector(HttpRequestTest::onHttpRequestCompleted));
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpRequestTest::onLabelPostTestClicked(cocos2d::CCObject *sender)
|
||||||
|
{
|
||||||
|
string url = POSTURL;
|
||||||
|
string content = "username=hello&password=world";
|
||||||
|
|
||||||
|
CCHttpRequest *requestor = CCHttpRequest::sharedHttpRequest();
|
||||||
|
//You may name the request
|
||||||
|
requestor->setReqId("login");
|
||||||
|
requestor->addPostTask(url, content, this, callfuncND_selector(HttpRequestTest::onHttpRequestCompleted));
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpRequestTest::onLabelPostBinaryTestClicked(cocos2d::CCObject *sender)
|
||||||
|
{
|
||||||
|
string url = POSTURL;
|
||||||
|
const char *content = "username=hello&password=worl\0d";
|
||||||
|
|
||||||
|
CCHttpRequest *requestor = CCHttpRequest::sharedHttpRequest();
|
||||||
|
requestor->setReqId("postbinary");
|
||||||
|
requestor->addPostTask(url, content, strlen(content) + 2, this, callfuncND_selector(HttpRequestTest::onHttpRequestCompleted));
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpRequestTest::onLabelDownloadTestClicked(cocos2d::CCObject *sender)
|
||||||
|
{
|
||||||
|
string url = DOWNLOADURL;
|
||||||
|
vector<string> files;
|
||||||
|
|
||||||
|
files.push_back(url);
|
||||||
|
|
||||||
|
CCHttpRequest *requestor = CCHttpRequest::sharedHttpRequest();
|
||||||
|
requestor->setReqId("download");
|
||||||
|
requestor->addDownloadTask(files, this, callfuncND_selector(HttpRequestTest::onHttpRequestCompleted));
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpRequestTest::onHttpRequestCompleted(cocos2d::CCObject *sender, void *data)
|
||||||
|
{
|
||||||
|
HttpResponsePacket *response = (HttpResponsePacket *)data;
|
||||||
|
|
||||||
|
//You can get original request type from: response->request->reqType
|
||||||
|
|
||||||
|
if (response->request->reqId != "") {
|
||||||
|
CCLog("%s completed", response->request->reqId.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
char buffer[128];
|
||||||
|
sprintf(buffer, "Response code: %d", response->responseCode);
|
||||||
|
getLabelStatusCode()->setString(buffer);
|
||||||
|
|
||||||
|
if (!response->succeed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//If the response is binary, use response->responseData.data() and response->responseData.length()
|
||||||
|
//To process the response
|
||||||
|
CCLog("Response Content: %s", response->responseData.c_str());
|
||||||
|
|
||||||
|
if (response->request->reqId == "download") {
|
||||||
|
string downloaded = response->request->files[0];
|
||||||
|
string saved = downloaded.substr(downloaded.rfind("/") + 1);
|
||||||
|
|
||||||
|
CCLog("%s downloaded, and saved as %s in your application's writeable directory", downloaded.c_str(), saved.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpRequestTest::toExtensionsMainLayer(cocos2d::CCObject *sender)
|
||||||
|
{
|
||||||
|
ExtensionsTestScene *pScene = new ExtensionsTestScene();
|
||||||
|
pScene->runThisTest();
|
||||||
|
pScene->release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void runHttpRequestTest()
|
||||||
|
{
|
||||||
|
CCScene *pScene = CCScene::create();
|
||||||
|
HttpRequestTest *pLayer = new HttpRequestTest();
|
||||||
|
pScene->addChild(pLayer);
|
||||||
|
|
||||||
|
CCDirector::sharedDirector()->replaceScene(pScene);
|
||||||
|
pLayer->release();
|
||||||
|
}
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
|
@ -1,14 +1,26 @@
|
||||||
//
|
#ifndef __HTTPREQUESTHTTP_H
|
||||||
// HttpRequestTest.h
|
#define __HTTPREQUESTHTTP_H
|
||||||
// TestCpp
|
|
||||||
//
|
|
||||||
// Created by qingyun on 12-8-4.
|
|
||||||
// Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef TestCpp_HttpRequestTest_h
|
#include "cocos2d.h"
|
||||||
#define TestCpp_HttpRequestTest_h
|
#include "cocos-ext.h"
|
||||||
|
|
||||||
|
class HttpRequestTest : public cocos2d::CCLayer
|
||||||
|
{
|
||||||
|
CC_SYNTHESIZE(CCLabelTTF *, m_labelStatusCode, LabelStatusCode);
|
||||||
|
public:
|
||||||
|
HttpRequestTest();
|
||||||
|
void toExtensionsMainLayer(cocos2d::CCObject *sender);
|
||||||
|
|
||||||
|
//Menu Callbacks
|
||||||
|
void onLabelGetTestClicked(cocos2d::CCObject *sender);
|
||||||
|
void onLabelPostTestClicked(cocos2d::CCObject *sender);
|
||||||
|
void onLabelPostBinaryTestClicked(cocos2d::CCObject *sender);
|
||||||
|
void onLabelDownloadTestClicked(cocos2d::CCObject *sender);
|
||||||
|
|
||||||
#endif
|
//Http Response Callback
|
||||||
|
void onHttpRequestCompleted(cocos2d::CCObject *sender, void *data);
|
||||||
|
};
|
||||||
|
|
||||||
|
void runHttpRequestTest();
|
||||||
|
|
||||||
|
#endif //__HTTPREQUESTHTTP_H
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
7dea09f758e229595c7992fee3cc0a0f0fb49f79
|
eae8f176936098bc77ca4472b94f9e018f5c368c
|
Loading…
Reference in New Issue