mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-01-17 18:29:46 +00:00
c8bf8a7733
The CLI and server main loop now have no conditional JNI code. All JNI code has been moved into separate source files, which #include the new "jni_common.h" instead of <jni.h>. The "cli.h" header no longer includes <jni.h>, so the rest of the Serval source code is now unaffected by JNI definitions. The 'cf_limbo' global variable is now thread-local, so that each thread has its own independent copy of the loaded configuration. The JNI server entry point now calls cf_init() once. The new 'cf_initialised' flag prevents clobbering the config state by redundant calls to cf_init(). The CLI "stop" command now sends SIGHUP to the specific thread in which the server is running. This is achieved by writing the PID and TID (Linux Thread ID) into the pidfile, separated by a space, on systems that support the Linux gettid() and tgkill() system calls. The server's signal handler has been overhauled, and its logging improved.
149 lines
4.3 KiB
Java
149 lines
4.3 KiB
Java
/**
|
|
* Copyright (C) 2016 Flinders University
|
|
* Copyright (C) 2014 Serval Project Inc.
|
|
*
|
|
* This file is part of Serval Software (http://www.servalproject.org)
|
|
*
|
|
* Serval Software is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This source code is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this source code; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
package org.servalproject.servaldna;
|
|
|
|
import java.nio.BufferUnderflowException;
|
|
import java.nio.ByteBuffer;
|
|
|
|
public abstract class AbstractId {
|
|
|
|
abstract int getBinarySize();
|
|
|
|
public static class InvalidHexException extends Exception {
|
|
private static final long serialVersionUID = 1L;
|
|
|
|
private InvalidHexException(AbstractId id, String message) {
|
|
super(id.getClass().getName() + ": " + message);
|
|
}
|
|
}
|
|
|
|
public static class InvalidBinaryException extends Exception {
|
|
private static final long serialVersionUID = 1L;
|
|
|
|
private InvalidBinaryException(AbstractId id, String message) {
|
|
super(id.getClass().getName() + ": " + message);
|
|
}
|
|
}
|
|
|
|
private final byte[] binary;
|
|
|
|
public byte[] getBinary(){
|
|
//TODO always copy bytes so they can't be tampered with?
|
|
return binary;
|
|
}
|
|
|
|
public abstract String getMimeType();
|
|
|
|
public AbstractId(String hex) throws InvalidHexException {
|
|
if (hex==null)
|
|
throw new InvalidHexException(this, "null is not a invalid hex value");
|
|
if (hex.length() != getBinarySize()*2)
|
|
throw new InvalidHexException(this, "invalid length " + hex.length() + " (should be " + (getBinarySize() * 2) + ") of '" + hex + "'");
|
|
binary = new byte[getBinarySize()];
|
|
int j = 0;
|
|
for (int i = 0; i != binary.length; i++) {
|
|
int d1 = Character.digit(hex.charAt(j++), 16);
|
|
int d2 = Character.digit(hex.charAt(j++), 16);
|
|
if (d1 == -1 || d2 == -1)
|
|
throw new InvalidHexException(this, "non-hex digit in '" + hex + "'");
|
|
binary[i] = (byte) ((d1 << 4) | d2);
|
|
}
|
|
}
|
|
|
|
public AbstractId(ByteBuffer b) throws InvalidBinaryException {
|
|
this.binary = new byte[getBinarySize()];
|
|
try {
|
|
b.get(this.binary);
|
|
}
|
|
catch (BufferUnderflowException e) {
|
|
throw new InvalidBinaryException(this, "not enough bytes (expecting " + getBinarySize() + ")");
|
|
}
|
|
}
|
|
|
|
public AbstractId(byte[] binary) throws InvalidBinaryException {
|
|
if (binary.length != getBinarySize())
|
|
throw new InvalidBinaryException(this, "invalid number of bytes (" + binary.length + "), should be " + getBinarySize());
|
|
this.binary = binary;
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object other) {
|
|
// must be the exact same type with the same binary contents to be considered equal
|
|
if (other==null)
|
|
return false;
|
|
if (other==this)
|
|
return true;
|
|
if (other.getClass() == this.getClass()) {
|
|
AbstractId oBinary = (AbstractId) other;
|
|
for (int i = 0; i < this.binary.length; i++)
|
|
if (this.binary[i] != oBinary.binary[i])
|
|
return false;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
int hashCode = 0;
|
|
for (int i = 0; i < this.binary.length; i++)
|
|
hashCode = (hashCode << 8 | hashCode >>> 24) ^ this.binary[i];
|
|
return hashCode;
|
|
}
|
|
|
|
public void toByteBuffer(ByteBuffer buff){
|
|
buff.put(this.binary);
|
|
}
|
|
|
|
public static String toHex(byte[] binary) {
|
|
return toHex(binary, 0, binary.length);
|
|
}
|
|
|
|
public static String toHex(byte[] binary, int offset, int len) {
|
|
StringBuilder sb = new StringBuilder();
|
|
for (int i = offset; i < offset + len && i < binary.length; i++) {
|
|
sb.append(Character.forDigit(((binary[i]) & 0xf0) >> 4, 16));
|
|
sb.append(Character.forDigit((binary[i]) & 0x0f, 16));
|
|
}
|
|
return sb.toString().toUpperCase();
|
|
}
|
|
|
|
public String toHex(int len) {
|
|
return toHex(binary, 0, len);
|
|
}
|
|
|
|
public String toHex() {
|
|
return toHex(binary, 0, binary.length);
|
|
}
|
|
|
|
public String abbreviation() {
|
|
return toHex(binary, 0, 4);
|
|
}
|
|
|
|
|
|
@Override
|
|
public String toString() {
|
|
return toHex();
|
|
}
|
|
|
|
}
|