Missing value in SNMP - java

I use snmp4j ver 1.10.1 from org.snmp4j and this is my trap receiver code to catch data from snmp trap.
public class TrapReceiver extends Thread implements CommandResponder {
//#Autowired
private CarService carService;
List<PDUv1> listPdu = new ArrayList<PDUv1>();
List<PDUv1> temp = new ArrayList<PDUv1>();
String message = "";
int totReceivedTrap = 0;
public TrapReceiver(CarService carService){
this.carService = carService;
}
public synchronized void processPdu(CommandResponderEvent cmdRespEvent) {
PDUv1 pdu = (PDUv1) cmdRespEvent.getPDU();
if (pdu != null) {
System.out.println(pdu.getVariableBindings().toString());
}
totReceivedTrap++;
System.out.println("total received trap "+totReceivedTrap);
}
public void run() {
while (true) {
try {
this.listen(new UdpAddress("192.168.1.5/162")); //alamat PDU akan listen
} catch (Exception e) {
e.printStackTrace();
}
}
}
public synchronized void listen(TransportIpAddress address) throws IOException {
AbstractTransportMapping transport;
if (address instanceof TcpAddress) {
transport = new DefaultTcpTransportMapping((TcpAddress) address);
} else {
transport = new DefaultUdpTransportMapping((UdpAddress) address);
}
ThreadPool threadPool = ThreadPool.create("DispatcherPool", 10);
MessageDispatcher mDispathcher = new MultiThreadedMessageDispatcher(
threadPool, new MessageDispatcherImpl());
// add message processing models
mDispathcher.addMessageProcessingModel(new MPv1());
mDispathcher.addMessageProcessingModel(new MPv2c());
// add all security protocols
SecurityProtocols.getInstance().addDefaultProtocols();
SecurityProtocols.getInstance().addPrivacyProtocol(new Priv3DES());
// Create Target
CommunityTarget target = new CommunityTarget();
target.setCommunity(new OctetString("public"));
Snmp snmp = new Snmp(mDispathcher, transport);
snmp.addCommandResponder(this);
transport.listen();
message ="Listening on " + address;
System.out.println(message);
try {
this.wait();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
public String getMessage(){
return this.message;
}
}
But one variable value is missing, the value of this variable is latitude and longitude (format : -903849323.20384;+230349402.03000). And when i catch the data using wireshark, I got the value is missing too.
The screenshot
http://www.mediafire.com/view/?kjz1drb9jhda88a
http://www.mediafire.com/view/?ov6lqn6u9n669my
Why the data is null, what wrong.

If you do not see the value inside the packet captured by wireshark, then it is completely valid that you get the null value in the code. What else would you expect?
This seems to be more likely a problem/feature of the SNMP agent running on the device (e.g. geo location was not set, GPS signal is not available, etc.)

Related

Why does client not receive final server answer in non-blocking client-server app?

I am trying to figure out NIO in Java doing some simple client-server project.
The case is I have to concurrent clients in cached thread pool executor, who are communicating with single-threaded server using non-blocking NIO channels.
The problem is that last client cannot receive last server's sent message. It locks in infinite loop waiting for upcoming data.
ClientTask class:
public class ClientTask extends FutureTask<String> {
private Client client;
private List<String> reqList; // requests list (without last and first)
private boolean showRes; // print request results
public ClientTask(Client client, List<String> reqList, boolean showRes) {
super(() -> ClientTask.getLogWhenArrives(client, reqList, showRes));
this.client = client;
this.reqList = reqList;
this.showRes = showRes;
}
public static ClientTask create(Client c, List<String> reqList, boolean showRes) {
return new ClientTask(c, reqList, showRes);
}
private static String getLogWhenArrives(Client client, List<String> reqList, boolean showRes) {
client.connect();
String response = client.send("login " + client.getId());
if (showRes) System.out.println(response);
for (String req : reqList) {
response = client.send(req);
if (showRes) System.out.println(response);
}
String responseLog = client.send("bye and log transfer");
client.close();
return responseLog;
}
}
Client send():
public String send(String req) {
ByteBuffer reqBuffer = ByteBuffer.wrap((req + END).getBytes());
try {
channel.write(reqBuffer);
} catch (IOException e) {
e.printStackTrace();
}
return receive();
}
Client receive()
public String receive() {
StringBuilder result = new StringBuilder();
try {
inBuff.clear();
readLoop:
while (true) { // THIS LOOP WON'T END
int n = channel.read(inBuff);
if (n == -1) {
break;
}
if (n > 0) {
inBuff.flip();
CharBuffer cb = charset.decode(inBuff);
while (cb.hasRemaining()) {
char c = cb.get();
if (c == END.charAt(0)) {
break readLoop;
}
result.append(c);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
return result.toString();
}
Main:
public class Main {
public static void main(String[] args) throws Exception {
String fileName = System.getProperty("user.home") + "/PassTimeServerOptions.yaml";
Options opts = Tools.createOptionsFromYaml(fileName);
String host = opts.getHost();
int port = opts.getPort();
boolean concur = opts.isConcurMode();
boolean showRes = opts.isShowSendRes();
Map<String, List<String>> clRequests = opts.getClientsMap();
ExecutorService es = Executors.newCachedThreadPool();
List<ClientTask> ctasks = new ArrayList<>();
List<String> clogs = new ArrayList<>();
Server s = new Server(host, port);
s.startServer();
// start clients
clRequests.forEach( (id, reqList) -> {
Client c = new Client(host, port, id);
if (concur) {
ClientTask ctask = ClientTask.create(c, reqList, showRes);
ctasks.add(ctask);
es.execute(ctask);
}
});
if (concur) {
ctasks.forEach( task -> {
try {
String log = task.get();
clogs.add(log);
} catch (InterruptedException | ExecutionException exc) {
System.out.println(exc);
}
});
clogs.forEach( System.out::println);
es.shutdown();
}
s.stopServer();
System.out.println("\n=== Server log ===");
System.out.println(s.getServerLog());
}
}
Server is sending all the info and channels are open and connected.

Java two threads work with the same data (one get, one set)

I'm taking my first steps with Java Sockets and Threads.
I want to try make synchonized connection with serwer where multiple threades adds their request to the queue and signle thread send all this request. In the meantime other threads wait for there resoults.
How it's work:
Client ask servert to log in by caling method
User user = logIn("sdasd");
public User logIn(String name){
System.out.println("!Log in");
//Function create request
RequestHandler<User> request = new RequestHandler<>("logIn", name, out, results);
//Request is added to queue
requestQueue.addLast(request);
RequestStatus status;
//Thread who call this function wait for request to be handle (changed status)
while (true){
status = request.getStatus();
System.out.println(status);
if (status == RequestStatus.SUCCESSFUL) {
System.out.println("Try to get result: ");
User user = request.result();
System.out.println(user.getName());
return request.result();
}
if(status == RequestStatus.FAILED) {
return null;
}
}
}
In the meantime other thread send request to server:
new Thread(new Runnable() {
#Override
public void run() {
while(isConnected()){
//is request to be handle?
if(requestQueue.size() != 0){
//remove request form queue
RequestHandler request = (RequestHandler) requestQueue.removeFirst();
//change request status
request.setStatus(RequestStatus.IN_PROGRESS);
System.out.println("!Request: ");
System.out.println(request.getStatus());
//process request
request.request();
//change request status to finished
request.setStatus(RequestStatus.SUCCESSFUL);
System.out.print("!Request end: ");
System.out.println(request.getStatus());
}
}
Iterator<Request> iterator = requestQueue.iterator();
for (Iterator<Request> it = iterator; it.hasNext(); ) {
Request request = it.next();
request.setStatus(RequestStatus.FAILED);
}
}
}).start();
Inside class RequestHandler is process this code:
#Override
public void request() {
try {
//send commend
out.writeObject(requestCommend);
//wait for result (other thread handle this functionality)
while(!results.containsKey(commend)){}
//attach result
result = (T) results.remove(commend);
} catch (IOException e) {
e.printStackTrace();
}
}
When the request is send to the server other thread wait for response for the server and add result to the HashMap:
new Thread(new Runnable() {
#Override
public void run() {
while(isConnected()) {
try {
String commend = (String) in.readObject();
if(commend.charAt(0) == '#') { // # mean its result of request
Object object = in.readObject();
//This is debug case to see everything work properly
if(object == null){
System.out.println("!I am null");
}else{
System.out.println("I am user: " +((User) object).getName());
}
System.out.println(commend);
results.put(commend, object);
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}).start();
This is it. Required code for this question:
public class ServerConnection extends Socket{
public static final int PORT = 8888;
private ObjectInputStream in;
private ObjectOutputStream out;
private LinkedList<Request> requestQueue;
private ConcurrentHashMap<String, Object> results;
public ServerConnection() throws IOException{
super("localhost", PORT);
System.out.println("Connected to the server.");
in = new ObjectInputStream(getInputStream());
out = new ObjectOutputStream(getOutputStream());
requestQueue = new LinkedList<>();
results = new ConcurrentHashMap<>();
new Thread(new Runnable() {
#Override
public void run() {
while(isConnected()){
if(requestQueue.size() != 0){
RequestHandler request = (RequestHandler) requestQueue.removeFirst();
request.setStatus(RequestStatus.IN_PROGRESS);
System.out.println("!Request: ");
System.out.println(request.getStatus());
request.request();
request.setStatus(RequestStatus.SUCCESSFUL);
System.out.print("!Request end: ");
System.out.println(request.getStatus());
}
}
Iterator<Request> iterator = requestQueue.iterator();
for (Iterator<Request> it = iterator; it.hasNext(); ) {
Request request = it.next();
request.setStatus(RequestStatus.FAILED);
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
while(isConnected()) {
try {
String commend = (String) in.readObject();
if(commend.charAt(0) == '#') { // # mean its result of request
Object object = in.readObject();
//This is debug case
if(object == null){
System.out.println("!I am null");
}else{
System.out.println("I am user: " +((User) object).getName());
}
System.out.println(commend);
results.put(commend, object);
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}).start();
}
public User logIn(String name){
System.out.println("!Log in");
RequestHandler<User> request = new RequestHandler<>("logIn", name, out, results);
requestQueue.addLast(request);
RequestStatus status;
while (true){
status = request.getStatus();
System.out.println(status);
if (status == RequestStatus.SUCCESSFUL) {
System.out.println("Try to get result: ");
User user = request.result();
System.out.println(user.getName());
return request.result();
}
if(status == RequestStatus.FAILED) {
return null;
}
}
}
public ArrayList<Room> getListOfRooms(){
Request<ArrayList<Room>> request = new RequestHandler<>("listOfRooms", out, results);
requestQueue.addLast(request);
while (true){
RequestStatus status = request.getStatus();
if (status == RequestStatus.SUCCESSFUL)
return request.result();
if(status == RequestStatus.FAILED) {
return null;
}
}
}
}
RequestHandler looks like this:
public class RequestHandler<T> implements Request<T>{
private T result;
private RequestStatus status = RequestStatus.NEW;
private ObjectOutputStream out;
private String commend;
private String requestCommend;
private ConcurrentHashMap<String, Object> results;
public RequestHandler(String commend, String parameters, ObjectOutputStream out, ConcurrentHashMap<String, Object> results) {
this.commend = "#" + commend;
this.requestCommend = "?" + commend + ":" + parameters;
this.out = out;
this.results = results;
}
public RequestHandler(String commend, ObjectOutputStream out, ConcurrentHashMap<String, Object> results) {
this.commend = "#" + commend;
this.requestCommend = "?" + commend;
this.out = out;
this.results = results;
}
#Override
public void request() {
try {
out.writeObject(requestCommend);
while(!results.containsKey(commend)){}
result = (T) results.remove(commend);
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public T result() {
return result;
}
#Override
public RequestStatus getStatus() {
return status;
}
#Override
public void setStatus(RequestStatus status) {
this.status = status;
}
}
The output looks like this WHEN ITS WORK:
Connected to the server.
!Log in
NEW
IN_PROGRESS
...
IN_PROGRESS
!Request: IN_PROGRESS
IN_PROGRESS
...
IN_PROGRESS
I am user: sdsad
#logIn
IN_PROGRESS
IN_PROGRESS
SUCCESSFUL
!Request end: SUCCESSFUL
Try to get result:
sdsad
But when I COMMENT one debug msg I got this:
Connected to the server.
!Log in
!Request: IN_PROGRESS
I am user: dfdsfsdf4324
#logIn
!Request end: SUCCESSFUL
And the loop while(true) never end becouse I got always status IN_PROGRESS.
That's why I want to ask you why it's happen? Is Java have some weird way to optimalize output of functions to make is faster and is it thinking if it was reapet milion times so it has to be this state always?

Netty ChannelFuture timeout when response received

I am new in netty I have a tcp client application developed with netty. When i use future get async response from server some response returning but future is not completing into timeout. TCPClient class like following;
public TcpClient {
public boolean connect(Host host) {
try {
Bootstrap clientBootstrap = new Bootstrap()
.group(group)
.channel(NioSocketChannel.class)
.option(ChannelOption.SO_KEEPALIVE,true)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 50)
.remoteAddress(new InetSocketAddress(host.getIp(), host.getPort()))
.handler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel socketChannel) {
socketChannel.config().setRecvByteBufAllocator(new FixedRecvByteBufAllocator(2146));
FalconClientHandler falconClientHandler = new FalconClientHandler(host);
host.setFalconClientHandler(falconClientHandler);
socketChannel.pipeline().addLast(falconClientHandler);
}
});
channelFuture = clientBootstrap.connect().sync(); //BAŞARI İLE BAĞLANDI
channelFuture.channel().closeFuture().sync();
return host.isActive();
} catch (Exception e) {
log.info("Connection timed out --> " + e);
host.setActive(false);
return false;
} finally {
host.setActive(false);
}
}
public synchronized ResponseFuture send(long transactionId,String message) {
final Map<Long,ResponseFuture> responseFuture = new ConcurrentHashMap<>();
responseFuture.put(transactionId,new ResponseFuture());
if (!hostSelector.getUpHostList().isEmpty()) {
int hostCount = hostSelector.getUpHostList().size();
Host host;
host = hostSelector.getUpHostList().get(index.incrementAndGet() % hostCount);
if (host.isActive()) {
int headerLength = Integer.parseInt(message.substring(8, 12));
log.info("[{}] Host {} Tcp Request",message.substring(52, 52 + headerLength),host.getIp());
channelFuture.addListener((GenericFutureListener<ChannelFuture>) future -> {
log.info("[{}] Tcp request added to map",transactionId);
channelFuture.channel().pipeline().get(FalconClientHandler.class).setResponseFuture(responseFuture);
byte[] byteBuffer = message.getBytes();
channelFuture.channel().writeAndFlush(Unpooled.copiedBuffer(byteBuffer));
});
}
} else {
log.error("AYAKTA HOST YOK");
}
return responseFuture.get(transactionId);
}
}
Send method have transactionId and request message, When i send this message with transaction id response will return with this thransaction id. I am calling this send like following;
ResponseFuture responseFuture = falconClient.send(Long.valueOf(transactionId), finalMessage);
try {
Object obj = responseFuture.get(ddaTimeoutParam, TimeUnit.MILLISECONDS);
if(obj!=null) {
response = obj.toString();
ddaDelta = System.currentTimeMillis()-ddaRequestStartTime;
}
} catch (InterruptedException | ExecutionException | TimeoutException e) {
log.warn("[{}] DDA timeout. Timeout parameter: {}",transactionId,ddaTimeoutParam);
responseFuture.cancel(true);
response = "TIMEOUT";
ddaDelta = System.currentTimeMillis()-ddaRequestStartTime;
}
Response future is a basic Future implementation class. Put and get methods like that;
public class ResponseFuture implements Future<String> {
private volatile State state = State.WAITING;
ArrayBlockingQueue<String> blockingResponse = new ArrayBlockingQueue<String>(1);
private enum State {
WAITING,
DONE
}
#Override
public String get(long timeout, TimeUnit unit) throws InterruptedException,
ExecutionException, TimeoutException {
final String responseAfterWait = blockingResponse.poll(timeout, unit);
if (responseAfterWait == null) {
throw new TimeoutException();
}
return responseAfterWait;
}
public void set(String msg) {
if (state == State.DONE) {
return;
}
try {
blockingResponse.put(msg);
state = State.DONE;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
My Handler class for receive server response message like following;
public class FalconClientHandler extends SimpleChannelInboundHandler<ByteBuf> {
private ChannelHandlerContext ctx;
private Map<Long,ResponseFuture> responseFuture;
public synchronized void setResponseFuture(Map<Long,ResponseFuture> responseFuture) {
log.info("{} ResponseFuture setted",responseFuture.keySet());
this.responseFuture = responseFuture;
}
#Override
public void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf in) {
String input = in.toString(CharsetUtil.UTF_8);
String transactionKey = input.substring(52, 66).trim();
if(responseFuture.get(Long.valueOf(transactionKey))!=null)
responseFuture.get(Long.valueOf(transactionKey)).set(input);
else
log.info("[{}] Tcp Response map is empty",transactionKey);
}
}
When i run this code under high load like 30 transaction per second, tcp response returned from netty server but future get method received timeout.This situation not occuring every request for example %20 request is fail when 30 tps %50 request fail in 40 tps. What can be occur under load?

Custom concurrent TcpOutboundGateway in spring integration

I am trying to communicate with an external TCP server using TcpOutboundGateway and a client TcpConnectionFactory. In my scenario, each connection should be associated with different thread (each connection on the thread might be used for more then one request/response).
So I used a ThreadAffinityClientConnectionFactory from this topic: Spring Integration tcp client multiple connections
It worked fine until I tried to open more than 4 concurrent connections, the fifth (and over) connection is failing on timeout.
I figured out that org.springframework.integration.ip.tcp.TcpOutboundGateway uses semaphore in handleRequestMessage method to acquire a connection, so I overridden TcpOuboundGateway like this:
public class NoSemaphoreTcpOutboundGateway extends TcpOutboundGateway {
private volatile AbstractClientConnectionFactory connectionFactory;
private final Map<String, NoSemaphoreTcpOutboundGateway.AsyncReply> pendingReplies = new ConcurrentHashMap();
#Override
public boolean onMessage(Message<?> message) {
String connectionId = (String)message.getHeaders().get("ip_connectionId");
if(connectionId == null) {
this.logger.error("Cannot correlate response - no connection id");
this.publishNoConnectionEvent(message, (String)null, "Cannot correlate response - no connection id");
return false;
}
if(this.logger.isTraceEnabled()) {
this.logger.trace("onMessage: " + connectionId + "(" + message + ")");
}
NoSemaphoreTcpOutboundGateway.AsyncReply reply = (NoSemaphoreTcpOutboundGateway.AsyncReply)this.pendingReplies.get(connectionId);
if(reply == null) {
if(message instanceof ErrorMessage) {
return false;
} else {
String errorMessage = "Cannot correlate response - no pending reply for " + connectionId;
this.logger.error(errorMessage);
this.publishNoConnectionEvent(message, connectionId, errorMessage);
return false;
}
} else {
reply.setReply(message);
return false;
}
}
#Override
protected Message handleRequestMessage(Message<?> requestMessage) {
connectionFactory = (AbstractClientConnectionFactory) this.getConnectionFactory();
Assert.notNull(this.getConnectionFactory(), this.getClass().getName() + " requires a client connection factory");
TcpConnection connection = null;
String connectionId = null;
Message var7;
try {
/*if(!this.isSingleUse()) {
this.logger.debug("trying semaphore");
if(!this.semaphore.tryAcquire(this.requestTimeout, TimeUnit.MILLISECONDS)) {
throw new MessageTimeoutException(requestMessage, "Timed out waiting for connection");
}
haveSemaphore = true;
if(this.logger.isDebugEnabled()) {
this.logger.debug("got semaphore");
}
}*/
connection = this.getConnectionFactory().getConnection();
NoSemaphoreTcpOutboundGateway.AsyncReply e = new NoSemaphoreTcpOutboundGateway.AsyncReply(10000);
connectionId = connection.getConnectionId();
this.pendingReplies.put(connectionId, e);
if(this.logger.isDebugEnabled()) {
this.logger.debug("Added pending reply " + connectionId);
}
connection.send(requestMessage);
//connection may be closed after send (in interceptor) if its disconnect message
if (!connection.isOpen())
return null;
Message replyMessage = e.getReply();
if(replyMessage == null) {
if(this.logger.isDebugEnabled()) {
this.logger.debug("Remote Timeout on " + connectionId);
}
this.connectionFactory.forceClose(connection);
throw new MessageTimeoutException(requestMessage, "Timed out waiting for response");
}
if(this.logger.isDebugEnabled()) {
this.logger.debug("Response " + replyMessage);
}
var7 = replyMessage;
} catch (Exception var11) {
this.logger.error("Tcp Gateway exception", var11);
if(var11 instanceof MessagingException) {
throw (MessagingException)var11;
}
throw new MessagingException("Failed to send or receive", var11);
} finally {
if(connectionId != null) {
this.pendingReplies.remove(connectionId);
if(this.logger.isDebugEnabled()) {
this.logger.debug("Removed pending reply " + connectionId);
}
}
}
return var7;
}
private void publishNoConnectionEvent(Message<?> message, String connectionId, String errorMessage) {
ApplicationEventPublisher applicationEventPublisher = this.connectionFactory.getApplicationEventPublisher();
if(applicationEventPublisher != null) {
applicationEventPublisher.publishEvent(new TcpConnectionFailedCorrelationEvent(this, connectionId, new MessagingException(message, errorMessage)));
}
}
private final class AsyncReply {
private final CountDownLatch latch;
private final CountDownLatch secondChanceLatch;
private final long remoteTimeout;
private volatile Message<?> reply;
private AsyncReply(long remoteTimeout) {
this.latch = new CountDownLatch(1);
this.secondChanceLatch = new CountDownLatch(1);
this.remoteTimeout = remoteTimeout;
}
public Message<?> getReply() throws Exception {
try {
if(!this.latch.await(this.remoteTimeout, TimeUnit.MILLISECONDS)) {
return null;
}
} catch (InterruptedException var2) {
Thread.currentThread().interrupt();
}
for(boolean waitForMessageAfterError = true; this.reply instanceof ErrorMessage; waitForMessageAfterError = false) {
if(!waitForMessageAfterError) {
if(this.reply.getPayload() instanceof MessagingException) {
throw (MessagingException)this.reply.getPayload();
}
throw new MessagingException("Exception while awaiting reply", (Throwable)this.reply.getPayload());
}
NoSemaphoreTcpOutboundGateway.this.logger.debug("second chance");
this.secondChanceLatch.await(2L, TimeUnit.SECONDS);
}
return this.reply;
}
public void setReply(Message<?> reply) {
if(this.reply == null) {
this.reply = reply;
this.latch.countDown();
} else if(this.reply instanceof ErrorMessage) {
this.reply = reply;
this.secondChanceLatch.countDown();
}
}
}
}
the configurations of SpringContext looks like this:
#Configuration
#ImportResource("gateway.xml")
public class Conf {
#Bean
#Autowired
#ServiceActivator(inputChannel = "clientOutChannel")
public NoSemaphoreTcpOutboundGateway noSemaphoreTcpOutboundGateway(ThreadAffinityClientConnectionFactory cf, DirectChannel clientInChannel){
NoSemaphoreTcpOutboundGateway gw = new NoSemaphoreTcpOutboundGateway();
gw.setConnectionFactory(cf);
gw.setReplyChannel(clientInChannel);
gw.setRequestTimeout(10000);
return gw;
}
<int-ip:tcp-connection-factory
id="delegateCF"
type="client"
host="${remoteService.host}"
port="${remoteService.port}"
single-use="true"
lookup-host="false"
ssl-context-support="sslContext"
deserializer="clientDeserializer"
serializer="clientSerializer"
interceptor-factory-chain="clientLoggingTcpConnectionInterceptorFactory"
using-nio="false"/>
The delegateCF is passed to ThreadAffinityClientConnectionFactory constructor
So, the question is:
Is it OK to use NoSemaphoreTcpOutboundGateway in conjunction with ThreadAffinityClientConnectionFactory in terms of concurrency?
Looks like you go right way, but at the same time I think you don't need custom TcpOutboundGateway. The semaphore logic is based on the:
if (!this.isSingleUse) {
logger.debug("trying semaphore");
if (!this.semaphore.tryAcquire(this.requestTimeout, TimeUnit.MILLISECONDS)) {
throw new MessageTimeoutException(requestMessage, "Timed out waiting for connection");
}
at the same time look at Gary's solution for the ThreadAffinityClientConnectionFactory:
#Bean
public TcpNetClientConnectionFactory delegateCF() {
TcpNetClientConnectionFactory clientCF = new TcpNetClientConnectionFactory("localhost", 1234);
clientCF.setSingleUse(true); // so each thread gets his own connection
return clientCF;
}
#Bean
public ThreadAffinityClientConnectionFactory affinityCF() {
return new ThreadAffinityClientConnectionFactory(delegateCF());
}
Pay attention to the comment. Only you need is delegate isSingleUse().

Intercepting and modifying specific packets (IPv4/TCP)

I'm trying to intercept packets and be able to block them from incoming/outgoing, for a specific domain
In order to do that i made my (java) program adds the domain to the hosts file with a redirection to my own public ipv4 adress (this doesnt matter it just can't be the real IP and i must be able to intercept it, redirecting to my own IP makes sure nobody else in the world receives it). Secondly, i make the program listen to that signal and resend it on a different source port to the real server. (Checksum changes have been taken care of) Now the plan is to receive the response and do the exact same thing, but now by editting the source ip (my own public IP in this case) and the destination port
This should create a program where i'm a kind of middle men between a connection
But it doesnt work as expected, the moment im getting a response of the server (flags SYN/ACK), it's automatically sending them back a RST flag (IPv4/TCP) from the random chosen port by me which isnt the same as the port of the real client
I don't know if there are better ways to do this (there probably are) and how to prevent the problem I'm having, I couldn't really find similiar things to this on the internet. Any kind of help/hints would be appreciated
Keep in mind that I'm using jnetpscape at this moment and it would be nice to continue at what i'm doing right now
EDIT (code):
this is the "HConnection" class (not fully showed but all essential things):
public class HConnection {
private volatile int state = -1; // current state of the program
private volatile boolean HostFileEdited = false;
private volatile String domain = null;
private volatile boolean waitingConnection = false;
private volatile String ipOfDomain = null; // string of the server adress
private volatile byte[] ipofdomb; //4 bytes of the server adress
private volatile String myIpAdr = null; //my IP adress
private volatile byte[] myIpb; //my public IP in 4 bytes
private volatile byte[] port = null; //port of proxy
private volatile byte[] falseport = null; //port of client
private volatile ServerSocket server;
public HConnection() {
try {
server = new ServerSocket(0);
byte[] tempPortb = ByteBuffer.allocate(4).putInt(server.getLocalPort()).array();
System.out.println(server.getLocalPort());
port = new byte[]{tempPortb[2], tempPortb[3]};
(new Thread() {
public void run() {
try {
server.accept();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}).start();
state = 0;
} catch (UnknownHostException e) {System.out.println("fail");} catch (IOException e) {System.out.println("fail");}
}
public String getPublicIP () {
try{
myIpAdr = new BufferedReader(new InputStreamReader(new URL("http://checkip.amazonaws.com/").openStream())).readLine();
System.out.println(myIpAdr);
InetAddress ip = InetAddress.getByName(myIpAdr);
myIpb = ip.getAddress();
return myIpAdr;
}
catch (Exception e){}
return null;
}
public void setUrl(String domain) {
this.domain = domain;
}
public int getState() {
return state;
}
public void prepare() {
try{
URL urlofsite = new URL("https://"+domain);
InetAddress address = InetAddress.getByName(urlofsite.getHost());
ipOfDomain = address.getHostAddress();
System.out.println(ipOfDomain);
ipofdomb = address.getAddress();
addToHostsFile(getPublicIP() + "\t" + domain);
state = 1;
}
catch(Exception e){}
}
public void abort() {
removeFromHostsFile(domain);
HostFileEdited = false;
state = -1;
try {
server.close();
} catch (IOException e) { }
waitingConnection = false;
}
public void awaitConnection() {
if (state == 1) {
waitingConnection = true;
System.out.println("stap1");
StringBuilder errbuf = new StringBuilder(); // For any error msgs
int snaplen = 64 * 1024; // Capture all packets, no truncation
int flags = Pcap.MODE_PROMISCUOUS; // capture all packets
int timeout = 0; // 10 seconds in millis
Pcap pcap = Pcap.openLive("wlp4s0", snaplen, flags, timeout, errbuf);
if (pcap == null) {
System.err.printf("Error while opening device for capture: "
+ errbuf.toString());
return;
}
PcapHeader hdr = new PcapHeader(JMemory.POINTER);
JBuffer buf = new JBuffer(JMemory.POINTER);
int id = JRegistry.mapDLTToId(pcap.datalink());
while (HostFileEdited && waitingConnection && state == 1 && pcap.nextEx(hdr, buf) == Pcap.NEXT_EX_OK) {
PcapPacket packet = new PcapPacket(hdr, buf);
try {
packet.scan(id);
TcpPacket pkt = new TcpPacket(packet);
if (pkt.isTcp()) {
if (pkt.destinationIPequals(myIpAdr) && pkt.getDestinationPort() == 443 && (falseport == null || Arrays.equals(pkt.getSourcePortb(), falseport))) {
if (falseport == null) {
falseport = pkt.getSourcePortb();
}
pkt.changeDestinationIP(ipofdomb);
pkt.changeSourcePort(port);
pkt.iPchecksumFix();
pkt.tcPchecksumFix();
ByteBuffer b = ByteBuffer.wrap(pkt.getPacketInBytes());
System.out.println("10");
System.out.println("OUT"+ (pcap.sendPacket(b)));
}
else if (pkt.sourceIPequals(ipOfDomain) && pkt.getSourcePort() == 443 && falseport != null && Arrays.equals(pkt.getDestinationPortb(),port) ) {
pkt.changeSourceIP(myIpb);
pkt.changeDestinationPort(falseport);
pkt.iPchecksumFix();
pkt.tcPchecksumFix();
ByteBuffer b = ByteBuffer.wrap(pkt.getPacketInBytes());
System.out.println("IN"+ pcap.sendPacket(b));
}
}
}
catch (Exception e) {}
}
System.out.println("stap2");
if (state == 1 && waitingConnection == true) state = 2;
waitingConnection = false;
}
}
}
The "awaitConnection()" method is were currently most things are happening. But this will only be the beginning of my program
HConnection is called from the main class (SWT Designer):
private Button btnNewButton_1;
private HConnection connectie;
private void btnConnect_clicked(SelectionEvent e) throws InterruptedException {
if (btnNewButton_1.getText().equals("Connect")) {
String Url = combo.getText();
connectie = new HConnection();
connectie.setUrl(Url);
connectie.prepare();
lblNewLabel_2.setText("Waiting -> client");
new Thread(new Runnable() {
public void run() {
connectie.awaitConnection();
Display.getDefault().asyncExec(new Runnable() {
public void run() {
if (connectie.getState() == 2) {
lblNewLabel_2.setText("Replacing URL");
}
else {
lblNewLabel_2.setText("Failed");
connectie.abort();
btnNewButton_1.setText("Connect");
}
}
});
if (connectie.getState() == 2) {
// go on with the rest of the program
}
}
}).start();
btnNewButton_1.setText("Abort");
}
else if(btnNewButton_1.getText().equals("Abort")) {
connectie.abort();
lblNewLabel_2.setText("Aborted");
btnNewButton_1.setText("Connect");
}
}
The following code accepts a connection, but doesn't maintain a reference to the resulting Socket instance. This Socket is eligible for garbage collection, and when that happens, it is automatically closed. A client sending data to that socket will then receive an RST.
public void run() {
try {
server.accept();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}

Categories