android - 对 'DTLS_client_method' 的 undefined reference

标签 android c++ c android-ndk dtls

我目前正在尝试在 android 上实现 DTLS 以加密 UDP 数据报。 为此,我构建了 openssl-android 项目 available here ,由此我得到了两个共享库 libssl.so 和 libcrypto.so ,我将它们重命名为 libsslx.so 和 libcryptox.so 以避免与 android 系统中包含的库混淆。

然后我将这些文件(以及 openssl 头文件夹)放入我的 jni 文件夹下的 android 项目中,结构如下:

jni->|->includes--->openssl--->header files
     |
     |->precompiled-|->libcryptox.so
     |              |
     |              |->libsslx.so
     |
     |->Android.mk
     |
     |->security.cpp

Android.mk 文件的内容:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := sslx
LOCAL_SRC_FILES := precompiled/libsslx.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/includes
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := cryptox
LOCAL_SRC_FILES := precompiled/libcryptox.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/includes
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)

LOCAL_MODULE    := security
LOCAL_SRC_FILES := security.cpp
LOCAL_SHARED_LIBRARIES := sslx cryptox

include $(BUILD_SHARED_LIBRARY)

security.cpp 文件的内容

1 #include <jni.h>
2 #include <string.h>
3 #include <sys/types.h>
4 #include <sys/socket.h>
5 #include <netinet/in.h>
6 #include <arpa/inet.h>

7 extern "C" {

8  #include "openssl/bio.h"
9  #include "openssl/ssl.h"
10 #include "openssl/err.h"

11 struct sockaddr_in dst;

12 static int const SOCKET_ERROR = 1000;
13 static int const SOCKET_CREATED = 1100;
14 static int const BIO_ERROR = 1200;
15 static int const BIO_CREATED = 1300;
16 static int const CTX_ERROR = 1400;
17 static int const CTX_CREATED = 1500;
18 static int const SSL_ERROR = 1600;
19 static int const SSL_CREATED = 1700;

20 void Java_ch_gt_gcservjni_TestOpenSSLJni_initOpenSSL(JNIEnv *pEnv, jobject jObj){
21      SSL_load_error_strings();
22      ERR_load_BIO_strings();
23          OpenSSL_add_all_algorithms();
24 }

25 jlong Java_ch_gt_gcservjni_TestOpenSSLJni_startConnection(JNIEnv *pEnv, jobject jObj, jstring jAddress, jint jPort){

26    char *address;

27      jclass clazz = pEnv->GetObjectClass(jObj);
28      jmethodID mid = pEnv->GetMethodID(clazz, "printMessage", "(I)V");
29      if(mid == 0) return -1;

30      address = 0;
31      if (jAddress) {
32          address = (char *)pEnv->GetStringUTFChars( jAddress, 0);
33          if (!jAddress) return 0;
34      }

    //Socket creation/////////////////////////////////////////////////////////////////////////////
35      int sock = 0;
36      int port = (int)jPort;

37      struct sockaddr_in addr;
38      addr.sin_addr.s_addr = htonl(INADDR_ANY);
39      addr.sin_port = htons(port);

40      sock = socket(PF_INET, SOCK_DGRAM, 0);
41      if(sock < 0){
42          pEnv->CallVoidMethod(jObj, mid, SOCKET_ERROR);
43      }else{
44          pEnv->CallVoidMethod(jObj, mid, SOCKET_CREATED);
45      }

    ///////////////////////////////////////////////////////////////////////////////////////////////

    //Basic IO functionalities initialisation//////////////////////////////////////////////////////
46      BIO* cnx = BIO_new_dgram(sock, BIO_NOCLOSE);
47      if(cnx == NULL){
48          pEnv->CallVoidMethod(jObj, mid, BIO_ERROR);
49      }else{
50          pEnv->CallVoidMethod(jObj, mid, BIO_CREATED);
51      }
    ///////////////////////////////////////////////////////////////////////////////////////////////

52      struct sockaddr_in dst;
53      struct sockaddr* d = (struct sockaddr*)&dst;

54      dst.sin_family = AF_INET;
55      dst.sin_port = htons(port);
56      dst.sin_addr.s_addr = inet_addr(address);

    //Set the BIO connection
57      int err = BIO_dgram_set_peer(cnx, d);

    //Initialisalisation of the Context///////////////////////////////////////////////////////////
58      SSL_CTX *ctx = SSL_CTX_new(DTLSv1_client_method());
59      if(ctx == NULL){
60          pEnv->CallVoidMethod(jObj, mid, CTX_ERROR);
61      }
62      else{
63          pEnv->CallVoidMethod(jObj, mid, CTX_CREATED);
64      }

65      SSL_CTX_set_read_ahead(ctx, 1);
66      SSL_CTX_set_cipher_list(ctx, "HIGH:MEDIUM:aNull");

67      SSL *ssl = SSL_new(ctx);
68      if(ssl == NULL){
69          pEnv->CallVoidMethod(jObj, mid, SSL_ERROR);
70      }
71      else{
72          pEnv->CallVoidMethod(jObj, mid, SSL_CREATED);
73      }

74      SSL_set_bio(ssl, cnx, cnx);
75      SSL_set_connect_state(ssl);
76      return 0;
77   }

78 }

这就是问题所在,当我构建这段代码时,除了最重要的一个是 DTLSv1_client_method(),当我在第 58 行初始化上下文对象时,所有函数都正常。

生成的错误是这个:

/Applications/eclipse_bundle_mac/android-ndk-r8d/toolchains/arm-linux-androideabi-      4.6/prebuilt/darwin-x86/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/security/security.o: in function Java_ch_gt_gcservjni_TestOpenSSLJni_startConnection:jni/security.cpp:107: error: undefined reference to 'DTLSv1_client_method'

所以我构建的库中似乎没有引用该函数,我检查了我的头文件,DTLS 函数在那里,我检查了 openssl-android 项目的 android-config.mk 文件以查看函数没有被排除在 buid 结果之外,我试图查看 .so 文件的内容但没有成功,顺便说一句,我正在 Mac OS X 上工作。

有没有人在 android 上有过 DTLS 的经验?对于这个问题,我将不胜感激。

编辑:我设法使用 arm-linux-androideabi-objdump 工具获取了我的 .so 文件的内容,但没有任何 DTLS 函数的踪迹。它可能来 self 所做的 openssl 构建过程,但这很奇怪,因为 DTLS 没有在 android-config.mk 中被丢弃。

最佳答案

好的,只需选择另一个项目来构建 openssl 并更改位于/apps/ssl 和/crypto 文件夹中的 .mk 文件中的共享库名称即可解决此问题,以避免像本 topic 中所说的那样混淆。 .

你可以在这个url下找到我使用的项目

关于android - 对 'DTLS_client_method' 的 undefined reference ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18419123/

相关文章:

android - DEX 无法使用 Gradle 解析包含 BuildConfig 和 R 的 jar,但可以与 Ant 一起使用

c# - 如何在调试输出窗口中删除不需要的消息 - Xamarin on visual studio

安卓模拟器ip地址

c++ - 是否需要用C++检查0MQ中send的返回值?

c++ - 存储可变数量变量的最佳方法是什么?

无法在 Curl 请求中获取响应错误文本

Android.os.Build 数据示例,请

c++ - 在 boost.python 中包装 std::vector<pointer*>

c - 面试题: C program to sort a binary array in O(n)

c - 在 C(不是 C++)中使用 fork() 从 1 个父项中生成 3 个子项