blob: ed67d090a03a10ce29b851013fcb3a30748b0e78 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "sslSocket.h"
#include <stdio.h>
#include "jni.h"
#include "hysock.h"
#include "openssl/bio.h"
#include "openssl/ssl.h"
#include "openssl/err.h"
#include "errno.h"
jlong getFD(jlong fd) {
hysocket_t hysocketP = jlong2addr(hysocket_struct, fd);
#if defined(WIN32) || defined(WIN64)
if (hysocketP->flags & SOCKET_IPV4_OPEN_MASK) {
return (jlong)(hysocketP->ipv4);
} else if (hysocketP->flags & SOCKET_IPV6_OPEN_MASK) {
return (jlong)(hysocketP->ipv6);
} else {
return 0;
}
#else
return (jlong)(hysocketP->sock);
#endif
}
JNIEXPORT jlong JNICALL Java_org_apache_harmony_xnet_provider_jsse_SSLSocketImpl_initImpl
(JNIEnv *env, jclass clazz, jlong context) {
return addr2jlong(SSL_new(jlong2addr(SSL_CTX, context)));
}
JNIEXPORT void JNICALL Java_org_apache_harmony_xnet_provider_jsse_SSLSocketImpl_sslAcceptImpl
(JNIEnv *env, jclass clazz, jlong jssl, jlong fd) {
jlong socket = getFD(fd);
SSL *ssl = jlong2addr(SSL, jssl);
BIO *bio;
int ret;
bio = BIO_new_socket((int)socket, BIO_NOCLOSE);
SSL_set_bio(ssl, bio, bio);
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
// Put our SSL into accept state
SSL_set_accept_state(ssl);
// Start the server handshake
ret = SSL_do_handshake(ssl);
if (ret<=0) {
jclass exception = (*env)->FindClass(env, "javax/net/ssl/SSLHandshakeException");
(*env)->ThrowNew(env, exception, ERR_reason_error_string(ERR_get_error()));
}
}
JNIEXPORT void JNICALL Java_org_apache_harmony_xnet_provider_jsse_SSLSocketImpl_sslConnectImpl
(JNIEnv *env, jclass clazz, jlong jssl, jlong fd) {
jlong socket = getFD(fd);
SSL *ssl = jlong2addr(SSL, jssl);
BIO *bio;
int ret;
bio = BIO_new_socket((int)socket, BIO_NOCLOSE);
SSL_set_bio(ssl, bio, bio);
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
// Put our SSL into connect state
SSL_set_connect_state(ssl);
// Start the client handshake
ret = SSL_do_handshake(ssl);
if (ret<=0) {
jclass exception = (*env)->FindClass(env, "javax/net/ssl/SSLHandshakeException");
(*env)->ThrowNew(env, exception, ERR_reason_error_string(ERR_get_error()));
}
}
JNIEXPORT void JNICALL Java_org_apache_harmony_xnet_provider_jsse_SSLSocketImpl_writeAppDataImpl
(JNIEnv *env, jclass clazz, jlong jssl, jbyteArray data, jint offset, jint len) {
SSL *ssl = jlong2addr(SSL, jssl);
int ret;
jbyte *buffer = (jbyte*) malloc(len * sizeof(jbyte*));
(*env)->GetByteArrayRegion(env, data, offset, len, buffer);
ret = SSL_write(ssl, (const void *)buffer, (int)len);
// Check len bytes were written to the socket and loop if not
if (ret == -1) {
// The socket has been closed
jclass exception = (*env)->FindClass(env, "java/net/SocketException");
(*env)->ThrowNew(env, exception, "Connection was reset");
}
free(buffer);
}
JNIEXPORT jint JNICALL Java_org_apache_harmony_xnet_provider_jsse_SSLSocketImpl_readAppDataImpl
(JNIEnv *env, jclass clazz, jlong jssl, jbyteArray data, jint offset, jint len) {
SSL *ssl = jlong2addr(SSL, jssl);
int ret;
jbyte *buffer = (jbyte*) malloc(len * sizeof(jbyte*));
ret = SSL_read(ssl, (void *)buffer, (int)len);
if (ret == -1) {
// The socket has been closed
jclass exception = (*env)->FindClass(env, "java/net/SocketException");
(*env)->ThrowNew(env, exception, "Connection was reset");
return -1;
}
(*env)->SetByteArrayRegion(env, data, offset, ret, buffer);
free(buffer);
return ret;
}
JNIEXPORT void JNICALL Java_org_apache_harmony_xnet_provider_jsse_SSLSocketImpl_closeImpl
(JNIEnv *env, jclass clazz, jlong jssl) {
SSL *ssl = jlong2addr(SSL, jssl);
// The SSLSocket is being closed, so shutdown and free our SSL
SSL_shutdown(ssl);
SSL_free(ssl);
}