Android API update

This commit is contained in:
Joseph Henry
2016-08-11 23:34:40 -07:00
parent c0a89129fa
commit 30db7ae58c
14 changed files with 565 additions and 165 deletions

View File

@@ -120,8 +120,12 @@ ssize_t zts_recvmsg(RECVMSG_SIG);
//JNIEXPORT void JNICALL Java_ZeroTier_SDK_zt_1getsockopt(JNIEnv *env, jobject thisObj);
//JNIEXPORT void JNICALL Java_ZeroTier_SDK_zt_1getsockname(JNIEnv *env, jobject thisObj);
JNIEXPORT jint JNICALL Java_ZeroTier_SDK_zt_1close(JNIEnv *env, jobject thisObj, jint fd);
// TCP
JNIEXPORT jint JNICALL Java_ZeroTier_SDK_zt_1write(JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len);
JNIEXPORT jint JNICALL Java_ZeroTier_SDK_zt_1read(JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len);
// UDP
JNIEXPORT jint JNICALL Java_ZeroTier_SDK_zt_1sendto(JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len, jint flags, jobject ztaddr);
JNIEXPORT jint JNICALL Java_ZeroTier_SDK_zt_1recvfrom(JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len, jint flags, jobject ztaddr);
// Takes a given numerical file descriptor and manufactures a java FileDescriptor object for use in javaland
JNIEXPORT jobject JNICALL Java_ZeroTier_SDK_zt_1getFileDescriptor(JNIEnv *env, jobject thisObj, jint fd);
#endif

View File

@@ -46,7 +46,7 @@
#define SDK_DEBUG_H
// Set during make (e.g. make SDK_DEBUG=2)
#define DEBUG_LEVEL 5
#define DEBUG_LEVEL 4
#define MSG_TRANSFER 1 // RX/TX specific statements
#define MSG_ERROR 2 // Errors

View File

@@ -26,7 +26,7 @@
* LLC. Start here: http://www.zerotier.com/
*/
#define DEBUG_LEVEL 5 // Set this to adjust what you'd like to see in the debug traces
#define DEBUG_LEVEL 4 // Set this to adjust what you'd like to see in the debug traces
#define MSG_TRANSFER 1 // RX/TX specific statements
#define MSG_ERROR 2 // Errors

View File

@@ -382,11 +382,11 @@ Connection *NetconEthernetTap::getConnection(PhySocket *sock)
void NetconEthernetTap::closeConnection(PhySocket *sock)
{
dwr(MSG_DEBUG, "closeConnection(sock=%x):\n", sock);
dwr(MSG_DEBUG_EXTRA, "closeConnection(sock=%x):\n", sock);
Mutex::Lock _l(_close_m);
// Here we assume _tcpconns_m is already locked by caller
if(!sock) {
dwr(MSG_DEBUG,"closeConnection(): invalid PhySocket\n");
dwr(MSG_DEBUG_EXTRA,"closeConnection(): invalid PhySocket\n");
return;
}
Connection *conn = getConnection(sock);
@@ -396,14 +396,14 @@ void NetconEthernetTap::closeConnection(PhySocket *sock)
lwipstack->__udp_remove(conn->UDP_pcb);
}
if(conn->TCP_pcb && conn->TCP_pcb->state != CLOSED) {
dwr(MSG_DEBUG,"closeConnection(conn=%p,sock=%p): PCB->state = %d\n",
dwr(MSG_DEBUG_EXTRA,"closeConnection(conn=%p,sock=%p): PCB->state = %d\n",
(void*)&conn, (void*)&sock, conn->TCP_pcb->state);
if(conn->TCP_pcb->state == SYN_SENT /*|| conn->TCP_pcb->state == CLOSE_WAIT*/) {
dwr(MSG_DEBUG,"closeConnection(sock=%p): invalid PCB state for this operation. ignoring.\n",
dwr(MSG_DEBUG_EXTRA,"closeConnection(sock=%p): invalid PCB state for this operation. ignoring.\n",
(void*)&sock);
return;
}
dwr(MSG_DEBUG, "__tcp_close(...)\n");
dwr(MSG_DEBUG_EXTRA, "__tcp_close(...)\n");
if(lwipstack->__tcp_close(conn->TCP_pcb) == ERR_OK) {
// Unregister callbacks for this PCB
lwipstack->__tcp_arg(conn->TCP_pcb, NULL);
@@ -413,7 +413,7 @@ void NetconEthernetTap::closeConnection(PhySocket *sock)
lwipstack->__tcp_poll(conn->TCP_pcb, NULL, 1);
}
else {
dwr(MSG_ERROR,"closeConnection(sock=%p): error while calling tcp_close()\n", (void*)&sock);
dwr(MSG_DEBUG_EXTRA,"closeConnection(sock=%p): error while calling tcp_close()\n", (void*)&sock);
}
}
for(size_t i=0;i<_Connections.size();++i) {
@@ -430,7 +430,7 @@ void NetconEthernetTap::closeConnection(PhySocket *sock)
}
void NetconEthernetTap::phyOnUnixClose(PhySocket *sock,void **uptr) {
dwr(MSG_DEBUG, "phyOnUnixClose(sock=%p):\n", (void*)&sock);
dwr(MSG_DEBUG_EXTRA, "phyOnUnixClose(sock=%p):\n", (void*)&sock);
Mutex::Lock _l(_tcpconns_m);
closeConnection(sock);
}
@@ -454,12 +454,13 @@ void NetconEthernetTap::processReceivedData(PhySocket *sock,void **uptr,bool lwi
if(conn->type==SOCK_DGRAM){
conn->unread_udp_packet = false;
_phy.setNotifyWritable(conn->sock, false);
dwr(MSG_TRANSFER,"UDP RX <--- :: {TX: ------, RX: ------, sock=%x} :: %d bytes\n", conn->sock, n);
}
//dwr(MSG_DEBUG, "phyOnUnixWritable(): tid = %d\n", pthread_mach_thread_np(pthread_self()));
if(conn->type==SOCK_STREAM) { // Only acknolwedge receipt of TCP packets
lwipstack->__tcp_recved(conn->TCP_pcb, n);
float max = conn->type == SOCK_STREAM ? (float)DEFAULT_TCP_TX_BUF_SZ : (float)DEFAULT_UDP_TX_BUF_SZ;
dwr(MSG_TRANSFER," RX <--- :: {TX: %.3f%%, RX: %.3f%%, sock=%x} :: %d bytes\n",
dwr(MSG_TRANSFER,"TCP RX <--- :: {TX: %.3f%%, RX: %.3f%%, sock=%x} :: %d bytes\n",
(float)conn->txsz / max, (float)conn->rxsz / max, conn->sock, n);
}
} else {
@@ -486,7 +487,7 @@ void NetconEthernetTap::phyOnUnixWritable(PhySocket *sock,void **uptr,bool lwip_
void NetconEthernetTap::phyOnUnixData(PhySocket *sock, void **uptr, void *data, ssize_t len)
{
dwr(MSG_DEBUG, "phyOnUnixData(%p), len = %d\n", (void*)&sock, len);
dwr(MSG_DEBUG_EXTRA, "phyOnUnixData(%p), len = %d\n", (void*)&sock, len);
uint64_t CANARY_num;
pid_t pid, tid;
ssize_t wlen = len;
@@ -642,13 +643,13 @@ void NetconEthernetTap::phyOnUnixData(PhySocket *sock, void **uptr, void *data,
}
int NetconEthernetTap::sendReturnValue(PhySocket *sock, int retval, int _errno = 0){
dwr(MSG_DEBUG," sendReturnValue(sock=%p)\n", (void*)&sock);
dwr(MSG_DEBUG_EXTRA," sendReturnValue(sock=%p)\n", (void*)&sock);
return sendReturnValue(_phy.getDescriptor(sock), retval, _errno);
}
int NetconEthernetTap::sendReturnValue(int fd, int retval, int _errno = 0)
{
//#if !defined(USE_SOCKS_PROXY)
dwr(MSG_DEBUG," sendReturnValue(): fd = %d, retval = %d, errno = %d\n", fd, retval, _errno);
dwr(MSG_DEBUG_EXTRA," sendReturnValue(): fd = %d, retval = %d, errno = %d\n", fd, retval, _errno);
int sz = sizeof(char) + sizeof(retval) + sizeof(errno);
char retmsg[sz];
memset(&retmsg, 0, sizeof(retmsg));
@@ -717,7 +718,8 @@ err_t NetconEthernetTap::nc_accept(void *arg, struct tcp_pcb *newPCB, err_t err)
tap->lwipstack->__tcp_sent(newPCB, nc_sent);
tap->lwipstack->__tcp_poll(newPCB, nc_poll, 1);
if(conn->TCP_pcb->state == LISTEN) {
dwr(MSG_DEBUG," nc_accept(): can't call tcp_accept() on LISTEN socket (pcb = %x)\n", conn->TCP_pcb);
// FIX: This error likely doesn't have user significance and is a candidate for removal
// dwr(MSG_DEBUG," nc_accept(): can't call tcp_accept() on LISTEN socket (pcb = %x)\n", conn->TCP_pcb);
return ERR_OK;
}
tcp_accepted(conn->TCP_pcb); // Let lwIP know that it can queue additional incoming connections
@@ -739,6 +741,12 @@ void NetconEthernetTap::nc_udp_recved(void * arg, struct udp_pcb * upcb, struct
if(p) {
l->conn->rxsz = 0;
memset(l->conn->rxbuf, 0, DEFAULT_UDP_RX_BUF_SZ);
// Add address info beginning of data buffer
u32_t raw_addr = ip4_addr_get_u32(addr);
memcpy(l->conn->rxbuf + (l->conn->rxsz), &raw_addr, sizeof(u32_t)); // addr
l->conn->rxsz += sizeof(u32_t);
memcpy(l->conn->rxbuf + (l->conn->rxsz), &port, sizeof(u16_t)); // port
l->conn->rxsz += sizeof(u16_t);
}
while(p != NULL) {
if(p->len <= 0)
@@ -750,7 +758,8 @@ void NetconEthernetTap::nc_udp_recved(void * arg, struct udp_pcb * upcb, struct
tot += len;
}
if(tot) {
dwr(MSG_DEBUG, " nc_udp_recved(): tot = %d, rxsz = %d\n", tot, l->conn->rxsz);
dwr(MSG_DEBUG, " nc_udp_recved(): data_len = %d, rxsz = %d, addr_info_len = %d\n",
tot, l->conn->rxsz, sizeof(u32_t) + sizeof(u16_t));
l->conn->unread_udp_packet = true;
l->tap->phyOnUnixWritable(l->conn->sock, NULL, true);
l->tap->_phy.setNotifyWritable(l->conn->sock, true);
@@ -1005,8 +1014,11 @@ void NetconEthernetTap::handleListen(PhySocket *sock, PhySocket *rpcSock, void *
Mutex::Lock _l(_tcpconns_m);
Connection *conn = getConnection(sock);
if(conn->type==SOCK_DGRAM)
if(conn->type==SOCK_DGRAM) {
// FIX: Added sendReturnValue() call to fix listen() return bug on Android
sendReturnValue(rpcSock, ERR_OK, ERR_OK);
return;
}
if(!conn) {
dwr(MSG_ERROR," handleListen(): unable to locate Connection.\n");
sendReturnValue(rpcSock, -1, EBADF);
@@ -1200,9 +1212,16 @@ void NetconEthernetTap::handleConnect(PhySocket *sock, PhySocket *rpcSock, Conne
Mutex::Lock _l(_tcpconns_m);
struct sockaddr_in *rawAddr = (struct sockaddr_in *) &connect_rpc->__addr;
int port = lwipstack->__lwip_ntohs(rawAddr->sin_port);
ip_addr_t connAddr = convert_ip(rawAddr);
int err = 0;
ip_addr_t connAddr = convert_ip(rawAddr);
int err = 0, ip = rawAddr->sin_addr.s_addr;
unsigned char d[4];
d[0] = ip & 0xFF;
d[1] = (ip >> 8) & 0xFF;
d[2] = (ip >> 16) & 0xFF;
d[3] = (ip >> 24) & 0xFF;
dwr(MSG_DEBUG," handleConnect(): %d.%d.%d.%d: %d\n", d[0],d[1],d[2],d[3], port);
if(conn->type == SOCK_DGRAM) {
// Generates no network traffic
if((err = lwipstack->__udp_connect(conn->UDP_pcb,&connAddr,port)) < 0)
@@ -1217,15 +1236,7 @@ void NetconEthernetTap::handleConnect(PhySocket *sock, PhySocket *rpcSock, Conne
lwipstack->__tcp_err(conn->TCP_pcb, nc_err);
lwipstack->__tcp_poll(conn->TCP_pcb, nc_poll, APPLICATION_POLL_FREQ);
lwipstack->__tcp_arg(conn->TCP_pcb, new Larg(this, conn));
int ip = rawAddr->sin_addr.s_addr;
unsigned char d[4];
d[0] = ip & 0xFF;
d[1] = (ip >> 8) & 0xFF;
d[2] = (ip >> 16) & 0xFF;
d[3] = (ip >> 24) & 0xFF;
dwr(MSG_DEBUG," handleConnect(): %d.%d.%d.%d: %d\n", d[0],d[1],d[2],d[3], port);
dwr(MSG_DEBUG," handleConnect(): pcb->state = %x\n", conn->TCP_pcb->state);
if(conn->TCP_pcb->state != CLOSED) {
dwr(MSG_DEBUG," handleConnect(): PCB != CLOSED, cannot connect using this PCB\n");
@@ -1316,13 +1327,13 @@ void NetconEthernetTap::handleWrite(Connection *conn)
} else if(err != ERR_OK) {
dwr(MSG_DEBUG, " handleWrite(): Error sending packet - %d\n", err);
} else {
// Success
int buf_remaining = (conn->txsz)-udp_trans_len;
if(buf_remaining)
memmove(&conn->txbuf, (conn->txbuf+udp_trans_len), buf_remaining);
conn->txsz -= udp_trans_len;
int max = conn->type == SOCK_STREAM ? DEFAULT_TCP_TX_BUF_SZ : DEFAULT_UDP_TX_BUF_SZ;
dwr(MSG_TRANSFER," TX ---> :: {TX: %.3f%%, RX: %.3f%%, sock=%x} :: %d bytes\n",
(float)conn->txsz / (float)max, (float)conn->rxsz / max, conn->sock, udp_trans_len);
dwr(MSG_TRANSFER,"UDP TX ---> :: {TX: ------, RX: ------, sock=%x} :: %d bytes\n", conn->sock, udp_trans_len);
}
lwipstack->__pbuf_free(pb);
return;
@@ -1370,7 +1381,7 @@ void NetconEthernetTap::handleWrite(Connection *conn)
memmove(&conn->txbuf, (conn->txbuf+r), sz);
conn->txsz -= r;
int max = conn->type == SOCK_STREAM ? DEFAULT_TCP_TX_BUF_SZ : DEFAULT_UDP_TX_BUF_SZ;
dwr(MSG_TRANSFER," TX ---> :: {TX: %.3f%%, RX: %.3f%%, sock=%p} :: %d bytes\n",
dwr(MSG_TRANSFER,"TCP TX ---> :: {TX: %.3f%%, RX: %.3f%%, sock=%p} :: %d bytes\n",
(float)conn->txsz / (float)max, (float)conn->rxsz / max, (void*)&conn->sock, r);
return;
}

View File

@@ -154,6 +154,8 @@ namespace ZeroTier {
void (*_handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int);
void *_arg;
int proxyListenPort;
private:
// LWIP callbacks
// NOTE: these are called from within LWIP, meaning that lwipstack->_lock is ALREADY
@@ -454,20 +456,14 @@ namespace ZeroTier {
*/
void closeConnection(PhySocket *sock);
// --- Proxy stubs
int proxyListenPort;
//std::map<int,PhySocket> proxySockStates;
// --- Proxy
int sockstate;
int proxyListenSocket;
PhySocket *proxyListenPhySocket;
void StartProxy(const char *sockpath, const char *homepath, uint64_t nwid);
void phyOnFileDescriptorActivity(PhySocket *sock,void **uptr,bool readable,bool writable);
// --- end Proxy stubs
// --- end Proxy
ip_addr_t convert_ip(struct sockaddr_in * addr)
{

View File

@@ -105,7 +105,7 @@ namespace ZeroTier
void ExtractAddress(int addr_type, unsigned char *buf, struct sockaddr_in * addr)
{
// TODO: Generalize extraction logic
if(addr_type == 3)
if(addr_type == 144)
{
// Extract address from buffer
int domain_len = buf[IDX_DST_ADDR]; // (L):D
@@ -216,8 +216,10 @@ namespace ZeroTier
// CONNECT request
if(cmd == 1) {
dwr(MSG_DEBUG, "CONNECT request\n");
// Ipv4
if(addr_type == 1)
/*
if(addr_type == 144)
{
//printf("IPv4\n");
int raw_addr;
@@ -235,20 +237,22 @@ namespace ZeroTier
struct sockaddr_in addr;
addr.sin_addr.s_addr = IPADDR_ANY;
addr.sin_family = AF_INET;
addr.sin_port = Utils::hton(proxyListenPort);
addr.sin_port = Utils::hton(8080);
int fd = socket(AF_INET, SOCK_STREAM, 0);
dwr(MSG_DEBUG, "fd = %d\n", fd);
if(fd < 0)
perror("socket");
int err = connect(fd, (struct sockaddr*)&addr, sizeof(addr));
dwr(MSG_DEBUG, "connect_err = %d\n", err);
if(err < 0)
perror("connect");
}
*/
// Fully-qualified domain name
if(addr_type == 3)
if(addr_type == 144)
{
int domain_len = buf[IDX_DST_ADDR]; // (L):D
struct sockaddr_in addr;

View File

@@ -112,8 +112,20 @@ void zts_leave_network(const char * nwid) { zt1Service->leave(nwid); }
bool zts_is_running() { return zt1Service->isRunning(); }
void zts_terminate() { zt1Service->terminate(); }
std::vector<std::string> zt_get_addresses(std::string nwid)
// FIXME: Re-implemented to make it play nicer with the C-linkage required for Xcode integrations
// Now only returns first assigned address per network. Shouldn't normally be a problem
void zts_get_addresses(const char * nwid, char *addrstr)
{
uint64_t nwid_int = strtoull(nwid, NULL, 16);
ZeroTier::NetconEthernetTap * tap = zt1Service->getTaps()[nwid_int];
if(tap && tap->_ips.size()){
std::string addr = tap->_ips[0].toString();
memcpy(addrstr, addr.c_str(), addr.length());
}
else {
memcpy(addrstr, "-1.-1.-1.-1/-1", 14);
}
/*
uint64_t nwid_int = strtoull(nwid.c_str(), NULL, 16);
ZeroTier::NetconEthernetTap * tap = zt1Service->getTaps()[nwid_int];
std::vector<std::string> ip_strings;
@@ -124,6 +136,18 @@ std::vector<std::string> zt_get_addresses(std::string nwid)
return ip_strings;
}
return ip_strings;
*/
}
bool zts_is_relayed() {
// TODO
// zt1Service->getNode()->peers()
return false;
}
int zts_get_proxy_port(const char * nwid) {
uint64_t nwid_int = strtoull(nwid, NULL, 16);
return zt1Service->getTaps()[nwid_int]->proxyListenPort;
}
@@ -153,12 +177,23 @@ std::vector<std::string> zt_get_addresses(std::string nwid)
if(zt1Service)
zts_terminate();
}
// FIXME: Re-implemented to make it play nicer with the C-linkage required for Xcode integrations
// Now only returns first assigned address per network. Shouldn't normally be a problem
JNIEXPORT jobject JNICALL Java_ZeroTier_SDK_zt_1get_1addresses(JNIEnv *env, jobject thisObj, jstring nwid) {
const char *nwid_str = env->GetStringUTFChars(nwid, NULL);
std::vector<std::string> address_strings = zt_get_addresses(nwid_str);
char address_string[32];
memset(address_string, 0, 32);
zts_get_addresses(nwid_str, address_string);
jclass clazz = (*env).FindClass("java/util/ArrayList");
jobject addresses = (*env).NewObject(clazz, (*env).GetMethodID(clazz, "<init>", "()V"));
jstring _str = (*env).NewStringUTF(address_string);
env->CallBooleanMethod(addresses, env->GetMethodID(clazz, "add", "(Ljava/lang/Object;)Z"), _str);
return addresses;
/*
const char *nwid_str = env->GetStringUTFChars(nwid, NULL);
std::vector<std::string> address_strings = zts_get_addresses(nwid_str);
jclass clazz = (*env).FindClass("java/util/ArrayList");
jobject addresses = (*env).NewObject(clazz, (*env).GetMethodID(clazz, "<init>", "()V"));
if(address_strings.size()) {
for (int n=0;n<address_strings.size();n++) {
jstring _str = (*env).NewStringUTF(address_strings[n].c_str());
@@ -170,7 +205,15 @@ std::vector<std::string> zt_get_addresses(std::string nwid)
env->CallBooleanMethod(addresses, env->GetMethodID(clazz, "add", "(Ljava/lang/Object;)Z"), _str);
}
return addresses;
*/
}
JNIEXPORT jboolean JNICALL Java_ZeroTier_SDK_zt_1is_1relayed() {
return zts_is_relayed();
}
JNIEXPORT int JNICALL Java_ZeroTier_SDK_zt_1get_1proxy_1port(JNIEnv *env, jobject thisObj, jstring nwid) {
const char *nwid_str = env->GetStringUTFChars(nwid, NULL);
return zts_get_proxy_port(nwid_str);
}
#endif

View File

@@ -33,7 +33,7 @@ extern "C" {
#include <jni.h>
#endif
#include <vector>
//#include <vector>
#ifndef ONE_SERVICE_SETUP_HPP
#define ONE_SERVICE_SETUP_HPP
@@ -50,6 +50,8 @@ extern "C" {
JNIEXPORT void JNICALL Java_ZeroTier_SDK_zt_1leave_1network(JNIEnv *env, jobject thisObj, jstring nwid);
JNIEXPORT jboolean JNICALL Java_ZeroTier_SDK_zt_1running(JNIEnv *env, jobject thisObj);
JNIEXPORT jobject JNICALL Java_ZeroTier_SDK_zt_1get_1addresses(JNIEnv *env, jobject thisObj, jstring nwid);
JNIEXPORT jboolean JNICALL Java_ZeroTier_SDK_zt_1is_1relayed();
JNIEXPORT int JNICALL Java_ZeroTier_SDK_zt_1get_1proxy_1port(JNIEnv *env, jobject thisObj, jstring nwid);
#else
void init_service(int key, const char * path);
void init_service_and_rpc(int key, const char * path, const char * nwid);
@@ -67,7 +69,10 @@ void zts_join_network(const char * nwid);
void zts_leave_network(const char * nwid);
bool zts_is_running();
void zts_terminate();
std::vector<std::string> zt_get_addresses(std::string nwid);
void zts_get_addresses(const char * nwid, char * addrstr);
//std::vector<std::string> zts_get_addresses(std::string nwid);
bool zts_is_relayed();
int zts_get_proxy_port(const char * nwid);
#endif

View File

@@ -36,7 +36,7 @@
#define SENDMSG_SIG int socket, const struct msghdr *message, int flags
#define SENDTO_SIG int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addr_len
#define RECV_SIG int socket, void *buffer, size_t length, int flags
#define RECVFROM_SIG int socket, void * buffer, size_t length, int flags, struct sockaddr * __restrict address, socklen_t * __restrict address_len
#define RECVFROM_SIG int socket, void * buffer, size_t length, int flags, struct sockaddr_in * __restrict address, socklen_t * __restrict address_len
#define RECVMSG_SIG int socket, struct msghdr *message,int flags
#define SEND_SIG int socket, const void *buffer, size_t length, int flags

View File

@@ -127,14 +127,41 @@ int (*realclose)(CLOSE_SIG);
// int sockfd, const void *buf, size_t len, int flags,
// const struct sockaddr *addr, socklen_t addr_len
#if !defined(__ANDROID__)
#if defined(__ANDROID__)
// TODO: Check result of each JNI call
// UDP TX
JNIEXPORT jint JNICALL Java_ZeroTier_SDK_zt_1sendto(
JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len, jint flags, jobject ztaddr)
{
struct sockaddr_in addr;
jclass cls = (*env)->GetObjectClass(env, ztaddr);
jfieldID f = (*env)->GetFieldID(env, cls, "port", "I");
addr.sin_port = htons((*env)->GetIntField(env, ztaddr, f));
f = (*env)->GetFieldID(env, cls, "_rawAddr", "J");
addr.sin_addr.s_addr = (*env)->GetLongField(env, ztaddr, f);
addr.sin_family = AF_INET;
LOGV("zt_sendto(): fd = %d\naddr = %s\nport=%d", fd, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
// TODO: Optimize this
jbyte *body = (*env)->GetByteArrayElements(env, buf, 0);
char * bufp = (char *)malloc(sizeof(char)*len);
memcpy(bufp, body, len);
(*env)->ReleaseByteArrayElements(env, buf, body, 0);
// "connect" and send buffer contents
int sent_bytes = zts_sendto(fd, body, len, flags, (struct sockaddr *)&addr, sizeof(addr));
return sent_bytes;
}
#endif
//#if !defined(__ANDROID__)
#ifdef DYNAMIC_LIB
ssize_t zt_sendto(SENDTO_SIG) // Exposed as API
#else
ssize_t zts_sendto(SENDTO_SIG) // Used as internal implementation
#endif
{
dwr(MSG_DEBUG, "zt_sendto()\n");
LOGV("zt_sendto()\n");
if(len > ZT_UDP_DEFAULT_PAYLOAD_MTU) {
errno = EMSGSIZE; // Msg is too large
return -1;
@@ -162,14 +189,14 @@ int (*realclose)(CLOSE_SIG);
// TODO: More efficient solution
// This connect call is used to get the address info to the stack for sending the packet
int err;
if((err = connect(sockfd, addr, addr_len)) < 0) {
dwr(MSG_DEBUG, "sendto(): unknown problem passing address info to stack\n");
if((err = zts_connect(sockfd, addr, addr_len)) < 0) {
LOGV("sendto(): unknown problem passing address info to stack\n");
errno = EISCONN; // double-check this is correct
return -1;
}
return send(sockfd, buf, len, flags);
return write(sockfd, buf, len);
}
#endif
//#endif
// ------------------------------------------------------------------------------
// ----------------------------------- sendmsg() --------------------------------
@@ -216,7 +243,28 @@ int (*realclose)(CLOSE_SIG);
// int socket, void *restrict buffer, size_t length, int flags, struct sockaddr
// *restrict address, socklen_t *restrict address_len
#if !defined(__ANDROID__)
#if defined(__ANDROID__)
// UDP RX
JNIEXPORT jint JNICALL Java_ZeroTier_SDK_zt_1recvfrom(
JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len, jint flags, jobject ztaddr)
{
struct sockaddr_in addr;
dwr(MSG_DEBUG, "zt_recvfrom(): fd = %d\n", fd);
jbyte *body = (*env)->GetByteArrayElements(env, buf, 0);
int recvd_bytes = zts_recvfrom(fd, body, len, flags, &addr, sizeof(addr));
(*env)->ReleaseByteArrayElements(env, buf, body, 0);
// Update fields of Java ZTAddress object
jfieldID fid;
jclass cls = (*env)->GetObjectClass(env, ztaddr);
fid = (*env)->GetFieldID(env, cls, "port", "I");
(*env)->SetIntField(env, ztaddr, fid, addr.sin_port);
fid = (*env)->GetFieldID(env, cls,"_rawAddr", "J");
(*env)->SetLongField(env, ztaddr, fid,addr.sin_addr.s_addr);
return recvd_bytes;
}
#endif
//#if !defined(__ANDROID__)
#ifdef DYNAMIC_LIB
ssize_t zt_recvfrom(RECVFROM_SIG)
#else
@@ -233,14 +281,24 @@ int (*realclose)(CLOSE_SIG);
realgetsockopt(socket, SOL_SOCKET, SO_TYPE, (void *) &sock_type, &type_len);
*/
//if(sock_type == SOCK_DGRAM && address != NULL && address_len != NULL) {
zts_getsockname(socket, address, address_len);
//zts_getsockname(socket, address, address_len);
//}
// TODO: Explore more efficient means of adjusting buffer
unsigned short port;
unsigned int addr;
err = read(socket, buffer, length);
int addr_info_len = sizeof(addr) + sizeof(port);
memcpy(&addr, buffer, sizeof(addr));
memcpy(&port, buffer + sizeof(addr), sizeof(port));
memmove(buffer, (buffer + addr_info_len), err - addr_info_len);
address->sin_addr.s_addr = addr;
address->sin_port = port;
// zts_getsockname(socket, address, address_len);
if(err < 0)
perror("read:\n");
return err;
return err < 0 ? err : err - addr_info_len; // Adjust reported buffer size to exclude address info
}
#endif
//#endif
// ------------------------------------------------------------------------------
// ----------------------------------- recvmsg() --------------------------------
@@ -311,7 +369,7 @@ int (*realclose)(CLOSE_SIG);
// ------------------------------------------------------------------------------
#if defined(__ANDROID__)
// TX
// TCP TX
JNIEXPORT jint JNICALL Java_ZeroTier_SDK_zt_1write(JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len)
{
jbyte *body = (*env)->GetByteArrayElements(env, buf, 0);
@@ -319,14 +377,14 @@ int (*realclose)(CLOSE_SIG);
(*env)->ReleaseByteArrayElements(env, buf, body, 0);
return written_bytes;
}
// RX
// TCP RX
JNIEXPORT jint JNICALL Java_ZeroTier_SDK_zt_1read(JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len)
{
jbyte *body = (*env)->GetByteArrayElements(env, buf, 0);
int read_bytes = read(fd, body, len);
(*env)->ReleaseByteArrayElements(env, buf, body, 0);
return read_bytes;
}
}
#endif
// ------------------------------------------------------------------------------
@@ -657,20 +715,36 @@ int (*realclose)(CLOSE_SIG);
struct getsockname_st rpc_st;
rpc_st.sockfd = sockfd;
memcpy(&rpc_st.addrlen, &addrlen, sizeof(socklen_t));
LOGV("A\n");
int rpcfd = rpc_send_command(api_netpath, RPC_GETSOCKNAME, sockfd, &rpc_st, sizeof(struct getsockname_st));
LOGV("b\n");
/* read address info from service */
char addrbuf[sizeof(struct sockaddr_storage)];
LOGV("c\n");
memset(&addrbuf, 0, sizeof(struct sockaddr_storage));
LOGV("d\n");
if(rpcfd > -1)
if(read(rpcfd, &addrbuf, sizeof(struct sockaddr_storage)) > 0)
close(rpcfd);
LOGV("e\n");
struct sockaddr_storage sock_storage;
memcpy(&sock_storage, addrbuf, sizeof(struct sockaddr_storage));
LOGV("Afn");
*addrlen = sizeof(struct sockaddr_in);
memcpy(addr, &sock_storage, (*addrlen > sizeof(sock_storage)) ? sizeof(sock_storage) : *addrlen);
LOGV("g\n");
addr->sa_family = AF_INET;
LOGV("h-\n");
return 0;
}