mirror of https://github.com/axmolengine/axmol.git
Merge branch 'v3' into wp8-fix2
This commit is contained in:
commit
79e71b6c50
|
@ -704,7 +704,6 @@
|
|||
15AE1BAE19AADFDF00C27E9E /* UILayoutParameter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2905F9FD18CF08D000240AA3 /* UILayoutParameter.h */; };
|
||||
15AE1BAF19AADFDF00C27E9E /* UILayoutManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 29CB8F4A1929D1BB00C841D6 /* UILayoutManager.cpp */; };
|
||||
15AE1BB019AADFDF00C27E9E /* UILayoutManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 29CB8F4B1929D1BB00C841D6 /* UILayoutManager.h */; };
|
||||
15AE1BB119AADFEF00C27E9E /* HttpClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AAF5362180E3374000584C8 /* HttpClient.cpp */; };
|
||||
15AE1BB219AADFEF00C27E9E /* HttpClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AAF5363180E3374000584C8 /* HttpClient.h */; };
|
||||
15AE1BB319AADFEF00C27E9E /* HttpRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AAF5364180E3374000584C8 /* HttpRequest.h */; };
|
||||
15AE1BB419AADFEF00C27E9E /* HttpResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AAF5365180E3374000584C8 /* HttpResponse.h */; };
|
||||
|
@ -712,7 +711,6 @@
|
|||
15AE1BB619AADFEF00C27E9E /* SocketIO.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AAF5367180E3374000584C8 /* SocketIO.h */; };
|
||||
15AE1BB719AADFEF00C27E9E /* WebSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AAF5368180E3374000584C8 /* WebSocket.cpp */; };
|
||||
15AE1BB819AADFEF00C27E9E /* WebSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AAF5369180E3374000584C8 /* WebSocket.h */; };
|
||||
15AE1BB919AADFF000C27E9E /* HttpClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AAF5362180E3374000584C8 /* HttpClient.cpp */; };
|
||||
15AE1BBA19AADFF000C27E9E /* HttpClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AAF5363180E3374000584C8 /* HttpClient.h */; };
|
||||
15AE1BBB19AADFF000C27E9E /* HttpRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AAF5364180E3374000584C8 /* HttpRequest.h */; };
|
||||
15AE1BBC19AADFF000C27E9E /* HttpResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AAF5365180E3374000584C8 /* HttpResponse.h */; };
|
||||
|
@ -1749,6 +1747,12 @@
|
|||
50ED2BE519BEAF7900A0AB90 /* UIEditBoxImpl-win32.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 50ED2BDE19BEAF7900A0AB90 /* UIEditBoxImpl-win32.cpp */; };
|
||||
50ED2BE619BEAF7900A0AB90 /* UIEditBoxImpl-wp8.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 50ED2BDF19BEAF7900A0AB90 /* UIEditBoxImpl-wp8.cpp */; };
|
||||
50ED2BE719BEAF7900A0AB90 /* UIEditBoxImpl-wp8.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 50ED2BDF19BEAF7900A0AB90 /* UIEditBoxImpl-wp8.cpp */; };
|
||||
52B47A1E1A53489B004E4C60 /* HttpClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52B47A1D1A53489B004E4C60 /* HttpClient.cpp */; };
|
||||
52B47A2E1A5349A3004E4C60 /* HttpAsynConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B47A291A5349A3004E4C60 /* HttpAsynConnection.h */; };
|
||||
52B47A2F1A5349A3004E4C60 /* HttpAsynConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 52B47A2A1A5349A3004E4C60 /* HttpAsynConnection.m */; };
|
||||
52B47A301A5349A3004E4C60 /* HttpClient-ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 52B47A2B1A5349A3004E4C60 /* HttpClient-ios.mm */; };
|
||||
52B47A311A5349A3004E4C60 /* HttpCookie.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52B47A2C1A5349A3004E4C60 /* HttpCookie.cpp */; };
|
||||
52B47A321A5349A3004E4C60 /* HttpCookie.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B47A2D1A5349A3004E4C60 /* HttpCookie.h */; };
|
||||
5E9F61261A3FFE3D0038DE01 /* CCFrustum.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E9F61221A3FFE3D0038DE01 /* CCFrustum.cpp */; };
|
||||
5E9F61271A3FFE3D0038DE01 /* CCFrustum.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E9F61221A3FFE3D0038DE01 /* CCFrustum.cpp */; };
|
||||
5E9F61281A3FFE3D0038DE01 /* CCFrustum.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E9F61231A3FFE3D0038DE01 /* CCFrustum.h */; };
|
||||
|
@ -2276,7 +2280,6 @@
|
|||
1A9DCA03180E6955007A3AD4 /* CCGLBufferedNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCGLBufferedNode.h; sourceTree = "<group>"; };
|
||||
1AAF5351180E3060000584C8 /* AssetsManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AssetsManager.cpp; sourceTree = "<group>"; };
|
||||
1AAF5352180E3060000584C8 /* AssetsManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AssetsManager.h; sourceTree = "<group>"; };
|
||||
1AAF5362180E3374000584C8 /* HttpClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HttpClient.cpp; sourceTree = "<group>"; };
|
||||
1AAF5363180E3374000584C8 /* HttpClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HttpClient.h; sourceTree = "<group>"; };
|
||||
1AAF5364180E3374000584C8 /* HttpRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HttpRequest.h; sourceTree = "<group>"; };
|
||||
1AAF5365180E3374000584C8 /* HttpResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HttpResponse.h; sourceTree = "<group>"; };
|
||||
|
@ -2929,6 +2932,12 @@
|
|||
50FCEB9018C72017004AD434 /* WidgetReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WidgetReader.cpp; sourceTree = "<group>"; };
|
||||
50FCEB9118C72017004AD434 /* WidgetReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WidgetReader.h; sourceTree = "<group>"; };
|
||||
50FCEB9218C72017004AD434 /* WidgetReaderProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WidgetReaderProtocol.h; sourceTree = "<group>"; };
|
||||
52B47A1D1A53489B004E4C60 /* HttpClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HttpClient.cpp; sourceTree = "<group>"; };
|
||||
52B47A291A5349A3004E4C60 /* HttpAsynConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HttpAsynConnection.h; sourceTree = "<group>"; };
|
||||
52B47A2A1A5349A3004E4C60 /* HttpAsynConnection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HttpAsynConnection.m; sourceTree = "<group>"; };
|
||||
52B47A2B1A5349A3004E4C60 /* HttpClient-ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "HttpClient-ios.mm"; sourceTree = "<group>"; };
|
||||
52B47A2C1A5349A3004E4C60 /* HttpCookie.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HttpCookie.cpp; sourceTree = "<group>"; };
|
||||
52B47A2D1A5349A3004E4C60 /* HttpCookie.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HttpCookie.h; sourceTree = "<group>"; };
|
||||
5E9F61221A3FFE3D0038DE01 /* CCFrustum.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CCFrustum.cpp; sourceTree = "<group>"; };
|
||||
5E9F61231A3FFE3D0038DE01 /* CCFrustum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCFrustum.h; sourceTree = "<group>"; };
|
||||
5E9F61241A3FFE3D0038DE01 /* CCPlane.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CCPlane.cpp; sourceTree = "<group>"; };
|
||||
|
@ -3904,7 +3913,12 @@
|
|||
1AAF5360180E3374000584C8 /* network */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1AAF5362180E3374000584C8 /* HttpClient.cpp */,
|
||||
52B47A291A5349A3004E4C60 /* HttpAsynConnection.h */,
|
||||
52B47A2A1A5349A3004E4C60 /* HttpAsynConnection.m */,
|
||||
52B47A2B1A5349A3004E4C60 /* HttpClient-ios.mm */,
|
||||
52B47A2C1A5349A3004E4C60 /* HttpCookie.cpp */,
|
||||
52B47A2D1A5349A3004E4C60 /* HttpCookie.h */,
|
||||
52B47A1D1A53489B004E4C60 /* HttpClient.cpp */,
|
||||
1AAF5363180E3374000584C8 /* HttpClient.h */,
|
||||
1AAF5364180E3374000584C8 /* HttpRequest.h */,
|
||||
1AAF5365180E3374000584C8 /* HttpResponse.h */,
|
||||
|
@ -5973,6 +5987,7 @@
|
|||
15AE1C1819AAE2C700C27E9E /* CCPhysicsSprite.h in Headers */,
|
||||
15AE1BC819AAE00000C27E9E /* AssetsManager.h in Headers */,
|
||||
B29A7E0419EE1B7700872B35 /* BoundingBoxAttachment.h in Headers */,
|
||||
52B47A2E1A5349A3004E4C60 /* HttpAsynConnection.h in Headers */,
|
||||
15AE1BBC19AADFF000C27E9E /* HttpResponse.h in Headers */,
|
||||
15AE186019AAD31200C27E9E /* SimpleAudioEngine_objc.h in Headers */,
|
||||
50ABBDA61925AB4100A911A9 /* CCQuadCommand.h in Headers */,
|
||||
|
@ -6057,6 +6072,7 @@
|
|||
5034CA2C191D591100CE6051 /* ccShader_PositionTextureA8Color.vert in Headers */,
|
||||
50ABBE981925AB6F00A911A9 /* CCProtocols.h in Headers */,
|
||||
50CB247A19D9C5A100687767 /* AudioEngine-inl.h in Headers */,
|
||||
52B47A321A5349A3004E4C60 /* HttpCookie.h in Headers */,
|
||||
50ABBD431925AB0000A911A9 /* CCMathBase.h in Headers */,
|
||||
15EFA214198A2BB5000C57D3 /* CCProtectedNode.h in Headers */,
|
||||
15AE194419AAD35100C27E9E /* CCComBase.h in Headers */,
|
||||
|
@ -6618,7 +6634,6 @@
|
|||
1A570296180BCCAB0088DEC7 /* CCAnimationCache.cpp in Sources */,
|
||||
B29A7E1B19EE1B7700872B35 /* SkeletonJson.c in Sources */,
|
||||
50ABBE351925AB6F00A911A9 /* CCConsole.cpp in Sources */,
|
||||
15AE1BB119AADFEF00C27E9E /* HttpClient.cpp in Sources */,
|
||||
50ABBEAF1925AB6F00A911A9 /* CCUserDefault.cpp in Sources */,
|
||||
15AE1BCB19AAE01E00C27E9E /* CCControlButton.cpp in Sources */,
|
||||
50ABBE791925AB6F00A911A9 /* CCEventMouse.cpp in Sources */,
|
||||
|
@ -6690,6 +6705,7 @@
|
|||
50ABBEB31925AB6F00A911A9 /* CCUserDefault-apple.mm in Sources */,
|
||||
50ABBEB51925AB6F00A911A9 /* CCUserDefault-android.cpp in Sources */,
|
||||
5E9F61261A3FFE3D0038DE01 /* CCFrustum.cpp in Sources */,
|
||||
52B47A1E1A53489B004E4C60 /* HttpClient.cpp in Sources */,
|
||||
29394CF619B01DBA00D2DE1A /* UIWebViewImpl-ios.mm in Sources */,
|
||||
382383FC1A258FA7002C4610 /* idl_gen_text.cpp in Sources */,
|
||||
50ABBE831925AB6F00A911A9 /* ccFPSImages.c in Sources */,
|
||||
|
@ -6891,6 +6907,7 @@
|
|||
1A570072180BC5A10088DEC7 /* CCActionGrid.cpp in Sources */,
|
||||
15AE1ABC19AAD40300C27E9E /* b2PolygonAndCircleContact.cpp in Sources */,
|
||||
15AE1ADA19AAD41000C27E9E /* b2Rope.cpp in Sources */,
|
||||
52B47A301A5349A3004E4C60 /* HttpClient-ios.mm in Sources */,
|
||||
B29A7E1619EE1B7700872B35 /* BoundingBoxAttachment.c in Sources */,
|
||||
382384081A25900F002C4610 /* FlatBuffersSerialize.cpp in Sources */,
|
||||
DABC9FAA19E7DFA900FA252C /* CCClippingRectangleNode.cpp in Sources */,
|
||||
|
@ -6947,7 +6964,6 @@
|
|||
B29A7E2619EE1B7700872B35 /* Attachment.c in Sources */,
|
||||
15AE18C119AAD33D00C27E9E /* CCLayerColorLoader.cpp in Sources */,
|
||||
B37510851823ACA100B3BA6A /* CCPhysicsWorldInfo_chipmunk.cpp in Sources */,
|
||||
15AE1BB919AADFF000C27E9E /* HttpClient.cpp in Sources */,
|
||||
50ABBD551925AB0000A911A9 /* TransformUtils.cpp in Sources */,
|
||||
292DB14419B4574100A80320 /* UIEditBoxImpl-android.cpp in Sources */,
|
||||
15AE193619AAD35100C27E9E /* CCArmature.cpp in Sources */,
|
||||
|
@ -7201,6 +7217,7 @@
|
|||
50ABBD451925AB0000A911A9 /* CCVertex.cpp in Sources */,
|
||||
50ABBEB01925AB6F00A911A9 /* CCUserDefault.cpp in Sources */,
|
||||
50ABBE521925AB6F00A911A9 /* CCEventDispatcher.cpp in Sources */,
|
||||
52B47A2F1A5349A3004E4C60 /* HttpAsynConnection.m in Sources */,
|
||||
15AE1B8019AADA9A00C27E9E /* UITextAtlas.cpp in Sources */,
|
||||
15AE195919AAD35100C27E9E /* CCProcessBase.cpp in Sources */,
|
||||
15AE18D319AAD33D00C27E9E /* CCParticleSystemQuadLoader.cpp in Sources */,
|
||||
|
@ -7222,6 +7239,7 @@
|
|||
503DD8E71926736A00CD74DD /* CCEAGLView-ios.mm in Sources */,
|
||||
3E2BDAEC19C0436F0055CDCD /* AudioEngine.cpp in Sources */,
|
||||
382383F11A258FA7002C4610 /* flatc.cpp in Sources */,
|
||||
52B47A311A5349A3004E4C60 /* HttpCookie.cpp in Sources */,
|
||||
15B3707919EE414C00ABE682 /* AssetsManagerEx.cpp in Sources */,
|
||||
50ABBDA41925AB4100A911A9 /* CCQuadCommand.cpp in Sources */,
|
||||
15AE18C319AAD33D00C27E9E /* CCLayerGradientLoader.cpp in Sources */,
|
||||
|
|
|
@ -793,6 +793,8 @@
|
|||
527B1F4119EFAD44000A1F82 /* Default-736h@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 527B1F3F19EFAD44000A1F82 /* Default-736h@3x.png */; };
|
||||
527B1F4419EFAE13000A1F82 /* Default-667h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 527B1F4219EFAE13000A1F82 /* Default-667h@2x.png */; };
|
||||
527B1F4519EFAE13000A1F82 /* Default-736h@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 527B1F4319EFAE13000A1F82 /* Default-736h@3x.png */; };
|
||||
52B47A341A534B2B004E4C60 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52B47A331A534B2B004E4C60 /* Security.framework */; };
|
||||
52B47A351A53A43A004E4C60 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52B47A331A534B2B004E4C60 /* Security.framework */; };
|
||||
59620E8F1921E5CF002021B6 /* Bug-Child.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 59620E8D1921E5CF002021B6 /* Bug-Child.cpp */; };
|
||||
59620E901921E5CF002021B6 /* Bug-Child.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 59620E8D1921E5CF002021B6 /* Bug-Child.cpp */; };
|
||||
5EBEECB01995247000429821 /* DrawNode3D.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5EBEECAE1995247000429821 /* DrawNode3D.cpp */; };
|
||||
|
@ -1724,6 +1726,7 @@
|
|||
527B1F3F19EFAD44000A1F82 /* Default-736h@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-736h@3x.png"; sourceTree = "<group>"; };
|
||||
527B1F4219EFAE13000A1F82 /* Default-667h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-667h@2x.png"; sourceTree = "<group>"; };
|
||||
527B1F4319EFAE13000A1F82 /* Default-736h@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-736h@3x.png"; sourceTree = "<group>"; };
|
||||
52B47A331A534B2B004E4C60 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.1.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; };
|
||||
59620E8D1921E5CF002021B6 /* Bug-Child.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "Bug-Child.cpp"; sourceTree = "<group>"; };
|
||||
59620E8E1921E5CF002021B6 /* Bug-Child.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Bug-Child.h"; sourceTree = "<group>"; };
|
||||
5EBEECAE1995247000429821 /* DrawNode3D.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DrawNode3D.cpp; path = Sprite3DTest/DrawNode3D.cpp; sourceTree = "<group>"; };
|
||||
|
@ -1873,6 +1876,7 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
52B47A351A53A43A004E4C60 /* Security.framework in Frameworks */,
|
||||
15AE17DC19A725A000C27E9E /* libcurl.a in Frameworks */,
|
||||
15EFA66F198B356E000C57D3 /* libluacocos2d iOS.a in Frameworks */,
|
||||
15EFA666198B34D7000C57D3 /* libcocos2d iOS.a in Frameworks */,
|
||||
|
@ -1931,6 +1935,7 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
52B47A341A534B2B004E4C60 /* Security.framework in Frameworks */,
|
||||
15EE465B19A7200300AF29F1 /* libcurl.a in Frameworks */,
|
||||
3EA0FB66191B933000B170C8 /* MediaPlayer.framework in Frameworks */,
|
||||
1AAF5400180E39D4000584C8 /* libcocos2d iOS.a in Frameworks */,
|
||||
|
@ -3676,6 +3681,7 @@
|
|||
29B97323FDCFA39411CA2CEA /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
52B47A331A534B2B004E4C60 /* Security.framework */,
|
||||
15EE465A19A7200300AF29F1 /* libcurl.a */,
|
||||
15CBA9DC196EEAA6005877BB /* libz.dylib */,
|
||||
15CBA9DA196EEA90005877BB /* CoreMotion.framework */,
|
||||
|
|
|
@ -87,6 +87,7 @@ static const char* TRANSLATION = "translation";
|
|||
static const char* ROTATION = "rotation";
|
||||
static const char* SCALE = "scale";
|
||||
static const char* KEYTIME = "keytime";
|
||||
static const char* AABBS = "aabb";
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
|
@ -431,7 +432,22 @@ bool Bundle3D::loadMeshDatasBinary(MeshDatas& meshdatas)
|
|||
}
|
||||
meshData->subMeshIndices.push_back(indexArray);
|
||||
meshData->numIndex = (int)meshData->subMeshIndices.size();
|
||||
meshData->subMeshAABB.push_back(calculateAABB(meshData->vertex, meshData->getPerVertexSize(), indexArray));
|
||||
//meshData->subMeshAABB.push_back(calculateAABB(meshData->vertex, meshData->getPerVertexSize(), indexArray));
|
||||
if (_version != "0.3" && _version != "0.4" && _version != "0.5")
|
||||
{
|
||||
//read mesh aabb
|
||||
float aabb[6];
|
||||
if (_binaryReader.read(aabb, 4, 6) != 6)
|
||||
{
|
||||
CCLOG("warning: Failed to read meshdata: aabb '%s'.", _path.c_str());
|
||||
return false;
|
||||
}
|
||||
meshData->subMeshAABB.push_back(AABB(Vec3(aabb[0], aabb[1], aabb[2]), Vec3(aabb[3], aabb[4], aabb[5])));
|
||||
}
|
||||
else
|
||||
{
|
||||
meshData->subMeshAABB.push_back(calculateAABB(meshData->vertex, meshData->getPerVertexSize(), indexArray));
|
||||
}
|
||||
}
|
||||
meshdatas.meshDatas.push_back(meshData);
|
||||
}
|
||||
|
@ -710,7 +726,19 @@ bool Bundle3D::loadMeshDatasJson(MeshDatas& meshdatas)
|
|||
|
||||
meshData->subMeshIndices.push_back(indexArray);
|
||||
meshData->numIndex = (int)meshData->subMeshIndices.size();
|
||||
meshData->subMeshAABB.push_back(calculateAABB(meshData->vertex, meshData->getPerVertexSize(), indexArray));
|
||||
|
||||
//meshData->subMeshAABB.push_back(calculateAABB(meshData->vertex, meshData->getPerVertexSize(), indexArray));
|
||||
const rapidjson::Value& mesh_part_aabb = mesh_part[AABBS];
|
||||
if (mesh_part.HasMember(AABBS) && mesh_part_aabb.Size() == 6)
|
||||
{
|
||||
Vec3 min = Vec3(mesh_part_aabb[(rapidjson::SizeType)0].GetDouble(), mesh_part_aabb[(rapidjson::SizeType)1].GetDouble(), mesh_part_aabb[(rapidjson::SizeType)2].GetDouble());
|
||||
Vec3 max = Vec3(mesh_part_aabb[(rapidjson::SizeType)3].GetDouble(), mesh_part_aabb[(rapidjson::SizeType)4].GetDouble(), mesh_part_aabb[(rapidjson::SizeType)5].GetDouble());
|
||||
meshData->subMeshAABB.push_back(AABB(min, max));
|
||||
}
|
||||
else
|
||||
{
|
||||
meshData->subMeshAABB.push_back(calculateAABB(meshData->vertex, meshData->getPerVertexSize(), indexArray));
|
||||
}
|
||||
}
|
||||
meshdatas.meshDatas.push_back(meshData);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ LOCAL_MODULE := cocos_network_static
|
|||
|
||||
LOCAL_MODULE_FILENAME := libnetwork
|
||||
|
||||
LOCAL_SRC_FILES := HttpClient.cpp \
|
||||
LOCAL_SRC_FILES := HttpClient-android.cpp \
|
||||
SocketIO.cpp \
|
||||
WebSocket.cpp
|
||||
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2013-2014 Chukong Technologies Inc.
|
||||
|
||||
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 __HTTPASYNCONNECTION_H__
|
||||
#define __HTTPASYNCONNECTION_H__
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <Security/Security.h>
|
||||
|
||||
@interface HttpAsynConnection : NSObject <NSURLConnectionDelegate, NSURLConnectionDataDelegate>
|
||||
{
|
||||
}
|
||||
|
||||
// The original URL to download. Due to redirects the actual content may come from another URL
|
||||
@property (strong) NSString *srcURL;
|
||||
|
||||
@property (strong) NSString *sslFile;
|
||||
|
||||
@property (strong) NSDictionary *responseHeader;
|
||||
|
||||
@property (strong) NSMutableData *responseData;
|
||||
|
||||
@property (readonly) NSInteger getDataTime;
|
||||
|
||||
@property (readonly) NSInteger responseCode;
|
||||
|
||||
@property (strong) NSError *responseError;
|
||||
|
||||
@property (strong) NSURLConnection *conn;
|
||||
|
||||
@property bool finish;
|
||||
|
||||
@property (strong) NSRunLoop *runLoop;
|
||||
|
||||
// instructs the class to start the request.
|
||||
-(void) startRequest:(NSURLRequest*)request;
|
||||
|
||||
@end
|
||||
|
||||
#endif //__HTTPASYNCONNECTION_H__
|
|
@ -0,0 +1,176 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2013-2014 Chukong Technologies Inc.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
|
||||
#import "HttpAsynConnection.h"
|
||||
|
||||
@implementation HttpAsynConnection
|
||||
|
||||
@synthesize srcURL;
|
||||
@synthesize sslFile;
|
||||
@synthesize responseHeader;
|
||||
@synthesize responseData;
|
||||
@synthesize getDataTime;
|
||||
@synthesize responseCode;
|
||||
@synthesize responseError;
|
||||
@synthesize conn;
|
||||
@synthesize finish;
|
||||
@synthesize runLoop;
|
||||
|
||||
- (void) startRequest:(NSURLRequest *)request
|
||||
{
|
||||
NSLog(@"Starting to load %@", srcURL);
|
||||
finish = false;
|
||||
|
||||
responseData = [NSMutableData new];
|
||||
getDataTime = 0;
|
||||
responseError = nil;
|
||||
|
||||
// create the connection with the target request and this class as the delegate
|
||||
self.conn = [[NSURLConnection alloc] initWithRequest:request
|
||||
delegate:self
|
||||
startImmediately:NO];
|
||||
|
||||
[self.conn scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
|
||||
|
||||
// start the connection
|
||||
[self.conn start];
|
||||
}
|
||||
|
||||
#pragma mark NSURLConnectionDelegate methods
|
||||
/**
|
||||
* This delegate method is called when the NSURLConnection connects to the server. It contains the
|
||||
* NSURLResponse object with the headers returned by the server. This method may be called multiple times.
|
||||
* Therefore, it is important to reset the data on each call. Do not assume that it is the first call
|
||||
* of this method.
|
||||
**/
|
||||
- (void) connection:(NSURLConnection *)connection
|
||||
didReceiveResponse:(NSURLResponse *)response {
|
||||
NSLog(@"Received response from request to url %@", srcURL);
|
||||
|
||||
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
|
||||
//NSLog(@"All headers = %@", [httpResponse allHeaderFields]);
|
||||
responseHeader = [[httpResponse allHeaderFields] copy];
|
||||
|
||||
responseCode = httpResponse.statusCode;
|
||||
if (responseCode != 200)
|
||||
{// something went wrong, abort the whole thing
|
||||
|
||||
[connection cancel];
|
||||
finish = true;
|
||||
return;
|
||||
}
|
||||
|
||||
[responseData setLength:0];
|
||||
}
|
||||
|
||||
/**
|
||||
* This delegate method is called for each chunk of data received from the server. The chunk size
|
||||
* is dependent on the network type and the server configuration.
|
||||
*/
|
||||
- (void)connection:(NSURLConnection *)connection
|
||||
didReceiveData:(NSData *)data
|
||||
{
|
||||
//NSLog(@"get some data");
|
||||
[responseData appendData:data];
|
||||
getDataTime++;
|
||||
}
|
||||
|
||||
/**
|
||||
* This delegate methodis called if the connection cannot be established to the server.
|
||||
* The error object will have a description of the error
|
||||
**/
|
||||
- (void)connection:(NSURLConnection *)connection
|
||||
didFailWithError:(NSError *)error
|
||||
{
|
||||
//NSLog(@"Load failed with error %@", [error localizedDescription]);
|
||||
responseError = [error copy];
|
||||
|
||||
finish = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This delegate method is called when the data load is complete. The delegate will be released
|
||||
* following this call
|
||||
**/
|
||||
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
|
||||
{
|
||||
finish = true;
|
||||
}
|
||||
|
||||
//Server evaluates client's certificate
|
||||
- (BOOL) shouldTrustProtectionSpace:(NSURLProtectionSpace*)protectionSpace
|
||||
{
|
||||
if(sslFile == nil)
|
||||
return YES;
|
||||
//load the bundle client certificate
|
||||
NSString *certPath = [[NSBundle mainBundle] pathForResource:sslFile ofType:@"der"];
|
||||
NSData *certData = [[NSData alloc] initWithContentsOfFile:certPath];
|
||||
CFDataRef certDataRef = (CFDataRef)certData;
|
||||
SecCertificateRef cert = SecCertificateCreateWithData(NULL, certDataRef);
|
||||
|
||||
//Establish a chain of trust anchored on our bundled certificate
|
||||
CFArrayRef certArrayRef = CFArrayCreate(NULL, (void*)&cert, 1, NULL);
|
||||
SecTrustRef serverTrust = protectionSpace.serverTrust;
|
||||
SecTrustSetAnchorCertificates(serverTrust, certArrayRef);
|
||||
|
||||
//Verify that trust
|
||||
SecTrustResultType trustResult;
|
||||
SecTrustEvaluate(serverTrust, &trustResult);
|
||||
|
||||
if(trustResult == kSecTrustResultRecoverableTrustFailure)
|
||||
{
|
||||
CFDataRef errDataRef = SecTrustCopyExceptions(serverTrust);
|
||||
SecTrustSetExceptions(serverTrust, errDataRef);
|
||||
|
||||
SecTrustEvaluate(serverTrust, &trustResult);
|
||||
}
|
||||
|
||||
//Did our custom trust chain evaluate successfully?
|
||||
return trustResult = kSecTrustResultUnspecified || trustResult == kSecTrustResultProceed;
|
||||
}
|
||||
|
||||
- (void) connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
|
||||
{
|
||||
id <NSURLAuthenticationChallengeSender> sender = challenge.sender;
|
||||
NSURLProtectionSpace *protectionSpace = challenge.protectionSpace;
|
||||
|
||||
//Should server trust client?
|
||||
if([self shouldTrustProtectionSpace:protectionSpace])
|
||||
{
|
||||
SecTrustRef trust = [protectionSpace serverTrust];
|
||||
//
|
||||
// SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trust, 0);
|
||||
//
|
||||
// NSData *serverCertificateData = (NSData*)SecCertificateCopyData(certificate);
|
||||
// NSString *serverCertificateDataHash = [[serverCertificateData base64EncodedString] ]
|
||||
NSURLCredential *credential = [NSURLCredential credentialForTrust:trust];
|
||||
[sender useCredential:credential forAuthenticationChallenge:challenge];
|
||||
}
|
||||
else
|
||||
{
|
||||
[sender cancelAuthenticationChallenge:challenge];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,972 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2012 greathqy
|
||||
Copyright (c) 2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2014 Chukong Technologies Inc.
|
||||
|
||||
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 "HttpClient.h"
|
||||
|
||||
#include <thread>
|
||||
#include <queue>
|
||||
#include <sstream>
|
||||
#include <condition_variable>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "base/CCVector.h"
|
||||
#include "base/CCDirector.h"
|
||||
#include "base/CCScheduler.h"
|
||||
|
||||
#include "platform/CCFileUtils.h"
|
||||
#include "platform/android/jni/JniHelper.h"
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
namespace network {
|
||||
|
||||
typedef std::vector<std::string> HttpRequestHeaders;
|
||||
typedef HttpRequestHeaders::iterator HttpRequestHeadersIter;
|
||||
typedef std::vector<std::string> HttpCookies;
|
||||
typedef HttpCookies::iterator HttpCookiesIter;
|
||||
|
||||
static std::mutex s_requestQueueMutex;
|
||||
static std::mutex s_responseQueueMutex;
|
||||
static std::mutex s_cookieFileMutex;
|
||||
|
||||
static std::condition_variable_any s_sleepCondition;
|
||||
|
||||
static Vector<HttpRequest*>* s_requestQueue = nullptr;
|
||||
static Vector<HttpResponse*>* s_responseQueue = nullptr;
|
||||
|
||||
static HttpClient *s_httpClient = nullptr; // pointer to singleton
|
||||
|
||||
static std::string s_responseMessage = "";
|
||||
|
||||
static std::string s_cookieFilename = "";
|
||||
|
||||
static std::string s_sslCaFilename = "";
|
||||
|
||||
static HttpRequest *s_requestSentinel = new HttpRequest;
|
||||
|
||||
|
||||
struct CookiesInfo
|
||||
{
|
||||
std::string domain;
|
||||
bool tailmatch;
|
||||
std::string path;
|
||||
bool secure;
|
||||
std::string key;
|
||||
std::string value;
|
||||
std::string expires;
|
||||
};
|
||||
|
||||
//static size_t writeData(void *ptr, size_t size, size_t nmemb, void *stream)
|
||||
static size_t writeData(void* buffer, size_t sizes, HttpResponse* response)
|
||||
{
|
||||
std::vector<char> * recvBuffer = (std::vector<char>*)response->getResponseData();
|
||||
recvBuffer->clear();
|
||||
recvBuffer->insert(recvBuffer->end(), (char*)buffer, ((char*)buffer) + sizes);
|
||||
return sizes;
|
||||
}
|
||||
|
||||
//static size_t writeHeaderData(void *ptr, size_t size, size_t nmemb, void *stream)
|
||||
size_t writeHeaderData(void* buffer, size_t sizes,HttpResponse* response)
|
||||
{
|
||||
std::vector<char> * recvBuffer = (std::vector<char>*) response->getResponseHeader();
|
||||
recvBuffer->clear();
|
||||
recvBuffer->insert(recvBuffer->end(), (char*)buffer, (char*)buffer + sizes);
|
||||
return sizes;
|
||||
}
|
||||
|
||||
static void processResponse(HttpResponse* response, std::string& responseMessage);
|
||||
|
||||
class HttpURLConnection
|
||||
{
|
||||
public:
|
||||
HttpURLConnection():_httpURLConnection(nullptr),
|
||||
_requestmethod(""),
|
||||
_responseCookies(""),
|
||||
_cookieFileName(""),
|
||||
_contentLength(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
~HttpURLConnection()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void setRequestMethod(const char* method)
|
||||
{
|
||||
_requestmethod = method;
|
||||
|
||||
JniMethodInfo methodInfo;
|
||||
if (JniHelper::getStaticMethodInfo(methodInfo,
|
||||
"org/cocos2dx/lib/Cocos2dxHttpURLConnection",
|
||||
"setRequestMethod",
|
||||
"(Ljava/net/HttpURLConnection;Ljava/lang/String;)V"))
|
||||
{
|
||||
jstring jstr = methodInfo.env->NewStringUTF(_requestmethod.c_str());
|
||||
methodInfo.env->CallStaticVoidMethod(
|
||||
methodInfo.classID, methodInfo.methodID, _httpURLConnection, jstr);
|
||||
methodInfo.env->DeleteLocalRef(jstr);
|
||||
methodInfo.env->DeleteLocalRef(methodInfo.classID);
|
||||
}
|
||||
}
|
||||
|
||||
bool init(HttpRequest* request)
|
||||
{
|
||||
createHttpURLConnection(request->getUrl());
|
||||
if(!configure())
|
||||
return false;
|
||||
/* get custom header data (if set) */
|
||||
HttpRequestHeaders headers=request->getHeaders();
|
||||
if(!headers.empty())
|
||||
{
|
||||
/* append custom headers one by one */
|
||||
for (HttpRequestHeadersIter it = headers.begin(); it != headers.end(); ++it)
|
||||
{
|
||||
std::string val = *it;
|
||||
|
||||
int len = val.length();
|
||||
int pos = val.find(':');
|
||||
if (-1 == pos || pos >= len)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
std::string str1 = val.substr(0, pos);
|
||||
std::string str2 = val.substr(pos + 1, len - pos - 1);
|
||||
addRequestHeader(str1.c_str(), str2.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
addCookiesForRequestHeader();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int connect()
|
||||
{
|
||||
int suc = 0;
|
||||
JniMethodInfo methodInfo;
|
||||
if (JniHelper::getStaticMethodInfo(methodInfo,
|
||||
"org/cocos2dx/lib/Cocos2dxHttpURLConnection",
|
||||
"connect",
|
||||
"(Ljava/net/HttpURLConnection;)I"))
|
||||
{
|
||||
suc = methodInfo.env->CallStaticIntMethod(
|
||||
methodInfo.classID, methodInfo.methodID, _httpURLConnection);
|
||||
methodInfo.env->DeleteLocalRef(methodInfo.classID);
|
||||
}
|
||||
|
||||
return suc;
|
||||
}
|
||||
|
||||
void disconnect()
|
||||
{
|
||||
JniMethodInfo methodInfo;
|
||||
if (JniHelper::getStaticMethodInfo(methodInfo,
|
||||
"org/cocos2dx/lib/Cocos2dxHttpURLConnection",
|
||||
"disconnect",
|
||||
"(Ljava/net/HttpURLConnection;)V"))
|
||||
{
|
||||
methodInfo.env->CallStaticVoidMethod(
|
||||
methodInfo.classID, methodInfo.methodID, _httpURLConnection);
|
||||
methodInfo.env->DeleteLocalRef(methodInfo.classID);
|
||||
}
|
||||
}
|
||||
|
||||
int getResponseCode()
|
||||
{
|
||||
int responseCode = 0;
|
||||
JniMethodInfo methodInfo;
|
||||
if (JniHelper::getStaticMethodInfo(methodInfo,
|
||||
"org/cocos2dx/lib/Cocos2dxHttpURLConnection",
|
||||
"getResponseCode",
|
||||
"(Ljava/net/HttpURLConnection;)I"))
|
||||
{
|
||||
responseCode = methodInfo.env->CallStaticIntMethod(
|
||||
methodInfo.classID, methodInfo.methodID, _httpURLConnection);
|
||||
methodInfo.env->DeleteLocalRef(methodInfo.classID);
|
||||
}
|
||||
|
||||
return responseCode;
|
||||
}
|
||||
|
||||
char* getResponseMessage()
|
||||
{
|
||||
char* message = nullptr;
|
||||
JniMethodInfo methodInfo;
|
||||
if (JniHelper::getStaticMethodInfo(methodInfo,
|
||||
"org/cocos2dx/lib/Cocos2dxHttpURLConnection",
|
||||
"getResponseMessage",
|
||||
"(Ljava/net/HttpURLConnection;)Ljava/lang/String;"))
|
||||
{
|
||||
jobject jObj = methodInfo.env->CallStaticObjectMethod(
|
||||
methodInfo.classID, methodInfo.methodID, _httpURLConnection);
|
||||
message = getBufferFromJString((jstring)jObj, methodInfo.env);
|
||||
if (nullptr != jObj)
|
||||
{
|
||||
methodInfo.env->DeleteLocalRef(jObj);
|
||||
}
|
||||
methodInfo.env->DeleteLocalRef(methodInfo.classID);
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
void sendRequest(HttpRequest* request)
|
||||
{
|
||||
JniMethodInfo methodInfo;
|
||||
if (JniHelper::getStaticMethodInfo(methodInfo,
|
||||
"org/cocos2dx/lib/Cocos2dxHttpURLConnection",
|
||||
"sendRequest",
|
||||
"(Ljava/net/HttpURLConnection;[B)V"))
|
||||
{
|
||||
|
||||
jbyteArray bytearray;
|
||||
ssize_t dataSize = request->getRequestDataSize();
|
||||
bytearray = methodInfo.env->NewByteArray(dataSize);
|
||||
methodInfo.env->SetByteArrayRegion(bytearray, 0, dataSize, (const jbyte*)request->getRequestData());
|
||||
methodInfo.env->CallStaticVoidMethod(
|
||||
methodInfo.classID, methodInfo.methodID, _httpURLConnection, bytearray);
|
||||
methodInfo.env->DeleteLocalRef(bytearray);
|
||||
methodInfo.env->DeleteLocalRef(methodInfo.classID);
|
||||
}
|
||||
}
|
||||
|
||||
size_t saveResponseCookies(const char* responseCookies, size_t count)
|
||||
{
|
||||
if (nullptr == responseCookies || strlen(responseCookies) == 0 || count == 0)
|
||||
return 0;
|
||||
|
||||
if (_cookieFileName.empty())
|
||||
{
|
||||
_cookieFileName = FileUtils::getInstance()->getWritablePath() + "cookieFile.txt";
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(s_cookieFileMutex);
|
||||
|
||||
FILE* fp = fopen(_cookieFileName.c_str(), "w");
|
||||
if (nullptr == fp)
|
||||
{
|
||||
CCLOG("can't create or open response cookie files");
|
||||
return 0;
|
||||
}
|
||||
|
||||
fwrite(responseCookies, sizeof(char), count, fp);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
char* getResponseHeaders()
|
||||
{
|
||||
char* headers = nullptr;
|
||||
JniMethodInfo methodInfo;
|
||||
if (JniHelper::getStaticMethodInfo(methodInfo,
|
||||
"org/cocos2dx/lib/Cocos2dxHttpURLConnection",
|
||||
"getResponseHeaders",
|
||||
"(Ljava/net/HttpURLConnection;)Ljava/lang/String;"))
|
||||
{
|
||||
jobject jObj = methodInfo.env->CallStaticObjectMethod(
|
||||
methodInfo.classID, methodInfo.methodID, _httpURLConnection);
|
||||
headers = getBufferFromJString((jstring)jObj, methodInfo.env);
|
||||
if (nullptr != jObj) {
|
||||
methodInfo.env->DeleteLocalRef(jObj);
|
||||
}
|
||||
methodInfo.env->DeleteLocalRef(methodInfo.classID);
|
||||
}
|
||||
|
||||
return headers;
|
||||
|
||||
}
|
||||
|
||||
char* getResponseContent(HttpResponse* response)
|
||||
{
|
||||
if (nullptr == response)
|
||||
return nullptr;
|
||||
|
||||
char* content = nullptr;
|
||||
JniMethodInfo methodInfo;
|
||||
if (JniHelper::getStaticMethodInfo(methodInfo,
|
||||
"org/cocos2dx/lib/Cocos2dxHttpURLConnection",
|
||||
"getResponseContent",
|
||||
"(Ljava/net/HttpURLConnection;)[B"))
|
||||
{
|
||||
jobject jObj = methodInfo.env->CallStaticObjectMethod(
|
||||
methodInfo.classID, methodInfo.methodID, _httpURLConnection);
|
||||
|
||||
_contentLength = getCStrFromJByteArray((jbyteArray)jObj, methodInfo.env, &content);
|
||||
if (nullptr != jObj)
|
||||
{
|
||||
methodInfo.env->DeleteLocalRef(jObj);
|
||||
}
|
||||
methodInfo.env->DeleteLocalRef(methodInfo.classID);
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
char* getResponseHeaderByKey(const char* key)
|
||||
{
|
||||
char* value = nullptr;
|
||||
JniMethodInfo methodInfo;
|
||||
if (JniHelper::getStaticMethodInfo(methodInfo,
|
||||
"org/cocos2dx/lib/Cocos2dxHttpURLConnection",
|
||||
"getResponseHeaderByKey",
|
||||
"(Ljava/net/HttpURLConnection;Ljava/lang/String;)Ljava/lang/String;"))
|
||||
{
|
||||
jstring jstrKey = methodInfo.env->NewStringUTF(key);
|
||||
jobject jObj = methodInfo.env->CallStaticObjectMethod(
|
||||
methodInfo.classID, methodInfo.methodID, _httpURLConnection, jstrKey);
|
||||
value = getBufferFromJString((jstring)jObj, methodInfo.env);
|
||||
methodInfo.env->DeleteLocalRef(jstrKey);
|
||||
if (nullptr != jObj) {
|
||||
methodInfo.env->DeleteLocalRef(jObj);
|
||||
}
|
||||
methodInfo.env->DeleteLocalRef(methodInfo.classID);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
int getResponseHeaderByKeyInt(const char* key)
|
||||
{
|
||||
int contentLength = 0;
|
||||
JniMethodInfo methodInfo;
|
||||
if (JniHelper::getStaticMethodInfo(methodInfo,
|
||||
"org/cocos2dx/lib/Cocos2dxHttpURLConnection",
|
||||
"getResponseHeaderByKeyInt",
|
||||
"(Ljava/net/HttpURLConnection;Ljava/lang/String;)I"))
|
||||
{
|
||||
jstring jstrKey = methodInfo.env->NewStringUTF(key);
|
||||
contentLength = methodInfo.env->CallStaticIntMethod(
|
||||
methodInfo.classID, methodInfo.methodID, _httpURLConnection, jstrKey);
|
||||
methodInfo.env->DeleteLocalRef(jstrKey);
|
||||
methodInfo.env->DeleteLocalRef(methodInfo.classID);
|
||||
}
|
||||
|
||||
return contentLength;
|
||||
}
|
||||
|
||||
char* getResponseHeaderByIdx(int idx)
|
||||
{
|
||||
char* header = nullptr;
|
||||
JniMethodInfo methodInfo;
|
||||
if (JniHelper::getStaticMethodInfo(methodInfo,
|
||||
"org/cocos2dx/lib/Cocos2dxHttpURLConnection",
|
||||
"getResponseHeaderByIdx",
|
||||
"(Ljava/net/HttpURLConnection;I)Ljava/lang/String;"))
|
||||
{
|
||||
jobject jObj = methodInfo.env->CallStaticObjectMethod(
|
||||
methodInfo.classID, methodInfo.methodID, _httpURLConnection, idx);
|
||||
header = getBufferFromJString((jstring)jObj, methodInfo.env);
|
||||
if (nullptr != jObj) {
|
||||
methodInfo.env->DeleteLocalRef(jObj);
|
||||
}
|
||||
methodInfo.env->DeleteLocalRef(methodInfo.classID);
|
||||
}
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
const std::string getCookieFileName()
|
||||
{
|
||||
return _cookieFileName;
|
||||
}
|
||||
|
||||
void setCookieFileName(std::string& filename)
|
||||
{
|
||||
_cookieFileName = filename;
|
||||
}
|
||||
|
||||
int getContentLength()
|
||||
{
|
||||
return _contentLength;
|
||||
}
|
||||
|
||||
private:
|
||||
void createHttpURLConnection(std::string url)
|
||||
{
|
||||
JniMethodInfo methodInfo;
|
||||
if (JniHelper::getStaticMethodInfo(methodInfo,
|
||||
"org/cocos2dx/lib/Cocos2dxHttpURLConnection",
|
||||
"createHttpURLConnection",
|
||||
"(Ljava/lang/String;)Ljava/net/HttpURLConnection;"))
|
||||
{
|
||||
_url = url;
|
||||
jstring jurl = methodInfo.env->NewStringUTF(url.c_str());
|
||||
jobject jObj = methodInfo.env->CallStaticObjectMethod(methodInfo.classID, methodInfo.methodID, jurl);
|
||||
_httpURLConnection = methodInfo.env->NewGlobalRef(jObj);
|
||||
methodInfo.env->DeleteLocalRef(jurl);
|
||||
methodInfo.env->DeleteLocalRef(methodInfo.classID);
|
||||
}
|
||||
}
|
||||
|
||||
void addRequestHeader(const char* key, const char* value)
|
||||
{
|
||||
JniMethodInfo methodInfo;
|
||||
if (JniHelper::getStaticMethodInfo(methodInfo,
|
||||
"org/cocos2dx/lib/Cocos2dxHttpURLConnection",
|
||||
"addRequestHeader",
|
||||
"(Ljava/net/HttpURLConnection;Ljava/lang/String;Ljava/lang/String;)V"))
|
||||
{
|
||||
jstring jstrKey = methodInfo.env->NewStringUTF(key);
|
||||
jstring jstrVal = methodInfo.env->NewStringUTF(value);
|
||||
methodInfo.env->CallStaticVoidMethod(
|
||||
methodInfo.classID, methodInfo.methodID, _httpURLConnection, jstrKey, jstrVal);
|
||||
methodInfo.env->DeleteLocalRef(jstrKey);
|
||||
methodInfo.env->DeleteLocalRef(jstrVal);
|
||||
methodInfo.env->DeleteLocalRef(methodInfo.classID);
|
||||
}
|
||||
}
|
||||
|
||||
void addCookiesForRequestHeader()
|
||||
{
|
||||
if(s_cookieFilename.empty())
|
||||
return;
|
||||
|
||||
_cookieFileName = FileUtils::getInstance()->fullPathForFilename(s_cookieFilename.c_str());
|
||||
|
||||
std::lock_guard<std::mutex> lock(s_cookieFileMutex);
|
||||
|
||||
std::string cookiesInfo = FileUtils::getInstance()->getStringFromFile(_cookieFileName.c_str());
|
||||
|
||||
if (cookiesInfo.empty())
|
||||
return;
|
||||
|
||||
HttpCookies cookiesVec;
|
||||
cookiesVec.clear();
|
||||
|
||||
std::stringstream stream(cookiesInfo);
|
||||
std::string item;
|
||||
while (std::getline(stream, item, '\n'))
|
||||
{
|
||||
cookiesVec.push_back(item);
|
||||
}
|
||||
|
||||
if (cookiesVec.empty())
|
||||
return;
|
||||
|
||||
HttpCookiesIter iter = cookiesVec.begin();
|
||||
|
||||
std::vector<CookiesInfo> cookiesInfoVec;
|
||||
cookiesInfoVec.clear();
|
||||
|
||||
for (; iter != cookiesVec.end(); iter++)
|
||||
{
|
||||
std::string cookies = *iter;
|
||||
if (cookies.find("#HttpOnly_") != std::string::npos)
|
||||
{
|
||||
cookies = cookies.substr(10);
|
||||
}
|
||||
|
||||
if(cookies.at(0) == '#')
|
||||
continue;
|
||||
|
||||
CookiesInfo co;
|
||||
std::stringstream streamInfo(cookies);
|
||||
std::string item;
|
||||
std::vector<std::string> elems;
|
||||
|
||||
while (std::getline(streamInfo, item, '\t'))
|
||||
{
|
||||
elems.push_back(item);
|
||||
}
|
||||
|
||||
co.domain = elems[0];
|
||||
if (co.domain.at(0) == '.')
|
||||
{
|
||||
co.domain = co.domain.substr(1);
|
||||
}
|
||||
co.tailmatch = strcmp("TRUE", elems.at(1).c_str())?true: false;
|
||||
co.path = elems.at(2);
|
||||
co.secure = strcmp("TRUE", elems.at(3).c_str())?true: false;
|
||||
co.expires = elems.at(4);
|
||||
co.key = elems.at(5);
|
||||
co.value = elems.at(6);
|
||||
cookiesInfoVec.push_back(co);
|
||||
}
|
||||
|
||||
std::vector<CookiesInfo>::iterator cookiesIter = cookiesInfoVec.begin();
|
||||
std::string sendCookiesInfo = "";
|
||||
int cookiesCount = 0;
|
||||
for (; cookiesIter != cookiesInfoVec.end(); cookiesIter++)
|
||||
{
|
||||
if (_url.find(cookiesIter->domain) != std::string::npos)
|
||||
{
|
||||
std::string keyValue = cookiesIter->key;
|
||||
keyValue.append("=");
|
||||
keyValue.append(cookiesIter->value);
|
||||
if (cookiesCount != 0)
|
||||
sendCookiesInfo.append(";");
|
||||
|
||||
sendCookiesInfo.append(keyValue);
|
||||
}
|
||||
cookiesCount++;
|
||||
}
|
||||
|
||||
//set Cookie
|
||||
addRequestHeader("Cookie",sendCookiesInfo.c_str());
|
||||
}
|
||||
|
||||
void setReadAndConnectTimeout(int readMiliseconds, int connectMiliseconds)
|
||||
{
|
||||
JniMethodInfo methodInfo;
|
||||
if (JniHelper::getStaticMethodInfo(methodInfo,
|
||||
"org/cocos2dx/lib/Cocos2dxHttpURLConnection",
|
||||
"setReadAndConnectTimeout",
|
||||
"(Ljava/net/HttpURLConnection;II)V"))
|
||||
{
|
||||
methodInfo.env->CallStaticVoidMethod(
|
||||
methodInfo.classID, methodInfo.methodID, _httpURLConnection, readMiliseconds, connectMiliseconds);
|
||||
methodInfo.env->DeleteLocalRef(methodInfo.classID);
|
||||
}
|
||||
}
|
||||
|
||||
void setVerifySSL()
|
||||
{
|
||||
if(s_sslCaFilename.empty())
|
||||
return;
|
||||
|
||||
std::string fullpath = FileUtils::getInstance()->fullPathForFilename(s_sslCaFilename.c_str());
|
||||
|
||||
JniMethodInfo methodInfo;
|
||||
if (JniHelper::getStaticMethodInfo(methodInfo,
|
||||
"org/cocos2dx/lib/Cocos2dxHttpURLConnection",
|
||||
"setVerifySSL",
|
||||
"(Ljava/net/HttpURLConnection;Ljava/lang/String;)V"))
|
||||
{
|
||||
jstring jstrfullpath = methodInfo.env->NewStringUTF(fullpath.c_str());
|
||||
methodInfo.env->CallStaticVoidMethod(
|
||||
methodInfo.classID, methodInfo.methodID, _httpURLConnection, jstrfullpath);
|
||||
methodInfo.env->DeleteLocalRef(jstrfullpath);
|
||||
methodInfo.env->DeleteLocalRef(methodInfo.classID);
|
||||
}
|
||||
}
|
||||
|
||||
bool configure()
|
||||
{
|
||||
if(nullptr == _httpURLConnection)
|
||||
return false;
|
||||
|
||||
HttpClient* instnace = HttpClient::getInstance();
|
||||
if(nullptr == instnace)
|
||||
return false;
|
||||
|
||||
setReadAndConnectTimeout(instnace->getTimeoutForRead(), instnace->getTimeoutForConnect());
|
||||
|
||||
setVerifySSL();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
char* getBufferFromJString(jstring jstr, JNIEnv* env)
|
||||
{
|
||||
if (nullptr == jstr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char* str = nullptr;
|
||||
char* ret = nullptr;
|
||||
str = env->GetStringUTFChars(jstr, nullptr);
|
||||
if (nullptr != str)
|
||||
{
|
||||
ret = strdup(str);
|
||||
}
|
||||
|
||||
env->ReleaseStringUTFChars(jstr, str);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int getCStrFromJByteArray(jbyteArray jba, JNIEnv* env, char** ppData)
|
||||
{
|
||||
if (nullptr == jba)
|
||||
{
|
||||
*ppData = nullptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* str = nullptr;
|
||||
|
||||
int len = env->GetArrayLength(jba);
|
||||
str = (char*)malloc(sizeof(char)*len);
|
||||
env->GetByteArrayRegion(jba, 0, len, (jbyte*)str);
|
||||
|
||||
*ppData = str;
|
||||
return len;
|
||||
}
|
||||
|
||||
const std::string getCookieString()
|
||||
{
|
||||
return _responseCookies;
|
||||
}
|
||||
private:
|
||||
jobject _httpURLConnection;
|
||||
std::string _requestmethod;
|
||||
std::string _responseCookies;
|
||||
std::string _cookieFileName;
|
||||
std::string _url;
|
||||
int _contentLength;
|
||||
};
|
||||
|
||||
// Process Response
|
||||
static void processResponse(HttpResponse* response, std::string& responseMessage)
|
||||
{
|
||||
auto request = response->getHttpRequest();
|
||||
HttpRequest::Type requestType = request->getRequestType();
|
||||
|
||||
if (HttpRequest::Type::GET != requestType &&
|
||||
HttpRequest::Type::POST != requestType &&
|
||||
HttpRequest::Type::PUT != requestType &&
|
||||
HttpRequest::Type::DELETE != requestType)
|
||||
{
|
||||
CCASSERT(true, "CCHttpClient: unkown request type, only GET、POST、PUT、DELETE are supported");
|
||||
return;
|
||||
}
|
||||
|
||||
long responseCode = -1;
|
||||
int retValue = 0;
|
||||
|
||||
HttpURLConnection urlConnection;
|
||||
if(!urlConnection.init(request))
|
||||
{
|
||||
response->setSucceed(false);
|
||||
response->setErrorBuffer("HttpURLConnetcion init failed");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (requestType)
|
||||
{
|
||||
case HttpRequest::Type::GET:
|
||||
urlConnection.setRequestMethod("GET");
|
||||
break;
|
||||
|
||||
case HttpRequest::Type::POST:
|
||||
urlConnection.setRequestMethod("POST");
|
||||
break;
|
||||
|
||||
case HttpRequest::Type::PUT:
|
||||
urlConnection.setRequestMethod("PUT");
|
||||
break;
|
||||
|
||||
case HttpRequest::Type::DELETE:
|
||||
urlConnection.setRequestMethod("DELETE");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
int suc = urlConnection.connect();
|
||||
if (0 != suc)
|
||||
{
|
||||
response->setSucceed(false);
|
||||
response->setErrorBuffer("connect failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (HttpRequest::Type::POST == requestType ||
|
||||
HttpRequest::Type::PUT == requestType)
|
||||
{
|
||||
urlConnection.sendRequest(request);
|
||||
}
|
||||
|
||||
responseCode = urlConnection.getResponseCode();
|
||||
|
||||
char* headers = urlConnection.getResponseHeaders();
|
||||
if (nullptr != headers)
|
||||
{
|
||||
writeHeaderData(headers, strlen(headers), response);
|
||||
}
|
||||
free(headers);
|
||||
|
||||
//get and save cookies
|
||||
char* cookiesInfo = urlConnection.getResponseHeaderByKey("set-cookie");
|
||||
if (nullptr != cookiesInfo)
|
||||
{
|
||||
urlConnection.saveResponseCookies(cookiesInfo, strlen(cookiesInfo));
|
||||
}
|
||||
free(cookiesInfo);
|
||||
|
||||
//content len
|
||||
int contentLength = urlConnection.getResponseHeaderByKeyInt("Content-Length");
|
||||
char* contentInfo = urlConnection.getResponseContent(response);
|
||||
if (nullptr != contentInfo) {
|
||||
// response->setResponseDataString(contentInfo, contentLength);
|
||||
std::vector<char> * recvBuffer = (std::vector<char>*)response->getResponseData();
|
||||
recvBuffer->clear();
|
||||
recvBuffer->insert(recvBuffer->begin(), (char*)contentInfo, ((char*)contentInfo) + urlConnection.getContentLength());
|
||||
}
|
||||
free(contentInfo);
|
||||
|
||||
responseMessage = urlConnection.getResponseMessage();
|
||||
urlConnection.disconnect();
|
||||
|
||||
// write data to HttpResponse
|
||||
response->setResponseCode(responseCode);
|
||||
|
||||
if (responseCode == -1)
|
||||
{
|
||||
response->setSucceed(false);
|
||||
response->setErrorBuffer(responseMessage.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
response->setSucceed(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Worker thread
|
||||
void HttpClient::networkThread()
|
||||
{
|
||||
auto scheduler = Director::getInstance()->getScheduler();
|
||||
|
||||
while (true)
|
||||
{
|
||||
HttpRequest *request;
|
||||
|
||||
// step 1: send http request if the requestQueue isn't empty
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_requestQueueMutex);
|
||||
while (s_requestQueue->empty()) {
|
||||
s_sleepCondition.wait(s_requestQueueMutex);
|
||||
}
|
||||
request = s_requestQueue->at(0);
|
||||
s_requestQueue->erase(0);
|
||||
}
|
||||
|
||||
if (request == s_requestSentinel) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Create a HttpResponse object, the default setting is http access failed
|
||||
HttpResponse *response = new (std::nothrow) HttpResponse(request);
|
||||
processResponse(response, s_responseMessage);
|
||||
|
||||
// add response packet into queue
|
||||
s_responseQueueMutex.lock();
|
||||
s_responseQueue->pushBack(response);
|
||||
s_responseQueueMutex.unlock();
|
||||
|
||||
if (nullptr != s_httpClient) {
|
||||
scheduler->performFunctionInCocosThread(CC_CALLBACK_0(HttpClient::dispatchResponseCallbacks, this));
|
||||
}
|
||||
}
|
||||
|
||||
// cleanup: if worker thread received quit signal, clean up un-completed request queue
|
||||
s_requestQueueMutex.lock();
|
||||
s_requestQueue->clear();
|
||||
s_requestQueueMutex.unlock();
|
||||
|
||||
|
||||
if (s_requestQueue != nullptr) {
|
||||
delete s_requestQueue;
|
||||
s_requestQueue = nullptr;
|
||||
delete s_responseQueue;
|
||||
s_responseQueue = nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Worker thread
|
||||
void HttpClient::networkThreadAlone(HttpRequest* request)
|
||||
{
|
||||
// Create a HttpResponse object, the default setting is http access failed
|
||||
HttpResponse *response = new (std::nothrow) HttpResponse(request);
|
||||
std::string responseMessage = "";
|
||||
processResponse(response, responseMessage);
|
||||
|
||||
auto scheduler = Director::getInstance()->getScheduler();
|
||||
scheduler->performFunctionInCocosThread([response, request]{
|
||||
const ccHttpRequestCallback& callback = request->getCallback();
|
||||
Ref* pTarget = request->getTarget();
|
||||
SEL_HttpResponse pSelector = request->getSelector();
|
||||
|
||||
if (callback != nullptr)
|
||||
{
|
||||
callback(s_httpClient, response);
|
||||
}
|
||||
else if (pTarget && pSelector)
|
||||
{
|
||||
(pTarget->*pSelector)(s_httpClient, response);
|
||||
}
|
||||
response->release();
|
||||
// do not release in other thread
|
||||
request->release();
|
||||
});
|
||||
}
|
||||
|
||||
// HttpClient implementation
|
||||
HttpClient* HttpClient::getInstance()
|
||||
{
|
||||
if (s_httpClient == nullptr) {
|
||||
s_httpClient = new (std::nothrow) HttpClient();
|
||||
}
|
||||
|
||||
return s_httpClient;
|
||||
}
|
||||
|
||||
void HttpClient::destroyInstance()
|
||||
{
|
||||
CC_SAFE_DELETE(s_httpClient);
|
||||
}
|
||||
|
||||
void HttpClient::enableCookies(const char* cookieFile) {
|
||||
if (cookieFile) {
|
||||
s_cookieFilename = std::string(cookieFile);
|
||||
}
|
||||
else {
|
||||
s_cookieFilename = (FileUtils::getInstance()->getWritablePath() + "cookieFile.txt");
|
||||
}
|
||||
}
|
||||
|
||||
void HttpClient::setSSLVerification(const std::string& caFile)
|
||||
{
|
||||
s_sslCaFilename = caFile;
|
||||
}
|
||||
|
||||
HttpClient::HttpClient()
|
||||
: _timeoutForConnect(30*1000)
|
||||
, _timeoutForRead(60*1000)
|
||||
{
|
||||
}
|
||||
|
||||
HttpClient::~HttpClient()
|
||||
{
|
||||
if (s_requestQueue != nullptr) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_requestQueueMutex);
|
||||
s_requestQueue->pushBack(s_requestSentinel);
|
||||
}
|
||||
s_sleepCondition.notify_one();
|
||||
}
|
||||
|
||||
s_httpClient = nullptr;
|
||||
}
|
||||
|
||||
//Lazy create semaphore & mutex & thread
|
||||
bool HttpClient::lazyInitThreadSemphore()
|
||||
{
|
||||
if (s_requestQueue != nullptr) {
|
||||
return true;
|
||||
} else {
|
||||
|
||||
s_requestQueue = new (std::nothrow) Vector<HttpRequest*>();
|
||||
s_responseQueue = new (std::nothrow) Vector<HttpResponse*>();
|
||||
|
||||
auto t = std::thread(CC_CALLBACK_0(HttpClient::networkThread, this));
|
||||
t.detach();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//Add a get task to queue
|
||||
void HttpClient::send(HttpRequest* request)
|
||||
{
|
||||
if (false == lazyInitThreadSemphore())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!request)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
request->retain();
|
||||
|
||||
if (nullptr != s_requestQueue) {
|
||||
s_requestQueueMutex.lock();
|
||||
s_requestQueue->pushBack(request);
|
||||
s_requestQueueMutex.unlock();
|
||||
|
||||
// Notify thread start to work
|
||||
s_sleepCondition.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
void HttpClient::sendImmediate(HttpRequest* request)
|
||||
{
|
||||
if(!request)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
request->retain();
|
||||
auto t = std::thread(&HttpClient::networkThreadAlone, this, request);
|
||||
t.detach();
|
||||
}
|
||||
|
||||
// Poll and notify main thread if responses exists in queue
|
||||
void HttpClient::dispatchResponseCallbacks()
|
||||
{
|
||||
// log("CCHttpClient::dispatchResponseCallbacks is running");
|
||||
//occurs when cocos thread fires but the network thread has already quited
|
||||
if (nullptr == s_responseQueue) {
|
||||
return;
|
||||
}
|
||||
HttpResponse* response = nullptr;
|
||||
|
||||
s_responseQueueMutex.lock();
|
||||
|
||||
if (!s_responseQueue->empty())
|
||||
{
|
||||
response = s_responseQueue->at(0);
|
||||
s_responseQueue->erase(0);
|
||||
}
|
||||
|
||||
s_responseQueueMutex.unlock();
|
||||
|
||||
if (response)
|
||||
{
|
||||
HttpRequest *request = response->getHttpRequest();
|
||||
const ccHttpRequestCallback& callback = request->getCallback();
|
||||
Ref* pTarget = request->getTarget();
|
||||
SEL_HttpResponse pSelector = request->getSelector();
|
||||
|
||||
if (callback != nullptr)
|
||||
{
|
||||
callback(this, response);
|
||||
}
|
||||
else if (pTarget && pSelector)
|
||||
{
|
||||
(pTarget->*pSelector)(this, response);
|
||||
}
|
||||
|
||||
response->release();
|
||||
// do not release in other thread
|
||||
request->release();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
NS_CC_END
|
||||
|
||||
|
|
@ -0,0 +1,516 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2012 greathqy
|
||||
Copyright (c) 2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2014 Chukong Technologies Inc.
|
||||
|
||||
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 "HttpClient.h"
|
||||
|
||||
#include <thread>
|
||||
#include <queue>
|
||||
#include <condition_variable>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#import "HttpAsynConnection.h"
|
||||
#include "HttpCookie.h"
|
||||
|
||||
#include "base/CCVector.h"
|
||||
#include "base/CCDirector.h"
|
||||
#include "base/CCScheduler.h"
|
||||
|
||||
#include "platform/CCFileUtils.h"
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
#define ERROR_SIZE 256
|
||||
|
||||
namespace network {
|
||||
|
||||
static std::mutex s_requestQueueMutex;
|
||||
static std::mutex s_responseQueueMutex;
|
||||
|
||||
static std::condition_variable_any s_SleepCondition;
|
||||
|
||||
static Vector<HttpRequest*>* s_requestQueue = nullptr;
|
||||
static Vector<HttpResponse*>* s_responseQueue = nullptr;
|
||||
|
||||
static HttpClient *s_pHttpClient = nullptr; // pointer to singleton
|
||||
|
||||
static HttpAsynConnection *httpAsynConn = nullptr;
|
||||
static HttpCookie *s_cookie = nullptr;
|
||||
|
||||
static char s_errorBuffer[ERROR_SIZE] = {0};
|
||||
|
||||
static std::string s_cookieFilename = "";
|
||||
|
||||
static std::string s_sslCaFilename = "";
|
||||
|
||||
|
||||
static int processTask(HttpRequest *request, NSString *requestType, void *stream, long *errorCode, void *headerStream, char *errorBuffer);
|
||||
|
||||
static void processResponse(HttpResponse* response, char* errorBuffer);
|
||||
|
||||
static HttpRequest *s_requestSentinel = new HttpRequest;
|
||||
|
||||
// Worker thread
|
||||
void HttpClient::networkThread()
|
||||
{
|
||||
auto scheduler = Director::getInstance()->getScheduler();
|
||||
|
||||
while (true)
|
||||
{
|
||||
HttpRequest *request;
|
||||
|
||||
// step 1: send http request if the requestQueue isn't empty
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_requestQueueMutex);
|
||||
while (s_requestQueue->empty()) {
|
||||
s_SleepCondition.wait(s_requestQueueMutex);
|
||||
}
|
||||
request = s_requestQueue->at(0);
|
||||
s_requestQueue->erase(0);
|
||||
}
|
||||
|
||||
if (request == s_requestSentinel) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Create a HttpResponse object, the default setting is http access failed
|
||||
HttpResponse *response = new (std::nothrow) HttpResponse(request);
|
||||
|
||||
processResponse(response, s_errorBuffer);
|
||||
|
||||
// add response packet into queue
|
||||
s_responseQueueMutex.lock();
|
||||
s_responseQueue->pushBack(response);
|
||||
s_responseQueueMutex.unlock();
|
||||
|
||||
if (nullptr != s_pHttpClient) {
|
||||
scheduler->performFunctionInCocosThread(CC_CALLBACK_0(HttpClient::dispatchResponseCallbacks, this));
|
||||
}
|
||||
}
|
||||
|
||||
// cleanup: if worker thread received quit signal, clean up un-completed request queue
|
||||
s_requestQueueMutex.lock();
|
||||
s_requestQueue->clear();
|
||||
s_requestQueueMutex.unlock();
|
||||
|
||||
|
||||
if (s_requestQueue != nullptr) {
|
||||
delete s_requestQueue;
|
||||
s_requestQueue = nullptr;
|
||||
delete s_responseQueue;
|
||||
s_responseQueue = nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Worker thread
|
||||
void HttpClient::networkThreadAlone(HttpRequest* request)
|
||||
{
|
||||
// Create a HttpResponse object, the default setting is http access failed
|
||||
HttpResponse *response = new (std::nothrow) HttpResponse(request);
|
||||
char errorBuffer[ERROR_SIZE] = { 0 };
|
||||
processResponse(response, errorBuffer);
|
||||
|
||||
auto scheduler = Director::getInstance()->getScheduler();
|
||||
scheduler->performFunctionInCocosThread([response, request]{
|
||||
const ccHttpRequestCallback& callback = request->getCallback();
|
||||
Ref* pTarget = request->getTarget();
|
||||
SEL_HttpResponse pSelector = request->getSelector();
|
||||
|
||||
if (callback != nullptr)
|
||||
{
|
||||
callback(s_pHttpClient, response);
|
||||
}
|
||||
else if (pTarget && pSelector)
|
||||
{
|
||||
(pTarget->*pSelector)(s_pHttpClient, response);
|
||||
}
|
||||
response->release();
|
||||
// do not release in other thread
|
||||
request->release();
|
||||
});
|
||||
}
|
||||
|
||||
//Process Request
|
||||
static int processTask(HttpRequest *request, NSString* requestType, void *stream, long *responseCode, void *headerStream, char *errorBuffer)
|
||||
{
|
||||
//create request with url
|
||||
NSString* urlstring = [NSString stringWithUTF8String:request->getUrl()];
|
||||
NSURL *url = [NSURL URLWithString:urlstring];
|
||||
|
||||
NSMutableURLRequest *nsrequest = [NSMutableURLRequest requestWithURL:url
|
||||
cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
|
||||
timeoutInterval:HttpClient::getInstance()->getTimeoutForConnect()];
|
||||
|
||||
//set request type
|
||||
[nsrequest setHTTPMethod:requestType];
|
||||
|
||||
//if request type is post or put,set header and data
|
||||
if([requestType isEqual: @"POST"] || [requestType isEqual: @"PUT"])
|
||||
{
|
||||
/* get custom header data (if set) */
|
||||
std::vector<std::string> headers=request->getHeaders();
|
||||
if(!headers.empty())
|
||||
{
|
||||
/* append custom headers one by one */
|
||||
for (std::vector<std::string>::iterator it = headers.begin(); it != headers.end(); ++it)
|
||||
{
|
||||
unsigned long i = it->find(':', 0);
|
||||
unsigned long length = it->size();
|
||||
std::string field = it->substr(0, i);
|
||||
std::string value = it->substr(i+1, length-i);
|
||||
NSString *headerField = [NSString stringWithUTF8String:field.c_str()];
|
||||
NSString *headerValue = [NSString stringWithUTF8String:value.c_str()];
|
||||
[nsrequest setValue:headerValue forHTTPHeaderField:headerField];
|
||||
}
|
||||
}
|
||||
|
||||
NSString* requestData = [NSString stringWithUTF8String:request->getRequestData()];
|
||||
NSData *postData = [requestData dataUsingEncoding:NSUTF8StringEncoding];
|
||||
[nsrequest setHTTPBody:postData];
|
||||
}
|
||||
|
||||
//read cookie propertities from file and set cookie
|
||||
if(!s_cookieFilename.empty())
|
||||
{
|
||||
const CookiesInfo* cookieInfo = s_cookie->getMatchCookie(request->getUrl());
|
||||
if(cookieInfo != nullptr)
|
||||
{
|
||||
NSString *domain = [NSString stringWithCString:cookieInfo->domain.c_str() encoding:[NSString defaultCStringEncoding]];
|
||||
NSString *path = [NSString stringWithCString:cookieInfo->path.c_str() encoding:[NSString defaultCStringEncoding]];
|
||||
NSString *value = [NSString stringWithCString:cookieInfo->value.c_str() encoding:[NSString defaultCStringEncoding]];
|
||||
NSString *name = [NSString stringWithCString:cookieInfo->name.c_str() encoding:[NSString defaultCStringEncoding]];
|
||||
|
||||
// create the properties for a cookie
|
||||
NSDictionary *properties = [NSDictionary dictionaryWithObjectsAndKeys: name,NSHTTPCookieName,
|
||||
value, NSHTTPCookieValue, path, NSHTTPCookiePath,
|
||||
domain, NSHTTPCookieDomain,
|
||||
nil];
|
||||
|
||||
// create the cookie from the properties
|
||||
NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:properties];
|
||||
|
||||
// add the cookie to the cookie storage
|
||||
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
|
||||
}
|
||||
}
|
||||
|
||||
httpAsynConn = [HttpAsynConnection new];
|
||||
httpAsynConn.srcURL = urlstring;
|
||||
httpAsynConn.sslFile = nil;
|
||||
NSString *sslFile = nil;
|
||||
if(!s_sslCaFilename.empty())
|
||||
{
|
||||
long len = s_sslCaFilename.length();
|
||||
long pos = s_sslCaFilename.rfind('.', len-1);
|
||||
[sslFile initWithUTF8String:s_sslCaFilename.substr(0, pos-1).c_str()];
|
||||
httpAsynConn.sslFile = sslFile;
|
||||
}
|
||||
[httpAsynConn startRequest:nsrequest];
|
||||
|
||||
while( httpAsynConn.finish != true)
|
||||
{
|
||||
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
|
||||
}
|
||||
|
||||
//if http connection return error
|
||||
if (httpAsynConn.responseError != nil)
|
||||
{
|
||||
NSString* errorString = [httpAsynConn.responseError localizedDescription];
|
||||
strcpy(errorBuffer, [errorString UTF8String]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*responseCode = httpAsynConn.responseCode;
|
||||
|
||||
//add cookie to cookies vector
|
||||
if(!s_cookieFilename.empty())
|
||||
{
|
||||
NSArray *cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:httpAsynConn.responseHeader forURL:url];
|
||||
for (NSHTTPCookie *cookie in cookies)
|
||||
{
|
||||
//NSLog(@"Cookie: %@", cookie);
|
||||
NSString *domain = cookie.domain;
|
||||
//BOOL session = cookie.sessionOnly;
|
||||
NSString *path = cookie.path;
|
||||
BOOL secure = cookie.secure;
|
||||
NSDate *date = cookie.expiresDate;
|
||||
NSString *name = cookie.name;
|
||||
NSString *value = cookie.value;
|
||||
|
||||
CookiesInfo cookieInfo;
|
||||
cookieInfo.domain = [domain cStringUsingEncoding: NSUTF8StringEncoding];
|
||||
cookieInfo.path = [path cStringUsingEncoding: NSUTF8StringEncoding];
|
||||
cookieInfo.secure = (secure == YES) ? true : false;
|
||||
cookieInfo.expires = [[NSString stringWithFormat:@"%ld", (long)[date timeIntervalSince1970]] cStringUsingEncoding: NSUTF8StringEncoding];
|
||||
cookieInfo.name = [name cStringUsingEncoding: NSUTF8StringEncoding];
|
||||
cookieInfo.value = [value cStringUsingEncoding: NSUTF8StringEncoding];
|
||||
cookieInfo.tailmatch = true;
|
||||
|
||||
s_cookie->updateOrAddCookie(&cookieInfo);
|
||||
}
|
||||
}
|
||||
|
||||
//handle response header
|
||||
NSMutableString *header = [NSMutableString new];
|
||||
for (id key in httpAsynConn.responseHeader)
|
||||
{
|
||||
[header appendFormat:@"%@: %@\n", key, [httpAsynConn.responseHeader objectForKey:key]];
|
||||
}
|
||||
if (header.length > 0)
|
||||
{
|
||||
NSRange range = NSMakeRange(header.length-1, 1);
|
||||
[header deleteCharactersInRange:range];
|
||||
}
|
||||
NSData *headerData = [header dataUsingEncoding:NSUTF8StringEncoding];
|
||||
std::vector<char> *headerBuffer = (std::vector<char>*)headerStream;
|
||||
const void* headerptr = [headerData bytes];
|
||||
long headerlen = [headerData length];
|
||||
headerBuffer->insert(headerBuffer->end(), (char*)headerptr, (char*)headerptr+headerlen);
|
||||
|
||||
//handle response data
|
||||
std::vector<char> *recvBuffer = (std::vector<char>*)stream;
|
||||
const void* ptr = [httpAsynConn.responseData bytes];
|
||||
long len = [httpAsynConn.responseData length];
|
||||
recvBuffer->insert(recvBuffer->end(), (char*)ptr, (char*)ptr+len);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Process Response
|
||||
static void processResponse(HttpResponse* response, char* errorBuffer)
|
||||
{
|
||||
auto request = response->getHttpRequest();
|
||||
long responseCode = -1;
|
||||
int retValue = 0;
|
||||
NSString* requestType = nil;
|
||||
|
||||
// Process the request -> get response packet
|
||||
switch (request->getRequestType())
|
||||
{
|
||||
case HttpRequest::Type::GET: // HTTP GET
|
||||
requestType = @"GET";
|
||||
break;
|
||||
|
||||
case HttpRequest::Type::POST: // HTTP POST
|
||||
requestType = @"POST";
|
||||
break;
|
||||
|
||||
case HttpRequest::Type::PUT:
|
||||
requestType = @"PUT";
|
||||
break;
|
||||
|
||||
case HttpRequest::Type::DELETE:
|
||||
requestType = @"DELETE";
|
||||
break;
|
||||
|
||||
default:
|
||||
CCASSERT(true, "CCHttpClient: unkown request type, only GET and POSt are supported");
|
||||
break;
|
||||
}
|
||||
|
||||
retValue = processTask(request,
|
||||
requestType,
|
||||
response->getResponseData(),
|
||||
&responseCode,
|
||||
response->getResponseHeader(),
|
||||
errorBuffer);
|
||||
|
||||
// write data to HttpResponse
|
||||
response->setResponseCode(responseCode);
|
||||
|
||||
if (retValue != 0)
|
||||
{
|
||||
response->setSucceed(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
response->setSucceed(false);
|
||||
response->setErrorBuffer(errorBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
// HttpClient implementation
|
||||
HttpClient* HttpClient::getInstance()
|
||||
{
|
||||
if (s_pHttpClient == nullptr) {
|
||||
s_pHttpClient = new (std::nothrow) HttpClient();
|
||||
}
|
||||
|
||||
return s_pHttpClient;
|
||||
}
|
||||
|
||||
void HttpClient::destroyInstance()
|
||||
{
|
||||
CC_SAFE_DELETE(s_pHttpClient);
|
||||
}
|
||||
|
||||
void HttpClient::enableCookies(const char* cookieFile) {
|
||||
if (cookieFile) {
|
||||
s_cookieFilename = std::string(cookieFile);
|
||||
s_cookieFilename = FileUtils::getInstance()->fullPathForFilename(s_cookieFilename);
|
||||
}
|
||||
else {
|
||||
s_cookieFilename = (FileUtils::getInstance()->getWritablePath() + "cookieFile.txt");
|
||||
}
|
||||
|
||||
s_cookie = new(std::nothrow)HttpCookie;
|
||||
s_cookie->setCookieFileName(s_cookieFilename);
|
||||
s_cookie->readFile();
|
||||
}
|
||||
|
||||
void HttpClient::setSSLVerification(const std::string& caFile)
|
||||
{
|
||||
s_sslCaFilename = caFile;
|
||||
}
|
||||
|
||||
HttpClient::HttpClient()
|
||||
: _timeoutForConnect(30)
|
||||
, _timeoutForRead(60)
|
||||
{
|
||||
}
|
||||
|
||||
HttpClient::~HttpClient()
|
||||
{
|
||||
if (s_requestQueue != nullptr) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_requestQueueMutex);
|
||||
s_requestQueue->pushBack(s_requestSentinel);
|
||||
}
|
||||
s_SleepCondition.notify_one();
|
||||
}
|
||||
|
||||
s_pHttpClient = nullptr;
|
||||
|
||||
if(!s_cookieFilename.empty())
|
||||
{
|
||||
s_cookie->writeFile();
|
||||
//delete s_cookie;
|
||||
}
|
||||
//s_cookie = nullptr;
|
||||
}
|
||||
|
||||
//Lazy create semaphore & mutex & thread
|
||||
bool HttpClient::lazyInitThreadSemphore()
|
||||
{
|
||||
if (s_requestQueue != nullptr) {
|
||||
return true;
|
||||
} else {
|
||||
|
||||
s_requestQueue = new (std::nothrow) Vector<HttpRequest*>();
|
||||
s_responseQueue = new (std::nothrow) Vector<HttpResponse*>();
|
||||
|
||||
auto t = std::thread(CC_CALLBACK_0(HttpClient::networkThread, this));
|
||||
t.detach();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//Add a get task to queue
|
||||
void HttpClient::send(HttpRequest* request)
|
||||
{
|
||||
if (false == lazyInitThreadSemphore())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!request)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
request->retain();
|
||||
|
||||
if (nullptr != s_requestQueue) {
|
||||
s_requestQueueMutex.lock();
|
||||
s_requestQueue->pushBack(request);
|
||||
s_requestQueueMutex.unlock();
|
||||
|
||||
// Notify thread start to work
|
||||
s_SleepCondition.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
void HttpClient::sendImmediate(HttpRequest* request)
|
||||
{
|
||||
if(!request)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
request->retain();
|
||||
auto t = std::thread(&HttpClient::networkThreadAlone, this, request);
|
||||
t.detach();
|
||||
}
|
||||
|
||||
// Poll and notify main thread if responses exists in queue
|
||||
void HttpClient::dispatchResponseCallbacks()
|
||||
{
|
||||
// log("CCHttpClient::dispatchResponseCallbacks is running");
|
||||
//occurs when cocos thread fires but the network thread has already quited
|
||||
if (nullptr == s_responseQueue) {
|
||||
return;
|
||||
}
|
||||
HttpResponse* response = nullptr;
|
||||
|
||||
s_responseQueueMutex.lock();
|
||||
|
||||
if (!s_responseQueue->empty())
|
||||
{
|
||||
response = s_responseQueue->at(0);
|
||||
s_responseQueue->erase(0);
|
||||
}
|
||||
|
||||
s_responseQueueMutex.unlock();
|
||||
|
||||
if (response)
|
||||
{
|
||||
HttpRequest *request = response->getHttpRequest();
|
||||
const ccHttpRequestCallback& callback = request->getCallback();
|
||||
Ref* pTarget = request->getTarget();
|
||||
SEL_HttpResponse pSelector = request->getSelector();
|
||||
|
||||
if (callback != nullptr)
|
||||
{
|
||||
callback(this, response);
|
||||
}
|
||||
else if (pTarget && pSelector)
|
||||
{
|
||||
(pTarget->*pSelector)(this, response);
|
||||
}
|
||||
|
||||
response->release();
|
||||
// do not release in other thread
|
||||
request->release();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
NS_CC_END
|
||||
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2013-2014 Chukong Technologies Inc.
|
||||
|
||||
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 "HttpCookie.h"
|
||||
#include "CCFileUtils.h"
|
||||
#include <sstream>
|
||||
#include <stdio.h>
|
||||
|
||||
void HttpCookie::readFile()
|
||||
{
|
||||
std::string inString = cocos2d::FileUtils::getInstance()->getStringFromFile(_cookieFileName);
|
||||
if(inString.length() != 0)
|
||||
{
|
||||
std::vector<std::string> cookiesVec;
|
||||
cookiesVec.clear();
|
||||
|
||||
std::stringstream stream(inString);
|
||||
std::string item;
|
||||
while(std::getline(stream, item, '\n'))
|
||||
{
|
||||
cookiesVec.push_back(item);
|
||||
}
|
||||
|
||||
if(cookiesVec.empty())
|
||||
return;
|
||||
|
||||
_cookies.clear();
|
||||
|
||||
for(auto iter = cookiesVec.begin();iter != cookiesVec.end(); iter++)
|
||||
{
|
||||
std::string cookie = *iter;
|
||||
|
||||
if(cookie.length() == 0)
|
||||
continue;
|
||||
|
||||
if(cookie.find("#HttpOnly_") != std::string::npos)
|
||||
{
|
||||
cookie = cookie.substr(10);
|
||||
}
|
||||
|
||||
if(cookie.at(0) == '#')
|
||||
continue;
|
||||
|
||||
CookiesInfo co;
|
||||
std::stringstream streamInfo(cookie);
|
||||
std::vector<std::string> elems;
|
||||
std::string elemsItem;
|
||||
|
||||
while (std::getline(streamInfo, elemsItem, '\t'))
|
||||
{
|
||||
elems.push_back(elemsItem);
|
||||
}
|
||||
|
||||
co.domain = elems[0];
|
||||
if (co.domain.at(0) == '.')
|
||||
{
|
||||
co.domain = co.domain.substr(1);
|
||||
}
|
||||
co.tailmatch = strcmp("TRUE", elems[1].c_str())?true: false;
|
||||
co.path = elems[2];
|
||||
co.secure = strcmp("TRUE", elems[3].c_str())?true: false;
|
||||
co.expires = elems[4];
|
||||
co.name = elems[5];
|
||||
co.value = elems[6];
|
||||
_cookies.push_back(co);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<CookiesInfo>* HttpCookie::getCookies() const
|
||||
{
|
||||
return &_cookies;
|
||||
}
|
||||
|
||||
const CookiesInfo* HttpCookie::getMatchCookie(const std::string& url) const
|
||||
{
|
||||
for(auto iter = _cookies.begin(); iter != _cookies.end(); iter++)
|
||||
{
|
||||
if(url.find(iter->domain) != std::string::npos)
|
||||
return &(*iter);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void HttpCookie::updateOrAddCookie(CookiesInfo* cookie)
|
||||
{
|
||||
for(auto iter = _cookies.begin(); iter != _cookies.end(); iter++)
|
||||
{
|
||||
if(cookie->domain == iter->domain)
|
||||
{
|
||||
*iter = *cookie;
|
||||
return;
|
||||
}
|
||||
}
|
||||
_cookies.push_back(*cookie);
|
||||
}
|
||||
|
||||
void HttpCookie::writeFile()
|
||||
{
|
||||
FILE *out;
|
||||
out = fopen(_cookieFileName.c_str(), "w");
|
||||
fputs("# Netscape HTTP Cookie File\n"
|
||||
"# http://curl.haxx.se/docs/http-cookies.html\n"
|
||||
"# This file was generated by cocos2d-x! Edit at your own risk.\n"
|
||||
"# Test cocos2d-x cookie write.\n\n",
|
||||
out);
|
||||
|
||||
std::string line;
|
||||
for(auto iter = _cookies.begin(); iter != _cookies.end(); iter++)
|
||||
{
|
||||
line.clear();
|
||||
line.append(iter->domain);
|
||||
line.append(1, '\t');
|
||||
iter->tailmatch ? line.append("TRUE") : line.append("FALSE");
|
||||
line.append(1, '\t');
|
||||
line.append(iter->path);
|
||||
line.append(1, '\t');
|
||||
iter->secure ? line.append("TRUE") : line.append("FALSE");
|
||||
line.append(1, '\t');
|
||||
line.append(iter->expires);
|
||||
line.append(1, '\t');
|
||||
line.append(iter->name);
|
||||
line.append(1, '\t');
|
||||
line.append(iter->value);
|
||||
//line.append(1, '\n');
|
||||
|
||||
fprintf(out, "%s\n", line.c_str());
|
||||
}
|
||||
|
||||
fclose(out);
|
||||
}
|
||||
|
||||
void HttpCookie::setCookieFileName(std::string filename)
|
||||
{
|
||||
_cookieFileName = filename;
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2013-2014 Chukong Technologies Inc.
|
||||
|
||||
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 HTTP_COOKIE_H
|
||||
#define HTTP_COOKIE_H
|
||||
|
||||
struct CookiesInfo
|
||||
{
|
||||
std::string domain;
|
||||
bool tailmatch;
|
||||
std::string path;
|
||||
bool secure;
|
||||
std::string name;
|
||||
std::string value;
|
||||
std::string expires;
|
||||
};
|
||||
|
||||
class HttpCookie
|
||||
{
|
||||
public:
|
||||
void readFile();
|
||||
|
||||
void writeFile();
|
||||
void setCookieFileName(const std::string fileName);
|
||||
|
||||
const std::vector<CookiesInfo>* getCookies()const;
|
||||
const CookiesInfo* getMatchCookie(const std::string& url) const;
|
||||
void updateOrAddCookie(CookiesInfo* cookie);
|
||||
|
||||
private:
|
||||
std::string _cookieFileName;
|
||||
std::vector<CookiesInfo> _cookies;
|
||||
};
|
||||
|
||||
#endif /* HTTP_COOKIE_H */
|
|
@ -54,6 +54,7 @@ public:
|
|||
_succeed = false;
|
||||
_responseData.clear();
|
||||
_errorBuffer.clear();
|
||||
_responseDataString = "";
|
||||
}
|
||||
|
||||
/** Destructor, it will be called in HttpClient internal,
|
||||
|
@ -166,6 +167,17 @@ public:
|
|||
_errorBuffer.assign(value);
|
||||
};
|
||||
|
||||
inline void setResponseDataString(const char* value, size_t n)
|
||||
{
|
||||
_responseDataString.clear();
|
||||
_responseDataString.assign(value, n);
|
||||
}
|
||||
|
||||
inline const char* getResponseDataString()
|
||||
{
|
||||
return _responseDataString.c_str();
|
||||
}
|
||||
|
||||
protected:
|
||||
bool initWithRequest(HttpRequest* request);
|
||||
|
||||
|
@ -175,7 +187,8 @@ protected:
|
|||
std::vector<char> _responseData; /// the returned raw data. You can also dump it as a string
|
||||
std::vector<char> _responseHeader; /// the returned raw header data. You can also dump it as a string
|
||||
long _responseCode; /// the status code returned from libcurl, e.g. 200, 404
|
||||
std::string _errorBuffer; /// if _responseCode != 200, please read _errorBuffer to find the reason
|
||||
std::string _errorBuffer; /// if _responseCode != 200, please read _errorBuffer to find the reason
|
||||
std::string _responseDataString; // the returned raw data. You can also dump it as a string
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,391 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2010-2014 cocos2d-x.org
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
package org.cocos2dx.lib;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
|
||||
import java.net.ProtocolException;
|
||||
import java.net.URL;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.KeyStore;
|
||||
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
|
||||
import org.cocos2dx.lib.Cocos2dxHelper;
|
||||
|
||||
import android.content.res.AssetManager;
|
||||
import android.util.Log;
|
||||
|
||||
public class Cocos2dxHttpURLConnection
|
||||
{
|
||||
private static final String POST_METHOD = "POST" ;
|
||||
private static final String PUT_METHOD = "PUT" ;
|
||||
|
||||
static HttpURLConnection createHttpURLConnection(String linkURL) {
|
||||
URL url;
|
||||
HttpURLConnection urlConnection;
|
||||
try {
|
||||
url = new URL(linkURL);
|
||||
urlConnection = (HttpURLConnection) url.openConnection();
|
||||
//Accept-Encoding
|
||||
urlConnection.setRequestProperty("Accept-Encoding", "identity");
|
||||
urlConnection.setDoInput(true);
|
||||
} catch (Exception e) {
|
||||
Log.e("Cocos2dxHttpURLConnection exception", e.toString());
|
||||
return null;
|
||||
}
|
||||
|
||||
return urlConnection;
|
||||
}
|
||||
|
||||
static void setReadAndConnectTimeout(HttpURLConnection urlConnection, int readMiliseconds, int connectMiliseconds) {
|
||||
urlConnection.setReadTimeout(readMiliseconds);
|
||||
urlConnection.setConnectTimeout(connectMiliseconds);
|
||||
}
|
||||
|
||||
static void setRequestMethod(HttpURLConnection urlConnection, String method){
|
||||
try {
|
||||
urlConnection.setRequestMethod(method);
|
||||
if(method.equalsIgnoreCase(POST_METHOD) || method.equalsIgnoreCase(PUT_METHOD)) {
|
||||
urlConnection.setDoOutput(true);
|
||||
}
|
||||
} catch (ProtocolException e) {
|
||||
Log.e("Cocos2dxHttpURLConnection exception", e.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void setVerifySSL(HttpURLConnection urlConnection, String sslFilename) {
|
||||
if(!(urlConnection instanceof HttpsURLConnection))
|
||||
return;
|
||||
|
||||
|
||||
HttpsURLConnection httpsURLConnection = (HttpsURLConnection)urlConnection;
|
||||
|
||||
try {
|
||||
InputStream caInput = null;
|
||||
if (sslFilename.startsWith("/")) {
|
||||
caInput = new BufferedInputStream(new FileInputStream(sslFilename));
|
||||
}else {
|
||||
String assetString = "assets/";
|
||||
String assetsfilenameString = sslFilename.substring(assetString.length());
|
||||
caInput = new BufferedInputStream(Cocos2dxHelper.getActivity().getAssets().open(assetsfilenameString));
|
||||
}
|
||||
|
||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||
Certificate ca;
|
||||
ca = cf.generateCertificate(caInput);
|
||||
System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
|
||||
caInput.close();
|
||||
|
||||
// Create a KeyStore containing our trusted CAs
|
||||
String keyStoreType = KeyStore.getDefaultType();
|
||||
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
|
||||
keyStore.load(null, null);
|
||||
keyStore.setCertificateEntry("ca", ca);
|
||||
|
||||
// Create a TrustManager that trusts the CAs in our KeyStore
|
||||
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
|
||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
|
||||
tmf.init(keyStore);
|
||||
|
||||
// Create an SSLContext that uses our TrustManager
|
||||
SSLContext context = SSLContext.getInstance("TLS");
|
||||
context.init(null, tmf.getTrustManagers(), null);
|
||||
|
||||
httpsURLConnection.setSSLSocketFactory(context.getSocketFactory());
|
||||
} catch (Exception e) {
|
||||
Log.e("Cocos2dxHttpURLConnection exception", e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
//Add header
|
||||
static void addRequestHeader(HttpURLConnection urlConnection, String key, String value) {
|
||||
urlConnection.setRequestProperty(key, value);
|
||||
}
|
||||
|
||||
static int connect(HttpURLConnection http) {
|
||||
int suc = 0;
|
||||
|
||||
try {
|
||||
http.connect();
|
||||
} catch (IOException e) {
|
||||
Log.e("cocos2d-x debug info", "come in connect");
|
||||
Log.e("cocos2d-x debug info", e.toString());
|
||||
suc = 1;
|
||||
}
|
||||
|
||||
return suc;
|
||||
}
|
||||
|
||||
static void disconnect(HttpURLConnection http) {
|
||||
http.disconnect();
|
||||
}
|
||||
|
||||
static void sendRequest(HttpURLConnection http, byte[] byteArray) {
|
||||
try {
|
||||
OutputStream out = http.getOutputStream();
|
||||
if(null != byteArray) {
|
||||
out.write(byteArray);
|
||||
out.flush();
|
||||
}
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
Log.e("Cocos2dxHttpURLConnection exception", e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
static String getResponseHeaders(HttpURLConnection http) {
|
||||
Map<String, List<String>> headers = http.getHeaderFields();
|
||||
if (null == headers) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String header = null;
|
||||
|
||||
for (Entry<String, List<String>> entry: headers.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
if (null == key) {
|
||||
header += listToString(entry.getValue(), ",");
|
||||
} else {
|
||||
header += key + ":" + listToString(entry.getValue(), ",");
|
||||
}
|
||||
}
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
static String getResponseHeaderByIdx(HttpURLConnection http, int idx) {
|
||||
Map<String, List<String>> headers = http.getHeaderFields();
|
||||
if (null == headers) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String header = null;
|
||||
|
||||
int counter = 0;
|
||||
for (Entry<String, List<String>> entry: headers.entrySet()) {
|
||||
if (counter == idx) {
|
||||
String key = entry.getKey();
|
||||
if (null == key) {
|
||||
header = listToString(entry.getValue(), ",") + "\n";
|
||||
} else {
|
||||
header = key + ":" + listToString(entry.getValue(), ",") + "\n";
|
||||
}
|
||||
break;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
static String getResponseHeaderByKey(HttpURLConnection http, String key) {
|
||||
if (null == key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Map<String, List<String>> headers = http.getHeaderFields();
|
||||
if (null == headers) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String header = null;
|
||||
|
||||
for (Entry<String, List<String>> entry: headers.entrySet()) {
|
||||
if (key.equalsIgnoreCase(entry.getKey())) {
|
||||
if ("set-cookie".equalsIgnoreCase(key)) {
|
||||
header = combinCookies(entry.getValue(), http.getURL().getHost());
|
||||
} else {
|
||||
header = listToString(entry.getValue(), ",");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
static int getResponseHeaderByKeyInt(HttpURLConnection http, String key) {
|
||||
String value = http.getHeaderField(key);
|
||||
|
||||
if (null == value) {
|
||||
return 0;
|
||||
} else {
|
||||
return Integer.parseInt(value);
|
||||
}
|
||||
}
|
||||
|
||||
static byte[] getResponseContent(HttpURLConnection http) {
|
||||
try {
|
||||
DataInputStream in = new DataInputStream(http.getInputStream());
|
||||
byte[] buffer = new byte[1024];
|
||||
int size = 0;
|
||||
ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
|
||||
while((size = in.read(buffer, 0 , 1024)) != -1)
|
||||
{
|
||||
bytestream.write(buffer, 0, size);
|
||||
}
|
||||
byte retbuffer[] = bytestream.toByteArray();
|
||||
bytestream.close();
|
||||
return retbuffer;
|
||||
} catch (Exception e) {
|
||||
Log.e("Cocos2dxHttpURLConnection exception", e.toString());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static int getResponseCode(HttpURLConnection http) {
|
||||
int code = 0;
|
||||
try {
|
||||
code = http.getResponseCode();
|
||||
} catch (IOException e) {
|
||||
Log.e("Cocos2dxHttpURLConnection exception", e.toString());
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static String getResponseMessage(HttpURLConnection http) {
|
||||
String msg;
|
||||
try {
|
||||
msg = http.getResponseMessage();
|
||||
} catch (IOException e) {
|
||||
msg = e.toString();
|
||||
Log.e("Cocos2dxHttpURLConnection exception", msg);
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
public static String listToString(List<String> list, String strInterVal) {
|
||||
if (list == null) {
|
||||
return null;
|
||||
}
|
||||
StringBuilder result = new StringBuilder();
|
||||
boolean flag = false;
|
||||
for (String str : list) {
|
||||
if (flag) {
|
||||
result.append(strInterVal);
|
||||
}
|
||||
if (null == str) {
|
||||
str = "";
|
||||
}
|
||||
result.append(str);
|
||||
flag = true;
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public static String combinCookies(List<String> list, String hostDomain) {
|
||||
StringBuilder sbCookies = new StringBuilder();
|
||||
String domain = hostDomain;
|
||||
String tailmatch = "FALSE";
|
||||
String path = "/";
|
||||
String secure = "FALSE";
|
||||
String key = null;
|
||||
String value = null;
|
||||
String expires = null;
|
||||
for (String str : list) {
|
||||
String[] parts = str.split(";");
|
||||
for (String part : parts) {
|
||||
int firstIndex = part.indexOf("=");
|
||||
if (-1 == firstIndex)
|
||||
continue;
|
||||
|
||||
String[] item = {part.substring(0, firstIndex), part.substring(firstIndex + 1)};
|
||||
if ("expires".equalsIgnoreCase(item[0].trim())) {
|
||||
expires = str2Seconds(item[1].trim());
|
||||
} else if("path".equalsIgnoreCase(item[0].trim())) {
|
||||
path = item[1];
|
||||
} else if("secure".equalsIgnoreCase(item[0].trim())) {
|
||||
secure = item[1];
|
||||
} else if("domain".equalsIgnoreCase(item[0].trim())) {
|
||||
domain = item[1];
|
||||
} else if("version".equalsIgnoreCase(item[0].trim()) || "max-age".equalsIgnoreCase(item[0].trim())) {
|
||||
//do nothing
|
||||
} else {
|
||||
key = item[0];
|
||||
value = item[1];
|
||||
}
|
||||
}
|
||||
|
||||
if (null == domain) {
|
||||
domain = "none";
|
||||
}
|
||||
|
||||
sbCookies.append(domain);
|
||||
sbCookies.append('\t');
|
||||
sbCookies.append(tailmatch); //access
|
||||
sbCookies.append('\t');
|
||||
sbCookies.append(path); //path
|
||||
sbCookies.append('\t');
|
||||
sbCookies.append(secure); //secure
|
||||
sbCookies.append('\t');
|
||||
sbCookies.append(expires); //expires
|
||||
sbCookies.append("\t");
|
||||
sbCookies.append(key); //key
|
||||
sbCookies.append("\t");
|
||||
sbCookies.append(value); //value
|
||||
sbCookies.append('\n');
|
||||
}
|
||||
|
||||
return sbCookies.toString();
|
||||
}
|
||||
|
||||
private static String str2Seconds(String strTime) {
|
||||
Calendar c = Calendar.getInstance();
|
||||
long millisSecond = 0;
|
||||
|
||||
try {
|
||||
c.setTime(new SimpleDateFormat("EEE, dd-MMM-yy hh:mm:ss zzz", Locale.US).parse(strTime));
|
||||
millisSecond = c.getTimeInMillis()/1000;
|
||||
} catch (ParseException e) {
|
||||
Log.e("Cocos2dxHttpURLConnection exception", e.toString());
|
||||
}
|
||||
|
||||
return Long.toString(millisSecond);
|
||||
}
|
||||
}
|
|
@ -798,8 +798,13 @@
|
|||
"cocos/math/Vec4.inl",
|
||||
"cocos/network/Android.mk",
|
||||
"cocos/network/CMakeLists.txt",
|
||||
"cocos/network/HttpAsynConnection.h",
|
||||
"cocos/network/HttpAsynConnection.m",
|
||||
"cocos/network/HttpClient-ios.mm",
|
||||
"cocos/network/HttpClient.cpp",
|
||||
"cocos/network/HttpClient.h",
|
||||
"cocos/network/HttpCookie.cpp",
|
||||
"cocos/network/HttpCookie.h",
|
||||
"cocos/network/HttpRequest.h",
|
||||
"cocos/network/HttpResponse.h",
|
||||
"cocos/network/SocketIO.cpp",
|
||||
|
|
Loading…
Reference in New Issue