mirror of
https://github.com/corda/corda.git
synced 2025-01-03 19:54:13 +00:00
Implement socket API
This commit is contained in:
parent
2800ffe826
commit
45ee25f68c
@ -9,33 +9,70 @@
|
||||
details. */
|
||||
|
||||
#include "jni.h"
|
||||
#include "jni-util.h"
|
||||
#include "avian/machine.h"
|
||||
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
# include <winsock2.h>
|
||||
# define ONLY_ON_WINDOWS(x) x
|
||||
#else
|
||||
# include <netdb.h>
|
||||
# include <sys/socket.h>
|
||||
# include <netinet/in.h>
|
||||
# define ONLY_ON_WINDOWS(x)
|
||||
#endif
|
||||
#include "sockets.h"
|
||||
|
||||
using namespace avian::classpath::sockets;
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_net_Socket_init(JNIEnv* ONLY_ON_WINDOWS(e), jclass)
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
static bool wsaInitialized = false;
|
||||
if (not wsaInitialized) {
|
||||
WSADATA data;
|
||||
int r = WSAStartup(MAKEWORD(2, 2), &data);
|
||||
if (r or LOBYTE(data.wVersion) != 2 or HIBYTE(data.wVersion) != 2) {
|
||||
throwNew(e, "java/io/IOException", "WSAStartup failed");
|
||||
} else {
|
||||
wsaInitialized = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Java_java_net_Socket_init(JNIEnv* e, jclass) {
|
||||
init(e);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT SOCKET JNICALL
|
||||
Java_java_net_Socket_create(JNIEnv* e, jclass) {
|
||||
return create(e);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_net_Socket_connect(JNIEnv* e, jclass, SOCKET sock, long addr, short port) {
|
||||
connect(e, sock, addr, port);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_net_Socket_bind(JNIEnv* e, jclass, SOCKET sock, long addr, short port) {
|
||||
bind(e, sock, addr, port);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_net_Socket_abort(JNIEnv* e, jclass, SOCKET sock) {
|
||||
abort(e, sock);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_net_Socket_close(JNIEnv* e, jclass, SOCKET sock) {
|
||||
close(e, sock);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_net_Socket_closeOutput(JNIEnv* e, jclass, SOCKET sock) {
|
||||
close_output(e, sock);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_net_Socket_closeInput(JNIEnv* e, jclass, SOCKET sock) {
|
||||
close_input(e, sock);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_java_net_Socket_send(vm::Thread* t, vm::object, uintptr_t* arguments) { /* SOCKET s, object buffer_obj, int start_pos, int count */
|
||||
SOCKET& s = *(reinterpret_cast<SOCKET*>(&arguments[0]));
|
||||
vm::object buffer_obj = reinterpret_cast<vm::object>(arguments[2]);
|
||||
int32_t& start_pos = *(reinterpret_cast<int32_t*>(&arguments[3]));
|
||||
int32_t& count = *(reinterpret_cast<int32_t*>(&arguments[4]));
|
||||
char* buffer = reinterpret_cast<char*>(&vm::byteArrayBody(t, buffer_obj, start_pos));
|
||||
avian::classpath::sockets::send((JNIEnv*)t, s, buffer, count);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_java_net_Socket_recv(vm::Thread* t, vm::object, uintptr_t* arguments) { /* SOCKET s, object buffer_obj, int start_pos, int count */
|
||||
SOCKET& s = *(reinterpret_cast<SOCKET*>(&arguments[0]));
|
||||
vm::object buffer_obj = reinterpret_cast<vm::object>(arguments[2]);
|
||||
int32_t& start_pos = *(reinterpret_cast<int32_t*>(&arguments[3]));
|
||||
int32_t& count = *(reinterpret_cast<int32_t*>(&arguments[4]));
|
||||
char* buffer = reinterpret_cast<char*>(&vm::byteArrayBody(t, buffer_obj, start_pos));
|
||||
return avian::classpath::sockets::recv((JNIEnv*)t, s, buffer, count);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
@ -49,7 +86,7 @@ Java_java_net_InetAddress_ipv4AddressForName(JNIEnv* e,
|
||||
hostent* host = gethostbyname(chars);
|
||||
e->ReleaseStringUTFChars(name, chars);
|
||||
if (host) {
|
||||
return htonl(reinterpret_cast<in_addr*>(host->h_addr_list[0])->s_addr);
|
||||
return ntohl(reinterpret_cast<in_addr*>(host->h_addr_list[0])->s_addr);
|
||||
} else {
|
||||
fprintf(stderr, "trouble %d\n", WSAGetLastError());
|
||||
}
|
||||
@ -67,7 +104,7 @@ Java_java_net_InetAddress_ipv4AddressForName(JNIEnv* e,
|
||||
if (r != 0) {
|
||||
address = 0;
|
||||
} else {
|
||||
address = htonl
|
||||
address = ntohl
|
||||
(reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr.s_addr);
|
||||
|
||||
freeaddrinfo(result);
|
||||
@ -78,3 +115,4 @@ Java_java_net_InetAddress_ipv4AddressForName(JNIEnv* e,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
15
classpath/java/lang/AutoCloseable.java
Normal file
15
classpath/java/lang/AutoCloseable.java
Normal file
@ -0,0 +1,15 @@
|
||||
/* Copyright (c) 2008-2013, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
package java.lang;
|
||||
|
||||
public interface AutoCloseable {
|
||||
void close() throws Exception;
|
||||
}
|
@ -123,4 +123,7 @@ public class Throwable implements Serializable {
|
||||
trace = trace(0);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void addSuppressed(Throwable exception) {
|
||||
}
|
||||
}
|
||||
|
@ -13,41 +13,61 @@ package java.net;
|
||||
import java.io.IOException;
|
||||
|
||||
public class InetAddress {
|
||||
private final String address;
|
||||
private final String name;
|
||||
private final int ip;
|
||||
|
||||
private InetAddress(String address) {
|
||||
this.address = address;
|
||||
private InetAddress(String name) throws UnknownHostException {
|
||||
this.name = name;
|
||||
this.ip = ipv4AddressForName(name);
|
||||
if (ip == 0) {
|
||||
throw new UnknownHostException(name);
|
||||
}
|
||||
}
|
||||
|
||||
public String getHostName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getHostAddress() {
|
||||
return address;
|
||||
try {
|
||||
return new InetAddress(name).toString();
|
||||
} catch (UnknownHostException e) {
|
||||
return null; // Strange case
|
||||
}
|
||||
}
|
||||
|
||||
public static InetAddress getByName(String name)
|
||||
throws UnknownHostException
|
||||
{
|
||||
public static InetAddress getByName(String name) throws UnknownHostException {
|
||||
try {
|
||||
Socket.init();
|
||||
return new InetAddress(name);
|
||||
} catch (IOException e) {
|
||||
UnknownHostException uhe = new UnknownHostException(name);
|
||||
uhe.initCause(e);
|
||||
throw uhe;
|
||||
}
|
||||
|
||||
int address = ipv4AddressForName(name);
|
||||
if (address == 0) {
|
||||
throw new UnknownHostException(name);
|
||||
} else {
|
||||
return new InetAddress(ipv4AddressToString(address));
|
||||
}
|
||||
}
|
||||
|
||||
private static String ipv4AddressToString(int address) {
|
||||
return (((address >>> 24) ) + "." +
|
||||
((address >>> 16) & 0xFF) + "." +
|
||||
((address >>> 8 ) & 0xFF) + "." +
|
||||
((address ) & 0xFF));
|
||||
public byte[] getAddress() {
|
||||
byte[] res = new byte[4];
|
||||
res[0] = (byte) ( ip >>> 24);
|
||||
res[1] = (byte) ((ip >>> 16) & 0xFF);
|
||||
res[2] = (byte) ((ip >>> 8 ) & 0xFF);
|
||||
res[3] = (byte) ((ip ) & 0xFF);
|
||||
return res;
|
||||
}
|
||||
|
||||
private static native int ipv4AddressForName(String name);
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
byte[] addr = getAddress();
|
||||
return (int)((addr[0] + 256) % 256) + "." +
|
||||
(int)((addr[1] + 256) % 256) + "." +
|
||||
(int)((addr[2] + 256) % 256) + "." +
|
||||
(int)((addr[3] + 256) % 256);
|
||||
}
|
||||
|
||||
int getRawAddress() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
static native int ipv4AddressForName(String name);
|
||||
}
|
||||
|
@ -11,16 +11,25 @@
|
||||
package java.net;
|
||||
|
||||
public class InetSocketAddress extends SocketAddress {
|
||||
private final String host;
|
||||
private final InetAddress address;
|
||||
private final int port;
|
||||
|
||||
public InetSocketAddress(String host, int port) {
|
||||
this.host = host;
|
||||
public InetSocketAddress(String host, int port) throws UnknownHostException {
|
||||
this.address = InetAddress.getByName(host);
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public InetSocketAddress(InetAddress address, int port) {
|
||||
this.address = address;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public InetAddress getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public String getHostName() {
|
||||
return host;
|
||||
return address.getHostName();
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
|
@ -10,10 +10,191 @@
|
||||
|
||||
package java.net;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public abstract class Socket {
|
||||
public static native void init() throws IOException;
|
||||
public class Socket implements Closeable, AutoCloseable {
|
||||
|
||||
public abstract void setTcpNoDelay(boolean on) throws SocketException;
|
||||
private static final int SD_RECEIVE = 0x00;
|
||||
private static final int SD_SEND = 0x01;
|
||||
private static final int SD_BOTH = 0x02;
|
||||
|
||||
private static final int BUFFER_SIZE = 65535;
|
||||
|
||||
/**
|
||||
* This method is called from all routines that depend on winsock in windows,
|
||||
* so it has public visibility
|
||||
* @throws IOException
|
||||
*/
|
||||
public static native void init() throws IOException;
|
||||
|
||||
/**
|
||||
* Creates the native socket object
|
||||
* @return Handle to the native object
|
||||
* @throws IOException
|
||||
*/
|
||||
private static native /* SOCKET */long create() throws IOException;
|
||||
|
||||
/**
|
||||
* Connects the native socket object to an address:port
|
||||
* @param sock Native socket handler
|
||||
* @param addr Address to connect to
|
||||
* @param port Port to connect to
|
||||
* @throws IOException
|
||||
*/
|
||||
private static native void connect(/* SOCKET */long sock, long addr, short port) throws IOException;
|
||||
private static native void bind(/* SOCKET */long sock, long addr, short port) throws IOException;
|
||||
|
||||
private static native void send(/* SOCKET */long sock, byte[] buffer, int start_pos, int count) throws IOException;
|
||||
private static native int recv(/* SOCKET */long sock, byte[] buffer, int start_pos, int count) throws IOException;
|
||||
|
||||
private static native void abort(/* SOCKET */long sock);
|
||||
private static native void close(/* SOCKET */long sock);
|
||||
private static native void closeOutput(/* SOCKET */long sock);
|
||||
private static native void closeInput(/* SOCKET */long sock);
|
||||
|
||||
private class SocketInputStream extends InputStream {
|
||||
|
||||
private boolean closed = false;
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (!closed) {
|
||||
closeInput(sock);
|
||||
closed = true;
|
||||
}
|
||||
super.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
close();
|
||||
super.finalize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
byte[] buffer = new byte[1];
|
||||
int size = recv(sock, buffer, 0, 1);
|
||||
if (size == 0) {
|
||||
return -1;
|
||||
}
|
||||
return buffer[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] buffer) throws IOException {
|
||||
int fullSize = buffer.length;
|
||||
int index = 0;
|
||||
int size;
|
||||
do {
|
||||
size = recv(sock, buffer, index, Math.min(fullSize, Socket.BUFFER_SIZE));
|
||||
fullSize -= size;
|
||||
index += size;
|
||||
} while (fullSize != 0 && size != 0);
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private class SocketOutputStream extends OutputStream {
|
||||
|
||||
private boolean closed = false;
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (!closed) {
|
||||
closeOutput(sock);
|
||||
closed = true;
|
||||
}
|
||||
super.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
close();
|
||||
super.finalize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int c) throws IOException {
|
||||
byte[] res = new byte[1];
|
||||
res[0] = (byte)c;
|
||||
send(sock, res, 0, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] buffer) throws IOException {
|
||||
int fullSize = buffer.length;
|
||||
int index = 0;
|
||||
int size;
|
||||
do {
|
||||
size = Math.min(fullSize, Socket.BUFFER_SIZE);
|
||||
send(sock, buffer, index, size);
|
||||
fullSize -= size;
|
||||
index += size;
|
||||
} while (fullSize != 0 && size != 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private long sock;
|
||||
private SocketInputStream inputStream;
|
||||
private SocketOutputStream outputStream;
|
||||
|
||||
public Socket() throws IOException {
|
||||
Socket.init();
|
||||
sock = create();
|
||||
inputStream = new SocketInputStream();
|
||||
outputStream = new SocketOutputStream();
|
||||
}
|
||||
|
||||
public SocketInputStream getInputStream() {
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
public SocketOutputStream getOutputStream() {
|
||||
return outputStream;
|
||||
}
|
||||
|
||||
public Socket(InetAddress address, int port) throws IOException {
|
||||
this();
|
||||
connect(sock, address.getRawAddress(), (short)port);
|
||||
}
|
||||
|
||||
public Socket(String host, int port) throws UnknownHostException, IOException {
|
||||
this(InetAddress.getByName(host), port);
|
||||
}
|
||||
|
||||
public void bind(SocketAddress bindpoint) throws IOException {
|
||||
if (bindpoint instanceof InetSocketAddress) {
|
||||
InetSocketAddress inetBindpoint = (InetSocketAddress)bindpoint;
|
||||
bind(sock, inetBindpoint.getAddress().getRawAddress(), (short) inetBindpoint.getPort());
|
||||
}
|
||||
}
|
||||
|
||||
public void setTcpNoDelay(boolean on) throws SocketException {}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
close(sock);
|
||||
}
|
||||
|
||||
public void shutdownInput() throws IOException {
|
||||
inputStream.close();
|
||||
}
|
||||
|
||||
public void shutdownOutput() throws IOException {
|
||||
outputStream.close();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
close();
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,11 @@ public class SocketChannel extends SelectableChannel
|
||||
}
|
||||
|
||||
public Socket socket() {
|
||||
return new Handle();
|
||||
try {
|
||||
return new Handle();
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean connect(SocketAddress address) throws IOException {
|
||||
@ -165,7 +169,11 @@ public class SocketChannel extends SelectableChannel
|
||||
}
|
||||
|
||||
public class Handle extends Socket {
|
||||
public void setTcpNoDelay(boolean on) throws SocketException {
|
||||
public Handle() throws IOException {
|
||||
super();
|
||||
}
|
||||
|
||||
public void setTcpNoDelay(boolean on) throws SocketException {
|
||||
natSetTcpNoDelay(socket, on);
|
||||
}
|
||||
}
|
||||
|
184
classpath/sockets.cpp
Normal file
184
classpath/sockets.cpp
Normal file
@ -0,0 +1,184 @@
|
||||
/* Copyright (c) 2008-2013, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
/*
|
||||
* This file implements a simple cross-platform JNI sockets API
|
||||
* It is used from different classes of the default Avian classpath
|
||||
*/
|
||||
|
||||
#include "sockets.h"
|
||||
|
||||
namespace avian {
|
||||
namespace classpath {
|
||||
namespace sockets {
|
||||
|
||||
int last_socket_error() {
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
int error = WSAGetLastError();
|
||||
#else
|
||||
int error = errno;
|
||||
#endif
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
void init(JNIEnv* ONLY_ON_WINDOWS(e)) {
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
static bool wsaInitialized = false;
|
||||
if (not wsaInitialized) {
|
||||
WSADATA data;
|
||||
int r = WSAStartup(MAKEWORD(2, 2), &data);
|
||||
if (r or LOBYTE(data.wVersion) != 2 or HIBYTE(data.wVersion) != 2) {
|
||||
throwNew(e, "java/io/IOException", "WSAStartup failed");
|
||||
} else {
|
||||
wsaInitialized = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SOCKET create(JNIEnv* e) {
|
||||
SOCKET sock;
|
||||
if (INVALID_SOCKET == (sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))) {
|
||||
char buf[255];
|
||||
sprintf(buf, "Can't create a socket. System error: %d", last_socket_error());
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
return 0; // This doesn't matter cause we have risen an exception
|
||||
}
|
||||
return sock;
|
||||
}
|
||||
|
||||
void connect(JNIEnv* e, SOCKET sock, long addr, short port) {
|
||||
sockaddr_in adr;
|
||||
adr.sin_family = AF_INET;
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
adr.sin_addr.S_un.S_addr = htonl(addr);
|
||||
#else
|
||||
adr.sin_addr.s_addr = htonl(addr);
|
||||
#endif
|
||||
adr.sin_port = htons (port);
|
||||
|
||||
if (SOCKET_ERROR == ::connect(sock, (sockaddr* )&adr, sizeof(adr)))
|
||||
{
|
||||
char buf[255];
|
||||
sprintf(buf, "Can't connect a socket. System error: %d", last_socket_error());
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void bind(JNIEnv* e, SOCKET sock, long addr, short port) {
|
||||
sockaddr_in adr;
|
||||
adr.sin_family = AF_INET;
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
adr.sin_addr.S_un.S_addr = htonl(addr);
|
||||
#else
|
||||
adr.sin_addr.s_addr = htonl(addr);
|
||||
#endif
|
||||
adr.sin_port = htons (port);
|
||||
|
||||
if (SOCKET_ERROR == ::bind(sock, (sockaddr* )&adr, sizeof(adr)))
|
||||
{
|
||||
char buf[255];
|
||||
sprintf(buf, "Can't bind a socket. System error: %d", last_socket_error());
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SOCKET accept(JNIEnv* e, SOCKET sock, long* client_addr, short* client_port) {
|
||||
sockaddr_in adr;
|
||||
SOCKET client_socket = ::accept(sock, (sockaddr* )&adr, NULL);
|
||||
if (INVALID_SOCKET == client_socket) {
|
||||
char buf[255];
|
||||
sprintf(buf, "Can't accept the incoming connection. System error: %d", last_socket_error());
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
if (client_addr != NULL) {
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
*client_addr = ntohl(adr.sin_addr.S_un.S_addr);
|
||||
#else
|
||||
*client_addr = ntohl(adr.sin_addr.s_addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (client_port != NULL) {
|
||||
*client_port = ntohs (adr.sin_port);
|
||||
}
|
||||
|
||||
return client_socket;
|
||||
}
|
||||
|
||||
void send(JNIEnv* e, SOCKET sock, const char* buff_ptr, int buff_size) {
|
||||
if (SOCKET_ERROR == ::send(sock, buff_ptr, buff_size, 0)) {
|
||||
char buf[255];
|
||||
sprintf(buf, "Can't send data through the socket. System error: %d", last_socket_error());
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int recv(JNIEnv* e, SOCKET sock, char* buff_ptr, int buff_size) {
|
||||
int length = ::recv(sock, buff_ptr, buff_size, 0);
|
||||
if (SOCKET_ERROR == length) {
|
||||
char buf[255];
|
||||
sprintf(buf, "Can't receive data through the socket. System error: %d", last_socket_error());
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
return 0; // This doesn't matter cause we have risen an exception
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
void abort(JNIEnv* e, SOCKET sock) {
|
||||
if (SOCKET_ERROR == ::closesocket(sock)) {
|
||||
char buf[255];
|
||||
sprintf(buf, "Can't close the socket. System error: %d", last_socket_error());
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
}
|
||||
}
|
||||
|
||||
void close(JNIEnv* e, SOCKET sock) {
|
||||
if (SOCKET_ERROR == ::shutdown(sock, SD_BOTH)) {
|
||||
int errcode = last_socket_error();
|
||||
if (errcode != ENOTCONN) {
|
||||
char buf[255];
|
||||
sprintf(buf, "Can't shutdown the socket. System error: %d", errcode);
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void close_input(JNIEnv* e, SOCKET sock) {
|
||||
if (SOCKET_ERROR == ::shutdown(sock, SD_RECEIVE)) {
|
||||
int errcode = last_socket_error();
|
||||
if (errcode != ENOTCONN) {
|
||||
char buf[255];
|
||||
sprintf(buf, "Can't shutdown the socket. System error: %d", errcode);
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void close_output(JNIEnv* e, SOCKET sock) {
|
||||
if (SOCKET_ERROR == ::shutdown(sock, SD_SEND)) {
|
||||
int errcode = last_socket_error();
|
||||
if (errcode != ENOTCONN) {
|
||||
char buf[255];
|
||||
sprintf(buf, "Can't shutdown the socket. System error: %d", errcode);
|
||||
throwNew(e, "java/io/IOException", buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
72
classpath/sockets.h
Normal file
72
classpath/sockets.h
Normal file
@ -0,0 +1,72 @@
|
||||
/* Copyright (c) 2008-2013, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
|
||||
/*
|
||||
* This file represents a simple cross-platform JNI sockets API
|
||||
* It is used from different classes of the default Avian classpath
|
||||
*/
|
||||
|
||||
#ifndef SOCKETS_H_
|
||||
#define SOCKETS_H_
|
||||
|
||||
#include "avian/common.h"
|
||||
#include "jni.h"
|
||||
#include "jni-util.h"
|
||||
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
# include <winsock2.h>
|
||||
|
||||
# define ONLY_ON_WINDOWS(x) x
|
||||
#else
|
||||
# include <netdb.h>
|
||||
# include <sys/socket.h>
|
||||
# include <netinet/in.h>
|
||||
# include <unistd.h>
|
||||
|
||||
# define ONLY_ON_WINDOWS(x)
|
||||
# define SOCKET int
|
||||
# define INVALID_SOCKET -1
|
||||
# define SOCKET_ERROR -1
|
||||
# define closesocket(x) close(x)
|
||||
|
||||
# define SD_RECEIVE SHUT_RD
|
||||
# define SD_SEND SHUT_WR
|
||||
# define SD_BOTH SHUT_RDWR
|
||||
|
||||
#endif
|
||||
|
||||
namespace avian {
|
||||
namespace classpath {
|
||||
namespace sockets {
|
||||
|
||||
// Library initialization
|
||||
void init(JNIEnv* ONLY_ON_WINDOWS(e));
|
||||
|
||||
// Socket initialization
|
||||
SOCKET create(JNIEnv* e);
|
||||
void connect(JNIEnv* e, SOCKET sock, long addr, short port);
|
||||
void bind(JNIEnv* e, SOCKET sock, long addr, short port);
|
||||
SOCKET accept(JNIEnv* e, SOCKET sock, long* client_addr, short* client_port);
|
||||
|
||||
// I/O
|
||||
void send(JNIEnv* e, SOCKET sock, const char* buff_ptr, int buff_size);
|
||||
int recv(JNIEnv* e, SOCKET sock, char* buff_ptr, int buff_size);
|
||||
|
||||
// Socket closing
|
||||
void abort(JNIEnv* e, SOCKET sock);
|
||||
void close(JNIEnv* e, SOCKET sock);
|
||||
void close_input(JNIEnv* e, SOCKET sock);
|
||||
void close_output(JNIEnv* e, SOCKET sock);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* SOCKETS_H_ */
|
37
test/Sockets.java
Normal file
37
test/Sockets.java
Normal file
@ -0,0 +1,37 @@
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
public class Sockets {
|
||||
|
||||
/**
|
||||
* @param args
|
||||
* @throws IOException
|
||||
* @throws UnknownHostException
|
||||
*/
|
||||
public static void main(String[] args) throws UnknownHostException,
|
||||
IOException {
|
||||
System.out.print("Requesting...\n");
|
||||
try (Socket sock = new Socket("www.google.com", 80)) {
|
||||
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));
|
||||
String request = "GET /?gws_rd=cr HTTP/1.1\r\n"
|
||||
+ "Host: www.google.com\r\n" + "Accept: */*\r\n"
|
||||
+ "User-Agent: Java\r\n" + "Connection: close\r\n" + "\r\n";
|
||||
bw.write(request);
|
||||
bw.flush();
|
||||
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(sock.getInputStream()));
|
||||
String read = null;
|
||||
while ((read = br.readLine()) != null) {
|
||||
System.out.println(read);
|
||||
}
|
||||
bw.close();
|
||||
sock.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user