#include "stdafx.h" #include "SonyHttp_Vita.h" static const int sc_SSLHeapSize = (304 * 1024U); static const int sc_HTTPHeapSize = (80 * 1024); static const int sc_NetHeapSize = (16 * 1024); #define TEST_USER_AGENT "SimpleSample/1.00" // int SonyHttp_Vita::libnetMemId = 0; int SonyHttp_Vita::libsslCtxId = 0; int SonyHttp_Vita::libhttpCtxId = 0; bool SonyHttp_Vita:: bInitialised = false; bool SonyHttp_Vita::init() { // int ret = sceNetPoolCreate("simple", sc_NetHeapSize, 0); // assert(ret >= 0); // libnetMemId = ret; // int ret = sceSslInit(sc_SSLHeapSize); // assert(ret >= 0 || ret == SCE_SSL_ERROR_ALREADY_INITED); // libsslCtxId = ret; // // ret = sceHttpInit(sc_HTTPHeapSize); // assert(ret >= 0 || ret == SCE_HTTP_ERROR_ALREADY_INITED); // libhttpCtxId = ret; bInitialised = true; return true; } void SonyHttp_Vita::shutdown() { PSVITA_STUBBED; // int ret = sceHttpTerm(libhttpCtxId); // assert(ret == SCE_OK); // // ret = sceSslTerm(libsslCtxId); // assert(ret == SCE_OK); // // /* libnet */ // ret = sceNetPoolDestroy(libnetMemId); // assert(ret == SCE_OK); } void SonyHttp_Vita::printSslError(SceInt32 sslErr, SceUInt32 sslErrDetail) { switch (sslErr) { case (SCE_HTTPS_ERROR_CERT): /* Verify error */ /* Internal error at verifying certificate*/ if (sslErrDetail & SCE_HTTPS_ERROR_SSL_INTERNAL){ app.DebugPrintf("ssl verify error: unexpcted error\n"); } /* Error of server certificate or CA certificate */ if (sslErrDetail & SCE_HTTPS_ERROR_SSL_INVALID_CERT){ app.DebugPrintf("ssl verify error: invalid server cert or CA cert\n"); } /* Server hostname and server certificate are mismatched*/ if (sslErrDetail & SCE_HTTPS_ERROR_SSL_CN_CHECK){ app.DebugPrintf("ssl verify error: invalid server hostname\n"); } /* Server certificate or CA certificate is expired.*/ if (sslErrDetail & SCE_HTTPS_ERROR_SSL_NOT_AFTER_CHECK){ app.DebugPrintf("ssl verify error: server cert or CA cert had expired\n"); } /* Server certificate or CA certificate is before validated.*/ if (sslErrDetail & SCE_HTTPS_ERROR_SSL_NOT_BEFORE_CHECK){ app.DebugPrintf("ssl verify error: server cert or CA cert isn't validated yet.\n"); } /* Unknown CA error */ if (sslErrDetail & SCE_HTTPS_ERROR_SSL_UNKNOWN_CA){ app.DebugPrintf("ssl verify error: unknown CA\n"); } break; case (SCE_HTTPS_ERROR_HANDSHAKE): /* fail to ssl-handshake */ app.DebugPrintf("ssl error: handshake error\n"); break; case (SCE_HTTPS_ERROR_IO): /* Error of Socket IO */ app.DebugPrintf("ssl error: io error\n"); break; case (SCE_HTTP_ERROR_OUT_OF_MEMORY): /* Out of memory*/ app.DebugPrintf("ssl error: out of memory\n"); break; case (SCE_HTTPS_ERROR_INTERNAL): /* Unexpected Internal Error*/ app.DebugPrintf("ssl error: unexpcted error\n"); break; default: break; } return; } void SonyHttp_Vita::printSslCertInfo(SceSslCert *sslCert) { SceInt32 ret; const SceUChar8 *sboData; SceSize sboLen, counter; ret = sceSslGetSerialNumber(sslCert, &sboData, &sboLen); if (ret < 0){ app.DebugPrintf ("sceSslGetSerialNumber() returns 0x%x\n", ret); } else { app.DebugPrintf("Serial number="); for (counter = 0; counter < sboLen; counter++){ app.DebugPrintf("%02X", sboData[counter]); } app.DebugPrintf("\n"); } } bool SonyHttp_Vita::getDataFromURL( const char* szURL, void** ppOutData, int* pDataSize) { if(!bInitialised) return false; return http_get(szURL, ppOutData, pDataSize); } int SonyHttp_Vita::sslCallback(SceUInt32 verifyErr, SceSslCert * const sslCert[], SceInt32 certNum, void *userArg) { SceInt32 i; (void)userArg; app.DebugPrintf("Ssl callback:\n"); app.DebugPrintf("\tbase tmpl[%x]\n", (SceInt32)userArg); if (verifyErr != 0){ printSslError((SceInt32)SCE_HTTPS_ERROR_CERT, verifyErr); } for (i = 0; i < certNum; i++){ printSslCertInfo(sslCert[i]); } if (verifyErr == 0){ return SCE_OK; } else { return -1; } } bool SonyHttp_Vita::http_get_close(bool bOK, SceInt32 tmplId, SceInt32 connId, SceInt32 reqId) { SceInt32 ret; if (reqId > 0) { ret = sceHttpDeleteRequest(reqId); assert(ret >= 0); } if (connId > 0) { ret = sceHttpDeleteConnection(connId); assert(ret >= 0); } if (tmplId > 0) { ret = sceHttpDeleteTemplate(tmplId); assert(ret >= 0); } assert(bOK); return bOK; } bool SonyHttp_Vita::http_get(const char *targetUrl, void** ppOutData, int* pDataSize) { SceInt32 ret, tmplId=0, connId=0, reqId=0, statusCode; SceULong64 contentLength=0; SceBool finFlag=SCE_FALSE; SceUChar8* recvBuf; ret = sceHttpCreateTemplate(TEST_USER_AGENT, SCE_HTTP_VERSION_1_1, SCE_TRUE); if (ret < 0) { app.DebugPrintf("sceHttpCreateTemplate() error: 0x%08X\n", ret); return http_get_close(false, tmplId, connId, reqId); } tmplId = ret; /* Perform http_get without server verification */ ret = sceHttpsDisableOption(SCE_HTTPS_FLAG_SERVER_VERIFY); if (ret < 0) { app.DebugPrintf("sceHttpsDisableOption() error: 0x%08X\n", ret); return http_get_close(false, tmplId, connId, reqId); } /* Register SSL callback */ ret = sceHttpsSetSslCallback(tmplId, sslCallback, (void*)&tmplId); if (ret < 0) { app.DebugPrintf("sceHttpsSetSslCallback() error: 0x%08X\n", ret); return http_get_close(false, tmplId, connId, reqId); } ret = sceHttpCreateConnectionWithURL(tmplId, targetUrl, SCE_TRUE); if (ret < 0) { app.DebugPrintf("sceHttpCreateConnectionWithURL() error: 0x%08X\n", ret); return http_get_close(false, tmplId, connId, reqId); } connId = ret; ret = sceHttpCreateRequestWithURL(connId, SCE_HTTP_METHOD_GET, targetUrl, 0); if (ret < 0) { app.DebugPrintf("sceHttpCreateRequestWithURL() error: 0x%08X\n", ret); return http_get_close(false, tmplId, connId, reqId); } reqId = ret; ret = sceHttpSendRequest(reqId, NULL, 0); if (ret < 0) { app.DebugPrintf("sceHttpSendRequest() error: 0x%08X\n", ret); return http_get_close(false, tmplId, connId, reqId); } ret = sceHttpGetStatusCode(reqId, &statusCode); if (ret < 0) { app.DebugPrintf("sceHttpGetStatusCode() error: 0x%08X\n", ret); return http_get_close(false, tmplId, connId, reqId); } app.DebugPrintf("response code = %d\n", statusCode); if(statusCode == 200) { ret = sceHttpGetResponseContentLength(reqId, &contentLength); if(ret < 0) { app.DebugPrintf("sceHttpGetContentLength() error: 0x%08X\n", ret); return http_get_close(false, tmplId, connId, reqId); } else { app.DebugPrintf("Content-Length = %lu\n", contentLength); } recvBuf = new SceUChar8[contentLength+1]; int bufferLeft = contentLength+1; SceUChar8* pCurrBuffPos = recvBuf; int totalBytesRead = 0; while(finFlag != SCE_TRUE) { ret = sceHttpReadData(reqId, pCurrBuffPos, bufferLeft); if (ret < 0) { app.DebugPrintf("\n sceHttpReadData() failed 0x%08X\n", ret); return http_get_close(false, tmplId, connId, reqId); } else if (ret == 0) { finFlag = SCE_TRUE; } app.DebugPrintf("\n sceHttpReadData() read %d bytes\n", ret); pCurrBuffPos += ret; totalBytesRead += ret; bufferLeft -= ret; } } *ppOutData = recvBuf; *pDataSize = contentLength; return http_get_close(true, tmplId, connId, reqId); }