Files
2017-05-30 22:09:10 +08:00

382 lines
9.3 KiB
C++

#include "network/ImCore.h"
#include "TcpSocketsManager.h"
#include "OperationManager.h"
#include <process.h>
NAMESPACE_BEGIN(imcore)
#ifdef ANDROID
//全局变量
JavaVM *g_jvm = NULL;
jobject g_obj = NULL;
#endif
static CLock g_lock;
#ifdef _MSC_VER
HANDLE g_hThreadHandle = 0;
unsigned int __stdcall event_run(void* threadArgu)
{
LOG__(NET, _T("event_run"));
netlib_init();
netlib_set_running();
netlib_eventloop();
return NULL;
}
#else
void *event_run(void* arg) {
LOG__(NET, _T("event_run"));
netlib_init();
netlib_eventloop();
return NULL;
}
#endif
#ifdef ANDROID
JNIEXPORT void JNICALL Java_com_mogujie_im_libcore_LibCore_setJNIEnv(
JNIEnv* env, jobject thiz) {
env->GetJavaVM(&g_jvm);
g_obj = env->NewGlobalRef(thiz);
}
JNIEXPORT void JNICALL Java_com_mogujie_im_libcore_LibCore_runEvent(JNIEnv* env,
jclass thiz) {
IMLibCoreRunEvent();
}
JNIEXPORT void JNICALL Java_com_mogujie_im_libcore_LibCore_stopEvent(JNIEnv* env,
jclass thiz) {
IMLibCoreRunEvent();
}
JNIEXPORT jboolean JNICALL Java_com_mogujie_im_libcore_LibCore_isRunning(JNIEnv*, jclass)
{
jboolean running = IMLibCoreIsRunning();
return running ? JNI_TRUE : JNI_FALSE;
}
JNIEXPORT jint JNICALL Java_com_mogujie_im_libcore_LibCore_connect(JNIEnv* env,
jclass thiz, jstring ip, jint port) {
jint nRet = -1;
char* pIp = jstringTostr(env, ip);
int nPort = port;
return IMLibCoreConnect(pIp, port);
}
JNIEXPORT jint JNICALL Java_com_mogujie_im_libcore_LibCore_write(JNIEnv* env,
jclass thiz, jint key, jstring data) {
jint nRet = -1;
int nHandle = key;
char* pData = jstringTostr(env, data);
nRet = IMLibCoreWrite(nHandle, pData);
return nRet;
}
JNIEXPORT void JNICALL Java_com_mogujie_im_libcore_LibCore_close(JNIEnv* env,
jclass thiz, jint key) {
int nHandle = key;
IMLibCoreClose(nHandle);
}
void onRead(int nHandle, string strJson) {
JNIEnv *env;
jclass cls;
jmethodID mid;
if (g_jvm->AttachCurrentThread(&env, NULL) != JNI_OK) {
LOGE("%s: AttachCurrentThread() failed", __FUNCTION__);
return;
}
cls = env->GetObjectClass(g_obj);
//cls = env->FindClass("com/mogujie/im/LibCore");
if (NULL == cls) {
LOGE("FindClass() Error.....");
//Detach主线程
if (g_jvm->DetachCurrentThread() != JNI_OK) {
LOGE("%s: DetachCurrentThread() failed", __FUNCTION__);
}
return;
}
mid = env->GetStaticMethodID(cls, "onRead", "(ILjava/lang/String;)V");
if (NULL == mid) {
LOGE("GetMethodID() Error.....");
//Detach主线程
if (g_jvm->DetachCurrentThread() != JNI_OK) {
LOGE("%s: DetachCurrentThread() failed", __FUNCTION__);
}
return;
}
jstring data = strToJstring(env, strJson.c_str());
env->CallStaticVoidMethod(cls, mid, nHandle, data);
if (g_jvm->DetachCurrentThread() != JNI_OK) {
LOGE("%s: DetachCurrentThread() failed", __FUNCTION__);
}
}
void onClose(int nHandle) {
JNIEnv *env;
jclass cls;
jmethodID mid;
if (g_jvm->AttachCurrentThread(&env, NULL) != JNI_OK) {
LOGE("%s: AttachCurrentThread() failed", __FUNCTION__);
return;
}
cls = env->GetObjectClass(g_obj);
//cls = env->FindClass("com/mogujie/im/LibCore");
if (NULL == cls) {
LOGE("FindClass() Error.....");
//Detach主线程
if (g_jvm->DetachCurrentThread() != JNI_OK) {
LOGE("%s: DetachCurrentThread() failed", __FUNCTION__);
}
return;
}
mid = env->GetStaticMethodID(cls, "onClose", "(I)V");
if (NULL == mid) {
LOGE("GetMethodID() Error.....");
//Detach主线程
if (g_jvm->DetachCurrentThread() != JNI_OK) {
LOGE("%s: DetachCurrentThread() failed", __FUNCTION__);
}
return;
}
env->CallStaticVoidMethod(cls, mid, nHandle);
if (g_jvm->DetachCurrentThread() != JNI_OK) {
LOGE("%s: DetachCurrentThread() failed", __FUNCTION__);
}
}
void onConnect(int nHandle) {
JNIEnv *env;
jclass cls;
jmethodID mid;
if (g_jvm->AttachCurrentThread(&env, NULL) != JNI_OK) {
LOGE("%s: AttachCurrentThread() failed", __FUNCTION__);
return;
}
cls = env->GetObjectClass(g_obj);
//cls = env->FindClass("com/mogujie/im/LibCore");
if (NULL == cls) {
LOGE("FindClass() Error.....");
//Detach主线程
if (g_jvm->DetachCurrentThread() != JNI_OK) {
LOGE("%s: DetachCurrentThread() failed", __FUNCTION__);
}
return;
}
mid = env->GetStaticMethodID(cls, "onConnect", "(I)V");
if (NULL == mid) {
LOGE("GetMethodID() Error.....");
//Detach主线程
if (g_jvm->DetachCurrentThread() != JNI_OK) {
LOGE("%s: DetachCurrentThread() failed", __FUNCTION__);
}
return;
}
env->CallStaticVoidMethod(cls, mid, nHandle);
if (g_jvm->DetachCurrentThread() != JNI_OK) {
LOGE("%s: DetachCurrentThread() failed", __FUNCTION__);
}
}
char* jstringTostr(JNIEnv* env, jstring jstr) {
char* pStr = NULL;
jclass jstrObj = env->FindClass("java/lang/String");
jstring encode = env->NewStringUTF("utf-8");
jmethodID methodId = env->GetMethodID(jstrObj, "getBytes",
"(Ljava/lang/String;)[B");
jbyteArray byteArray = (jbyteArray)env->CallObjectMethod(jstr, methodId,
encode);
jsize strLen = env->GetArrayLength(byteArray);
jbyte *jBuf = env->GetByteArrayElements(byteArray, JNI_FALSE);
if (jBuf > 0) {
pStr = (char*)malloc(strLen + 1);
if (!pStr) {
return NULL;
}
memcpy(pStr, jBuf, strLen);
pStr[strLen] = 0;
}
env->ReleaseByteArrayElements(byteArray, jBuf, 0);
return pStr;
}
//C字符串转java字符串
jstring strToJstring(JNIEnv* env, const char* pStr) {
int strLen = strlen(pStr);
jclass jstrObj = env->FindClass("java/lang/String");
jmethodID methodId = env->GetMethodID(jstrObj, "<init>",
"([BLjava/lang/String;)V");
jbyteArray byteArray = env->NewByteArray(strLen);
jstring encode = env->NewStringUTF("utf-8");
env->SetByteArrayRegion(byteArray, 0, strLen, (jbyte*)pStr);
return (jstring)env->NewObject(jstrObj, methodId, byteArray, encode);
}
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv* env = NULL;
jint result = -1;
//获取JNI版本
if (vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK) {
LOGE("GetEnv failed!");
return result;
}
return JNI_VERSION_1_4;
}
JNIEXPORT jstring JNICALL Java_com_mogujie_im_libcore_LibCore_getToken(JNIEnv* env, jclass thiz, jstring uuid)
{
char* pData = jstringTostr(env, uuid);
char token[64];
int uid = urltoid(pData);
genToken(uid, 0, token);
return strToJstring(env, token);
}
#endif
bool IMLibCoreRunEvent()
{
LOG__(NET, _T("==============================================================================="));
//在这里启动任务队列处理线程
getOperationManager()->startup();
CAutoLock lock(&g_lock);
if (!netlib_is_running())
{
#ifdef _MSC_VER
unsigned int m_dwThreadID;
//在这里启动网络IO线程
g_hThreadHandle = (HANDLE)_beginthreadex(0, 0, event_run, 0, 0, (unsigned*)&m_dwThreadID);
if (g_hThreadHandle < (HANDLE)2)
{
m_dwThreadID = 0;
g_hThreadHandle = 0;
}
return g_hThreadHandle >(HANDLE)1;
#else
pthread_t pt;
pthread_create(&pt, NULL, event_run, NULL);
#endif
}
return true;
}
bool IMLibCoreStopEvent()
{
bool bRet = false;
netlib_stop_event();
#ifdef _MSC_VER
if (g_hThreadHandle)
{
if (::WaitForSingleObject(g_hThreadHandle, 3000) == WAIT_TIMEOUT)
{
::TerminateThread(g_hThreadHandle, 0);
WaitForSingleObject(g_hThreadHandle, 500);
}
::CloseHandle(g_hThreadHandle);
g_hThreadHandle = 0;
}
#endif
netlib_destroy();
getOperationManager()->shutdown();
return bRet;
}
bool IMLibCoreIsRunning()
{
return netlib_is_running();
}
int IMLibCoreConnect(string ip, int port)
{
return TcpSocketsManager::getInstance()->connect(ip.c_str(), port);
}
int IMLibCoreWrite(int key, uchar_t* data, uint32_t size)
{
int nRet = -1;
int nHandle = key;
CImConn* pConn = TcpSocketsManager::getInstance()->get_client_conn(nHandle);
if (pConn) {
pConn->Send((void*)data, size);
}
else {
LOG__(NET, _T("connection is invalied:%d"), key);
}
return nRet;
}
void IMLibCoreClose(int key)
{
LOG__(NET, _T("close key:%d"), key);
int nHandle = key;
CImConn* pConn = TcpSocketsManager::getInstance()->get_client_conn(nHandle);
if (pConn) {
pConn->Close();
}
}
NETWORK_DLL void IMLibCoreShutdown(int key)
{
LOG__(NET, _T("shutdown key:%d"), key);
int nHandle = key;
CImConn* pConn = TcpSocketsManager::getInstance()->get_client_conn(nHandle);
if (pConn) {
pConn->Shutdown();
}
}
void IMLibCoreRegisterCallback(int handle,ITcpSocketCallback* pCB)
{
TcpSocketsManager::getInstance()->registerCallback(handle,pCB);
}
void IMLibCoreUnRegisterCallback(int handle)
{
TcpSocketsManager::getInstance()->unRegisterCallback(handle);
}
void IMLibCoreStartOperation(IN Operation* pOperation, Int32 delay /*= 0*/)
{
if (getOperationManager()->startOperation(pOperation, delay) != IMCORE_OK)
{
LOG__(ERR, _T("push operation failed"));
}
}
void IMLibCoreStartOperationWithLambda(std::function<void()> operationRun, Int32 delay /*= 0*/, std::string oper_name)
{
if (getOperationManager()->startOperationWithLambda(operationRun, delay, oper_name) != IMCORE_OK)
{
LOG__(ERR, _T("push operation with lambda failed"));
}
}
void IMLibCoreClearOperationByName(std::string oper_name)
{
if (getOperationManager()->clearOperationByName(oper_name) != IMCORE_OK)
{
LOG__(ERR, _T("clear operation by name failed"));
}
}
NAMESPACE_END(imcore)