The online racing simulator
Searching in All forums
(26 results)
2
szaboaz
Demo licensed
Hi,

I'm thinking of creating a request ID aware Client which would be able to register any number of "default" listeners (where reqI=0), and listeners with specific (non-zero) request IDs would only get the packets they are subscribed for.

I realize that QueueClient is the one for encapsulating the request ID handling, but it seems to assign only the first listener to reqI=0, but then it sends all reqI=0 packets to all the listeners.

What do you think?

Edit: I've come up with this class. Use it if you need and/or like it.

<?php 
package net
.sf.jinsim;

import java.io.IOException;
import java.util.ArrayList;
import net.sf.jinsim.request.InSimRequest;
import net.sf.jinsim.response.InSimListener;
import net.sf.jinsim.response.InSimResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/*
 * This Client handles both request and default listeners.
 * 
 * Request listeners
 * A request packet can be associated with a request listener via the send(packet,listener) method.
 * The request packet will be signed with a request ID.
 * Incoming packets with the same request ID are directed to the associated listener.
 * A maximum number of 255 listeners is possible to be associated at a time.
 * 
 * Default listeners
 * The send(packet) method can be used to send requests without associating listeners. 
 * Incoming packets with the default (0) request ID are directed to "default" listeners.
 * The number of default listeners is not limited.
 * 
 * @author szaboaz at freemail dot hu
 */
public class RequestClient extends Client {

    private static 
Logger log LoggerFactory.getLogger(RequestClient.class);
    
//for reqI = 0
    
private ArrayList<InSimListenerdefaultListeners;
    
//for reqI != 0
    
private InSimListener[] requestListeners;

    public 
RequestClient() {
        
defaultListeners = new ArrayList<InSimListener>();

        
// "0" is taken as "default" from the byte type's 256 different values,
        // so 255 other values remain. 
        
requestListeners = new InSimListener[255];
        
        
// request ID = (array index + 1)
    
}

    public 
void addDefaultListener(InSimListener listener) {
        
defaultListeners.add(listener);
    }

    public 
void removeDefaultListener(InSimListener listener) {
        
defaultListeners.remove(listener);
    }

    public 
void addRequestListener(InSimListener listener) {
        
        
// search for the next empty space in the array
        
int arrayIndex 0;
        while (
requestListeners[arrayIndex] != null) {
            
arrayIndex++;
        }
        if (
arrayIndex 254) {
            throw new 
IndexOutOfBoundsException("Maximum number of listeners exceeded!");
        }

        
requestListeners[arrayIndex] = listener;

        if (
log.isDebugEnabled()) {
            
log.debug("Added " listener.getClass().getName() + " to requestListeners at index " arrayIndex);
        }
    }

    public 
void removeRequestListener(InSimListener listener) {
        if (
listener != null) {
            for (
int i 0255i++) {
                if (
listener.equals(requestListeners[i])) {
                    
requestListeners[i] = null;
                }
            }
        }
    }

    @
Override
    
public void notifyListeners(InSimResponse packetData) {
        
int requestID packetData.getRequestInfo();

        
log.debug("\nIncoming packet " packetData.getClass().getName());
        
log.debug("RequestID: " requestID);

        if (
requestID == 0) {
            for (
InSimListener listener defaultListeners) {
                if (
listener != null) {
                    
log.debug("Packet goes to default listener: " listener.getClass().getName() + "\n");
                    
listener.packetReceived(packetData);
                } else {
                    
log.debug("Listener is null!\n");
                }
            }
        } else {
            
InSimListener listener requestListeners[requestID 1];
            if (
listener != null) {
                
log.debug("Packet goes to request listener: " listener.getClass().getName() + "\n");
                
listener.packetReceived(packetData);
            } else {
                
log.debug("Listener is null!\n");
            }
        }
    }

    @
Override
    
public void send(InSimRequest packetthrows IOException {
        
log.debug("Sending out packet.");
        
super.send(packet);
    }

    public 
void send(InSimRequest packetInSimListener listenerthrows IOException {
        
//let's get the array index of that listener
        
if (listener == null) {
            
log.debug("Listener is null!");
            return;
        }

        
int arrayIndex 0;
        while (!
listener.equals(requestListeners[arrayIndex])) {
            
arrayIndex++;
        }
        
//at this point, arrayIndex is the index of our listener
        //and since requestID = array index + 1:
        
byte requestID = (byte) (arrayIndex 1);
        
        
log.debug("Sending out packet with requestListener " listener.getClass().getName() + " Index: " requestID);
        
packet.setRequestInfo(requestID);
        
super.send(packet);
    }
}
?>

Edit: as my understanding grows, I see how my humble class above might not be adequate for general use. I'm pondering about other requests where request ID is prohibited from being zero, for example button requests.
Maybe I should fix the code above by sending all responses whose request ID is not zero, still don't have specific listeners assigned to them, so all those responses should still go to (all of the) default listeners.

Edit: I did just that, here's the current version:

<?php 
package net
.sf.jinsim;

import java.io.IOException;
import java.util.ArrayList;
import net.sf.jinsim.request.InSimRequest;
import net.sf.jinsim.response.InSimListener;
import net.sf.jinsim.response.InSimResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/*
 * This Client handles both request and default listeners.
 * 
 * Request listeners
 * A request packet can be associated with a request listener via the send(packet,listener) method.
 * The request packet will be signed with a request ID.
 * Incoming packets with the same request ID are directed to the associated listener.
 * If there are no listeners associated to the incoming packet's request ID, the packet
 * will be sent to all default listeners.
 * A maximum number of 255 listeners is possible to be associated at a time.
 * 
 * Default listeners
 * The send(packet) method can be used to send requests without associating listeners. 
 * Incoming packets with the default (0) request ID are directed to "default" listeners.
 * The number of default listeners is not limited.
 * 
 * 
 * @author szaboaz at freemail dot hu
 */
public class RequestClient extends Client {

    private static 
Logger log LoggerFactory.getLogger(RequestClient.class);
    
//for reqI = 0
    
private ArrayList<InSimListenerdefaultListeners;
    
//for reqI != 0
    
private InSimListener[] requestListeners;

    public 
RequestClient() {
        
defaultListeners = new ArrayList<InSimListener>();

        
// "0" is taken as "default" from the byte type's 256 different values,
        // so 255 other values remain. 
        
requestListeners = new InSimListener[255];
        
        
// request ID = (array index + 1)
    
}

    public 
void addDefaultListener(InSimListener listener) {
        
defaultListeners.add(listener);
    }

    public 
void removeDefaultListener(InSimListener listener) {
        
defaultListeners.remove(listener);
    }

    public 
void addRequestListener(InSimListener listener) {
        
        
// search for the next empty space in the array
        
int arrayIndex 0;
        while (
requestListeners[arrayIndex] != null) {
            
arrayIndex++;
        }
        if (
arrayIndex 254) {
            throw new 
IndexOutOfBoundsException("Maximum number of listeners exceeded!");
        }

        
requestListeners[arrayIndex] = listener;

        if (
log.isDebugEnabled()) {
            
log.debug("Added " listener.getClass().getName() + " to requestListeners at index " arrayIndex);
        }
    }

    public 
void removeRequestListener(InSimListener listener) {
        if (
listener != null) {
            for (
int i 0255i++) {
                if (
listener.equals(requestListeners[i])) {
                    
requestListeners[i] = null;
                }
            }
        }
    }

    @
Override
    
public void notifyListeners(InSimResponse packetData) {
        
int requestID packetData.getRequestInfo();

        
log.debug("\nIncoming packet " packetData.getClass().getName());
        
log.debug("RequestID: " requestID);

        if (
requestID == 0) {
            for (
InSimListener defaultListener defaultListeners) {
                if (
defaultListener != null) {
                    
log.debug("Packet goes to default listener: " defaultListener.getClass().getName() + "\n");
                    
defaultListener.packetReceived(packetData);
                } else {
                    
log.debug("Listener is null!\n");
                }
            }
        } else {
            
InSimListener listener requestListeners[requestID 1];
            if (
listener != null) {
                
log.debug("Packet goes to request listener: " listener.getClass().getName() + "\n");
                
listener.packetReceived(packetData);
            } else {
                
log.debug("No request listener is associated with this Request ID!\n");
                for (
InSimListener defaultListener defaultListeners) {
                    if (
defaultListener != null) {
                        
log.debug("Packet goes to default listener: " defaultListener.getClass().getName() + "\n");
                        
defaultListener.packetReceived(packetData);
                    } else {
                        
log.debug("Listener is null!\n");
                    }
                }
            }
        }
    }

    @
Override
    
public void send(InSimRequest packetthrows IOException {
        
log.debug("Sending out packet.");
        
super.send(packet);
    }

    public 
void send(InSimRequest packetInSimListener listenerthrows IOException {
        
//let's get the array index of that listener
        
if (listener == null) {
            
log.debug("Listener is null!");
            return;
        }

        
int arrayIndex 0;
        while (!
listener.equals(requestListeners[arrayIndex])) {
            
arrayIndex++;
        }
        
//at this point, arrayIndex is the index of our listener
        //and since requestID = array index + 1:
        
byte requestID = (byte) (arrayIndex 1);
        
        
log.debug("Sending out packet with requestListener " listener.getClass().getName() + " Index: " requestID);
        
packet.setRequestInfo(requestID);
        
super.send(packet);
    }
}
?>

I've just realized another possible shortcoming: what if I want to use the same request ID with two different listeners. Not possible at the moment.
Of course if an incoming packet comes with a request ID, the same listener can handle different things... Still...

Edit: Okay, here's a new version. Any number of listeners can be assigned to any of the request IDs. It's more elegant too, without that ugly array
For convenience, there're methods for adding and removing listeners to all the request IDs.


<?php 
package net
.sf.jinsim;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import net.sf.jinsim.request.InSimRequest;
import net.sf.jinsim.response.InSimListener;
import net.sf.jinsim.response.InSimResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/*
 * You can subscribe to this Client any number of
 * - request ID specific listeners (which listen only to responses
 *   with the specified IDs).
 * - general listeners (which listen to responses with any request IDs),
 * 
 * Specified request ID values must be in the range of 0 to 255.
 * 
 * @author szaboaz at freemail dot hu
 */
public class RequestClient extends Client {

    private static 
Logger log LoggerFactory.getLogger(RequestClient.class);
    private 
ArrayList<HashSet<InSimListener>> listeners;
    
    public 
RequestClient(){
        
listeners = new ArrayList<HashSet<InSimListener>>();
        for (
int i=0i<=255i++){
            
listeners.add(new HashSet<InSimListener>());
        }
    }
    
    public 
boolean addListener(InSimListener listener) {
        
boolean returnValue true;
        for (
int i=0i<=255i++){
            
returnValue listeners.get(i).add(listener);
        }
        return 
returnValue;
    }

    public 
boolean addListener(InSimListener listenerint requestID) {
        if (
requestID >= && requestID <=255){
            return 
listeners.get(requestID).add(listener);
        }
        else {
            return 
false;
        }
    }
    
    public 
boolean removeListener(InSimListener listener) {
        
boolean returnValue true;
        for (
int i=0i<=255i++){
            
returnValue listeners.get(i).remove(listener);
        }
        return 
returnValue;
    }
    
    public 
boolean removeListener(InSimListener listenerint requestID) {
        if (
requestID >= && requestID <=255){
            return 
listeners.get(requestID).remove(listener);
        }
        else {
            return 
false;
        }
    }
    
    @
Override
    
public void notifyListeners(InSimResponse packetData) {
        
int requestID packetData.getRequestInfo();
        
        
HashSet<InSimListenerlistenerSet listeners.get(requestID);
        for (
InSimListener listener listenerSet){
            
listener.packetReceived(packetData);
        }
    }
    
    public 
void send(InSimRequest packetint requestIDthrows IOException {
        
packet.setRequestInfo((byte)requestID);
        
send(packet);
    }
    
}
?>

Last edited by szaboaz, .
2
FGED GREDG RDFGDR GSFDG