Skip to content
This repository
Fetching contributors…

Cannot retrieve contributors at this time

file 184 lines (160 sloc) 4.873 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
/* Copyright (c) 2008-2014, 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);
}
}
}

}
}
}
Something went wrong with that request. Please try again.