代码之家  ›  专栏  ›  技术社区  ›  onizukaek

对“DTLS_client_method”的未定义引用

  •  1
  • onizukaek  · 技术社区  · 12 年前

    我目前正试图在android上实现DTLS,以便加密UDP数据报。 为此,我构建了openssl android项目 available here ,从中我得到了两个共享库libssl.so和libcrypto.so,我将其重命名为libsslx.so和libcruptox.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文件,看看这些函数是否没有被排除在构建结果之外,我试图查看.So文件的内容,但没有成功,顺便说一句,我正在Mac OS X上工作。

    有人有关于安卓DTLS的经验吗?对于这个问题,我将不胜感激。

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

    1 回复  |  直到 12 年前
        1
  •  1
  •   Community Mohan Dere    9 年前

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

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