open source
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
//文字相关的函数
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
void CToObjectCLog( const char* szFormat,...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, szFormat);
|
||||
NSString* nsFormat = [NSString stringWithUTF8String:szFormat];
|
||||
NSLogv( nsFormat, args);
|
||||
va_end(args);
|
||||
}
|
||||
void CToObjectCLogI( const char* szFormat,...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, szFormat);
|
||||
NSString* nsFormat = [NSString stringWithUTF8String:szFormat];
|
||||
NSLogv( nsFormat, args);
|
||||
va_end(args);
|
||||
}
|
||||
void CToObjectCLogE( const char* szFormat,...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, szFormat);
|
||||
NSString* nsFormat = [NSString stringWithUTF8String:szFormat];
|
||||
NSLogv( nsFormat, args);
|
||||
va_end(args);
|
||||
}
|
||||
void CToObjectCLogW( const char* szFormat,...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, szFormat);
|
||||
NSString* nsFormat = [NSString stringWithUTF8String:szFormat];
|
||||
NSLogv( nsFormat, args);
|
||||
va_end(args);
|
||||
}
|
||||
void alert(const char* fmt, ...)
|
||||
{
|
||||
char buf[1024];
|
||||
char* pBuf = NULL;
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
int len = vsprintf(buf, fmt, args);
|
||||
if (len < 0) {
|
||||
pBuf = new char[4096];
|
||||
len = vsprintf(pBuf, fmt, args);
|
||||
}
|
||||
va_end(args);
|
||||
CToObjectCLog(pBuf ? pBuf : buf);
|
||||
if (pBuf)
|
||||
{
|
||||
delete[] pBuf;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
|
||||
|
||||
#include "LayaCacheManager.h"
|
||||
#include "resource/JCFileResManager.h"
|
||||
#include "downloadCache/JCServerFileCache.h"
|
||||
#include "downloadMgr/JCDownloadMgr.h"
|
||||
#include "misc/JCWorkerThread.h"
|
||||
#include <cmath>
|
||||
std::string gAssetRootPath = "";
|
||||
std::string gRedistPath = "";
|
||||
namespace laya {
|
||||
|
||||
LayaCacheManager* LayaCacheManager::m_pInstance = nullptr;
|
||||
|
||||
LayaCacheManager::LayaCacheManager()
|
||||
{
|
||||
m_pSvFileCache = nullptr;
|
||||
pthread_key_create(&JCWorkerThread::s_tls_curThread, NULL);
|
||||
pthread_key_create(&s_tls_curDataThread, NULL);
|
||||
JCDownloadMgr::getInstance()->init(3);//多加一个线程,可能要给优先级较低的任务用。
|
||||
m_pFileResMgr = new JCFileResManager(JCDownloadMgr::getInstance());
|
||||
|
||||
m_CallbackRef.reset(new int(1));
|
||||
}
|
||||
|
||||
LayaCacheManager::~LayaCacheManager()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
LayaCacheManager* LayaCacheManager::getInstance(){
|
||||
if( m_pInstance == NULL){
|
||||
m_pInstance = new LayaCacheManager();
|
||||
}
|
||||
return m_pInstance;
|
||||
}
|
||||
|
||||
void LayaCacheManager::delInstance(){
|
||||
if(m_pInstance){
|
||||
delete m_pInstance;
|
||||
m_pInstance = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
std::string LayaCacheManager::preUpdateDcc(const std::string& redistPath,const std::string& domain)
|
||||
{
|
||||
if (m_pSvFileCache != nullptr){
|
||||
delete m_pSvFileCache;
|
||||
}
|
||||
m_pSvFileCache = new laya::JCServerFileCache();
|
||||
m_pFileResMgr->setFileCache(m_pSvFileCache);
|
||||
m_pSvFileCache->setCachePath((redistPath + "appCache").c_str());
|
||||
m_pSvFileCache->switchToApp(domain.c_str());
|
||||
|
||||
m_pSvFileCache->setResourceID("appurl", domain.c_str());
|
||||
return m_pSvFileCache->getResourceID("netassetsid");
|
||||
}
|
||||
|
||||
void LayaCacheManager::updateDccClearAssetsid(const std::string& redistPath,const std::string& domain)
|
||||
{
|
||||
m_pSvFileCache->saveFileTable("");
|
||||
m_pSvFileCache->setResourceID("netassetsid", "");
|
||||
if (m_pSvFileCache != nullptr){
|
||||
delete m_pSvFileCache;
|
||||
}
|
||||
m_pSvFileCache = new laya::JCServerFileCache();
|
||||
m_pFileResMgr->setFileCache(m_pSvFileCache);
|
||||
m_pSvFileCache->setCachePath((redistPath + "appCache").c_str());
|
||||
m_pSvFileCache->switchToApp(domain.c_str());
|
||||
}
|
||||
|
||||
void LayaCacheManager::doUpdateDcc(const std::string& redistPath,const std::string& domain,const std::string& txtdcc,const std::string& assetsid)
|
||||
{
|
||||
m_pSvFileCache->saveFileTable(txtdcc.c_str());
|
||||
if (m_pSvFileCache != nullptr){
|
||||
delete m_pSvFileCache;
|
||||
}
|
||||
m_pSvFileCache = new laya::JCServerFileCache();
|
||||
m_pFileResMgr->setFileCache(m_pSvFileCache);
|
||||
m_pSvFileCache->setCachePath((redistPath + "appCache").c_str());
|
||||
m_pSvFileCache->switchToApp(domain.c_str());
|
||||
|
||||
m_pSvFileCache->setResourceID("netassetsid", assetsid.c_str());
|
||||
}
|
||||
void LayaCacheManager::handleRequest(const char* strUrl, std::function<void(void* pData, int length)> onDownload, std::function<void(int errCode)> onError)
|
||||
{
|
||||
laya::JCFileRes* pRes = m_pFileResMgr->getRes(strUrl);
|
||||
std::weak_ptr<int> cbref(m_CallbackRef);
|
||||
pRes->setOnReadyCB(std::bind(&LayaCacheManager::onDownloadEnd,this, std::placeholders::_1, cbref, onDownload));
|
||||
pRes->setOnErrorCB(std::bind(&LayaCacheManager::onDownloadErr, this, std::placeholders::_1, std::placeholders::_2, cbref, onError));
|
||||
|
||||
}
|
||||
bool LayaCacheManager::onDownloadErr(void* p_pRes, int p_nErrCode,std::weak_ptr<int> callbackref, std::function<void(int errCode)> onError)
|
||||
{
|
||||
if (!callbackref.lock())
|
||||
return false;
|
||||
onError(p_nErrCode);
|
||||
return true;
|
||||
}
|
||||
bool LayaCacheManager::onDownloadEnd(void* p_pRes, std::weak_ptr<int> callbackref, std::function<void(void* pData, int length)> onDownload)
|
||||
{
|
||||
if( !callbackref.lock() )
|
||||
return false;
|
||||
|
||||
laya::JCResStateDispatcher* pRes = (laya::JCResStateDispatcher*)p_pRes;
|
||||
laya::JCFileRes* pFileRes = (laya::JCFileRes*)pRes;
|
||||
|
||||
if( pFileRes->m_pBuffer.get()==NULL || pFileRes->m_nLength==0 ){
|
||||
return false;
|
||||
}
|
||||
|
||||
onDownload(pFileRes->m_pBuffer.get(), pFileRes->m_nLength);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
#ifndef LayaCacheManager_hpp
|
||||
#define LayaCacheManager_hpp
|
||||
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include <functional>
|
||||
|
||||
namespace laya {
|
||||
|
||||
class JCFileResManager;
|
||||
class JCServerFileCache;
|
||||
class JCFileRes;
|
||||
class LayaCacheManager
|
||||
{
|
||||
public:
|
||||
LayaCacheManager();
|
||||
virtual ~LayaCacheManager();
|
||||
static LayaCacheManager* getInstance();
|
||||
static void delInstance();
|
||||
void handleRequest(const char* strUrl, std::function<void(void* pData, int length)> onDownload, std::function<void(int errCode)> onError);
|
||||
bool onDownloadErr(void* p_pRes, int p_nErrCode,std::weak_ptr<int> callbackref, std::function<void(int errCode)> onError);
|
||||
bool onDownloadEnd(void* p_pRes, std::weak_ptr<int> callbackref, std::function<void(void* pData, int length)> onDownload);
|
||||
std::string preUpdateDcc(const std::string& redistPath,const std::string& domain);
|
||||
void updateDccClearAssetsid(const std::string& redistPath,const std::string& domain);
|
||||
void doUpdateDcc(const std::string& redistPath,const std::string& domain,const std::string& txtdcc,const std::string& assetsid);
|
||||
protected:
|
||||
JCFileResManager* m_pFileResMgr;
|
||||
JCServerFileCache* m_pSvFileCache;
|
||||
static LayaCacheManager* m_pInstance;
|
||||
std::shared_ptr<int> m_CallbackRef;
|
||||
};
|
||||
}
|
||||
#endif /* LayaCacheManager_hpp */
|
||||
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// LayaWKWebview.h
|
||||
// LayaWKWebview
|
||||
//
|
||||
// Created by helloworldlv on 2018/3/23.
|
||||
// Copyright © 2018年 render. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <WebKit/WebKit.h>
|
||||
#import <WebKit/WKWebview.h>
|
||||
#import <WebKit/WKUserContentController.h>
|
||||
#import <WebKit/WKUserScript.h>
|
||||
|
||||
@interface LayaWKWebview : NSObject
|
||||
@property(nonatomic, strong) WKWebView* webview;
|
||||
/*接管下载,支持DCC*/
|
||||
- (instancetype)initWithWebview:(WKWebView*)webview url:(NSString*)url hostPort:(int)port;
|
||||
/*直接调WKWebview,不支持DCC*/
|
||||
- (instancetype)initWithWebview:(WKWebView*)webview url:(NSString*)url;
|
||||
- (void)loadUrl:(NSString*)url;
|
||||
- (NSString*)callMethod:(int)objid className:(NSString*)cls methodName:(NSString*)method param:(NSString*)param;
|
||||
-(void)callbackToJSWithClass:(Class)cls methodName:(NSString*)name ret:(NSObject*)retObj;
|
||||
-(void)callbackToJSWithClassName:(NSString*)cls methodName:(NSString*)name ret:(NSObject*)retObj;
|
||||
-(void)callbackToJSWithObject:(id)obj methodName:(NSString*)name ret:(NSObject*)retObj;
|
||||
-(void)runJS:(NSString*)script;
|
||||
+(LayaWKWebview*)GetLayaWKWebview;
|
||||
@end
|
||||
@@ -0,0 +1,325 @@
|
||||
//
|
||||
// LayaWKWebview.m
|
||||
// LayaWKWebview
|
||||
//
|
||||
// Created by helloworldlv on 2018/3/23.
|
||||
// Copyright © 2018年 render. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LayaWKWebview.h"
|
||||
#import "GCDWebServer.h"
|
||||
#import "GCDWebServerDataResponse.h"
|
||||
#import "GCDWebServerFunctions.h"
|
||||
#import "refection.h"
|
||||
#include <string>
|
||||
#include "LayaCache/LayaCacheManager.h"
|
||||
extern std::string gRedistPath;
|
||||
extern std::string gAssetRootPath;
|
||||
|
||||
static LayaWKWebview* g_pLayaWKWebview = nil;
|
||||
|
||||
@implementation LayaWKWebview
|
||||
{
|
||||
NSString* _url;
|
||||
int _hostPort;
|
||||
GCDWebServer* _GCDWebServer;
|
||||
Reflection* _reflection;
|
||||
NSString* _urlSuffix;
|
||||
}
|
||||
+(LayaWKWebview*)GetLayaWKWebview
|
||||
{
|
||||
return g_pLayaWKWebview;
|
||||
}
|
||||
- (instancetype)initWithWebview:(WKWebView*)webview url:(NSString*)url
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
g_pLayaWKWebview = self;
|
||||
_webview = webview;
|
||||
_url = url;
|
||||
_hostPort = 0;
|
||||
NSURL* pUrl = [NSURL URLWithString:url];
|
||||
NSURLRequest* pUrlRequest = [NSURLRequest requestWithURL:pUrl];
|
||||
[_webview loadRequest:pUrlRequest];
|
||||
_reflection = [[Reflection alloc]init:self];
|
||||
_urlSuffix = nil;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
- (instancetype)initWithWebview:(WKWebView*)webview url:(NSString*)url hostPort:(int)port;
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
g_pLayaWKWebview = self;
|
||||
_reflection = [[Reflection alloc]init:self];
|
||||
_webview = webview;
|
||||
_url = url;
|
||||
_hostPort = port;
|
||||
if ([url isEqual:@"http://stand.alone.version/index.html"] || [url isEqual:@"http://stand.alone.version/index.js"])
|
||||
{
|
||||
gRedistPath = [[self getRootCachePath] cStringUsingEncoding:NSUTF8StringEncoding];
|
||||
gAssetRootPath= [[self getResourcePath] cStringUsingEncoding:NSUTF8StringEncoding];
|
||||
gAssetRootPath += "/cache/";
|
||||
NSString* urlpath = [self getLaunchUrlDomain:url];
|
||||
NSLog(@"[dcc] [%@]",url);
|
||||
laya::LayaCacheManager::getInstance()->preUpdateDcc(gRedistPath,urlpath.UTF8String);
|
||||
[self requestGame:url];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self updateDcc:_url];
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
-(NSString *)convertDataToHexStr:(NSData *)data
|
||||
{
|
||||
if (!data || [data length] == 0)
|
||||
{
|
||||
return @"";
|
||||
}
|
||||
NSMutableString *string = [[NSMutableString alloc] initWithCapacity:[data length]];
|
||||
[data enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop)
|
||||
{
|
||||
unsigned char *dataBytes = (unsigned char*)bytes;
|
||||
for (NSInteger i = byteRange.length - 1; i >=0 ; i--)
|
||||
{
|
||||
NSString *hexStr = [NSString stringWithFormat:@"%x", (dataBytes[i]) & 0xff];
|
||||
if ([hexStr length] == 2)
|
||||
{
|
||||
[string appendString:hexStr];
|
||||
} else
|
||||
{
|
||||
[string appendFormat:@"0%@", hexStr];
|
||||
}
|
||||
}
|
||||
}];
|
||||
return string;
|
||||
}
|
||||
-(NSString*)getLaunchUrlDomain:(NSString*)url
|
||||
{
|
||||
NSString* domain = [[NSString alloc] initWithString:url];
|
||||
domain = [domain stringByReplacingOccurrencesOfString:@"?" withString:@""];
|
||||
domain = [[NSURL alloc] initWithString:domain].URLByDeletingLastPathComponent.absoluteString;
|
||||
return domain;
|
||||
}
|
||||
-(NSString*)getLayaBoxUrl
|
||||
{
|
||||
return [NSString stringWithFormat:@"http://127.0.0.1:%lu/s/%@", (unsigned long)(_GCDWebServer.port),_url];
|
||||
}
|
||||
-(NSString*) getResourcePath
|
||||
{
|
||||
return [[NSBundle mainBundle] resourcePath];
|
||||
}
|
||||
-(NSString*) getRootCachePath
|
||||
{
|
||||
NSString* sAppDirctory = NSHomeDirectory();
|
||||
NSString* sDownloadRootPath = [ NSString stringWithFormat: @"%@/Library/Caches/", sAppDirctory ];
|
||||
return sDownloadRootPath;
|
||||
}
|
||||
- (void)updateDcc:(NSString*)url
|
||||
{
|
||||
gRedistPath = [[self getRootCachePath] cStringUsingEncoding:NSUTF8StringEncoding];
|
||||
gAssetRootPath= [[self getResourcePath] cStringUsingEncoding:NSUTF8StringEncoding];
|
||||
gAssetRootPath += "/cache/";
|
||||
NSLog(@"[dcc] update dcc start [%@] ...",url);
|
||||
NSString* urlpath = [self getLaunchUrlDomain:url];
|
||||
/*NSString* urlpath = [[NSString alloc] initWithString:url];
|
||||
urlpath = [urlpath stringByReplacingOccurrencesOfString:@"?" withString:@""];
|
||||
urlpath = [[NSURL alloc] initWithString:urlpath].URLByDeletingLastPathComponent.absoluteString;*/
|
||||
NSLog(@"[dcc] [%@]",url);
|
||||
std::string curassets = laya::LayaCacheManager::getInstance()->preUpdateDcc(gRedistPath,urlpath.UTF8String);
|
||||
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:nil delegateQueue:[NSOperationQueue mainQueue]];
|
||||
NSString* asidUrl = [[NSString alloc] initWithFormat:@"%@update/assetsid.txt?rand=%f",urlpath,(rand()/(float)RAND_MAX) * [NSDate date].timeIntervalSince1970];
|
||||
NSLog(@"[dcc] %@",asidUrl);
|
||||
|
||||
NSURLSessionDataTask *task = [session dataTaskWithURL:[NSURL URLWithString:asidUrl] completionHandler:^(NSData * data, NSURLResponse * response, NSError * error)
|
||||
{
|
||||
NSLog(@"[dcc] assetsid.txt download complete");
|
||||
NSString* assetsidStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
||||
if (error || (assetsidStr == nil) || [assetsidStr isEqualToString:@""])
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
NSLog(@"[dcc] assetsid.txt download error [%@] [%@] [%@]",error.localizedFailureReason,error.localizedDescription,error.localizedRecoverySuggestion);
|
||||
}
|
||||
laya::LayaCacheManager::getInstance()->updateDccClearAssetsid(gRedistPath,urlpath.UTF8String);
|
||||
[self requestGame:url];
|
||||
}
|
||||
else
|
||||
{
|
||||
if ([assetsidStr UTF8String] != curassets)
|
||||
{
|
||||
|
||||
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:nil delegateQueue:[NSOperationQueue mainQueue]];
|
||||
NSString* asidUrl = [[NSString alloc] initWithFormat:@"%@update/filetable.bin?%@",urlpath,assetsidStr];
|
||||
NSLog(@"[dcc] %@", asidUrl);
|
||||
NSURLSessionDataTask *task = [session dataTaskWithURL:[NSURL URLWithString:asidUrl] completionHandler:^(NSData * data, NSURLResponse * response, NSError * error)
|
||||
{
|
||||
NSMutableString* txtdcc = [[NSMutableString alloc]init];
|
||||
NSLog(@"[dcc] filetable.bin download complete");
|
||||
if (error)
|
||||
{
|
||||
NSLog(@"[dcc] filetable.bin download error");
|
||||
}
|
||||
if (data == nil || data.length % 8 != 0)
|
||||
{
|
||||
NSLog(@"[dcc] filetable.bin length error");
|
||||
}
|
||||
else
|
||||
{
|
||||
int32_t* v = (int32_t*)data.bytes;
|
||||
if (v[0] != 0xffeeddcc || v[1] != 1)
|
||||
{
|
||||
NSLog(@"dcc.bin file err!");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (v[2] == 0x00ffffff)
|
||||
{
|
||||
int stp = (4 + 8) / 2;
|
||||
NSData* md5 = [data subdataWithRange:NSMakeRange(4*4, 8*4)];
|
||||
NSString* so = [[NSString alloc] initWithData:md5 encoding:NSUTF8StringEncoding];
|
||||
NSLog(@"--------------------------------------------");
|
||||
NSLog(@"so=%@",so);
|
||||
NSLog(@"netid=%@",assetsidStr);
|
||||
if ([so isEqualToString:assetsidStr])
|
||||
{
|
||||
for (NSUInteger ii = stp, isz = data.length / (2*4); ii < isz; ii++)
|
||||
{
|
||||
NSData* data1 = [data subdataWithRange:NSMakeRange(ii * 2 * 4, 4)];
|
||||
NSData* data2 = [data subdataWithRange:NSMakeRange(ii * 2 * 4 + 4, 4)];
|
||||
NSString* dccstr = [[NSString alloc] initWithFormat:@"%@ %@\n",[self convertDataToHexStr:data1],[self convertDataToHexStr:data2]];
|
||||
[txtdcc appendString:dccstr];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"error old format unsupport");
|
||||
}
|
||||
}
|
||||
}
|
||||
if ([txtdcc length] > 0)
|
||||
{
|
||||
laya::LayaCacheManager::getInstance()->doUpdateDcc(gRedistPath,urlpath.UTF8String,txtdcc.UTF8String,assetsidStr.UTF8String);
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
[self requestGame:url];
|
||||
}];
|
||||
[task resume];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self requestGame:url];
|
||||
}
|
||||
}
|
||||
}];
|
||||
[task resume];
|
||||
}
|
||||
-(void)requestGame:(NSString*)url
|
||||
{
|
||||
NSURL* nsurl = [[NSURL alloc] initWithString:url];
|
||||
NSString* caturl = nil;
|
||||
if (nsurl.port)
|
||||
{
|
||||
caturl = [[NSString alloc] initWithFormat:@"%@://%@:%@",nsurl.scheme, nsurl.host, nsurl.port];
|
||||
}
|
||||
else
|
||||
{
|
||||
caturl = [[NSString alloc] initWithFormat:@"%@://%@",nsurl.scheme, nsurl.host];
|
||||
}
|
||||
NSLog(@"%@", caturl);
|
||||
// Create server
|
||||
_GCDWebServer = [[GCDWebServer alloc] init];
|
||||
|
||||
// Add a handler to respond to GET requests on any URL
|
||||
[_GCDWebServer addDefaultHandlerForMethod:@"GET"
|
||||
requestClass:[GCDWebServerRequest class]
|
||||
asyncProcessBlock:^(GCDWebServerRequest* request, GCDWebServerCompletionBlock completionBlock) {
|
||||
NSString* urlOCStr = nil;
|
||||
if (![request.path hasPrefix:@"/s"]) {
|
||||
urlOCStr =[[NSString alloc] initWithFormat:@"%@%@",caturl, request.URL.resourceSpecifier];
|
||||
//TODO 没考虑 ?
|
||||
}
|
||||
else {
|
||||
urlOCStr = [request.URL.absoluteString stringByReplacingOccurrencesOfString:_urlSuffix withString:@""];
|
||||
}
|
||||
if ([urlOCStr containsString:@"http://stand.alone.version/"])
|
||||
{
|
||||
NSURL* tempUrl = [NSURL URLWithString:urlOCStr];
|
||||
if (tempUrl.query && ![tempUrl.query isEqualToString:@""] )
|
||||
{
|
||||
urlOCStr = [urlOCStr stringByReplacingOccurrencesOfString:[[NSString alloc] initWithFormat:@"?%@", tempUrl.query] withString:@""];
|
||||
}
|
||||
}
|
||||
|
||||
NSString* contentType = GCDWebServerGetMimeTypeForExtension([[request path] pathExtension], nil);
|
||||
const char* pURL = urlOCStr.UTF8String;
|
||||
laya::LayaCacheManager::getInstance()->handleRequest(pURL, [contentType,completionBlock,request](void* pData, int length) {
|
||||
NSData *data = [[NSData alloc] initWithBytes:pData length:length];
|
||||
|
||||
GCDWebServerDataResponse* response = [GCDWebServerDataResponse responseWithData:data contentType:contentType];
|
||||
completionBlock(response);
|
||||
|
||||
},[completionBlock](int errCode){
|
||||
//NSLog(@"dowlonad error [%d]",errCode);
|
||||
completionBlock(nil);
|
||||
});
|
||||
}];
|
||||
NSError *error = nil;
|
||||
int httpPort = (_hostPort != 0) ? _hostPort :12344;
|
||||
|
||||
NSMutableDictionary *options = [NSMutableDictionary dictionary];
|
||||
[options setObject:[NSNumber numberWithBool:YES] forKey:GCDWebServerOption_BindToLocalhost];
|
||||
[options setObject:@"GCD Web Server" forKey:GCDWebServerOption_ServerName];
|
||||
|
||||
do {
|
||||
NSLog(@"Starting http daemon port %d",httpPort);
|
||||
[options setObject:[NSNumber numberWithInteger:httpPort++] forKey:GCDWebServerOption_Port];
|
||||
} while(![_GCDWebServer startWithOptions:options error:&error]);
|
||||
|
||||
if (error) {
|
||||
NSLog(@"Error starting http daemon: %@", error);
|
||||
} else {
|
||||
//[_GCDWebServer setLogLevel:kGCDWebServerLoggingLevel_Warning];
|
||||
NSLog(@"Started http daemon port %lu",(unsigned long)_GCDWebServer.port);
|
||||
}
|
||||
[self loadUrl:[self getLayaBoxUrl]];
|
||||
_urlSuffix = [NSString stringWithFormat:@"http://127.0.0.1:%lu/s/", (unsigned long)(_GCDWebServer.port)];
|
||||
}
|
||||
- (void)loadUrl:(NSString*)url
|
||||
{
|
||||
NSURL* pUrl = [NSURL URLWithString:url ];
|
||||
NSURLRequest* pUrlRequest = [NSURLRequest requestWithURL:pUrl];
|
||||
[_webview loadRequest:pUrlRequest];
|
||||
}
|
||||
- (NSString*)callMethod:(int)objid className:(NSString*)cls methodName:(NSString*)method param:(NSString*)param
|
||||
{
|
||||
return [_reflection callMethod:objid className:cls methodName:method param:param];
|
||||
}
|
||||
-(void)callbackToJSWithClass:(Class)cls methodName:(NSString*)name ret:(NSObject*)retObj
|
||||
{
|
||||
[_reflection callbackToJSWithClass:cls methodName:name ret:retObj];
|
||||
}
|
||||
-(void)callbackToJSWithClassName:(NSString*)cls methodName:(NSString*)name ret:(NSObject*)retObj
|
||||
{
|
||||
[_reflection callbackToJSWithClassName:cls methodName:name ret:retObj];
|
||||
}
|
||||
-(void)callbackToJSWithObject:(id)obj methodName:(NSString*)name ret:(NSObject*)retObj
|
||||
{
|
||||
[_reflection callbackToJSWithObject:obj methodName:name ret:retObj];
|
||||
}
|
||||
-(void)runJS:(NSString*)script
|
||||
{
|
||||
[self.webview evaluateJavaScript:script completionHandler:^(id _Nullable response, NSError * _Nullable error) {
|
||||
if (response || error)
|
||||
{
|
||||
NSLog(@"value: %@ error: %@", response, error);
|
||||
|
||||
}
|
||||
}];
|
||||
}
|
||||
@end
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
@file conchConfig.h
|
||||
@brief 配置用到的,比如版本号 或者描述信息
|
||||
@author James
|
||||
@version 1.0
|
||||
@date 2013_7_5
|
||||
@company LayaBox
|
||||
*/
|
||||
#import "UIKit/UIKit.h"
|
||||
#import <GLKit/GLKit.h>
|
||||
#import <string>
|
||||
|
||||
@interface conchConfig : NSObject
|
||||
{
|
||||
@public
|
||||
|
||||
NSString* m_sAppVersion; //对外版本号
|
||||
NSString* m_sAppLocalVersion; //对内版本号
|
||||
NSString* m_sLaya8Url; //如果是Laya8启动,启动的url
|
||||
std::string m_sBackgroundcolor; //背景色
|
||||
NSString* m_sGameID; //appStroe用到的
|
||||
bool m_bCheckNetwork; //是否检查网络
|
||||
bool m_bNotification; //是否打开推送
|
||||
bool m_bShowAssistantTouch; //是否显示AssitantTouch
|
||||
/*
|
||||
UIInterfaceOrientationMaskPortrait, ===2
|
||||
UIInterfaceOrientationMaskPortraitUpsideDown, ===4
|
||||
UIInterfaceOrientationMaskLandscapeLeft, ===8
|
||||
UIInterfaceOrientationMaskLandscapeRight, ===16
|
||||
*/
|
||||
int m_nOrientationType; //游戏的方向
|
||||
NSString* m_sUrl; //游戏url
|
||||
int m_nHostPort; //hostPort
|
||||
}
|
||||
+(conchConfig*)GetInstance;
|
||||
-(bool)readIni;
|
||||
-(conchConfig*)init;
|
||||
@end
|
||||
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
@file conchConfig.h
|
||||
@brief 配置用到的,比如版本号 或者描述信息
|
||||
@author wyw
|
||||
@version 1.0
|
||||
@date 2013_7_5
|
||||
@company JoyChina
|
||||
*/
|
||||
|
||||
#import "conchConfig.h"
|
||||
#import <util/JCIniFile.h>
|
||||
#import <string>
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
static conchConfig* g_pConchConfig = nil;
|
||||
//-------------------------------------------------------------------------------
|
||||
@implementation conchConfig
|
||||
//-------------------------------------------------------------------------------
|
||||
+(conchConfig*)GetInstance
|
||||
{
|
||||
if( g_pConchConfig == nil )
|
||||
{
|
||||
g_pConchConfig = [[conchConfig alloc] init];
|
||||
}
|
||||
return g_pConchConfig;
|
||||
}
|
||||
//-------------------------------------------------------------------------------
|
||||
-(conchConfig*)init
|
||||
{
|
||||
self = [super init];
|
||||
m_sLaya8Url=nil; //如果是Laya8启动,启动的url
|
||||
m_sBackgroundcolor="#FFFFFF";//背景色
|
||||
m_sGameID=nil; //appStroe用到的
|
||||
m_bCheckNetwork=true; //是否检查网络
|
||||
m_bNotification=false; //是否打开消息推送
|
||||
m_nOrientationType = 30; //屏幕的方向
|
||||
m_sUrl=nil;
|
||||
m_nHostPort=0;
|
||||
m_bShowAssistantTouch = false;
|
||||
[self readIni];
|
||||
m_sAppVersion=nil; //版本号
|
||||
m_sAppLocalVersion = nil; //对内版本号
|
||||
NSDictionary* infoDictionary = [[NSBundle mainBundle] infoDictionary];
|
||||
// 当前应用软件版本 Bundle versions string, short
|
||||
m_sAppVersion = [infoDictionary objectForKey:@"CFBundleShortVersionString"];
|
||||
NSLog(@"当前应用软件版本:%@",m_sAppVersion);
|
||||
// 当前应用版本号码 Bundle versions
|
||||
m_sAppLocalVersion = [infoDictionary objectForKey:@"CFBundleVersion"];
|
||||
NSLog(@"当前应用Local版本号码:%@",m_sAppLocalVersion);
|
||||
return self;
|
||||
}
|
||||
//-------------------------------------------------------------------------------
|
||||
-(bool) readIni
|
||||
{
|
||||
std::string sIniFileName = [[self getResourcePath] cStringUsingEncoding:NSUTF8StringEncoding];
|
||||
sIniFileName += "/config.ini";
|
||||
// 初始化 IAP
|
||||
laya::JCIniFile *pConfigFile = laya::JCIniFile::loadFile( sIniFileName.c_str() );
|
||||
|
||||
if( 0 == pConfigFile )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* sGameID=pConfigFile->GetValue("gameID");
|
||||
const char* sBackgroundColor=pConfigFile->GetValue("backgroundColor");
|
||||
const char* sCheckNetwork=pConfigFile->GetValue("checkNetwork");
|
||||
const char* sOrientation=pConfigFile->GetValue("orientation");
|
||||
const char* sHostPort = pConfigFile->GetValue("hostport");
|
||||
const char* sUrl = pConfigFile->GetValue("url");
|
||||
const char* sNotification = pConfigFile->GetValue("notification");
|
||||
const char* sAssistantTouch = pConfigFile->GetValue("assistantTouch");
|
||||
if( sGameID )
|
||||
{
|
||||
m_sGameID = [[NSString alloc] initWithUTF8String:sGameID ];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"读取ini gameID 错误");
|
||||
}
|
||||
if( sBackgroundColor )
|
||||
{
|
||||
m_sBackgroundcolor = sBackgroundColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"读取ini backgroundColor 错误");
|
||||
}
|
||||
if( sCheckNetwork )
|
||||
{
|
||||
m_bCheckNetwork = atoi(sCheckNetwork)>0;
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"读取ini checkNetworkd 错误");
|
||||
}
|
||||
if( sOrientation )
|
||||
{
|
||||
m_nOrientationType = atoi(sOrientation);
|
||||
if( m_nOrientationType < 1 )
|
||||
{
|
||||
NSLog(@"读取ini orientation 错误");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"读取ini orientation错误");
|
||||
}
|
||||
if( sHostPort )
|
||||
{
|
||||
m_nHostPort = atoi(sHostPort);
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"读取ini hostport错误");
|
||||
}
|
||||
if( sUrl )
|
||||
{
|
||||
m_sUrl = [[NSString alloc]initWithUTF8String:sUrl];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"读取ini url错误");
|
||||
}
|
||||
if( sNotification )
|
||||
{
|
||||
m_bNotification = atoi(sNotification)>0;
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"读取ini notification 错误");
|
||||
}
|
||||
if( sAssistantTouch )
|
||||
{
|
||||
m_bShowAssistantTouch = atoi(sAssistantTouch)>0;
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"读取ini assistantTouch 错误");
|
||||
}
|
||||
delete pConfigFile;
|
||||
pConfigFile = NULL;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
-(NSString*) getResourcePath
|
||||
{
|
||||
return [[NSBundle mainBundle] resourcePath];
|
||||
}
|
||||
@end
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
@file
|
||||
@brief
|
||||
@author
|
||||
@version 1.0
|
||||
@date
|
||||
@company LayaBox
|
||||
*/
|
||||
#import <objc/NSObject.h>
|
||||
#import <objc/objc.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSInvocation.h>
|
||||
#import "LayaWKWebview.h"
|
||||
|
||||
@interface Reflection : NSObject
|
||||
-(id)init:(LayaWKWebview*)webview;
|
||||
-(void)clearReflectionObjects;
|
||||
-(NSString*)callMethod:(int)objid className:(NSString*)cls methodName:(NSString*)method param:(NSString*)param;
|
||||
-(void)callbackToJSWithClass:(Class)cls methodName:(NSString*)name ret:(NSObject*)retObj;
|
||||
-(void)callbackToJSWithClassName:(NSString*)cls methodName:(NSString*)name ret:(NSObject*)retObj;
|
||||
-(void)callbackToJSWithObject:(id)obj methodName:(NSString*)name ret:(NSObject*)retObj;
|
||||
@end
|
||||
@@ -0,0 +1,221 @@
|
||||
#import "refection.h"
|
||||
#import <Foundation/Foundation.h>
|
||||
#include <string>
|
||||
//#import "../../../../source/conch/CToObjectC.h"
|
||||
//#import "CToObjectCIOS.h"
|
||||
//#import "../../../../../source/conch/JCScriptRuntime.h"
|
||||
//#import "JCThreadCmdMgr.h"
|
||||
|
||||
extern void reflectionCallback(const std::string& jsonret);
|
||||
|
||||
@implementation Reflection
|
||||
{
|
||||
NSMutableDictionary* m_pIDToObjectDic;
|
||||
NSMutableDictionary* m_pObjectToIDDic;
|
||||
NSLock* m_lock;
|
||||
LayaWKWebview* m_webview;
|
||||
}
|
||||
-(id)init:(LayaWKWebview*)webview;
|
||||
{
|
||||
self = [super init];
|
||||
if( self != nil )
|
||||
{
|
||||
m_webview = webview;
|
||||
m_pIDToObjectDic = [NSMutableDictionary dictionary];
|
||||
m_pObjectToIDDic = [NSMutableDictionary dictionary];
|
||||
m_lock = [NSLock new];
|
||||
return self;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
-(void)clearReflectionObjects
|
||||
{
|
||||
[m_lock lock];
|
||||
[m_pIDToObjectDic removeAllObjects];
|
||||
[m_pObjectToIDDic removeAllObjects];
|
||||
[m_lock unlock];
|
||||
}
|
||||
-(NSString*)invoke: (Class) objc_class isStatic:(BOOL) isStatic target:(id)target select:(SEL)select Param:(NSString*)param
|
||||
{
|
||||
NSMethodSignature* signature = isStatic ? [objc_class methodSignatureForSelector:select] : [objc_class instanceMethodSignatureForSelector:select];
|
||||
if (signature == nil){
|
||||
NSLog(@"reflection error: can not find method signature");
|
||||
return @"{}";
|
||||
}
|
||||
|
||||
NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:signature];
|
||||
if (invocation == nil){
|
||||
NSLog(@"reflection error: can not find invocation");
|
||||
return @"{}";
|
||||
}
|
||||
|
||||
[invocation setTarget:target];
|
||||
[invocation setSelector:select];
|
||||
|
||||
|
||||
NSUInteger numArgs = [signature numberOfArguments];
|
||||
|
||||
NSData* jsonData = [param dataUsingEncoding:NSUTF8StringEncoding];
|
||||
if (jsonData == nil){
|
||||
NSLog(@"reflection error");
|
||||
return @"{}";
|
||||
}
|
||||
|
||||
NSError* error = nil;
|
||||
id idPara = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
|
||||
|
||||
if (idPara == nil || ![idPara isKindOfClass:[NSArray class]]){
|
||||
NSLog(@"reflection error");
|
||||
return @"{}";
|
||||
}
|
||||
|
||||
NSArray* paraArray = idPara;
|
||||
NSUInteger num = [paraArray count];
|
||||
|
||||
if (numArgs != num + 2){
|
||||
NSLog(@"reflection error: argument number is [%lu] but need [%lu]",(unsigned long)num,(unsigned long)(numArgs-2));
|
||||
return @"{}";
|
||||
}
|
||||
|
||||
|
||||
for(int i = 2; i < num + 2; i++){
|
||||
NSObject* obj = [paraArray objectAtIndex:i-2];
|
||||
[invocation setArgument:&obj atIndex:i];
|
||||
}
|
||||
|
||||
[invocation invoke];
|
||||
|
||||
if (!strcmp(signature.methodReturnType, @encode(void))) {
|
||||
return @"{}";
|
||||
}
|
||||
|
||||
const char* methodReturnType = signature.methodReturnType;
|
||||
if (!strcmp(methodReturnType, "@")) {
|
||||
NSLog(@"method return type %s",methodReturnType);
|
||||
id returnValue;
|
||||
[invocation getReturnValue:&returnValue];
|
||||
NSDictionary* dic = [NSDictionary dictionaryWithObjectsAndKeys:returnValue, @"v",nil];
|
||||
NSError* pError = nil;
|
||||
NSData* pJsonData = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:&pError];
|
||||
if (pError) {
|
||||
NSLog(@"%@ %@", pError.debugDescription, pError.description);
|
||||
return @"{}";
|
||||
}
|
||||
return [[NSString alloc] initWithData:pJsonData encoding:NSUTF8StringEncoding];
|
||||
}
|
||||
else {
|
||||
NSLog(@"method return type %s not supported",methodReturnType);
|
||||
return @"{}";
|
||||
}
|
||||
return @"{}";
|
||||
}
|
||||
|
||||
-(NSString*)callMethod:(int)objid className:(NSString*)cls methodName:(NSString*)method param:(NSString*)param
|
||||
{
|
||||
Class objc_class = NSClassFromString(cls);
|
||||
if (objc_class == nil){
|
||||
NSLog(@"reflection error : can not find class [%@]",cls);
|
||||
return @"{}";
|
||||
}
|
||||
|
||||
if (objid == -1){
|
||||
|
||||
SEL select = NSSelectorFromString(method);
|
||||
if (select == 0){
|
||||
NSLog(@"reflection error");
|
||||
return @"{}";
|
||||
}
|
||||
return [self invoke:objc_class isStatic:TRUE target:objc_class select:select Param:param];
|
||||
}
|
||||
else{
|
||||
|
||||
if ([method isEqualToString:@"<init>"]){//构造函数
|
||||
NSObject* object = [[objc_class alloc] init];
|
||||
if (object == nil){
|
||||
NSLog(@"reflection error : alloc init class [%@] object failed",cls);
|
||||
return @"{}";
|
||||
}
|
||||
[m_lock lock];
|
||||
[m_pIDToObjectDic setObject:object forKey:[NSNumber numberWithInt:objid]];
|
||||
[m_pObjectToIDDic setObject:[NSNumber numberWithInt:objid] forKey:[NSNumber numberWithInteger:(NSInteger)object]];
|
||||
[m_lock unlock];
|
||||
}
|
||||
else{
|
||||
NSObject* object = [m_pIDToObjectDic objectForKey:[NSNumber numberWithInt:objid]];
|
||||
|
||||
if (object == nil){
|
||||
NSLog(@"reflection error : can not find object id [%i]",objid);
|
||||
return @"{}";
|
||||
}
|
||||
|
||||
if (![object isKindOfClass:objc_class]){
|
||||
NSLog(@"reflection error : object of id [%i] is not king of class [%@]",objid,cls);
|
||||
return @"{}";
|
||||
}
|
||||
|
||||
SEL select = NSSelectorFromString(method);
|
||||
if (select == 0){
|
||||
NSLog(@"reflection error");
|
||||
return @"{}";
|
||||
}
|
||||
return [self invoke:objc_class isStatic:FALSE target:object select:select Param:param];
|
||||
}
|
||||
}
|
||||
return @"{}";
|
||||
}
|
||||
|
||||
-(void)callbackToJSWithClass:(Class)cls methodName:(NSString*)name ret:(NSObject*)retObj
|
||||
{
|
||||
[self callbackToJSWithClassName:NSStringFromClass(cls) methodName:name ret:retObj];
|
||||
}
|
||||
|
||||
-(void)callbackToJSWithClassName:(NSString*)cls methodName:(NSString*)name ret:(NSObject*)retObj
|
||||
{
|
||||
NSMutableDictionary* dic = [NSMutableDictionary dictionary];
|
||||
|
||||
[dic setObject:@-1 forKey:@"objId"];
|
||||
[dic setObject:cls forKey:@"cName"];
|
||||
[dic setObject:name forKey:@"mName"];
|
||||
if (retObj == nil)
|
||||
[dic setObject:@"" forKey:@"v"];
|
||||
else
|
||||
[dic setObject:retObj forKey:@"v"];
|
||||
|
||||
NSError* error = nil;
|
||||
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:dic options:0 error:&error];
|
||||
if (error != nil){
|
||||
NSLog(@"callbackToJS error");
|
||||
return;
|
||||
}
|
||||
NSString* jason = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
||||
NSString* js = [NSString stringWithFormat:@"window.conchPlatCallBack(%@)", jason];
|
||||
js = [[js stringByReplacingOccurrencesOfString:@"\n" withString:@""] stringByReplacingOccurrencesOfString:@" " withString:@""];
|
||||
[m_webview runJS:js];
|
||||
NSLog(@"run js: %@", js);
|
||||
}
|
||||
-(void)callbackToJSWithObject:(id)obj methodName:(NSString*)name ret:(NSObject*)retObj
|
||||
{
|
||||
NSMutableDictionary* dic = [NSMutableDictionary dictionary];
|
||||
[m_lock lock];
|
||||
[dic setObject:[m_pObjectToIDDic objectForKey:[NSNumber numberWithInteger:(NSInteger)obj]] forKey:@"objId"];
|
||||
[m_lock unlock];
|
||||
[dic setObject:@"" forKey:@"cName"];
|
||||
[dic setObject:name forKey:@"mName"];
|
||||
if (retObj == nil)
|
||||
[dic setObject:@"" forKey:@"v"];
|
||||
else
|
||||
[dic setObject:retObj forKey:@"v"];
|
||||
|
||||
NSError* error = nil;
|
||||
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:dic options:0 error:&error];
|
||||
if (error != nil){
|
||||
NSLog(@"callbackToJS error");
|
||||
return;
|
||||
}
|
||||
NSString* jason = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
||||
NSString* js = [NSString stringWithFormat:@"window.conchPlatCallBack(%@)", jason];
|
||||
js = [[js stringByReplacingOccurrencesOfString:@"\n" withString:@""] stringByReplacingOccurrencesOfString:@" " withString:@""];
|
||||
[m_webview runJS:js];
|
||||
NSLog(@"run js: %@", js);
|
||||
}
|
||||
@end
|
||||
Reference in New Issue
Block a user