All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.questdb.network.Net Maven / Gradle / Ivy

/*******************************************************************************
 *     ___                  _   ____  ____
 *    / _ \ _   _  ___  ___| |_|  _ \| __ )
 *   | | | | | | |/ _ \/ __| __| | | |  _ \
 *   | |_| | |_| |  __/\__ \ |_| |_| | |_) |
 *    \__\_\\__,_|\___||___/\__|____/|____/
 *
 *  Copyright (c) 2014-2019 Appsicle
 *  Copyright (c) 2019-2023 QuestDB
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 ******************************************************************************/

package io.questdb.network;

import io.questdb.log.Log;
import io.questdb.log.LogFactory;
import io.questdb.std.*;
import io.questdb.std.str.CharSinkBase;
import io.questdb.std.str.LPSZ;
import io.questdb.std.str.Path;
import io.questdb.std.str.StdoutSink;

import java.util.concurrent.atomic.AtomicInteger;

public final class Net {

    @SuppressWarnings("unused")
    public static final int EOTHERDISCONNECT = -2;
    @SuppressWarnings("unused")
    public static final int EPEERDISCONNECT = -1;
    @SuppressWarnings("unused")
    public static final int ERETRY = 0;
    public static final int EWOULDBLOCK;
    public static final long MMSGHDR_BUFFER_ADDRESS_OFFSET;
    public static final long MMSGHDR_BUFFER_LENGTH_OFFSET;
    public static final long MMSGHDR_SIZE;
    public static final int SHUT_WR = 1;
    private static final AtomicInteger ADDR_INFO_COUNTER = new AtomicInteger();
    private static final Log LOG = LogFactory.getLog(Net.class);
    private static final AtomicInteger SOCK_ADDR_COUNTER = new AtomicInteger();
    // TCP KeepAlive not meant to be configurable. It's a last resort measure to disable/change keepalive if the default
    // value causes problems in some environments. If it does not cause problems then this option should be removed after a few releases.
    // It's not exposed as PropertyKey, because it would become a supported and hard to remove API.
    private static final int TCP_KEEPALIVE_SECONDS = Integer.getInteger("questdb.unsupported.tcp.keepalive.seconds", 30);

    private Net() {
    }

    /**
     * Aborts blocking accept() call. On Darwin and Windows
     * this method simply closes the underlying file descriptor.
     * On Linux this method calls shutdown().
     * 

* Once accept() exists it is by convention liable for * closing its own file descriptor. * * @param fd file descriptor * @return 0 when call was successful and -1 otherwise. In case of * error errno() would return error code. */ public static native int abortAccept(int fd); public static int accept(int serverFd) { return Files.bumpFileCount(accept0(serverFd)); } public static void appendIP4(CharSinkBase sink, long ip) { sink.put((ip >> 24) & 0xff).putAscii('.') .put((ip >> 16) & 0xff).putAscii('.') .put((ip >> 8) & 0xff).putAscii('.') .put(ip & 0xff); } public native static boolean bindTcp(int fd, int ipv4address, int port); public static boolean bindTcp(int fd, CharSequence ipv4address, int port) { return bindTcp(fd, parseIPv4(ipv4address), port); } public native static boolean bindUdp(int fd, int ipv4Address, int port); public static void bumpFdCount(int fd) { Files.bumpFileCount(fd); } public static int close(int fd) { return Files.close(fd); } public static void configureKeepAlive(int fd) { if (TCP_KEEPALIVE_SECONDS < 0 || fd < 0) { return; } if (setKeepAlive0(fd, TCP_KEEPALIVE_SECONDS) < 0) { int errno = Os.errno(); LOG.error().$("could not set tcp keepalive [fd=").$(fd).$(", errno=").$(errno).I$(); } } public native static int configureLinger(int fd, int seconds); public static int configureNoLinger(int fd) { return configureLinger(fd, 0); } public static native int configureNonBlocking(int fd); public native static int connect(int fd, long sockaddr); public native static int connectAddrInfo(int fd, long lpAddrInfo); public static void dump(long buffer, int len) { if (len > 0) { for (int i = 0; i < len; i++) { Numbers.appendHex(StdoutSink.INSTANCE, Unsafe.getUnsafe().getByte(buffer + i) & 0xff); } StdoutSink.INSTANCE.put('\n'); StdoutSink.INSTANCE.flush(); } } @SuppressWarnings("unused") public static void dumpAscii(long buffer, int len) { if (len > 0) { for (int i = 0; i < len; i++) { char c = (char) (Unsafe.getUnsafe().getByte(buffer + i) & 0xff); switch (c) { case '\r': System.out.print("\\r"); break; case '\n': System.out.print("\\n"); System.out.print(c); break; default: System.out.print(c); break; } } } } public static void freeAddrInfo(long pAddrInfo) { if (pAddrInfo != 0) { ADDR_INFO_COUNTER.decrementAndGet(); } freeAddrInfo0(pAddrInfo); } public static native void freeMsgHeaders(long msgHeaders); public static void freeSockAddr(long sockaddr) { if (sockaddr != 0) { SOCK_ADDR_COUNTER.decrementAndGet(); } freeSockAddr0(sockaddr); } public static long getAddrInfo(LPSZ host, int port) { return getAddrInfo(host.ptr(), port); } public static long getAddrInfo(CharSequence host, int port) { try (Path p = new Path().of(host).$()) { return getAddrInfo(p, port); } } public static long getAddrInfo(long lpszHost, int port) { long addrInfo = getAddrInfo0(lpszHost, port); if (addrInfo != -1) { ADDR_INFO_COUNTER.incrementAndGet(); } return addrInfo; } public static int getAllocatedAddrInfoCount() { return ADDR_INFO_COUNTER.get(); } public static int getAllocatedSockAddrCount() { return SOCK_ADDR_COUNTER.get(); } public static long getMMsgBuf(long msgPtr) { return Unsafe.getUnsafe().getLong(Unsafe.getUnsafe().getLong(msgPtr + MMSGHDR_BUFFER_ADDRESS_OFFSET)); } public static int getMMsgBufLen(long msgPtr) { return Unsafe.getUnsafe().getInt(msgPtr + MMSGHDR_BUFFER_LENGTH_OFFSET); } public native static int getPeerIP(int fd); public native static int getPeerPort(int fd); public native static int getRcvBuf(int fd); public native static int getSndBuf(int fd); public native static int getTcpNoDelay(int fd); /** * This method reads 1 byte (or none if the socket is non-blocking and there is no data). * If there is no error (EOF ?) then it returns false * If there is an error (EOF ?) then it returns true * * @param fd network file descriptor * @return check the description */ public static native boolean isDead(int fd); public static boolean join(int fd, CharSequence bindIPv4Address, CharSequence groupIPv4Address) { return join(fd, parseIPv4(bindIPv4Address), parseIPv4(groupIPv4Address)); } public native static boolean join(int fd, int bindIPv4Address, int groupIPv4Address); public native static void listen(int fd, int backlog); public static native long msgHeaders(int blockSize, int count); public static int parseIPv4(CharSequence ipv4Address) { int ip = 0; int count = 0; int lo = 0; int hi; try { while ((hi = Chars.indexOf(ipv4Address, lo, '.')) > -1) { int n = Numbers.parseInt(ipv4Address, lo, hi); ip = (ip << 8) | n; count++; lo = hi + 1; } if (count != 3) { throw NetworkError.instance(0, "invalid address [").put(ipv4Address).put(']'); } return (ip << 8) | Numbers.parseInt(ipv4Address, lo, ipv4Address.length()); } catch (NumericException e) { throw NetworkError.instance(0, "invalid address [").put(ipv4Address).put(']'); } } public static native int peek(int fd, long ptr, int len); public static native int recv(int fd, long ptr, int len); public static native int recvmmsg(int fd, long msgvec, int vlen); public native static int resolvePort(int fd); public static native int send(int fd, long ptr, int len); public native static int sendTo(int fd, long ptr, int len, long sockaddr); public native static int setMulticastInterface(int fd, int ipv4address); public native static int setMulticastLoop(int fd, boolean loop); public native static int setMulticastTtl(int fd, int ttl); public native static int setRcvBuf(int fd, int size); public native static int setReuseAddress(int fd); public native static int setReusePort(int fd); public native static int setSndBuf(int fd, int size); public native static int setTcpNoDelay(int fd, boolean noDelay); public native static int shutdown(int fd, int how); public static long sockaddr(CharSequence ipv4address, int port) { return sockaddr(parseIPv4(ipv4address), port); } public static long sockaddr(int ipv4address, int port) { SOCK_ADDR_COUNTER.incrementAndGet(); return sockaddr0(ipv4address, port); } public static int socketTcp(boolean blocking) { return Files.bumpFileCount(socketTcp0(blocking)); } public static int socketUdp() { return Files.bumpFileCount(socketUdp0()); } private native static int accept0(int serverFd); private static native void freeAddrInfo0(long pAddrInfo); private static native void freeSockAddr0(long sockaddr); private static native long getAddrInfo0(long lpszHost, int port); private native static int getEwouldblock(); private static native long getMsgHeaderBufferAddressOffset(); private static native long getMsgHeaderBufferLengthOffset(); private static native long getMsgHeaderSize(); private static native int setKeepAlive0(int fd, int seconds); private native static long sockaddr0(int ipv4address, int port); private native static int socketTcp0(boolean blocking); private native static int socketUdp0(); static { Os.init(); EWOULDBLOCK = getEwouldblock(); if (Os.isLinux()) { MMSGHDR_SIZE = getMsgHeaderSize(); MMSGHDR_BUFFER_ADDRESS_OFFSET = getMsgHeaderBufferAddressOffset(); MMSGHDR_BUFFER_LENGTH_OFFSET = getMsgHeaderBufferLengthOffset(); } else { MMSGHDR_SIZE = -1L; MMSGHDR_BUFFER_ADDRESS_OFFSET = -1L; MMSGHDR_BUFFER_LENGTH_OFFSET = -1L; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy