📄 jni_socket.c
字号:
/* * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved * * @author Scott Ferguson */#ifdef WIN32#ifndef _WINSOCKAPI_ #define _WINSOCKAPI_#endif #include <windows.h>#include <winsock2.h>#include <io.h>#else#include <sys/param.h>#include <sys/time.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/resource.h>#include <dirent.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#ifdef EPOLL#include <sys/epoll.h>#endif#ifdef POLL#include <sys/poll.h>#else#include <sys/select.h>#endif#include <pwd.h>#include <syslog.h>#include <netdb.h>#endif#ifdef linux#include <linux/version.h>#endif#include <sys/stat.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <string.h>#include <signal.h>#include <errno.h>/* probably system-dependent */#include <jni.h>#include "resin.h"#define STACK_BUFFER_SIZE (16 * 1024)voidcse_log(char *fmt, ...){#ifdef DEBUG va_list list; va_start(list, fmt); vfprintf(stderr, fmt, list); va_end(list);#endif}static char *q_strdup(char *str){ int len = strlen(str); char *dup = cse_malloc(len + 1); strcpy(dup, str); return dup;}static intset_byte_array_region(JNIEnv *env, jbyteArray j_buf, jint offset, jint sublen, char *c_buf){ (*env)->SetByteArrayRegion(env, j_buf, offset, sublen, (void*) c_buf); return 1;}static intget_byte_array_region(JNIEnv *env, jbyteArray buf, jint offset, jint sublen, char *buffer){ (*env)->GetByteArrayRegion(env, buf, offset, sublen, (void*) buffer); return 1;}JNIEXPORT jlong JNICALLJava_com_caucho_vfs_JniSocketImpl_nativeAllocate(JNIEnv *env, jobject obj){ connection_t *conn; conn = (connection_t *) cse_malloc(sizeof(connection_t)); memset(conn, 0, sizeof(connection_t)); conn->fd = -1; conn->client_sin = (struct sockaddr *) conn->client_data; conn->server_sin = (struct sockaddr *) conn->server_data; conn->ops = &std_ops;#ifdef WIN32 // conn->event = WSACreateEvent();#endif return (jlong) (PTR) conn;}JNIEXPORT jint JNICALLJava_com_caucho_vfs_JniSocketImpl_readNative(JNIEnv *env, jobject obj, jlong conn_fd, jbyteArray buf, jint offset, jint length, jlong timeout){ connection_t *conn = (connection_t *) (PTR) conn_fd; int sublen; char buffer[STACK_BUFFER_SIZE]; if (! conn || conn->fd < 0) return -1; conn->jni_env = env; if (length < STACK_BUFFER_SIZE) sublen = length; else sublen = STACK_BUFFER_SIZE; sublen = conn->ops->read(conn, buffer, sublen, (int) timeout); /* Should probably have a different response for EINTR */ if (sublen < 0) return sublen; set_byte_array_region(env, buf, offset, sublen, buffer); return sublen;}JNIEXPORT jint JNICALLJava_com_caucho_vfs_JniStream_readNonBlockNative(JNIEnv *env, jobject obj, jlong conn_fd, jbyteArray buf, jint offset, jint length){ connection_t *conn = (connection_t *) (PTR) conn_fd; int sublen; char buffer[STACK_BUFFER_SIZE]; if (! conn || conn->fd < 0) return -1; conn->jni_env = env; if (length < STACK_BUFFER_SIZE) sublen = length; else sublen = STACK_BUFFER_SIZE; sublen = conn->ops->read_nonblock(conn, buffer, sublen); /* Should probably have a different response for EINTR */ if (sublen < 0) return sublen; set_byte_array_region(env, buf, offset, sublen, buffer); return sublen;}JNIEXPORT jint JNICALLJava_com_caucho_vfs_JniSocketImpl_writeNative(JNIEnv *env, jobject obj, jlong conn_fd, jbyteArray buf, jint offset, jint length){ connection_t *conn = (connection_t *) (PTR) conn_fd; char buffer[STACK_BUFFER_SIZE]; int sublen; int write_length = 0; if (! conn || conn->fd < 0 || ! buf) return -1; conn->jni_env = env; while (length > 0) { int result; if (length < sizeof(buffer)) sublen = length; else sublen = sizeof(buffer); get_byte_array_region(env, buf, offset, sublen, buffer); result = conn->ops->write(conn, buffer, sublen); if (result < 0) { return result; } length -= result; offset += result; write_length += result; } return write_length;}JNIEXPORT jint JNICALLJava_com_caucho_vfs_JniSocketImpl_writeNative2(JNIEnv *env, jobject obj, jlong conn_fd, jbyteArray buf1, jint off1, jint len1, jbyteArray buf2, jint off2, jint len2){ connection_t *conn = (connection_t *) (PTR) conn_fd; char buffer[2 * STACK_BUFFER_SIZE]; int sublen; int buffer_offset; int write_length = 0; buffer_offset = 0; if (! conn || conn->fd < 0 || ! buf1 || ! buf2) return -1; conn->jni_env = env; while (sizeof(buffer) < len1) { sublen = sizeof(buffer); get_byte_array_region(env, buf1, off1, sublen, buffer); sublen = conn->ops->write(conn, buffer, sublen); if (sublen < 0) { /* XXX: probably should throw exception */ return sublen; } len1 -= sublen; off1 += sublen; write_length += sublen; } get_byte_array_region(env, buf1, off1, len1, buffer); buffer_offset = len1; while (buffer_offset + len2 > 0) { int result; if (len2 < sizeof(buffer) - buffer_offset) sublen = len2; else sublen = sizeof(buffer) - buffer_offset; get_byte_array_region(env, buf2, off2, sublen, buffer + buffer_offset); result = conn->ops->write(conn, buffer, buffer_offset + sublen); if (result < 0) { /* XXX: probably should throw exception */ return result; } len2 -= sublen; off2 += sublen; write_length += sublen + buffer_offset; buffer_offset = 0; } return write_length;}JNIEXPORT jint JNICALLJava_com_caucho_vfs_JniSocketImpl_flushNative(JNIEnv *env, jobject obj, jlong conn_fd){ connection_t *conn = (connection_t *) (PTR) conn_fd; if (! conn) return -1; else return 0; /* return cse_flush_request(res); */}JNIEXPORT void JNICALLJava_com_caucho_vfs_JniSocketImpl_nativeClose(JNIEnv *env, jobject obj, jlong conn_fd){ connection_t *conn = (connection_t *) (PTR) conn_fd; if (conn && conn->fd >= 0) { conn->jni_env = env; conn->ops->close(conn); }}JNIEXPORT void JNICALLJava_com_caucho_vfs_JniSocketImpl_nativeFree(JNIEnv *env, jobject obj, jlong conn_fd){ connection_t *conn = (connection_t *) (PTR) conn_fd; if (conn) {#ifdef WIN32 /* if (conn->event) WSACloseEvent(conn->event); */#endif cse_free(conn); }}JNIEXPORT jboolean JNICALLJava_com_caucho_vfs_JniSocketImpl_isSecure(JNIEnv *env, jobject obj, jlong conn_fd){ connection_t *conn = (connection_t *) (PTR) conn_fd; if (! conn) return 0; return conn->sock != 0 && conn->ssl_cipher != 0;}JNIEXPORT jstring JNICALLJava_com_caucho_vfs_JniSocketImpl_getCipher(JNIEnv *env, jobject obj, jlong conn_fd){ connection_t *conn = (connection_t *) (PTR) conn_fd; if (! conn || ! conn->sock || ! conn->ssl_cipher) return 0; return (*env)->NewStringUTF(env, conn->ssl_cipher);}JNIEXPORT jint JNICALLJava_com_caucho_vfs_JniSocketImpl_getCipherBits(JNIEnv *env, jobject obj, jlong conn_fd){ connection_t *conn = (connection_t *) (PTR) conn_fd; if (! conn || ! conn->sock) return 0; else return conn->ssl_bits;}#ifdef POLLJNIEXPORT jboolean JNICALLJava_com_caucho_vfs_JniSocketImpl_nativeReadNonBlock(JNIEnv *env, jobject obj, jlong conn_fd, jint ms){ connection_t *conn = (connection_t *) (PTR) conn_fd; struct pollfd poll_item[1]; int fd; if (! conn) return 0; fd = conn->fd; if (fd < 0) return 0; poll_item[0].fd = fd; poll_item[0].events = POLLIN|POLLPRI; poll_item[0].revents = 0; return (poll(poll_item, 1, ms) > 0);}#else /* SELECT */JNIEXPORT jboolean JNICALLJava_com_caucho_vfs_JniSocketImpl_nativeReadNonBlock(JNIEnv *env, jobject obj, jlong conn_fd, jint ms){ connection_t *conn = (connection_t *) (PTR) conn_fd; fd_set read_set; struct timeval timeout; int result; int fd; if (! conn) return 0; fd = conn->fd; if (fd < 0) return 0; FD_ZERO(&read_set); FD_SET((unsigned int) fd, &read_set); timeout.tv_sec = ms / 1000; timeout.tv_usec = (ms % 1000) * 1000; result = select(fd + 1, &read_set, 0, 0, &timeout); return result > 0;}#endif#ifdef AI_NUMERICHOSTstatic struct sockaddr_in *lookup_addr(JNIEnv *env, char *addr_name, int port, char *buffer, int *p_family, int *p_protocol, int *p_sin_length){ struct addrinfo hints; struct addrinfo *addr; struct sockaddr_in *sin; int sin_length; char port_name[16]; memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_STREAM; hints.ai_family = PF_UNSPEC; hints.ai_flags = AI_NUMERICHOST; sprintf(port_name, "%d", port); if (getaddrinfo(addr_name, port_name, &hints, &addr)) { resin_printf_exception(env, "java/net/SocketException", "can't find address %s", addr_name); return 0; } *p_family = addr->ai_family; *p_protocol = addr->ai_protocol; sin_length = addr->ai_addrlen; memcpy(buffer, addr->ai_addr, sin_length); sin = (struct sockaddr_in *) buffer; freeaddrinfo(addr); *p_sin_length = sin_length; return sin;}#elsestatic struct sockaddr_in *lookup_addr(JNIEnv *env, char *addr_name, int port, char *buffer, int *p_family, int *p_protocol, int *p_sin_length){ struct sockaddr_in *sin = (struct sockaddr_in *) buffer; memset(sin, 0, sizeof(struct sockaddr_in)); *p_sin_length = sizeof(struct sockaddr_in); sin->sin_family = AF_INET; *p_family = AF_INET; *p_protocol = 0; sin->sin_addr.s_addr = inet_addr(addr_name); sin->sin_port = htons((unsigned short) port); return sin;}#endifstatic voidinit_server_socket(JNIEnv *env, server_socket_t *ss){ jclass jniServerSocketClass; jniServerSocketClass = (*env)->FindClass(env, "com/caucho/vfs/JniSocketImpl"); if (jniServerSocketClass) { ss->_isSecure = (*env)->GetFieldID(env, jniServerSocketClass, "_isSecure", "Z"); if (! ss->_isSecure) resin_throw_exception(env, "com/caucho/config/ConfigException", "can't load _isSecure field"); ss->_localAddrBuffer = (*env)->GetFieldID(env, jniServerSocketClass, "_localAddrBuffer", "[B"); if (! ss->_localAddrBuffer) resin_throw_exception(env, "com/caucho/config/ConfigException", "can't load _localAddrBuffer field"); ss->_localAddrLength = (*env)->GetFieldID(env, jniServerSocketClass, "_localAddrLength", "I"); if (! ss->_localAddrLength) resin_throw_exception(env, "com/caucho/config/ConfigException", "can't load _localAddrLength field"); ss->_localPort = (*env)->GetFieldID(env, jniServerSocketClass, "_localPort", "I"); if (! ss->_localPort) resin_throw_exception(env, "com/caucho/config/ConfigException", "can't load _localPort field"); ss->_remoteAddrBuffer = (*env)->GetFieldID(env, jniServerSocketClass, "_remoteAddrBuffer", "[B"); if (! ss->_remoteAddrBuffer) resin_throw_exception(env, "com/caucho/config/ConfigException", "can't load _remoteAddrBuffer field"); ss->_remoteAddrLength = (*env)->GetFieldID(env, jniServerSocketClass, "_remoteAddrLength", "I"); if (! ss->_remoteAddrLength)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -