Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

在Android源码里面编译的问题 #889

Closed
BDZNH opened this issue May 6, 2022 · 9 comments
Closed

在Android源码里面编译的问题 #889

BDZNH opened this issue May 6, 2022 · 9 comments

Comments

@BDZNH
Copy link
Contributor

BDZNH commented May 6, 2022

之前我在为 Android 平台编译里面写了在Android源码里面无法编译通过,当时我是通过预置 openssl 来间接绕过这个问题了。

现在贴一下具体的问题

问题1

int WFServerBase::init_ssl_ctx(const char *cert_file, const char *key_file)
{
	SSL_CTX *ssl_ctx = WFGlobal::new_ssl_server_ctx();

	if (!ssl_ctx)
		return -1;

	SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, NULL);
	if (SSL_CTX_use_certificate_file(ssl_ctx, cert_file, SSL_FILETYPE_PEM) > 0 &&
		SSL_CTX_use_PrivateKey_file(ssl_ctx, key_file, SSL_FILETYPE_PEM) > 0 &&
		SSL_CTX_set_tlsext_servername_callback(ssl_ctx, ssl_ctx_callback) > 0 &&
		SSL_CTX_set_tlsext_servername_arg(ssl_ctx, this) > 0)
	{
		this->set_ssl(ssl_ctx, this->params.ssl_accept_timeout);
		return 0;
	}

	SSL_CTX_free(ssl_ctx);
	return -1;
}

问题出现在 SSL_CTX_set_tlsext_servername_callback(ssl_ctx, ssl_ctx_callback) > 0 && 里面的 ssl_ctx_callback,boringssl 里面的原型定义是

int (*callback)(SSL *ssl, int *out_alert, void *arg)

但是 workflow 里面定义是

long ssl_ctx_callback(SSL *ssl, int *al, void *arg)

问题2

HttpTaskImpl.cc 里面的

static int __encode_auth(const char *p, std::string& auth)
{
	static SSL_CTX *init_ssl = WFGlobal::get_ssl_client_ctx();
	(void)init_ssl;
	BUF_MEM *bptr;
	BIO *bmem;
	BIO *b64;

	b64 = BIO_new(BIO_f_base64());
	if (b64)
	{
		bmem = BIO_new(BIO_s_mem());
		if (bmem)
		{
			BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
			b64 = BIO_push(b64, bmem);
			BIO_write(b64, p, strlen(p));
			(void)BIO_flush(b64);
			BIO_get_mem_ptr(b64, &bptr);

			if (bptr->length > 0)
			{
				auth.append("Basic ");
				auth.append(bptr->data, bptr->length);
			}

			BIO_free_all(b64);
			return 0;
		}

		BIO_free_all(b64);
	}

	return -1;
}

实际编译时报 BIO_f_base64() 未定义,看了下是因为 boringssl 里面,BIO_f_base64() 是弃用状态,Android 里面就没有把相应的实现编译到库里面。

一些解决方向

  1. 问题1
    如果就 C/C++本身,这里加一些宏定义就能区分开,但是之前我在某处看到过你们说不太倾向于使用这种办法来区分,那么这种情况有没有什么比较好的办法
  2. 问题2
  • 修改Android源码规则,将 BIO_f_base64() 编译到(这样做实测可行,但是有VNDK 的api变动,可能有未知风险)
  • 使用其他的方式来代替这里的 openssl 的base64计算过程
@BDZNH
Copy link
Contributor Author

BDZNH commented May 6, 2022

看了下 openssl 里面的SSL_CTX_set_tlsext_servername_callback声明,见SSL_CTX_set_tlsext_servername_callback,它的第二个参数也是

int (*callback)(SSL *ssl, int *out_alert, void *arg)

workflow 里面定义的回调看起来本身就和 openssl 里面声明的不一致。

@Barenboim
Copy link
Contributor

Barenboim commented May 6, 2022

看了下 openssl 里面的SSL_CTX_set_tlsext_servername_callback声明,见SSL_CTX_set_tlsext_servername_callback,它的第二个参数也是

int (*callback)(SSL *ssl, int *out_alert, void *arg)

workflow 里面定义的回调看起来本身就和 openssl 里面声明的不一致。

😳
我检查一下。
如果不一致,编译应该出错才对。这两个类型完全不一样。

@BDZNH
Copy link
Contributor Author

BDZNH commented May 6, 2022

下面是具体的报错信息

external/workflow-0.10.1/src/server/WFServer.cc:78:3: error: no matching function for call to 'SSL_CTX_set_tlsext_servername_callback'
                SSL_CTX_set_tlsext_servername_callback(ssl_ctx, ssl_ctx_callback) > 0 &&
                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
external/boringssl/src/include/openssl/ssl.h:4602:5: note: expanded from macro 'SSL_CTX_set_tlsext_servername_callback'
    SSL_CTX_set_tlsext_servername_callback
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
external/boringssl/src/include/openssl/ssl.h:2623:20: note: candidate function not viable: no known conversion from 'long (SSL *, int *, void *)' (aka 'long (ssl_st *, int *, void *)') to 'int (*)(SSL *, int *, void *)' (aka 'int (*)(ssl_st *, int *, void *)') for 2nd argument
OPENSSL_EXPORT int SSL_CTX_set_tlsext_servername_callback(
                   ^
1 error generated.
12:47:55 ninja failed with: exit status 1

应该确实是 workflow 里面声明出错了,Android 源码里面的默认的编译参数会执行更加严格的检查。下面是编译参数,看看是否有帮助

PWD=/proc/self/cwd prebuilts/clang/host/linux-x86/clang-r353983c/bin/clang++ -c -Wno-enum-compare -Wno-enum-compare-switch -Wno-null-pointer-arithmetic -Wno-null-dereference -Iexternal/workflow-0.10.1/src/include -Iexternal/workflow-0.10.1/src/manager -Iexternal/workflow-0.10.1/src/nameservice -Iexternal/workflow-0.10.1/src/protocol -Iexternal/workflow-0.10.1/src/client -Iexternal/workflow-0.10.1/src/server -Iexternal/workflow-0.10.1/src/protocol -Iexternal/workflow-0.10.1/src/server -Iexternal/workflow-0.10.1/src/protocol -Iexternal/workflow-0.10.1/src/server -Iexternal/workflow-0.10.1/src/algorithm -Iexternal/workflow-0.10.1/src/client -Iexternal/workflow-0.10.1/src/factory -Iexternal/workflow-0.10.1/src/kernel -Iexternal/workflow-0.10.1/src/manager -Iexternal/workflow-0.10.1/src/nameservice -Iexternal/workflow-0.10.1/src/protocol -Iexternal/workflow-0.10.1/src/server -Iexternal/workflow-0.10.1/src/util -Iexternal/workflow-0.10.1/src/kernel -Iexternal/workflow-0.10.1/src/util -Iexternal/workflow-0.10.1 -D__ANDROID_API__=29 -D__ANDROID_VNDK__  -Werror=implicit-function-declaration -DANDROID -fmessage-length=0 -W -Wall -Wno-unused -Winit-self -Wpointer-arith -no-canonical-prefixes -DNDEBUG -UDEBUG -fno-exceptions -Wno-multichar -O2 -g -fno-strict-aliasing -fdebug-prefix-map=/proc/self/cwd= -D__compiler_offsetof=__builtin_offsetof -faddrsig -Wimplicit-fallthrough -Werror=int-conversion -Wno-reserved-id-macro -Wno-format-pedantic -Wno-unused-command-line-argument -fcolor-diagnostics -Wno-zero-as-null-pointer-constant -Wno-sign-compare -Wno-defaulted-function-deleted -Wno-inconsistent-missing-override -ffunction-sections -fdata-sections -fno-short-enums -funwind-tables -fstack-protector-strong -Wa,--noexecstack -D_FORTIFY_SOURCE=2 -Wstrict-aliasing=2 -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Werror=date-time -Werror=format-security -nostdlibinc -m64 -march=x86-64 -DUSE_SSSE3 -mssse3 -msse4 -msse4.1 -msse4.2 -mpopcnt -Iexternal/boringssl/src/include -Iexternal/libcxx/include -Iexternal/libcxxabi/include -isystem out/soong/.intermediates/bionic/libc/libc.llndk/android_x86_64_vendor_shared/gen/include -isystem bionic/libc/kernel/android/uapi -isystem bionic/libc/kernel/uapi -isystem bionic/libc/kernel/uapi/asm-x86  -Wall -Werror -Wno-unused-parameter -Wno-unused-function -Wno-implicit-fallthrough -DUSE_BORINGSSL -target x86_64-linux-android -Bprebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/x86_64-linux-android/bin -fPIC -D_USING_LIBCXX -std=gnu++17 -Wsign-promo -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS -Wno-thread-safety-negative -Wno-gnu-include-next -fvisibility-inlines-hidden -frtti  -Werror=int-to-pointer-cast -Werror=pointer-to-int-cast -Werror=address-of-temporary -Werror=return-type -Wno-tautological-constant-compare -Wno-tautological-type-limit-compare -Wno-tautological-unsigned-enum-zero-compare -Wno-tautological-unsigned-zero-compare -Wno-c++98-compat-extra-semi -Wno-return-std-move-in-c++11 -MD -MF out/soong/.intermediates/external/workflow-0.10.1/libworkflow/android_x86_64_vendor_static/obj/external/workflow-0.10.1/src/server/WFServer.o.d -o out/soong/.intermediates/external/workflow-0.10.1/libworkflow/android_x86_64_vendor_static/obj/external/workflow-0.10.1/src/server/WFServer.o external/workflow-0.10.1/src/server/WFServer.cc

@Barenboim
Copy link
Contributor

看起来是我把SSL_CTX_set_tlsext_servername_callback的返回值和callback参数的返回值弄混了。我一会修一下。谢谢!

@BDZNH
Copy link
Contributor Author

BDZNH commented May 6, 2022

base64的问题,可以引入/集成第三方的实现,或者在 Util 里面实现一份,而不是用ssl的。看起来 boringssl 和openssl的base64部分,接口定义都不一样了。
解决回调问题和base64的问题,workflow应该就能无缝兼容Android了。

@BDZNH
Copy link
Contributor Author

BDZNH commented May 6, 2022

从 boringssl 的文档 base64.h
和 openssl 的文档 EVP_EncodeBlock
两者都共有的未弃用的 base64 编码的接口是 EVP_EncodeBlock
__encode_auth 的实现可以这样代替

static int EVP_GetEncodedLength(size_t *out_len, size_t len) {
  if (len + 2 < len) {
    return 0;
  }
  len += 2;
  len /= 3;

  if (((len << 2) >> 2) != len) {
    return 0;
  }
  len <<= 2;

  if (len + 1 < len) {
    return 0;
  }
  len++;

  *out_len = len;
  return 1;
}
static int __encode_auth(const char *p, std::string& auth)
{
    int len = strlen(p);
	size_t encodelen;
	if(EVP_GetEncodedLength(&encodelen,len) == 1)
	{
		std::vector<uint8_t> out_vec(encodelen);
		uint8_t *out = out_vec.data();
		size_t outlen = EVP_EncodeBlock(out, (const uint8_t *)p, len);
		if (outlen > 0)
		{
			auth.append("Basic ");
			auth.append((char *)out, outlen);
			return 0;
		}
	}
	return -1;
}

看看这样是否可行 ?

@Barenboim
Copy link
Contributor

#890
这个先修了。
openssl里把传进去的callback强转成返回值为void的函数指针,所以没有编译错误。

@Barenboim
Copy link
Contributor

#892
Base64也改好了。麻烦帮我们试一下!

@BDZNH
Copy link
Contributor Author

BDZNH commented May 9, 2022

可以了,我这边实测可以无修改的情况下,无错误编译出来so,tutorial里面helloworld可以正常跑。
这个pull request看看还有啥问题没有 ?
#894

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants