diff --git a/cocos/platform/CCNetwork.cpp b/cocos/platform/CCNetwork.cpp new file mode 100644 index 0000000..9dfa846 --- /dev/null +++ b/cocos/platform/CCNetwork.cpp @@ -0,0 +1,30 @@ +#include "platform/CCNetwork.h" +#include "base/CCConsole.h" + +NS_CC_BEGIN + +bool Network::isLocalWiFiAvailable(void) +{ + CCLOG("Network::isLocalWiFiAvailable() - not support this platform."); + return true; +} + +bool Network::isInternetConnectionAvailable(void) +{ + CCLOG("Network::isInternetConnectionAvailable() - not support this platform."); + return true; +} + +bool Network::isHostNameReachable(const char* hostName) +{ + CCLOG("Network::isHostNameReachable() - not support this platform."); + return true; +} + +int Network::getInternetConnectionStatus(void) +{ + CCLOG("Network::getInternetConnectionStatus() - not support this platform."); + return kCCNetworkStatusReachableViaWiFi; +} + +NS_CC_END diff --git a/cocos/platform/CCNetwork.h b/cocos/platform/CCNetwork.h new file mode 100644 index 0000000..18b2cb2 --- /dev/null +++ b/cocos/platform/CCNetwork.h @@ -0,0 +1,33 @@ +#ifndef __CC_NETWORK_H_ +#define __CC_NETWORK_H_ + +#include "platform/CCPlatformMacros.h" + +NS_CC_BEGIN + +#define kCCNetworkStatusNotReachable 0 +#define kCCNetworkStatusReachableViaWiFi 1 +#define kCCNetworkStatusReachableViaWWAN 2 + +class Network +{ +public: + /** @brief Checks whether a local wifi connection is available */ + static bool isLocalWiFiAvailable(void); + + /** @brief Checks whether the default route is available */ + static bool isInternetConnectionAvailable(void); + + /** @brief Checks the reachability of a particular host name */ + static bool isHostNameReachable(const char* hostName); + + /** @brief Checks Internet connection reachability status */ + static int getInternetConnectionStatus(void); + +private: + Network(void) {} +}; + +NS_CC_END + +#endif // __CC_NETWORK_H_ diff --git a/cocos/platform/CMakeLists.txt b/cocos/platform/CMakeLists.txt index 4700e25..21a6c58 100644 --- a/cocos/platform/CMakeLists.txt +++ b/cocos/platform/CMakeLists.txt @@ -30,6 +30,7 @@ if(ANDROID) platform/android/CCGLViewImpl-android.cpp platform/android/CCFileUtils-android.cpp platform/android/CCEnhanceAPI-android.cpp + platform/android/CCNetwork-Android.cpp ) elseif(WINDOWS) set(COCOS_PLATFORM_SPECIFIC_HEADER @@ -52,16 +53,20 @@ elseif(WINDOWS) platform/win32/CCDevice-win32.cpp platform/win32/inet_pton_mingw.cpp platform/desktop/CCGLViewImpl-desktop.cpp + platform/CCNetwork.cpp ) elseif(APPLE) set(COCOS_PLATFORM_SPECIFIC_HEADER platform/apple/CCFileUtils-apple.h platform/apple/CCDevice-apple.h + platform/apple/ReachabilityIOSMac.h ) set(COCOS_PLATFORM_SPECIFIC_SRC platform/apple/CCFileUtils-apple.mm platform/apple/CCDevice-apple.mm + platform/apple/ReachabilityIOSMac.m + platform/apple/CCNetwork-apple.mm ) if(MACOSX) set(COCOS_PLATFORM_SPECIFIC_HEADER @@ -70,7 +75,6 @@ elseif(APPLE) platform/mac/CCGLViewImpl-mac.h platform/mac/CCPlatformDefine-mac.h platform/mac/CCApplication-mac.h - # platform/desktop/CCGLViewImpl-desktop.h ) set(COCOS_PLATFORM_SPECIFIC_SRC ${COCOS_PLATFORM_SPECIFIC_SRC} @@ -78,7 +82,6 @@ elseif(APPLE) platform/mac/CCGLViewImpl-mac.mm platform/mac/CCCommon-mac.mm platform/mac/CCDevice-mac.mm - # platform/desktop/CCGLViewImpl-desktop.cpp ) elseif(IOS) set(COCOS_PLATFORM_SPECIFIC_HEADER @@ -128,6 +131,7 @@ elseif(LINUX) platform/linux/CCApplication-linux.cpp platform/linux/CCDevice-linux.cpp platform/desktop/CCGLViewImpl-desktop.cpp + platform/CCNetwork.cpp ) endif() @@ -146,6 +150,7 @@ set(COCOS_PLATFORM_HEADER platform/CCPlatformMacros.h platform/CCSAXParser.h platform/CCStdC.h + platform/CCNetwork.h ) set(COCOS_PLATFORM_SRC diff --git a/cocos/platform/android/CCNetwork-Android.cpp b/cocos/platform/android/CCNetwork-Android.cpp new file mode 100644 index 0000000..1efefdd --- /dev/null +++ b/cocos/platform/android/CCNetwork-Android.cpp @@ -0,0 +1,66 @@ + +#include "cocos/platform/CCNetwork.h" +#include "cocos2d.h" +#include +#include "platform/android/jni/JniHelper.h" + +#include +#include + +NS_CC_BEGIN + +bool Network::isLocalWiFiAvailable(void) +{ + JniMethodInfo methodInfo; + if (JniHelper::getStaticMethodInfo(methodInfo, "org/cocos2dx/utils/PSNetwork", "isLocalWiFiAvailable", + "()Z")) + { + jboolean ret = methodInfo.env->CallStaticBooleanMethod(methodInfo.classID, methodInfo.methodID); + methodInfo.env->DeleteLocalRef(methodInfo.classID); + return ret; + } + return false; +} + +bool Network::isInternetConnectionAvailable(void) +{ + JniMethodInfo methodInfo; + if (JniHelper::getStaticMethodInfo(methodInfo, "org/cocos2dx/utils/PSNetwork", "isInternetConnectionAvailable", + "()Z")) + { + jboolean ret = methodInfo.env->CallStaticBooleanMethod(methodInfo.classID, methodInfo.methodID); + methodInfo.env->DeleteLocalRef(methodInfo.classID); + return ret; + } + return false; +} + +bool Network::isHostNameReachable(const char* hostName) +{ + JniMethodInfo methodInfo; + if (JniHelper::getStaticMethodInfo(methodInfo, "org/cocos2dx/utils/PSNetwork", "isHostNameReachable", + "(Ljava/lang/String;)Z")) + { + jstring jhostName = methodInfo.env->NewStringUTF(hostName); + jboolean ret = methodInfo.env->CallStaticBooleanMethod(methodInfo.classID, methodInfo.methodID, jhostName); + methodInfo.env->DeleteLocalRef(jhostName); + methodInfo.env->DeleteLocalRef(methodInfo.classID); + return ret; + } + return false; +} + +int Network::getInternetConnectionStatus(void) +{ + JniMethodInfo methodInfo; + if (JniHelper::getStaticMethodInfo(methodInfo, "org/cocos2dx/utils/PSNetwork", "getInternetConnectionStatus", + "()I")) + { + jint ret = methodInfo.env->CallStaticIntMethod(methodInfo.classID, methodInfo.methodID); + methodInfo.env->DeleteLocalRef(methodInfo.classID); + return ret; + } + return kCCNetworkStatusNotReachable; +} + +NS_CC_END diff --git a/cocos/platform/android/ControllerManualAdapter/ant.properties b/cocos/platform/android/ControllerManualAdapter/ant.properties deleted file mode 100644 index b0971e8..0000000 --- a/cocos/platform/android/ControllerManualAdapter/ant.properties +++ /dev/null @@ -1,17 +0,0 @@ -# This file is used to override default values used by the Ant build system. -# -# This file must be checked into Version Control Systems, as it is -# integral to the build system of your project. - -# This file is only used by the Ant script. - -# You can use this to override default values such as -# 'source.dir' for the location of your java source folder and -# 'out.dir' for the location of your output folder. - -# You can also use it define how the release builds are signed by declaring -# the following properties: -# 'key.store' for the location of your keystore and -# 'key.alias' for the name of the key to use. -# The password will be asked during the build when you use the 'release' target. - diff --git a/cocos/platform/android/java/ant.properties b/cocos/platform/android/java/ant.properties deleted file mode 100644 index b0971e8..0000000 --- a/cocos/platform/android/java/ant.properties +++ /dev/null @@ -1,17 +0,0 @@ -# This file is used to override default values used by the Ant build system. -# -# This file must be checked into Version Control Systems, as it is -# integral to the build system of your project. - -# This file is only used by the Ant script. - -# You can use this to override default values such as -# 'source.dir' for the location of your java source folder and -# 'out.dir' for the location of your output folder. - -# You can also use it define how the release builds are signed by declaring -# the following properties: -# 'key.store' for the location of your keystore and -# 'key.alias' for the name of the key to use. -# The password will be asked during the build when you use the 'release' target. - diff --git a/cocos/platform/android/java/libs/android-async-http-1.4.9.jar b/cocos/platform/android/java/libs/android-async-http-1.4.9.jar deleted file mode 100644 index c2d8b86..0000000 Binary files a/cocos/platform/android/java/libs/android-async-http-1.4.9.jar and /dev/null differ diff --git a/cocos/platform/android/java/libs/httpclient-4.4.1.1.jar b/cocos/platform/android/java/libs/httpclient-4.4.1.1.jar deleted file mode 100644 index 3802380..0000000 Binary files a/cocos/platform/android/java/libs/httpclient-4.4.1.1.jar and /dev/null differ diff --git a/cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxActivity.java b/cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxActivity.java index b53feef..fb44f3f 100644 --- a/cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxActivity.java +++ b/cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxActivity.java @@ -36,13 +36,21 @@ import android.os.Bundle; import android.os.Message; import android.os.PowerManager; import android.preference.PreferenceManager.OnActivityResultListener; +import android.support.v4.content.ContextCompat; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; +import android.net.Uri; +import android.provider.Settings; +import android.content.DialogInterface; +import android.app.AlertDialog; +import android.Manifest; +import android.annotation.TargetApi; import org.cocos2dx.lib.Cocos2dxHelper.Cocos2dxHelperListener; +import org.cocos2dx.utils.PSNetwork; import javax.microedition.khronos.egl.EGL10; import javax.microedition.khronos.egl.EGLConfig; @@ -146,6 +154,8 @@ public abstract class Cocos2dxActivity extends Activity implements Cocos2dxHelpe Window window = this.getWindow(); window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); + + initPermission(); } //native method,call GLViewImpl::getGLContextAttrs() to get the OpenGL ES context attributions @@ -346,7 +356,95 @@ public abstract class Cocos2dxActivity extends Activity implements Cocos2dxHelpe return !powerManager.isScreenOn(); } } - + + private void initPermission() { + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + String allpermissions[] = {Manifest.permission.ACCESS_NETWORK_STATE, Manifest.permission.READ_PHONE_STATE}; + String permissions[] = {}; + boolean needPop = false; + + for (String permission : allpermissions) { + if (PackageManager.PERMISSION_DENIED == ContextCompat.checkSelfPermission(this, permission)) { + if (shouldShowRequestPermissionRationale(permission)) { + permissions[permissions.length] = permission; + } else { + needPop = true; + } + } + } + + if (needPop) { + // init Alert strings + String title = "请在设置中,开启程序权限, 点击权限。"; + String conform = "确认"; + String cancel = "取消"; + if (Cocos2dxHelper.getCurrentLanguage() != "zh") { + title = "Please grant the permissions in settings."; + conform = "OK"; + cancel = "Cancel"; + } + final String fTitle = title; + final String fconform = conform; + final String fcancel = cancel; + + // on clicked handler + final DialogInterface.OnClickListener okHandler = new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Intent intent = new Intent(); + intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); + Uri uri = Uri.fromParts("package", getPackageName(), null); + intent.setData(uri); + startActivity(intent); + finish(); + } + }; + + // on clicked handler + final DialogInterface.OnClickListener noHandler = new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + finish(); + } + }; + + // new alert + sContext.runOnUiThread(new Runnable() { + @Override + public void run() { + new AlertDialog.Builder(sContext) + .setMessage(fTitle) + .setPositiveButton(fconform, okHandler) + .setNegativeButton(fcancel, noHandler) + .create() + .show(); + } + }); + return; + } + + if (permissions.length > 0) { + this.requestPermissions(permissions, 1001); + return; + } + } + // final, can safe init PS module + PSNetwork.init(this); + } + + @TargetApi(Build.VERSION_CODES.M) + @Override + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults){ + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + this.hasFocus = true; + + if (requestCode != 1001) { // request code define by me. + return; + } + + initPermission(); + } + // =========================================================== // Inner and Anonymous Classes // =========================================================== diff --git a/cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxDownloader.java b/cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxDownloader.java deleted file mode 100644 index 69440c5..0000000 --- a/cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxDownloader.java +++ /dev/null @@ -1,451 +0,0 @@ -/**************************************************************************** - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - - 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 com.loopj.android.http.AsyncHttpClient; -import com.loopj.android.http.AsyncHttpResponseHandler; -import com.loopj.android.http.BinaryHttpResponseHandler; -import com.loopj.android.http.FileAsyncHttpResponseHandler; -import com.loopj.android.http.RequestHandle; - -import cz.msebera.android.httpclient.Header; -import cz.msebera.android.httpclient.message.BasicHeader; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.PrintWriter; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.*; - -class DataTaskHandler extends BinaryHttpResponseHandler { - int _id; - private Cocos2dxDownloader _downloader; - private long _lastBytesWritten; - - void LogD(String msg) { - android.util.Log.d("Cocos2dxDownloader", msg); - } - - public DataTaskHandler(Cocos2dxDownloader downloader, int id) { - super(new String[]{".*"}); - _downloader = downloader; - _id = id; - _lastBytesWritten = 0; - } - - @Override - public void onProgress(long bytesWritten, long totalSize) { - //LogD("onProgress(bytesWritten:" + bytesWritten + " totalSize:" + totalSize); - long dlBytes = bytesWritten - _lastBytesWritten; - long dlNow = bytesWritten; - long dlTotal = totalSize; - _downloader.onProgress(_id, dlBytes, dlNow, dlTotal); - _lastBytesWritten = bytesWritten; - } - - @Override - public void onStart() { - _downloader.onStart(_id); - } - - @Override - public void onFailure(int i, Header[] headers, byte[] errorResponse, Throwable throwable) { - LogD("onFailure(i:" + i + " headers:" + headers + " throwable:" + throwable); - String errStr = ""; - if (null != throwable) { - errStr = throwable.toString(); - } - _downloader.onFinish(_id, i, errStr, null); - } - - @Override - public void onSuccess(int i, Header[] headers, byte[] binaryData) { - LogD("onSuccess(i:" + i + " headers:" + headers); - _downloader.onFinish(_id, 0, null, binaryData); - } - - @Override - public void onFinish() { - // onFinish called after onSuccess/onFailure - _downloader.runNextTaskIfExists(); - } -} - -class HeadTaskHandler extends AsyncHttpResponseHandler { - int _id; - String _host; - String _url; - String _path; - private Cocos2dxDownloader _downloader; - - void LogD(String msg) { - android.util.Log.d("Cocos2dxDownloader", msg); - } - - public HeadTaskHandler(Cocos2dxDownloader downloader, int id, String host, String url, String path) { - super(); - _downloader = downloader; - _id = id; - _host = host; - _url = url; - _path = path; - } - - @Override - public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) { - Boolean acceptRanges = false; - for (int i = 0; i < headers.length; ++i) { - Header elem = headers[i]; - if (elem.getName().equals("Accept-Ranges")) { - acceptRanges = elem.getValue().equals("bytes"); - break; - } - } - Cocos2dxDownloader.setResumingSupport(_host, acceptRanges); - Cocos2dxDownloader.createTask(_downloader, _id, _url, _path); - } - - @Override - public void onFinish() { - // onFinish called after onSuccess/onFailure - _downloader.runNextTaskIfExists(); - } - - @Override - public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable throwable) { - LogD("onFailure(code:" + statusCode + " headers:" + headers + " throwable:" + throwable + " id:" + _id); - String errStr = ""; - if (null != throwable) { - errStr = throwable.toString(); - } - _downloader.onFinish(_id, statusCode, errStr, null); - } -} - -class FileTaskHandler extends FileAsyncHttpResponseHandler { - int _id; - File _finalFile; - - private long _initFileLen; - private long _lastBytesWritten; - private Cocos2dxDownloader _downloader; - - void LogD(String msg) { - android.util.Log.d("Cocos2dxDownloader", msg); - } - - public FileTaskHandler(Cocos2dxDownloader downloader, int id, File temp, File finalFile) { - super(temp, true); - _finalFile = finalFile; - _downloader = downloader; - _id = id; - _initFileLen = getTargetFile().length(); - _lastBytesWritten = 0; - } - - @Override - public void onProgress(long bytesWritten, long totalSize) { - //LogD("onProgress(bytesWritten:" + bytesWritten + " totalSize:" + totalSize); - long dlBytes = bytesWritten - _lastBytesWritten; - long dlNow = bytesWritten + _initFileLen; - long dlTotal = totalSize + _initFileLen; - _downloader.onProgress(_id, dlBytes, dlNow, dlTotal); - _lastBytesWritten = bytesWritten; - } - - @Override - public void onStart() { - _downloader.onStart(_id); - } - - @Override - public void onFinish() { - // onFinish called after onSuccess/onFailure - _downloader.runNextTaskIfExists(); - } - - @Override - public void onFailure(int i, Header[] headers, Throwable throwable, File file) { - LogD("onFailure(i:" + i + " headers:" + headers + " throwable:" + throwable + " file:" + file); - String errStr = ""; - if (null != throwable) { - errStr = throwable.toString(); - } - _downloader.onFinish(_id, i, errStr, null); - } - - @Override - public void onSuccess(int i, Header[] headers, File file) { - LogD("onSuccess(i:" + i + " headers:" + headers + " file:" + file); - String errStr = null; - do { - // rename temp file to final file - // if final file exist, remove it - if (_finalFile.exists()) { - if (_finalFile.isDirectory()) { - errStr = "Dest file is directory:" + _finalFile.getAbsolutePath(); - break; - } - if (false == _finalFile.delete()) { - errStr = "Can't remove old file:" + _finalFile.getAbsolutePath(); - break; - } - } - - File tempFile = getTargetFile(); - tempFile.renameTo(_finalFile); - } while (false); - _downloader.onFinish(_id, 0, errStr, null); - } -} - -class DownloadTask { - - DownloadTask() { - handle = null; - handler = null; - resetStatus(); - } - - void resetStatus() { - bytesReceived = 0; - totalBytesReceived = 0; - totalBytesExpected = 0; - data = null; - } - - RequestHandle handle; - AsyncHttpResponseHandler handler; - - // progress - long bytesReceived; - long totalBytesReceived; - long totalBytesExpected; - byte[] data; - -} - -public class Cocos2dxDownloader { - private int _id; - private AsyncHttpClient _httpClient = new AsyncHttpClient(); - private String _tempFileNameSufix; - private int _countOfMaxProcessingTasks; - private HashMap _taskMap = new HashMap(); - private Queue _taskQueue = new LinkedList(); - private int _runningTaskCount = 0; - private static HashMap _resumingSupport = new HashMap(); - - void onProgress(final int id, final long downloadBytes, final long downloadNow, final long downloadTotal) { - DownloadTask task = (DownloadTask)_taskMap.get(id); - if (null != task) { - task.bytesReceived = downloadBytes; - task.totalBytesReceived = downloadNow; - task.totalBytesExpected = downloadTotal; - } - Cocos2dxHelper.runOnGLThread(new Runnable() { - @Override - public void run() { - nativeOnProgress(_id, id, downloadBytes, downloadNow, downloadTotal); - } - }); - } - - public void onStart(int id) { - DownloadTask task = (DownloadTask)_taskMap.get(id); - if (null != task) { - task.resetStatus(); - } - } - - public void onFinish(final int id, final int errCode, final String errStr, final byte[] data) { - DownloadTask task = (DownloadTask)_taskMap.get(id); - if (null == task) return; - _taskMap.remove(id); - Cocos2dxHelper.runOnGLThread(new Runnable() { - @Override - public void run() { - nativeOnFinish(_id, id, errCode, errStr, data); - } - }); - } - - public static void setResumingSupport(String host, Boolean support) { - Cocos2dxDownloader._resumingSupport.put(host, support); - } - - public static Cocos2dxDownloader createDownloader(int id, int timeoutInSeconds, String tempFileNameSufix, int countOfMaxProcessingTasks) { - Cocos2dxDownloader downloader = new Cocos2dxDownloader(); - downloader._id = id; - - downloader._httpClient.setEnableRedirects(true); - if (timeoutInSeconds > 0) { - downloader._httpClient.setTimeout(timeoutInSeconds * 1000); - } - // downloader._httpClient.setMaxRetriesAndTimeout(3, timeoutInSeconds * 1000); - downloader._httpClient.allowRetryExceptionClass(javax.net.ssl.SSLException.class); - - //disable url auto decode - //fix https://github.com/cocos2d/cocos2d-x/issues/18949 - downloader._httpClient.setURLEncodingEnabled(false); - - downloader._tempFileNameSufix = tempFileNameSufix; - downloader._countOfMaxProcessingTasks = countOfMaxProcessingTasks; - return downloader; - } - - public static void createTask(final Cocos2dxDownloader downloader, int id_, String url_, String path_) { - final int id = id_; - final String url = url_; - final String path = path_; - - Runnable taskRunnable = new Runnable() { - @Override - public void run() { - DownloadTask task = new DownloadTask(); - if (0 == path.length()) { - // data task - task.handler = new DataTaskHandler(downloader, id); - task.handle = downloader._httpClient.get(Cocos2dxHelper.getActivity(), url, task.handler); - } - - do { - if (0 == path.length()) break; - - String domain; - try { - URI uri = new URI(url); - domain = uri.getHost(); - } - catch (URISyntaxException e) { - break; - } - final String host = domain.startsWith("www.") ? domain.substring(4) : domain; - Boolean supportResuming = false; - Boolean requestHeader = true; - if (_resumingSupport.containsKey(host)) { - supportResuming = _resumingSupport.get(host); - requestHeader = false; - } - - if (requestHeader) { - task.handler = new HeadTaskHandler(downloader, id, host, url, path); - task.handle = downloader._httpClient.head(Cocos2dxHelper.getActivity(), url, null, null, task.handler); - break; - } - - // file task - File tempFile = new File(path + downloader._tempFileNameSufix); - if (tempFile.isDirectory()) break; - - File parent = tempFile.getParentFile(); - if (!parent.isDirectory() && !parent.mkdirs()) break; - - File finalFile = new File(path); - if (finalFile.isDirectory()) break; - - task.handler = new FileTaskHandler(downloader, id, tempFile, finalFile); - Header[] headers = null; - long fileLen = tempFile.length(); - if (supportResuming && fileLen > 0) { - // continue download - List
list = new ArrayList
(); - list.add(new BasicHeader("Range", "bytes=" + fileLen + "-")); - headers = list.toArray(new Header[list.size()]); - } - else if (fileLen > 0) { - // Remove previous downloaded context - try { - PrintWriter writer = new PrintWriter(tempFile); - writer.print(""); - writer.close(); - } - // Not found then nothing to do - catch (FileNotFoundException e) {} - } - task.handle = downloader._httpClient.get(Cocos2dxHelper.getActivity(), url, headers, null, task.handler); - } while (false); - - if (null == task.handle) { - final String errStr = "Can't create DownloadTask for " + url; - Cocos2dxHelper.runOnGLThread(new Runnable() { - @Override - public void run() { - downloader.nativeOnFinish(downloader._id, id, 0, errStr, null); - } - }); - } else { - downloader._taskMap.put(id, task); - } - } - }; - downloader.enqueueTask(taskRunnable); - } - - public static void cancelAllRequests(final Cocos2dxDownloader downloader) { - Cocos2dxHelper.getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - - //downloader._httpClient.cancelAllRequests(true); - Iterator iter = downloader._taskMap.entrySet().iterator(); - while (iter.hasNext()) { - Map.Entry entry = (Map.Entry) iter.next(); - //Object key = entry.getKey(); - DownloadTask task = (DownloadTask) entry.getValue(); - if (null != task.handle) { - task.handle.cancel(true); - } - } - } - }); - } - - - public void enqueueTask(Runnable taskRunnable) { - synchronized (_taskQueue) { - if (_runningTaskCount < _countOfMaxProcessingTasks) { - Cocos2dxHelper.getActivity().runOnUiThread(taskRunnable); - _runningTaskCount++; - } else { - _taskQueue.add(taskRunnable); - } - } - } - - public void runNextTaskIfExists() { - synchronized (_taskQueue) { - Runnable taskRunnable = Cocos2dxDownloader.this._taskQueue.poll(); - if (taskRunnable != null) { - Cocos2dxHelper.getActivity().runOnUiThread(taskRunnable); - } else { - _runningTaskCount--; - } - } - } - - native void nativeOnProgress(int id, int taskId, long dl, long dlnow, long dltotal); - native void nativeOnFinish(int id, int taskId, int errCode, String errStr, final byte[] data); -} diff --git a/cocos/platform/android/java/src/org/cocos2dx/utils/PSNetwork.java b/cocos/platform/android/java/src/org/cocos2dx/utils/PSNetwork.java new file mode 100755 index 0000000..4ba7835 --- /dev/null +++ b/cocos/platform/android/java/src/org/cocos2dx/utils/PSNetwork.java @@ -0,0 +1,76 @@ +package org.cocos2dx.utils; + +import java.net.HttpURLConnection; +import java.net.URL; + +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.NetworkInfo.State; + +public class PSNetwork { + static ConnectivityManager mConnManager = null; + + public static void init(Context context) { + mConnManager = (ConnectivityManager) context + .getSystemService(Context.CONNECTIVITY_SERVICE); + } + + public static boolean isLocalWiFiAvailable() { + if (mConnManager == null) { + return false; + } + State state = mConnManager + .getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState(); + return State.CONNECTED == state; + } + + public static boolean isInternetConnectionAvailable() { + if (mConnManager == null) { + return false; + } + + if (isLocalWiFiAvailable()) { + return true; + } + + try { + State state = mConnManager.getNetworkInfo( + ConnectivityManager.TYPE_MOBILE).getState(); + return State.CONNECTED == state; + } catch (Exception e) { + return false; + } + } + + public static boolean isHostNameReachable(String hostName) { + int counts = 0; + if (hostName == null || hostName.length() <= 0) { + return false; + } + while (counts < 3) { + try { + URL url = new URL(hostName); + int state = ((HttpURLConnection) url.openConnection()) + .getResponseCode(); + if (state == 200) { + return true; + } + return false; + } catch (Exception ex) { + counts++; + continue; + } + } + return false; + } + + public static int getInternetConnectionStatus() { + if (isLocalWiFiAvailable()) { + return 1; // wifi + } + if (isInternetConnectionAvailable()) { + return 2; // gprs + } + return 0; + } +} diff --git a/cocos/platform/android/javaactivity-android.cpp b/cocos/platform/android/javaactivity-android.cpp index ce63ac1..5fea888 100644 --- a/cocos/platform/android/javaactivity-android.cpp +++ b/cocos/platform/android/javaactivity-android.cpp @@ -30,7 +30,6 @@ THE SOFTWARE. #include "base/CCEventDispatcher.h" #include "renderer/CCTextureCache.h" #include "platform/android/jni/JniHelper.h" -#include "network/CCDownloader-android.h" #include #include @@ -96,7 +95,6 @@ JNIEXPORT void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit(JNIEnv* env, j director->setGLDefaultValues(); cocos2d::VolatileTextureMgr::reloadAllTextures(); } - cocos2d::network::_preloadJavaDownloaderClass(); } JNIEXPORT jintArray Java_org_cocos2dx_lib_Cocos2dxActivity_getGLContextAttrs(JNIEnv* env, jobject thiz) diff --git a/cocos/platform/android/libcocos2dx/build.gradle b/cocos/platform/android/libcocos2dx/build.gradle index 44f9a32..a5d921c 100644 --- a/cocos/platform/android/libcocos2dx/build.gradle +++ b/cocos/platform/android/libcocos2dx/build.gradle @@ -26,4 +26,5 @@ android { dependencies { implementation fileTree(dir: '../java/libs', include: ['*.jar']) + implementation 'com.android.support:support-v4:26.1.0' } diff --git a/cocos/platform/apple/CCNetwork-apple.mm b/cocos/platform/apple/CCNetwork-apple.mm new file mode 100644 index 0000000..ebcfa4a --- /dev/null +++ b/cocos/platform/apple/CCNetwork-apple.mm @@ -0,0 +1,31 @@ + +#import "platform/apple/ReachabilityIOSMac.h" +#include "platform/CCNetwork.h" + +NS_CC_BEGIN + +bool Network::isLocalWiFiAvailable(void) +{ + return [[ReachabilityIOSMac reachabilityForLocalWiFi] currentReachabilityStatus] != NotReachable; +} + +bool Network::isInternetConnectionAvailable(void) +{ + return [[ReachabilityIOSMac reachabilityForInternetConnection] currentReachabilityStatus] != NotReachable; +} + +bool Network::isHostNameReachable(const char* hostName) +{ + NSString *hostName_ = [NSString stringWithUTF8String:hostName]; + return [[ReachabilityIOSMac reachabilityWithHostname:hostName_] currentReachabilityStatus] != NotReachable; +} + +int Network::getInternetConnectionStatus(void) +{ + NetworkStatus status = [[ReachabilityIOSMac reachabilityForInternetConnection] currentReachabilityStatus]; + if (status == ReachableViaWiFi) return kCCNetworkStatusReachableViaWiFi; + if (status == ReachableViaWWAN) return kCCNetworkStatusReachableViaWWAN; + return kCCNetworkStatusNotReachable; +} + +NS_CC_END diff --git a/cocos/platform/apple/ReachabilityIOSMac.h b/cocos/platform/apple/ReachabilityIOSMac.h new file mode 100644 index 0000000..5f3412a --- /dev/null +++ b/cocos/platform/apple/ReachabilityIOSMac.h @@ -0,0 +1,109 @@ +/* + Copyright (c) 2011, Tony Million. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#import +#import + +#import +#import +#import +#import +#import +#import + +/** + * Does ARC support support GCD objects? + * It does if the minimum deployment target is iOS 6+ or Mac OS X 8+ + * + * @see http://opensource.apple.com/source/libdispatch/libdispatch-228.18/os/object.h + **/ +#if OS_OBJECT_USE_OBJC +#define NEEDS_DISPATCH_RETAIN_RELEASE 0 +#else +#define NEEDS_DISPATCH_RETAIN_RELEASE 1 +#endif + + +extern NSString *const kReachabilityChangedNotification; + +typedef enum +{ + // Apple NetworkStatus Compatible Names. + NotReachable = 0, + ReachableViaWiFi = 2, + ReachableViaWWAN = 1 +} NetworkStatus; + +@class ReachabilityIOSMac; + +typedef void (^NetworkReachable)(ReachabilityIOSMac * reachability); +typedef void (^NetworkUnreachable)(ReachabilityIOSMac * reachability); + +@interface ReachabilityIOSMac : NSObject { + SCNetworkReachabilityRef reachabilityRef; + dispatch_queue_t reachabilitySerialQueue; + BOOL reachableOnWWAN; + NetworkReachable reachableBlock; + NetworkUnreachable unreachableBlock; + id reachabilityObject; +} + +@property (nonatomic, copy) NetworkReachable reachableBlock; +@property (nonatomic, copy) NetworkUnreachable unreachableBlock; + + +@property (nonatomic, assign) BOOL reachableOnWWAN; + ++(ReachabilityIOSMac*)reachabilityWithHostname:(NSString*)hostname; ++(ReachabilityIOSMac*)reachabilityForInternetConnection; ++(ReachabilityIOSMac*)reachabilityWithAddress:(const struct sockaddr_in*)hostAddress; ++(ReachabilityIOSMac*)reachabilityForLocalWiFi; + +-(ReachabilityIOSMac*)initWithReachabilityRef:(SCNetworkReachabilityRef)ref; + +-(BOOL)startNotifier; +-(void)stopNotifier; + +-(BOOL)isReachable; +-(BOOL)isReachableViaWWAN; +-(BOOL)isReachableViaWiFi; + +// WWAN may be available, but not active until a connection has been established. +// WiFi may require a connection for VPN on Demand. +-(BOOL)isConnectionRequired; // Identical DDG variant. +-(BOOL)connectionRequired; // Apple's routine. +// Dynamic, on demand connection? +-(BOOL)isConnectionOnDemand; +// Is user intervention required? +-(BOOL)isInterventionRequired; + +-(NetworkStatus)currentReachabilityStatus; +-(SCNetworkReachabilityFlags)reachabilityFlags; +-(NSString*)currentReachabilityString; +-(NSString*)currentReachabilityFlags; + +@end diff --git a/cocos/platform/apple/ReachabilityIOSMac.m b/cocos/platform/apple/ReachabilityIOSMac.m new file mode 100644 index 0000000..148f3fe --- /dev/null +++ b/cocos/platform/apple/ReachabilityIOSMac.m @@ -0,0 +1,520 @@ +/* + Copyright (c) 2011, Tony Million. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ReachabilityIOSMac.h" + + + +@interface ReachabilityIOSMac () + +@property (nonatomic, assign) SCNetworkReachabilityRef reachabilityRef; + + +#if NEEDS_DISPATCH_RETAIN_RELEASE +@property (nonatomic, assign) dispatch_queue_t reachabilitySerialQueue; +#else +@property (nonatomic, strong) dispatch_queue_t reachabilitySerialQueue; +#endif + + +@property (nonatomic, strong) id reachabilityObject; + +-(void)reachabilityChanged:(SCNetworkReachabilityFlags)flags; +-(BOOL)isReachableWithFlags:(SCNetworkReachabilityFlags)flags; + +@end + +static NSString *reachabilityFlags(SCNetworkReachabilityFlags flags) +{ + return [NSString stringWithFormat:@"%c%c %c%c%c%c%c%c%c", +#if TARGET_OS_IPHONE + (flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-', +#else + 'X', +#endif + (flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-', + (flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-', + (flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-', + (flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-', + (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-', + (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-', + (flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-', + (flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-']; +} + +//Start listening for reachability notifications on the current run loop +static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) +{ +#pragma unused (target) +#if __has_feature(objc_arc) + ReachabilityIOSMac *reachability = ((__bridge Reachability*)info); +#else + ReachabilityIOSMac *reachability = ((ReachabilityIOSMac*)info); +#endif + + // we probably dont need an autoreleasepool here as GCD docs state each queue has its own autorelease pool + // but what the heck eh? + @autoreleasepool + { + [reachability reachabilityChanged:flags]; + } +} + + +@implementation ReachabilityIOSMac + +@synthesize reachabilityRef; +@synthesize reachabilitySerialQueue; + +@synthesize reachableOnWWAN; + +@synthesize reachableBlock; +@synthesize unreachableBlock; + +@synthesize reachabilityObject; + +#pragma mark - class constructor methods ++(ReachabilityIOSMac*)reachabilityWithHostname:(NSString*)hostname +{ + SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithName(NULL, [hostname UTF8String]); + if (ref) + { + id reachability = [[self alloc] initWithReachabilityRef:ref]; + +#if __has_feature(objc_arc) + return reachability; +#else + return [reachability autorelease]; +#endif + + } + + return nil; +} + ++(ReachabilityIOSMac*)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress +{ + SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress); + if (ref) + { + id reachability = [[self alloc] initWithReachabilityRef:ref]; + +#if __has_feature(objc_arc) + return reachability; +#else + return [reachability autorelease]; +#endif + } + + return nil; +} + ++(ReachabilityIOSMac*)reachabilityForInternetConnection +{ + struct sockaddr_in zeroAddress; + bzero(&zeroAddress, sizeof(zeroAddress)); + zeroAddress.sin_len = sizeof(zeroAddress); + zeroAddress.sin_family = AF_INET; + + return [self reachabilityWithAddress:&zeroAddress]; +} + ++(ReachabilityIOSMac*)reachabilityForLocalWiFi +{ + struct sockaddr_in localWifiAddress; + bzero(&localWifiAddress, sizeof(localWifiAddress)); + localWifiAddress.sin_len = sizeof(localWifiAddress); + localWifiAddress.sin_family = AF_INET; + // IN_LINKLOCALNETNUM is defined in as 169.254.0.0 + localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM); + + return [self reachabilityWithAddress:&localWifiAddress]; +} + + +// initialization methods + +-(ReachabilityIOSMac*)initWithReachabilityRef:(SCNetworkReachabilityRef)ref +{ + self = [super init]; + if (self != nil) + { + self.reachableOnWWAN = YES; + self.reachabilityRef = ref; + } + + return self; +} + +-(void)dealloc +{ + [self stopNotifier]; + + if(self.reachabilityRef) + { + CFRelease(self.reachabilityRef); + self.reachabilityRef = nil; + } + + self.reachableBlock = nil; + self.unreachableBlock = nil; + +#if !(__has_feature(objc_arc)) + [super dealloc]; +#endif + + +} + +#pragma mark - notifier methods + +// Notifier +// NOTE: this uses GCD to trigger the blocks - they *WILL NOT* be called on THE MAIN THREAD +// - In other words DO NOT DO ANY UI UPDATES IN THE BLOCKS. +// INSTEAD USE dispatch_async(dispatch_get_main_queue(), ^{UISTUFF}) (or dispatch_sync if you want) + +-(BOOL)startNotifier +{ + SCNetworkReachabilityContext context = { 0, NULL, NULL, NULL, NULL }; + + // this should do a retain on ourself, so as long as we're in notifier mode we shouldn't disappear out from under ourselves + // woah + self.reachabilityObject = self; + + + + // first we need to create a serial queue + // we allocate this once for the lifetime of the notifier + self.reachabilitySerialQueue = dispatch_queue_create("com.tonymillion.reachability", NULL); + if(!self.reachabilitySerialQueue) + { + return NO; + } + +#if __has_feature(objc_arc) + context.info = (__bridge void *)self; +#else + context.info = (void *)self; +#endif + + if (!SCNetworkReachabilitySetCallback(self.reachabilityRef, TMReachabilityCallback, &context)) + { +#ifdef DEBUG + NSLog(@"SCNetworkReachabilitySetCallback() failed: %s", SCErrorString(SCError())); +#endif + + //clear out the dispatch queue + if(self.reachabilitySerialQueue) + { +#if NEEDS_DISPATCH_RETAIN_RELEASE + dispatch_release(self.reachabilitySerialQueue); +#endif + self.reachabilitySerialQueue = nil; + } + + self.reachabilityObject = nil; + + return NO; + } + + // set it as our reachability queue which will retain the queue + if(!SCNetworkReachabilitySetDispatchQueue(self.reachabilityRef, self.reachabilitySerialQueue)) + { +#ifdef DEBUG + NSLog(@"SCNetworkReachabilitySetDispatchQueue() failed: %s", SCErrorString(SCError())); +#endif + + //UH OH - FAILURE! + + // first stop any callbacks! + SCNetworkReachabilitySetCallback(self.reachabilityRef, NULL, NULL); + + // then clear out the dispatch queue + if(self.reachabilitySerialQueue) + { +#if NEEDS_DISPATCH_RETAIN_RELEASE + dispatch_release(self.reachabilitySerialQueue); +#endif + self.reachabilitySerialQueue = nil; + } + + self.reachabilityObject = nil; + + return NO; + } + + return YES; +} + +-(void)stopNotifier +{ + // first stop any callbacks! + SCNetworkReachabilitySetCallback(self.reachabilityRef, NULL, NULL); + + // unregister target from the GCD serial dispatch queue + SCNetworkReachabilitySetDispatchQueue(self.reachabilityRef, NULL); + + if(self.reachabilitySerialQueue) + { +#if NEEDS_DISPATCH_RETAIN_RELEASE + dispatch_release(self.reachabilitySerialQueue); +#endif + self.reachabilitySerialQueue = nil; + } + + self.reachabilityObject = nil; +} + +#pragma mark - reachability tests + +// this is for the case where you flick the airplane mode +// you end up getting something like this: +//Reachability: WR ct----- +//Reachability: -- ------- +//Reachability: WR ct----- +//Reachability: -- ------- +// we treat this as 4 UNREACHABLE triggers - really apple should do better than this + +#define testcase (kSCNetworkReachabilityFlagsConnectionRequired | kSCNetworkReachabilityFlagsTransientConnection) + +-(BOOL)isReachableWithFlags:(SCNetworkReachabilityFlags)flags +{ + BOOL connectionUP = YES; + + if(!(flags & kSCNetworkReachabilityFlagsReachable)) + connectionUP = NO; + + if( (flags & testcase) == testcase ) + connectionUP = NO; + +#if TARGET_OS_IPHONE + if(flags & kSCNetworkReachabilityFlagsIsWWAN) + { + // we're on 3G + if(!self.reachableOnWWAN) + { + // we dont want to connect when on 3G + connectionUP = NO; + } + } +#endif + + return connectionUP; +} + +-(BOOL)isReachable +{ + SCNetworkReachabilityFlags flags; + + if(!SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags)) + return NO; + + return [self isReachableWithFlags:flags]; +} + +-(BOOL)isReachableViaWWAN +{ +#if TARGET_OS_IPHONE + + SCNetworkReachabilityFlags flags = 0; + + if(SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) + { + // check we're REACHABLE + if(flags & kSCNetworkReachabilityFlagsReachable) + { + // now, check we're on WWAN + if(flags & kSCNetworkReachabilityFlagsIsWWAN) + { + return YES; + } + } + } +#endif + + return NO; +} + +-(BOOL)isReachableViaWiFi +{ + SCNetworkReachabilityFlags flags = 0; + + if(SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) + { + // check we're reachable + if((flags & kSCNetworkReachabilityFlagsReachable)) + { +#if TARGET_OS_IPHONE + // check we're NOT on WWAN + if((flags & kSCNetworkReachabilityFlagsIsWWAN)) + { + return NO; + } +#endif + return YES; + } + } + + return NO; +} + + +// WWAN may be available, but not active until a connection has been established. +// WiFi may require a connection for VPN on Demand. +-(BOOL)isConnectionRequired +{ + return [self connectionRequired]; +} + +-(BOOL)connectionRequired +{ + SCNetworkReachabilityFlags flags; + + if(SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) + { + return (flags & kSCNetworkReachabilityFlagsConnectionRequired); + } + + return NO; +} + +// Dynamic, on demand connection? +-(BOOL)isConnectionOnDemand +{ + SCNetworkReachabilityFlags flags; + + if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) + { + return ((flags & kSCNetworkReachabilityFlagsConnectionRequired) && + (flags & (kSCNetworkReachabilityFlagsConnectionOnTraffic | kSCNetworkReachabilityFlagsConnectionOnDemand))); + } + + return NO; +} + +// Is user intervention required? +-(BOOL)isInterventionRequired +{ + SCNetworkReachabilityFlags flags; + + if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) + { + return ((flags & kSCNetworkReachabilityFlagsConnectionRequired) && + (flags & kSCNetworkReachabilityFlagsInterventionRequired)); + } + + return NO; +} + + +#pragma mark - reachability status stuff + +-(NetworkStatus)currentReachabilityStatus +{ + if([self isReachable]) + { + if([self isReachableViaWiFi]) + return ReachableViaWiFi; + +#if TARGET_OS_IPHONE + return ReachableViaWWAN; +#endif + } + + return NotReachable; +} + +-(SCNetworkReachabilityFlags)reachabilityFlags +{ + SCNetworkReachabilityFlags flags = 0; + + if(SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) + { + return flags; + } + + return 0; +} + +-(NSString*)currentReachabilityString +{ + NetworkStatus temp = [self currentReachabilityStatus]; + + if(temp == reachableOnWWAN) + { + // updated for the fact we have CDMA phones now! + return NSLocalizedString(@"Cellular", @""); + } + if (temp == ReachableViaWiFi) + { + return NSLocalizedString(@"WiFi", @""); + } + + return NSLocalizedString(@"No Connection", @""); +} + +-(NSString*)currentReachabilityFlags +{ + return reachabilityFlags([self reachabilityFlags]); +} + +#pragma mark - callback function calls this method + +-(void)reachabilityChanged:(SCNetworkReachabilityFlags)flags +{ + if([self isReachableWithFlags:flags]) + { + if(self.reachableBlock) + { + self.reachableBlock(self); + } + } + else + { + if(self.unreachableBlock) + { + self.unreachableBlock(self); + } + } + + // this makes sure the change notification happens on the MAIN THREAD + dispatch_async(dispatch_get_main_queue(), ^{ + [[NSNotificationCenter defaultCenter] postNotificationName:@"kReachabilityChangedNotification" + object:self]; + }); +} + +#pragma mark - Debug Description + +- (NSString *) description; +{ + NSString *description = [NSString stringWithFormat:@"<%@: %#x>", + NSStringFromClass([self class]), (unsigned int) self]; + return description; +} + +@end diff --git a/cocos/scripting/lua-bindings/CMakeLists.txt b/cocos/scripting/lua-bindings/CMakeLists.txt index 3296b54..e6b18e5 100644 --- a/cocos/scripting/lua-bindings/CMakeLists.txt +++ b/cocos/scripting/lua-bindings/CMakeLists.txt @@ -61,7 +61,6 @@ set(lua_bindings_manual_files manual/network/lua_extensions.c manual/network/lua_cocos2dx_network_manual.cpp manual/network/Lua_web_socket.cpp - manual/network/LuasocketAsyn.cpp manual/network/lua_http_manual.cpp manual/network/CCHTTPRequest.cpp manual/spine/lua_cocos2dx_spine_manual.cpp diff --git a/cocos/scripting/lua-bindings/manual/network/LuasocketAsyn.cpp b/cocos/scripting/lua-bindings/manual/network/LuasocketAsyn.cpp deleted file mode 100644 index c5b050a..0000000 --- a/cocos/scripting/lua-bindings/manual/network/LuasocketAsyn.cpp +++ /dev/null @@ -1,143 +0,0 @@ -// Created by u0u0 on 2018/10/19. - -#include -#include - -// for cpp call c -#ifdef __cplusplus -extern "C" { -#endif - -#include "lua.h" -#include "auxiliar.h" -#include "inet.h" -#include "tcp.h" - -#ifdef __cplusplus -} -#endif - -#include "cocos2d.h" -#include "scripting/lua-bindings/manual/tolua_fix.h" -#include "scripting/lua-bindings/manual/CCLuaEngine.h" - -// first connect to server may block main thread, new a thread to void UI blocked -static void connectThread(p_tcp tcp, const char *address, const char *port) -{ - struct addrinfo connecthints; - const char *err; - memset(&connecthints, 0, sizeof(connecthints)); - connecthints.ai_socktype = SOCK_STREAM; - /* make sure we try to connect only to the same family */ - connecthints.ai_family = tcp->family; - timeout_markstart(&tcp->tm); - err = inet_tryconnect(&tcp->sock, &tcp->family, address, port, - &tcp->tm, &connecthints); - tcp->asynConnStat = 2;// DONE first connect -} - -extern "C" int asyn_connect(lua_State *L); // for c call cpp -int asyn_connect(lua_State *L) -{ - const char *address = luaL_checkstring(L, 2); - const char *port = luaL_checkstring(L, 3); - p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); - if (tcp->asynConnStat == 0) { - // start thread - tcp->asynConnStat = 1;// first connecting - auxiliar_setclass(L, "tcp{client}", 1); - std::thread th(connectThread, tcp, address, port); - th.detach();//exit from main thread, auto exit - } - if (tcp->asynConnStat < 2) { - lua_pushnil(L); - lua_pushstring(L, "Operation already in progress"); - return 2; - } - - // sync connect for check status - struct addrinfo connecthints; - const char *err; - memset(&connecthints, 0, sizeof(connecthints)); - connecthints.ai_socktype = SOCK_STREAM; - /* make sure we try to connect only to the same family */ - connecthints.ai_family = tcp->family; - timeout_markstart(&tcp->tm); - err = inet_tryconnect(&tcp->sock, &tcp->family, address, port, - &tcp->tm, &connecthints); - tcp->asynConnStat = 2;// DONE first connect - /* have to set the class even if it failed due to non-blocking connects */ - auxiliar_setclass(L, "tcp{client}", 1); - if (err) { - lua_pushnil(L); - lua_pushstring(L, err); - return 2; - } - lua_pushnumber(L, 1); - return 1; -} - -// new a thread to void UI blocked -static void checkIpv6Thread(lua_State *L, const char *hostname, int handler) -{ - struct addrinfo *iterator = NULL, *resolved = NULL; - struct addrinfo hints; - int ret = 0; - memset(&hints, 0, sizeof(hints)); - hints.ai_socktype = SOCK_STREAM; - hints.ai_family = PF_UNSPEC; - ret = getaddrinfo(hostname, NULL, &hints, &resolved); - if (ret != 0) { - cocos2d::Director::getInstance()->getScheduler()->performFunctionInCocosThread([=](){ - const char *err = socket_gaistrerror(ret); - CCLOG("== socket.dns.isIpv6 getaddrinfo error:%s", err); - cocos2d::LuaStack *stack = cocos2d::LuaEngine::getInstance()->getLuaStack(); - lua_pushstring(L, err); - stack->executeFunctionByHandler(handler, 1); - toluafix_remove_function_by_refid(L, handler); - }); - return; - } - - int isIpv6 = 0; - for (iterator = resolved; iterator; iterator = iterator->ai_next) { - char hbuf[NI_MAXHOST]; - ret = getnameinfo(iterator->ai_addr, (socklen_t) iterator->ai_addrlen, - hbuf, (socklen_t) sizeof(hbuf), NULL, 0, NI_NUMERICHOST); - if (ret) { - freeaddrinfo(resolved); - cocos2d::Director::getInstance()->getScheduler()->performFunctionInCocosThread([=](){ - const char *err = socket_gaistrerror(ret); - CCLOG("== socket.dns.isIpv6 getnameinfo error:%s", err); - cocos2d::LuaStack *stack = cocos2d::LuaEngine::getInstance()->getLuaStack(); - lua_pushstring(L, err); - stack->executeFunctionByHandler(handler, 1); - toluafix_remove_function_by_refid(L, handler); - }); - return; - } - if (iterator->ai_family == AF_INET6) { - isIpv6 = 1; - break; - } - } - freeaddrinfo(resolved); - cocos2d::Director::getInstance()->getScheduler()->performFunctionInCocosThread([=](){ - cocos2d::LuaStack *stack = cocos2d::LuaEngine::getInstance()->getLuaStack(); - lua_pushnil(L); - lua_pushboolean(L, isIpv6); - stack->executeFunctionByHandler(handler, 2); - toluafix_remove_function_by_refid(L, handler); - }); -} - -extern "C" int inet_isIpv6_asyn(lua_State *L); // for c call cpp -int inet_isIpv6_asyn(lua_State *L) -{ - const char *hostname = luaL_checkstring(L, 1); - int handler = toluafix_ref_function(L, 2, 0); - - std::thread th(checkIpv6Thread, L, hostname, handler); - th.detach();//exit from main thread, auto exit - return 0; -} diff --git a/cocos/scripting/lua-bindings/manual/network/lua_cocos2dx_network_manual.cpp b/cocos/scripting/lua-bindings/manual/network/lua_cocos2dx_network_manual.cpp index 4893d78..d554a6a 100644 --- a/cocos/scripting/lua-bindings/manual/network/lua_cocos2dx_network_manual.cpp +++ b/cocos/scripting/lua-bindings/manual/network/lua_cocos2dx_network_manual.cpp @@ -22,23 +22,222 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ +#include "scripting/lua-bindings/manual/tolua_fix.h" #include "scripting/lua-bindings/manual/network/lua_cocos2dx_network_manual.h" #include "scripting/lua-bindings/manual/network/lua_extensions.h" #include "scripting/lua-bindings/manual/network/Lua_web_socket.h" #include "scripting/lua-bindings/manual/network/lua_http_manual.h" #include "scripting/lua-bindings/manual/CCLuaEngine.h" +#include "cocos/platform/CCNetwork.h" +#include "base/CCDirector.h" +#include "base/CCScheduler.h" +#include "luasocket/socket.h" + +static int tolua_Network_isLocalWiFiAvailable(lua_State* tolua_S) +{ +#if COCOS2D_DEBUG >= 1 + tolua_Error tolua_err; + if ( + !tolua_isusertable(tolua_S,1,"Network",0,&tolua_err) || + !tolua_isnoobj(tolua_S,2,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + bool tolua_ret = (bool)cocos2d::Network::isLocalWiFiAvailable(); + tolua_pushboolean(tolua_S,(bool)tolua_ret); + } + return 1; +#if COCOS2D_DEBUG >= 1 +tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'isLocalWiFiAvailable'.",&tolua_err); + return 0; +#endif +} + +static int tolua_Network_isInternetConnectionAvailable(lua_State* tolua_S) +{ +#if COCOS2D_DEBUG >= 1 + tolua_Error tolua_err; + if ( + !tolua_isusertable(tolua_S,1,"Network",0,&tolua_err) || + !tolua_isnoobj(tolua_S,2,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + bool tolua_ret = (bool)cocos2d::Network::isInternetConnectionAvailable(); + tolua_pushboolean(tolua_S,(bool)tolua_ret); + } + return 1; +#if COCOS2D_DEBUG >= 1 +tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'isInternetConnectionAvailable'.",&tolua_err); + return 0; +#endif +} + +static int tolua_Network_isHostNameReachable(lua_State* tolua_S) +{ +#if COCOS2D_DEBUG >= 1 + tolua_Error tolua_err; + if ( + !tolua_isusertable(tolua_S,1,"Network",0,&tolua_err) || + !tolua_isstring(tolua_S,2,0,&tolua_err) || + !tolua_isnoobj(tolua_S,3,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + const char* hostName = ((const char*)tolua_tostring(tolua_S,2,0)); + bool tolua_ret = (bool)cocos2d::Network::isHostNameReachable(hostName); + tolua_pushboolean(tolua_S,(bool)tolua_ret); + } + return 1; +#if COCOS2D_DEBUG >= 1 +tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'isHostNameReachable'.",&tolua_err); + return 0; +#endif +} + +static int tolua_Network_getInternetConnectionStatus(lua_State* tolua_S) +{ +#if COCOS2D_DEBUG >= 1 + tolua_Error tolua_err; + if ( + !tolua_isusertable(tolua_S,1,"Network",0,&tolua_err) || + !tolua_isnoobj(tolua_S,2,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + int tolua_ret = (int)cocos2d::Network::getInternetConnectionStatus(); + tolua_pushnumber(tolua_S,(lua_Number)tolua_ret); + } + return 1; +#if COCOS2D_DEBUG >= 1 +tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'getInternetConnectionStatus'.",&tolua_err); + return 0; +#endif +} + +// new a thread to void UI blocked +static void checkIpv6Thread(lua_State *L, const char *hostname, int handler) +{ + struct addrinfo *iterator = NULL, *resolved = NULL; + struct addrinfo hints; + int ret = 0; + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_STREAM; + hints.ai_family = PF_UNSPEC; + ret = getaddrinfo(hostname, NULL, &hints, &resolved); + if (ret != 0) { + cocos2d::Director::getInstance()->getScheduler()->performFunctionInCocosThread([=](){ + CCLOG("== socket.dns.isIpv6 getaddrinfo error:%d", ret); + cocos2d::LuaStack *stack = cocos2d::LuaEngine::getInstance()->getLuaStack(); + lua_pushinteger(L, ret); + stack->executeFunctionByHandler(handler, 1); + toluafix_remove_function_by_refid(L, handler); + }); + return; + } + + int isIpv6 = 0; + for (iterator = resolved; iterator; iterator = iterator->ai_next) { + char hbuf[NI_MAXHOST]; + ret = getnameinfo(iterator->ai_addr, (socklen_t) iterator->ai_addrlen, + hbuf, (socklen_t) sizeof(hbuf), NULL, 0, NI_NUMERICHOST); + if (ret) { + freeaddrinfo(resolved); + cocos2d::Director::getInstance()->getScheduler()->performFunctionInCocosThread([=](){ + CCLOG("== socket.dns.isIpv6 getnameinfo error:%d", ret); + cocos2d::LuaStack *stack = cocos2d::LuaEngine::getInstance()->getLuaStack(); + lua_pushinteger(L, ret); + stack->executeFunctionByHandler(handler, 1); + toluafix_remove_function_by_refid(L, handler); + }); + return; + } + if (iterator->ai_family == AF_INET6) { + isIpv6 = 1; + break; + } + } + freeaddrinfo(resolved); + cocos2d::Director::getInstance()->getScheduler()->performFunctionInCocosThread([=](){ + cocos2d::LuaStack *stack = cocos2d::LuaEngine::getInstance()->getLuaStack(); + lua_pushnil(L); + lua_pushboolean(L, isIpv6); + stack->executeFunctionByHandler(handler, 2); + toluafix_remove_function_by_refid(L, handler); + }); +} + +static int tolua_Network_isIPv6(lua_State* tolua_S) +{ +#if COCOS2D_DEBUG >= 1 + tolua_Error tolua_err; + if ( + !tolua_isusertable(tolua_S, 1, "Network", 0, &tolua_err) || + !tolua_isstring(tolua_S, 2, 0, &tolua_err) || + !toluafix_isfunction(tolua_S, 3, "LUA_FUNCTION", 0, &tolua_err) + ) + goto tolua_lerror; + else +#endif + { + const char *hostname = luaL_checkstring(tolua_S, 1); + int handler = toluafix_ref_function(tolua_S, 2, 0); + + std::thread th(checkIpv6Thread, tolua_S, hostname, handler); + th.detach();//exit from main thread, auto exit + } + return 0; +#if COCOS2D_DEBUG >= 1 +tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'isIPv6'.",&tolua_err); + return 0; +#endif +} + +/* Open function */ +TOLUA_API int register_network_manual(lua_State* L) +{ + tolua_open(L); + tolua_usertype(L, "Network"); + tolua_module(L, "cc", 0); + tolua_beginmodule(L, "cc"); + tolua_cclass(L, "Network", "Network", "", NULL); + tolua_beginmodule(L, "Network"); + tolua_function(L, "isLocalWiFiAvailable", tolua_Network_isLocalWiFiAvailable); + tolua_function(L, "isInternetConnectionAvailable", tolua_Network_isInternetConnectionAvailable); + tolua_function(L, "isHostNameReachable", tolua_Network_isHostNameReachable); + tolua_function(L, "getInternetConnectionStatus", tolua_Network_getInternetConnectionStatus); + tolua_function(L, "isIPv6", tolua_Network_isIPv6); + tolua_endmodule(L); + tolua_endmodule(L); + + return 1; +} int register_network_module(lua_State* L) { - lua_getglobal(L, "_G"); - if (lua_istable(L,-1))//stack:...,_G, - { - luaopen_lua_extensions(L); - tolua_web_socket_open(L); - register_web_socket_manual(L); - register_http_manual(L); - } - lua_pop(L, 1); - - return 1; + lua_getglobal(L, "_G"); + if (lua_istable(L,-1))//stack:...,_G, + { + luaopen_lua_extensions(L); + tolua_web_socket_open(L); + register_web_socket_manual(L); + register_http_manual(L); + register_network_manual(L); + } + lua_pop(L, 1); + + return 1; } diff --git a/cocos/scripting/lua-bindings/manual/network/lua_http_manual.cpp b/cocos/scripting/lua-bindings/manual/network/lua_http_manual.cpp index f5dba52..190c298 100644 --- a/cocos/scripting/lua-bindings/manual/network/lua_http_manual.cpp +++ b/cocos/scripting/lua-bindings/manual/network/lua_http_manual.cpp @@ -695,8 +695,6 @@ tolua_lerror: /* Open function */ TOLUA_API int register_http_manual(lua_State* tolua_S) { - int a = lua_gettop(tolua_S); - tolua_open(tolua_S); tolua_usertype(tolua_S, "HTTPRequest"); tolua_module(tolua_S, "cc", 0); @@ -729,6 +727,5 @@ TOLUA_API int register_http_manual(lua_State* tolua_S) tolua_endmodule(tolua_S); tolua_endmodule(tolua_S); - a = lua_gettop(tolua_S); return 1; } diff --git a/cocos/scripting/lua-bindings/script/network/NetworkConstants.lua b/cocos/scripting/lua-bindings/script/network/NetworkConstants.lua index 08652dc..896ffe2 100644 --- a/cocos/scripting/lua-bindings/script/network/NetworkConstants.lua +++ b/cocos/scripting/lua-bindings/script/network/NetworkConstants.lua @@ -24,3 +24,7 @@ cc.kCCHTTPRequestStateInProgress = 2 cc.kCCHTTPRequestStateCompleted = 3 cc.kCCHTTPRequestStateCancelled = 4 cc.kCCHTTPRequestStateFailed = 5 + +cc.kCCNetworkStatusNotReachable = 0 +cc.kCCNetworkStatusReachableViaWiFi = 1 +cc.kCCNetworkStatusReachableViaWWAN = 2 diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 903d593..583ce27 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -58,11 +58,6 @@ if(BUILD_EXT_JPEG) add_subdirectory(jpeg) target_link_libraries(external ext_jpeg) endif(BUILD_EXT_JPEG) -if(BUILD_EXT_OPENSSL) - add_subdirectory(openssl) - target_link_libraries(external ext_ssl) - target_link_libraries(external ext_crypto) -endif(BUILD_EXT_OPENSSL) if(BUILD_EXT_UV) add_subdirectory(uv) target_link_libraries(external ext_uv) @@ -103,12 +98,21 @@ if(BUILD_EXT_POLY2TRI) add_subdirectory(poly2tri) target_link_libraries(external ext_poly2tri) endif(BUILD_EXT_POLY2TRI) - if(BUILD_EXT_MD5) add_subdirectory(md5) target_link_libraries(external ext_md5) endif(BUILD_EXT_MD5) - +if(BUILD_EXT_CURL) + add_subdirectory(curl) + target_link_libraries(external ext_curl) +endif(BUILD_EXT_CURL) +if(BUILD_EXT_OPENSSL) + add_subdirectory(openssl) + target_link_libraries(external ext_ssl) + target_link_libraries(external ext_crypto) +endif(BUILD_EXT_OPENSSL) +add_subdirectory(png) +target_link_libraries(external ext_png) # use lua/js specific libs by property to prevent conflict if(BUILD_LUA_LIBS) @@ -129,17 +133,6 @@ if(BUILD_LUA_LIBS) ) endif() -if(NOT LINUX) - if(BUILD_EXT_CURL) - add_subdirectory(curl) - target_link_libraries(external ext_curl) - endif(BUILD_EXT_CURL) - add_subdirectory(png) - target_link_libraries(external - ext_png - ) -endif(NOT LINUX) - if(ANDROID) add_subdirectory(android-specific/cpufeatures) target_link_libraries(external ext_cpufeatures) diff --git a/external/lua/luasocket/CMakeLists.txt b/external/lua/luasocket/CMakeLists.txt index 75aefda..972f8fc 100644 --- a/external/lua/luasocket/CMakeLists.txt +++ b/external/lua/luasocket/CMakeLists.txt @@ -6,6 +6,7 @@ set(target_name ext_${lib_name}) project(${lib_name}) set(${target_name}_src + asynconnect.cpp buffer.c io.c timeout.c diff --git a/external/lua/luasocket/asynconnect.cpp b/external/lua/luasocket/asynconnect.cpp new file mode 100644 index 0000000..5263487 --- /dev/null +++ b/external/lua/luasocket/asynconnect.cpp @@ -0,0 +1,74 @@ +// Created by u0u0 on 2018/10/19. + +#include +#include + +// for cpp call c +#ifdef __cplusplus +extern "C" { +#endif + +#include "lua.h" +#include "auxiliar.h" +#include "inet.h" +#include "tcp.h" + +#ifdef __cplusplus +} +#endif + +// first connect to server may block main thread, new a thread to void UI blocked +static void connectThread(p_tcp tcp, const char *address, const char *port) +{ + struct addrinfo connecthints; + const char *err; + memset(&connecthints, 0, sizeof(connecthints)); + connecthints.ai_socktype = SOCK_STREAM; + /* make sure we try to connect only to the same family */ + connecthints.ai_family = tcp->family; + timeout_markstart(&tcp->tm); + err = inet_tryconnect(&tcp->sock, &tcp->family, address, port, + &tcp->tm, &connecthints); + tcp->asynConnStat = 2;// DONE first connect +} + +extern "C" int asyn_connect(lua_State *L); // for c call cpp +int asyn_connect(lua_State *L) +{ + const char *address = luaL_checkstring(L, 2); + const char *port = luaL_checkstring(L, 3); + p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); + if (tcp->asynConnStat == 0) { + // start thread + tcp->asynConnStat = 1;// first connecting + auxiliar_setclass(L, "tcp{client}", 1); + std::thread th(connectThread, tcp, address, port); + th.detach();//exit from main thread, auto exit + } + if (tcp->asynConnStat < 2) { + lua_pushnil(L); + lua_pushstring(L, "Operation already in progress"); + return 2; + } + + // sync connect for check status + struct addrinfo connecthints; + const char *err; + memset(&connecthints, 0, sizeof(connecthints)); + connecthints.ai_socktype = SOCK_STREAM; + /* make sure we try to connect only to the same family */ + connecthints.ai_family = tcp->family; + timeout_markstart(&tcp->tm); + err = inet_tryconnect(&tcp->sock, &tcp->family, address, port, + &tcp->tm, &connecthints); + tcp->asynConnStat = 2;// DONE first connect + /* have to set the class even if it failed due to non-blocking connects */ + auxiliar_setclass(L, "tcp{client}", 1); + if (err) { + lua_pushnil(L); + lua_pushstring(L, err); + return 2; + } + lua_pushnumber(L, 1); + return 1; +} diff --git a/external/lua/luasocket/inet.c b/external/lua/luasocket/inet.c index 1ec3747..d89fd80 100644 --- a/external/lua/luasocket/inet.c +++ b/external/lua/luasocket/inet.c @@ -20,13 +20,11 @@ static int inet_global_tohostname(lua_State *L); static int inet_global_getnameinfo(lua_State *L); static void inet_pushresolved(lua_State *L, struct hostent *hp); static int inet_global_gethostname(lua_State *L); -int inet_isIpv6_asyn(lua_State *L); /* DNS functions */ static luaL_Reg func[] = { { "toip", inet_global_toip}, { "getaddrinfo", inet_global_getaddrinfo}, - { "isIpv6", inet_isIpv6_asyn}, { "tohostname", inet_global_tohostname}, { "getnameinfo", inet_global_getnameinfo}, { "gethostname", inet_global_gethostname}, diff --git a/templates/lua-template-default/frameworks/runtime-src/proj.android/app/AndroidManifest.xml b/templates/lua-template-default/frameworks/runtime-src/proj.android/app/AndroidManifest.xml index 20b7640..fe40e4e 100644 --- a/templates/lua-template-default/frameworks/runtime-src/proj.android/app/AndroidManifest.xml +++ b/templates/lua-template-default/frameworks/runtime-src/proj.android/app/AndroidManifest.xml @@ -31,12 +31,11 @@ - - - - - - - + + + + + +