/*
* 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/types.h>
#include <sys/socket.h>
#include <dirent.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/time.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 SELECT_MAX 65536
typedef struct select_t {
int max;
int has_more;
int has_update;
int pipe[2];
pthread_t thread_id;
int epoll_fd;
#ifndef WIN32
pthread_mutex_t lock;
#endif
#ifdef POLL
struct pollfd poll_items[SELECT_MAX];
#else
fd_set select_items;
#endif
} select_t;
#define STACK_BUFFER_SIZE (16 * 1024)
void
cse_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;
}
/*
* Issues with SetByteArrayRegion, Windows/Solaris
* see RSN-113, RSN-34, RSN-230
*/
#if 1
static int
set_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 int
get_byte_array_region(JNIEnv *env, jbyteArray buf, jint offset, jint sublen,
char *buffer)
{
(*env)->GetByteArrayRegion(env, buf, offset, sublen, (void*) buffer);
return 1;
}
#else
static int
set_byte_array_region(JNIEnv *env, jbyteArray buf, jint offset, jint sublen,
char *buffer)
{
jbyte *cBuf;
cBuf = (*env)->GetPrimitiveArrayCritical(env, buf, 0);
if (cBuf) {
memcpy(cBuf + offset, buffer, sublen);
(*env)->ReleasePrimitiveArrayCritical(env, buf, cBuf, 0);
return 1;
}
return 0;
}
static int
get_byte_array_region(JNIEnv *env, jbyteArray buf, jint offset, jint sublen,
char *buffer)
{
jbyte *cBuf;
cBuf = (*env)->GetPrimitiveArrayCritical(env, buf, 0);
if (cBuf) {
memcpy(buffer, cBuf + offset, sublen);
(*env)->ReleasePrimitiveArrayCritical(env, buf, cBuf, 0);
return 1;
}
return 0;
}
#endif
JNIEXPORT jlong JNICALL
Java_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 JNICALL
Java_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 JNICALL
Java_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 JNICALL
Java_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 JNICALL
Java_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 JNICALL
Java_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 JNICALL
Java_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 JNICALL
Java_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 JNICALL
Java_com_caucho_vfs_JniSocketImpl_isSecure(JNIEnv *env,
评论14
最新资源