public void handleUpdateWorldNode(long oid, WorldManagerClient.UpdateWorldNodeMessage wnodeMsg) { PerceiverData perceiverData = perceiverDataMap.get(oid); if (perceiverData == null) { if (Log.loggingDebug) Log.debug( "ProximityTracker.handleMessage: ignoring updateWNMsg for oid " + oid + " because PerceptionData for oid not found"); return; } BasicWorldNode bwnode = wnodeMsg.getWorldNode(); if (Log.loggingDebug) Log.debug( "ProximityTracker.handleMessage: UpdateWnode for " + oid + ", loc " + bwnode.getLoc() + ", dir " + bwnode.getDir()); if (perceiverData.wnode != null) { perceiverData.previousLoc = perceiverData.lastLoc; perceiverData.wnode.setDirLocOrient(bwnode); perceiverData.wnode.setInstanceOid(bwnode.getInstanceOid()); perceiverData.lastLoc = perceiverData.wnode.getLoc(); } else Log.error( "ProximityTracker.handleMessage: In UpdateWorldNodeMessage for oid " + oid + ", perceiverData.wnode is null!"); updateEntity(perceiverData); }
/** * there is a socket listening on the port for this packet. process if it is a new connection rdp * packet */ public void processNewConnection(RDPServerSocket serverSocket, RDPPacket packet) { if (Log.loggingNet) Log.net( "processNewConnection: RDPPACKET (localport=" + serverSocket.getPort() + "): " + packet); // int localPort = serverSocket.getPort(); InetAddress remoteAddr = packet.getInetAddress(); int remotePort = packet.getPort(); if (!packet.isSyn()) { // the client is not attemping to start a new connection // send a reset and forget about it Log.debug("socket got non-syn packet, replying with reset: packet=" + packet); RDPPacket rstPacket = RDPPacket.makeRstPacket(); rstPacket.setPort(remotePort); rstPacket.setInetAddress(remoteAddr); RDPServer.sendPacket(serverSocket.getDatagramChannel(), rstPacket); return; } // it is a syn packet, lets make a new connection for it RDPConnection con = new RDPConnection(); DatagramChannel dc = serverSocket.getDatagramChannel(); con.initConnection(dc, packet); // add new connection to allConnectionMap registerConnection(con, dc); // ack it with a syn RDPPacket synPacket = RDPPacket.makeSynPacket(con); con.sendPacketImmediate(synPacket, false); }
private synchronized String allocName(String type, String namePattern) { Map<String, Integer> patterns = nameTypes.get(type); if (patterns == null) { patterns = new HashMap<String, Integer>(); nameTypes.put(type, patterns); } Integer id = patterns.get(namePattern); if (id == null) id = 0; id++; patterns.put(namePattern, id); String agentName = namePattern.replaceFirst("#", id.toString()); if (agentName.equals(namePattern)) Log.warn("AllocName: missing '#' in name pattern '" + namePattern + "'"); else Log.debug( "AllocName: for type=" + type + " assigned '" + agentName + "' from pattern '" + namePattern + "'"); return agentName; }
protected void performNotification( long perceiverOid, long perceivedOid, boolean inRadius, boolean wasInRadius) { if (Log.loggingDebug) Log.debug( "ProximityTracker.performNotification: perceiverOid " + perceiverOid + ", perceivedOid " + perceivedOid + ", inRadius " + inRadius + ", wasInRadius " + wasInRadius); if (notifyCallback != null) { notifyCallback.notifyReactionRadius(perceivedOid, perceiverOid, inRadius, wasInRadius); notifyCallback.notifyReactionRadius(perceiverOid, perceivedOid, inRadius, wasInRadius); } else { ObjectTracker.NotifyReactionRadiusMessage nmsg = new ObjectTracker.NotifyReactionRadiusMessage( perceivedOid, perceiverOid, inRadius, wasInRadius); Engine.getAgent().sendBroadcast(nmsg); nmsg = new ObjectTracker.NotifyReactionRadiusMessage( perceiverOid, perceivedOid, inRadius, wasInRadius); Engine.getAgent().sendBroadcast(nmsg); } }
public void handleMessage(Message msg, int flags) { try { lock.lock(); if (activated == false) return; // return true; if (msg.getMsgType() == Behavior.MSG_TYPE_COMMAND) { Behavior.CommandMessage cmdMsg = (Behavior.CommandMessage) msg; String command = cmdMsg.getCmd(); // Remove the executor, because anything we do will // end the current execution. Engine.getExecutor().remove(this); if (Log.loggingDebug) Log.debug( "BaseBehavior.onMessage: command = " + command + "; oid = " + obj.getOid() + "; name " + obj.getName()); if (command.equals(MSG_CMD_TYPE_GOTO)) { GotoCommandMessage gotoMsg = (GotoCommandMessage) msg; Point destination = gotoMsg.getDestination(); mode = MSG_CMD_TYPE_GOTO; roamingBehavior = true; gotoSetup(destination, gotoMsg.getSpeed()); } else if (command.equals(MSG_CMD_TYPE_STOP)) { followTarget = null; pathState.clear(); obj.getWorldNode().setDir(new MVVector(0, 0, 0)); obj.updateWorldNode(); mode = MSG_CMD_TYPE_STOP; // If roamingBehavior is set, that means that we // used formerly had a roaming behavior, so send // an ArrivedEventMessage so that the other // behavior starts up again. if (roamingBehavior) { try { Engine.getAgent().sendBroadcast(new ArrivedEventMessage(obj)); } catch (Exception e) { Log.error( "BaseBehavior.onMessage: Error sending ArrivedEventMessage, error was '" + e.getMessage() + "'"); throw new RuntimeException(e); } } } else if (command.equals(BaseBehavior.MSG_CMD_TYPE_FOLLOW)) { FollowCommandMessage followMsg = (FollowCommandMessage) msg; mode = MSG_CMD_TYPE_FOLLOW; followSetup(followMsg.getTarget(), followMsg.getSpeed()); } } else if (msg.getMsgType() == WorldManagerClient.MSG_TYPE_MOB_PATH_CORRECTION) { Engine.getExecutor().remove(this); interpolatePath(); interpolatingPath = false; } // return true; } finally { lock.unlock(); } }
protected boolean interpolatePath() { long timeNow = System.currentTimeMillis(); PathLocAndDir locAndDir = pathState.interpolatePath(timeNow); long oid = obj.getOid(); // if (locAndDir != null) { // if (Log.loggingDebug) { // Log.debug("BaseBehavior.interpolatePath: oid = " + oid + "; loc = " + // locAndDir.getLoc() + "; dir = " + locAndDir.getDir()); // } // } // else { // if (Log.loggingDebug) // Log.debug("BaseBehavior.interpolatePath: oid = " + oid + "; locAndDir is // null"); // } if (locAndDir == null) { // We have arrived - - turn off interpolation, and cancel that path interpolatingPath = false; if (Log.loggingDebug) Log.debug( "BaseBehavior.interpolatePath: cancelling path: oid = " + oid + "; myLoc = " + obj.getWorldNode().getLoc()); cancelPathInterpolator(oid); obj.getWorldNode().setDir(new MVVector(0, 0, 0)); } else { obj.getWorldNode() .setPathInterpolatorValues( timeNow, locAndDir.getDir(), locAndDir.getLoc(), locAndDir.getOrientation()); MobManagerPlugin.getTracker(obj.getInstanceOid()).updateEntity(obj); } return interpolatingPath; }
public void addTrackedPerceiver( Long perceiverOid, InterpolatedWorldNode wnode, Integer reactionRadius) { lock.lock(); try { if (perceiverDataMap.containsKey(perceiverOid)) { // Don't add the object more than once. Log.error( "ProximityTracker.addTrackedPerceiver: perceiverOid " + perceiverOid + " is already in the set of local objects, for ProximityTracker instance " + this); return; } PerceiverData perceiverData = new PerceiverData(perceiverOid, reactionRadius, wnode); perceiverDataMap.put(perceiverOid, perceiverData); } finally { lock.unlock(); } if (Log.loggingDebug) Log.debug( "ProximityTracker.addTrackedPerceiver: perceiverOid=" + perceiverOid + " reactionRadius=" + reactionRadius + " instanceOid=" + instanceOid); }
public synchronized void pluginAvailable(String pluginType, String pluginName) { if (Log.loggingDebug) Log.debug("Plugin available type=" + pluginType + " name=" + pluginName); PluginSpec pluginSpec = plugins.get(pluginType); if (pluginSpec == null) { Log.error("DomainServer: unexpected plugin type=" + pluginType + " name=" + pluginName); return; } pluginSpec.running++; if (pluginSpec.running > pluginSpec.expected) { Log.warn( "DomainServer: more plugins than expected, type=" + pluginType + " name=" + pluginName + " expected=" + pluginSpec.expected + " available=" + pluginSpec.running); } if (pluginSpec.running >= pluginSpec.expected) { this.notifyAll(); } }
public void run() { synchronized (pluginStartGroup) { waitForDependencies(); } if (Log.loggingDebug) Log.debug( "Dependency satisfied for type=" + await.getPluginType() + " name=" + await.getPluginName()); MVByteBuffer buffer = new MVByteBuffer(1024); ResponseMessage response = new ResponseMessage(await); Message.toBytes(response, buffer); buffer.flip(); try { if (!ChannelUtil.writeBuffer(buffer, agentSocket)) { Log.error("could not write await dependencies response"); } } catch (java.io.IOException e) { Log.exception("could not write await dependencies response", e); } }
public void onTcpAccept(SocketChannel agentSocket) { Log.debug("Got connection: " + agentSocket); try { threadPool.execute(new AgentHandler(agentSocket)); } catch (IOException ex) { Log.exception("DomainServer listener", ex); } }
/** * Track union of perceived objects and keep filter in-sync. The filter must be a {@link * PerceptionFilter} and the message must be a {@link PerceptionMessage}. * * @param triggeringMessage The matched message. * @param triggeringFilter The matched filter. * @param agent The local message agent. */ public synchronized void trigger( Message triggeringMessage, IFilter triggeringFilter, MessageAgent agent) { PerceptionMessage message = (PerceptionMessage) triggeringMessage; List<ObjectNote> gainObjects = message.getGainObjects(); List<ObjectNote> lostObjects = message.getLostObjects(); if (gainObjects != null) { List<PerceptionFilter.TypedSubject> newSubjects = new ArrayList<PerceptionFilter.TypedSubject>(gainObjects.size()); for (ObjectNote gain : gainObjects) { IntHolder refCount = objectRefs.get(gain.subjectOid); if (refCount == null) { objectRefs.put(gain.subjectOid, new IntHolder(1)); newSubjects.add(new PerceptionFilter.TypedSubject(gain.subjectOid, gain.objectType)); } else refCount.count++; } if (newSubjects.size() > 0) { if (Log.loggingDebug) Log.debug("PerceptionTrigger adding " + newSubjects.size()); filter.addSubjects(newSubjects); } } if (lostObjects == null) return; List<Long> freeOids = new ArrayList<Long>(lostObjects.size()); for (ObjectNote lost : lostObjects) { IntHolder refCount = objectRefs.get(lost.subjectOid); if (refCount == null) Log.error("PerceptionTrigger: duplicate lost " + lost.subjectOid); else if (refCount.count == 1) { objectRefs.remove(lost.subjectOid); freeOids.add(lost.subjectOid); } else refCount.count--; } if (freeOids.size() > 0) { if (Log.loggingDebug) Log.debug("PerceptionTrigger removing " + freeOids.size()); filter.removeSubjects(freeOids); } }
public void removeTrackedPerceiver(Long perceiverOid) { lock.lock(); try { // Iterate over perceived objects, removing our // perceiverOid from their oid sets. PerceiverData perceiverData = perceiverDataMap.get(perceiverOid); if (perceiverData != null) { if (Log.loggingDebug) Log.debug( "ProximityTracker.removeTrackedPerceiver: perceiverOid " + perceiverOid + ", inRangeOids count " + perceiverData.inRangeOids.size()); // Iterate over perceived objects, removing our // perceiverOid from their oid sets. for (Long perceivedOid : perceiverData.perceivedOids) { PerceiverData perceivedData = perceiverDataMap.get(perceivedOid); if (perceivedData != null) { perceivedData.perceivedOids.remove(perceiverOid); if (perceivedData.inRangeOids.contains(perceiverOid)) { perceivedData.inRangeOids.remove(perceiverOid); performNotification(perceiverOid, perceivedOid, false, true); } } } perceiverData.perceivedOids.clear(); perceiverData.inRangeOids.clear(); perceiverDataMap.remove(perceiverOid); } else Log.warn( "ProximityTracker.removeTrackedPerceiver: For oid=" + perceiverOid + ", didn't find PerceiverData"); } finally { lock.unlock(); } if (Log.loggingDebug) Log.debug( "ProximityTracker.removeTrackedPerceiver: oid=" + perceiverOid + " instanceOid=" + instanceOid); }
public void gotoSetup(Point dest, int speed) { // calculate the vector to the destination destLoc = dest; mobSpeed = speed; Point myLoc = obj.getWorldNode().getLoc(); long oid = obj.getOid(); if (Log.loggingDebug) Log.debug("BaseBehavior.gotoSetup: oid = " + oid + "; myLoc = " + myLoc + "; dest = " + dest); scheduleMe( setupPathInterpolator(oid, myLoc, dest, false, obj.getWorldNode().getFollowsTerrain())); }
public void followUpdate() { ObjectStub followObj = (ObjectStub) followTarget.getEntity(Namespace.MOB); Point followLoc = followObj.getWorldNode().getLoc(); InterpolatedWorldNode node = obj.getWorldNode(); Point myLoc = node.getLoc(); long oid = obj.getOid(); float fdist = Point.distanceTo(followLoc, destLoc); float dist = Point.distanceTo(followLoc, myLoc); if (Log.loggingDebug) Log.debug( "BaseBehavior.followUpdate: oid = " + oid + "; myLoc = " + myLoc + "; followLoc = " + followLoc + "; fdist = " + fdist + "; dist = " + dist); long msToSleep = (long) 500; // If the new target location is more than a meter from // the old one, create a new path. if (fdist > 1000) { long msToDest = setupPathInterpolator(oid, myLoc, followLoc, true, node.getFollowsTerrain()); destLoc = followLoc; msToSleep = msToDest == 0 ? (long) 500 : Math.min((long) 500, msToDest); } // Else if we're interpolating, interpolate the current path else if (interpolatingPath) { interpolatePath(); if (Log.loggingDebug) Log.debug( "baseBehavior.followUpdate: oid = " + oid + "; interpolated myLoc = " + obj.getWorldNode().getLoc()); } scheduleMe(interpolatingPath ? msToSleep : pathState.pathTimeRemaining()); }
protected void update() { Log.debug("Updater.update: in update"); List<Long> perceiverOids = null; lock.lock(); try { perceiverOids = new ArrayList<Long>(perceiverDataMap.keySet()); } finally { lock.unlock(); } // We loop over the copied perceiverOids causing // interpolation to happen, and capturing the location in // the PerceiverData, so we can later do comparisons // cheaply. Note that underlying map can change while // we're doing so, so we don't raise errors if it happens. for (long perceiverOid : perceiverOids) { PerceiverData perceiverData = perceiverDataMap.get(perceiverOid); if (perceiverData != null) { perceiverData.previousLoc = perceiverData.lastLoc; // long lastInterp = perceiverData.wnode.getLastInterp(); perceiverData.lastLoc = perceiverData.wnode.getLoc(); // if (Log.loggingDebug) // Log.debug("Updater.update: perceiverOid " + perceiverOid + ", // previousLoc " + perceiverData.previousLoc + // ", lastLoc " + perceiverData.lastLoc + ", time since interp // " + (System.currentTimeMillis() - lastInterp)); } } // Now actually do the double loop to check if inRange has // changed for (long perceiverOid : perceiverOids) { PerceiverData perceiverData = perceiverDataMap.get(perceiverOid); if (perceiverData == null) continue; // If the perceiver hasn't moved much, no need to // iterate over it's perceived entities if (perceiverData.previousLoc != null && Point.distanceToSquared(perceiverData.previousLoc, perceiverData.lastLoc) < 100f) continue; ArrayList<Long> perceivedOids = new ArrayList<Long>(perceiverData.perceivedOids); for (long perceivedOid : perceivedOids) { PerceiverData perceivedData = perceiverDataMap.get(perceivedOid); if (perceivedData == null) continue; // Invoke the testProximity method but tell it not // to interpolate, but instead get its location // from the PerceptionData.lastLoc members testProximity(perceiverData, perceivedData, false, false); } } }
protected boolean maybeAddPerceivedObject(PerceptionMessage.ObjectNote objectNote) { ObjectType objType = (ObjectType) objectNote.getObjectType(); long perceivedOid = objectNote.getSubject(); long perceiverOid = objectNote.getTarget(); if (perceivedOid == perceiverOid) return true; boolean callbackNixedIt = false; if (remoteObjectFilter != null) callbackNixedIt = !remoteObjectFilter.objectShouldBeTracked(perceivedOid, objectNote); if (callbackNixedIt || !(objType.isMob())) { // if (Log.loggingDebug) // Log.debug("ProximityTracker.maybeAddPerceivedObject: ignoring oid=" + // perceivedOid // + " objType=" + objType // + " detected by " + perceiverOid // + ", instanceOid=" + instanceOid); return false; } if (Log.loggingDebug) Log.debug( "ProximityTracker.maybeAddPerceivedObject: oid=" + perceivedOid + " objType=" + objType + " detected by " + perceiverOid + ", instanceOid=" + instanceOid); lock.lock(); try { PerceiverData perceiverData = perceiverDataMap.get(perceiverOid); if (perceiverData == null) { Log.error( "ProximityTracker.maybeAddPerceivedObject: got perception msg with perceived obj oid=" + perceivedOid + " for unknown perceiver=" + perceiverOid); return false; } perceiverData.perceivedOids.add(perceivedOid); PerceiverData perceivedData = perceiverDataMap.get(perceivedOid); if (perceivedData != null) testProximity(perceiverData, perceivedData, true, false); } finally { lock.unlock(); } return true; }
protected void removePerceivedObject(long perceiverOid, long perceivedOid) { lock.lock(); try { PerceiverData perceiverData = perceiverDataMap.get(perceiverOid); if (perceiverData == null) { if (Log.loggingDebug) Log.debug( "ProximityTracker.removePerceivedObject: No perceiverData for oid " + perceiverOid); return; } perceiverData.perceivedOids.remove(perceivedOid); if (perceiverData.inRangeOids.contains(perceivedOid)) { performNotification(perceiverOid, perceivedOid, true, false); perceiverData.inRangeOids.remove(perceivedOid); } } finally { lock.unlock(); } }
protected long setupPathInterpolator( long oid, Point myLoc, Point dest, boolean follow, boolean followsTerrain) { long timeNow = System.currentTimeMillis(); WorldManagerClient.MobPathReqMessage reqMsg = pathState.setupPathInterpolator(timeNow, myLoc, dest, mobSpeed, follow, followsTerrain); if (reqMsg != null) { try { Engine.getAgent().sendBroadcast(reqMsg); if (Log.loggingDebug) Log.debug("BaseBehavior.setupPathInterpolator: send MobPathReqMessage " + reqMsg); } catch (Exception e) { throw new RuntimeException(e); } interpolatingPath = true; return pathState.pathTimeRemaining(); } else { interpolatingPath = false; return 0; } }
public void gotoUpdate() { Point myLoc = obj.getWorldNode().getLoc(); long oid = obj.getOid(); if (interpolatingPath) { interpolatePath(); if (!interpolatingPath) { Engine.getAgent().sendBroadcast(new ArrivedEventMessage(obj)); if (Log.loggingDebug) Log.debug( "BaseBehavior.gotoUpdate sending ArrivedEventMessage: oid = " + oid + "; myLoc = " + myLoc + "; destLoc = " + destLoc); mode = MSG_CMD_TYPE_STOP; } } if (interpolatingPath) scheduleMe(pathState.pathTimeRemaining()); }
public static void startRDPServer() { if (rdpServerStarted) return; rdpServerStarted = true; rdpServerThread = new Thread(rdpServer, "RDPServer"); retryThread = new Thread(new RetryThread(), "RDPRetry"); packetCallbackThread = new Thread(new PacketCallbackThread(), "RDPCallback"); if (Log.loggingNet) Log.net("static - starting rdpserver thread"); try { selector = Selector.open(); } catch (Exception e) { Log.exception("RDPServer caught exception opening selector", e); System.exit(1); } rdpServerThread.setPriority(rdpServerThread.getPriority() + 2); if (Log.loggingDebug) Log.debug( "RDPServer: starting rdpServerThread with priority " + rdpServerThread.getPriority()); rdpServerThread.start(); retryThread.start(); packetCallbackThread.start(); }
public void prepareDependencies(Properties properties, String worldName) { for (PluginSpec plugin : plugins.values()) { String depString; depString = properties.getProperty("multiverse.plugin_dep." + worldName + "." + plugin.pluginType); if (depString == null) { depString = properties.getProperty("multiverse.plugin_dep." + plugin.pluginType); } if (depString == null) continue; depString = depString.trim(); String[] deps = null; if (!depString.equals("")) deps = depString.split(","); dependencies.put(plugin.pluginType, deps); if (Log.loggingDebug) Log.debug( "plugin type " + plugin.pluginType + " depends on plugin types: " + ((deps == null) ? "*none*" : depString)); } }
public void handlePerception(PerceptionMessage perceptionMessage) { long targetOid = perceptionMessage.getTarget(); List<PerceptionMessage.ObjectNote> gain = perceptionMessage.getGainObjects(); List<PerceptionMessage.ObjectNote> lost = perceptionMessage.getLostObjects(); if (Log.loggingDebug) Log.debug( "ProximityTracker.handlePerception: targetOid + " + targetOid + ", instanceOid=" + instanceOid + " " + ((gain == null) ? 0 : gain.size()) + " gain and " + ((lost == null) ? 0 : lost.size()) + " lost"); if (gain != null) for (PerceptionMessage.ObjectNote note : gain) maybeAddPerceivedObject(note); if (lost != null) for (PerceptionMessage.ObjectNote note : lost) maybeRemovePerceivedObject(note.getSubject(), note, targetOid); }
public synchronized boolean hasDependencies(String pluginType, String pluginName) { String[] deps = dependencies.get(pluginType); if (deps == null) return false; for (String dependentType : deps) { PluginSpec pluginSpec = plugins.get(dependentType); if (pluginSpec == null) { Log.warn("No information for dependent type=" + dependentType); continue; } if (pluginSpec.running < pluginSpec.expected) { if (Log.loggingDebug) Log.debug( "Incomplete dependency for type=" + pluginType + " name=" + pluginName + " dependentType=" + dependentType); return true; } } return false; }
public void handleMessageData(int length, MVByteBuffer messageData, AgentInfo agentInfo) { if (length == -1 || messageData == null) { if ((agentInfo.flags & MessageAgent.DOMAIN_FLAG_TRANSIENT) != 0) { Log.info("Lost connection to '" + agentInfo.agentName + "' (transient)"); agents.remove(agentInfo.socket); agentNames.remove(agentInfo.agentName); messageIO.removeAgent(agentInfo); } else Log.info("Lost connection to '" + agentInfo.agentName + "'"); try { agentInfo.socket.close(); } catch (java.io.IOException ex) { Log.exception("close", ex); } agentInfo.socket = null; // ## clear buffers // ## keep agentInfo? to preserve agentId? return; } Message message = (Message) MarshallingRuntime.unmarshalObject(messageData); MessageType msgType = message.getMsgType(); if (Log.loggingDebug) Log.debug( "handleMessageData from " + agentInfo.agentName + "," + message.getMsgId() + " type=" + msgType.getMsgTypeString() + " len=" + length + " class=" + message.getClass().getName()); try { if (message instanceof AllocNameMessage) handleAllocName((AllocNameMessage) message, agentInfo.socket); else if (message instanceof AwaitPluginDependentsMessage) handleAwaitPluginDependents((AwaitPluginDependentsMessage) message, agentInfo.socket); else if (message instanceof PluginAvailableMessage) handlePluginAvailable((PluginAvailableMessage) message, agentInfo.socket); else Log.error( "Unsupported message from " + agentInfo.agentName + "," + message.getMsgId() + " type=" + msgType.getMsgTypeString() + " len=" + length + " class=" + message.getClass().getName()); } catch (java.io.IOException e) { Log.error( "IO error on message from " + agentInfo.agentName + "," + message.getMsgId() + " type=" + msgType.getMsgTypeString() + " len=" + length + " class=" + message.getClass().getName()); } }
/** * we have a packet that belongs to the passed in connection. process the packet for the * connection. It returns true if the connection is open and the packet was a data packet */ boolean processExistingConnection(RDPConnection con, RDPPacket packet) { if (Log.loggingNet) Log.net("RDPServer.processExistingConnection: con state=" + con + ", packet=" + packet); packetCounter.add(); int state = con.getState(); if (state == RDPConnection.LISTEN) { // something is wrong, we shouldn't be here // we get to this method after looking in the connections map // but all LISTEN connections should be listed direct // from serversockets Log.error("RDPServer.processExistingConnection: connection shouldnt be in LISTEN state"); return false; } if (state == RDPConnection.SYN_SENT) { if (!packet.isAck()) { Log.warn("got a non-ack packet when we're in SYN_SENT"); return false; } if (!packet.isSyn()) { Log.warn("got a non-syn packet when we're in SYN_SENT"); return false; } if (Log.loggingNet) Log.net("good: got syn-ack packet in syn_sent"); // make sure its acking our initial segment # if (packet.getAckNum() != con.getInitialSendSeqNum()) { if (Log.loggingNet) Log.net("syn's ack number does not match initial seq #"); return false; } con.setRcvCur(packet.getSeqNum()); con.setRcvIrs(packet.getSeqNum()); con.setMaxSendUnacks(packet.getSendUnacks()); con.setMaxReceiveSegmentSize(packet.getMaxRcvSegmentSize()); con.setSendUnackd(packet.getAckNum() + 1); // ack first before setting state to open // otherwise some other thread will get woken up and send data // before we send the ack if (Log.loggingNet) Log.net("new connection state: " + con); RDPPacket replyPacket = new RDPPacket(con); con.sendPacketImmediate(replyPacket, false); con.setState(RDPConnection.OPEN); return false; } if (state == RDPConnection.SYN_RCVD) { if (packet.getSeqNum() <= con.getRcvIrs()) { Log.error("seqnum is not above rcv initial seq num"); return false; } if (packet.getSeqNum() > (con.getRcvCur() + (con.getRcvMax() * 2))) { Log.error("seqnum is too big"); return false; } if (packet.isAck()) { if (packet.getAckNum() == con.getInitialSendSeqNum()) { if (Log.loggingNet) Log.net("got ack for our syn - setting state to open"); con.setState(RDPConnection.OPEN); // this will notify() // call the accept callback // first find the serversocket DatagramChannel dc = con.getDatagramChannel(); if (dc == null) { throw new MVRuntimeException( "RDPServer.processExistingConnection: no datagramchannel for connection that just turned OPEN"); } RDPServerSocket rdpSocket = RDPServer.getRDPSocket(dc); if (rdpSocket == null) { throw new MVRuntimeException( "RDPServer.processExistingConnection: no socket for connection that just turned OPEN"); } ClientConnection.AcceptCallback acceptCB = rdpSocket.getAcceptCallback(); if (acceptCB != null) { acceptCB.acceptConnection(con); } else { Log.warn("serversocket has no accept callback"); } if (Log.loggingNet) Log.net( "RDPServer.processExistingConnection: got ACK, removing from unack list: " + packet.getSeqNum()); con.removeUnackPacket(packet.getSeqNum()); } } } if (state == RDPConnection.CLOSE_WAIT) { // reply with a reset on all packets if (!packet.isRst()) { RDPPacket rstPacket = RDPPacket.makeRstPacket(); con.sendPacketImmediate(rstPacket, false); } } if (state == RDPConnection.OPEN) { if (packet.isRst()) { // the other side wants to close the connection // set the state, // dont call con.close() since that will send a reset packet if (Log.loggingDebug) Log.debug("RDPServer.processExistingConnection: got reset packet for con " + con); if (con.getState() != RDPConnection.CLOSE_WAIT) { con.setState(RDPConnection.CLOSE_WAIT); con.setCloseWaitTimer(); // Only invoke callback when moving into CLOSE_WAIT // state. This prevents two calls to connectionReset. Log.net("RDPServer.processExistingConnection: calling reset callback"); ClientConnection.MessageCallback pcb = con.getCallback(); pcb.connectionReset(con); } return false; } if (packet.isSyn()) { // this will close the connection (put into CLOSE_WAIT) // send a reset packet and call the connectionReset callback Log.error( "RDPServer.processExistingConnection: closing connection because we got a syn packet, con=" + con); con.close(); return false; } // TODO: shouldnt it be ok for it to have same seq num? // if it is a 0 data packet? long rcvCur = con.getRcvCur(); if (packet.getSeqNum() <= rcvCur) { if (Log.loggingNet) Log.net("RDPServer.processExistingConnection: seqnum too small - acking/not process"); if (packet.getData() != null) { if (Log.loggingNet) Log.net( "RDPServer.processExistingConnection: sending ack even though seqnum out of range"); RDPPacket replyPacket = new RDPPacket(con); con.sendPacketImmediate(replyPacket, false); } return false; } if (packet.getSeqNum() > (rcvCur + (con.getRcvMax() * 2))) { Log.error("RDPServer.processExistingConnection: seqnum too big - discarding"); return false; } if (packet.isAck()) { if (Log.loggingNet) Log.net("RDPServer.processExistingConnection: processing ack " + packet.getAckNum()); // lock for race condition (read then set) con.getLock().lock(); try { if (packet.getAckNum() >= con.getSendNextSeqNum()) { // acking something we didnt even send yet Log.error( "RDPServer.processExistingConnection: discarding -- got ack #" + packet.getAckNum() + ", but our next send seqnum is " + con.getSendNextSeqNum() + " -- " + con); return false; } if (con.getSendUnackd() <= packet.getAckNum()) { con.setSendUnackd(packet.getAckNum() + 1); if (Log.loggingNet) Log.net( "RDPServer.processExistingConnection: updated send_unackd num to " + con.getSendUnackd() + " (one greater than packet ack) - " + con); con.removeUnackPacketUpTo(packet.getAckNum()); } if (packet.isEak()) { List eackList = packet.getEackList(); Iterator iter = eackList.iterator(); while (iter.hasNext()) { Long seqNum = (Long) iter.next(); if (Log.loggingNet) Log.net("RDPServer.processExistingConnection: got EACK: " + seqNum); con.removeUnackPacket(seqNum.longValue()); } } } finally { con.getLock().unlock(); if (Log.loggingNet) Log.net("RDPServer.processExistingConnection: processed ack " + packet.getAckNum()); } } // process the data byte[] data = packet.getData(); if ((data != null) || packet.isNul()) { dataCounter.add(); // lock - since racecondition: we read then set con.getLock().lock(); try { rcvCur = con.getRcvCur(); // update rcvCur if (Log.loggingNet) Log.net("RDPServer.processExistingConnection: rcvcur is " + rcvCur); ClientConnection.MessageCallback pcb = con.getCallback(); if (pcb == null) { Log.warn("RDPServer.processExistingConnection: no packet callback registered"); } // call callback only if we havent seen it already - eackd if (!con.hasEack(packet.getSeqNum())) { if (con.isSequenced()) { // this is a sequential connection, // make sure this is the 'next' packet // is this the next sequential packet if (packet.getSeqNum() == (rcvCur + 1)) { // this is the next packet if (Log.loggingNet) Log.net( "RDPServer.processExistingConnection: conn is sequenced and received next packet, rcvCur=" + rcvCur + ", packet=" + packet); if ((pcb != null) && (data != null)) { queueForCallbackProcessing(pcb, con, packet); } } else { // not the next packet, place it in queue if (Log.loggingNet) Log.net( "RDPServer.processExistingConnection: conn is sequenced, BUT PACKET is OUT OF ORDER: rcvcur=" + rcvCur + ", packet=" + packet); con.addSequencePacket(packet); } } else { if ((pcb != null) && (data != null)) { // make sure we havent already processed packet queueForCallbackProcessing(pcb, con, packet); } } } else { if (Log.loggingNet) Log.net(con.toString() + " already seen this packet"); } // is this the next sequential packet if (packet.getSeqNum() == (rcvCur + 1)) { con.setRcvCur(rcvCur + 1); if (Log.loggingNet) Log.net( "RDPServer.processExistingConnection RCVD: incremented last sequenced rcvd: " + (rcvCur + 1)); // packet in order - dont add to eack // Take any additional sequential packets off eack long seqNum = rcvCur + 2; while (con.removeEack(seqNum)) { if (Log.loggingNet) Log.net("RDPServer.processExistingConnection: removing/collapsing eack: " + seqNum); con.setRcvCur(seqNum++); } if (con.isSequenced()) { rcvCur++; // since we just process the last one Log.net( "RDPServer.processExistingConnection: connection is sequenced, processing collapsed packets."); // send any saved sequential packets also Iterator iter = con.getSequencePackets().iterator(); while (iter.hasNext()) { RDPPacket p = (RDPPacket) iter.next(); if (Log.loggingNet) Log.net( "rdpserver: stored packet seqnum=" + p.getSeqNum() + ", if equal to (rcvcur + 1)=" + (rcvCur + 1)); if (p.getSeqNum() == (rcvCur + 1)) { Log.net( "RDPServer.processExistingConnection: this is the next packet, processing"); // this is the next packet - update rcvcur rcvCur++; // process this packet Log.net( "RDPServer.processExistingConnection: processing stored sequential packet " + p); byte[] storedData = p.getData(); if (pcb != null && storedData != null) { queueForCallbackProcessing(pcb, con, packet); } iter.remove(); } } } else { if (Log.loggingNet) Log.net("RDPServer.processExistingConnection: connection is not sequenced"); } } else { if (Log.loggingNet) Log.net( "RDPServer.processExistingConnection: RCVD OUT OF ORDER: packet seq#: " + packet.getSeqNum() + ", but last sequential rcvd packet was: " + con.getRcvCur() + " -- not incrementing counter"); if (packet.getSeqNum() > rcvCur) { // must be at least + 2 larger than rcvCur if (Log.loggingNet) Log.net("adding to eack list " + packet); con.addEack(packet); } } } finally { con.getLock().unlock(); } return true; } } return false; }
// getPlayer().sendServerInfo("You make progress on the quest " + // getName() + ". You have " + status.currentCount + "/" + status.targetCount + " " + // status.template.getName()); // } // return; // } // else { // Log.debug("CollectionGoalStatus.handleAcquire: no match"); // } // } // } // finally { // lock.unlock(); // } // } public void handleInvUpdate() { if (Log.loggingDebug) if (Log.loggingDebug) Log.debug("CollectionQuestState.handleAcquire: quest=" + getName()); lock.lock(); try { if (getConcluded()) { return; } // MarsMob player = getPlayer(); // Log.debug("CollectionQuestState.handleInvUpdate: player=" + // player.getName() + // ", questState=" + this.getName() + // ", numGoals=" + // goalsStatus.size()); // Iterator<CollectionGoalStatus> iter = goalsStatus.iterator(); // while(iter.hasNext()) { // CollectionGoalStatus status = iter.next(); // int invCount = player.getInvItemCount(status.template); // Log.debug("CollectionQuestState.handleInvUpdate: checking itemTemplate=" + status.template // + ", invCount=" + invCount); // if (getCompleted()) { // Log.debug("CollectionQuestState.handleInvUpdate: completed"); // // the quest was completed prior to getting this item // if (invCount > status.currentCount) { // // we must have just picked up a quest item // // but we dont need it // continue; // } // else if (invCount == status.currentCount) { // // quest is still completed - you can ignore // continue; // } // // // invCount < status.currentCount // // we must have just dropped an item, and // // the quest is no longer complete // setCompleted(false); // status.currentCount = invCount; // // // send a QuestCompleted event to mobs that perceive us // // so that if one of them can accept this quest for // // completion, it can update its state // QuestCompleted completeEvent = // new QuestCompleted(player, getQuest()); // Engine.getMessageServer().sendToPerceivers(player, // completeEvent, // RDPMessageServer.NON_USERS); // // // send a log update // Event questStateInfo = new QuestStateInfo(player, this); // player.sendEvent(questStateInfo); // // // send text message // player.sendServerInfo("Your quest " + getName() + " is no longer // completed. You have " + status.currentCount + "/" + status.targetCount + " " + // status.template.getName()); // continue; // } // // // quest is not completed // Log.debug("CollectionQuestState.handleInvUpdate: not completed"); // // if (invCount < status.currentCount) { // Log.debug("CollectionQuestState.handleInvUpdate: lost item"); // // we lost an item // status.currentCount = invCount; // // // send a log update // Event questStateInfo = new QuestStateInfo(player, this); // player.sendEvent(questStateInfo); // // // send text message // player.sendServerInfo("You lost an item for quest " + getName() + ". // You have " + status.currentCount + "/" + status.targetCount + " " + // status.template.getName()); // continue; // } // else if (invCount == status.currentCount) { // // we didnt get a new quest item // Log.debug("CollectionQuestState.handleInvUpdate: not quest item"); // continue; // } // if (invCount > status.currentCount) { // // we just got a new needed quest item // Log.debug("CollectionQuestState.handleInvUpdate: got new quest item"); // if (invCount > status.targetCount) { // // we have more than we need // status.currentCount = status.targetCount; // } // else { // status.currentCount = invCount; // } // // // send a log update // Event questStateInfo = new QuestStateInfo(player, this); // player.sendEvent(questStateInfo); // // // send text message // player.sendServerInfo("You make progress on the quest " + getName() + ". // You have " + status.currentCount + "/" + status.targetCount + " " + // status.template.getName()); // // // check if completed and handle if it is // // (sending message to user and also notifying // // mobs nearby in case one of them is a quest // // completer) // completeHandler(); // } // } } finally { lock.unlock(); } }
public static void main(String args[]) { String worldName = System.getProperty("multiverse.worldname"); Properties properties = InitLogAndPid.initLogAndPid(args, worldName, null); System.err.println("Multiverse server version " + ServerVersion.getVersionString()); List<String> agentNames = new LinkedList<String>(); LongOpt[] longopts = new LongOpt[2]; longopts[0] = new LongOpt("pid", LongOpt.REQUIRED_ARGUMENT, null, 2); longopts[1] = new LongOpt("port", LongOpt.REQUIRED_ARGUMENT, null, 3); Getopt opt = new Getopt("DomainServer", args, "a:m:t:p:P:", longopts); int c; int port = DEFAULT_PORT; String portStr = properties.getProperty("multiverse.msgsvr_port"); if (portStr != null) port = Integer.parseInt(portStr); PluginStartGroup pluginStartGroup = new PluginStartGroup(); while ((c = opt.getopt()) != -1) { switch (c) { case 'a': agentNames.add(opt.getOptarg()); break; case 't': case 'm': // ignore RuntimeMarshalling flags opt.getOptarg(); break; case 'p': String pluginSpec = opt.getOptarg(); String[] pluginDef = pluginSpec.split(",", 2); if (pluginDef.length != 2) { System.err.println("Invalid plugin spec format: " + pluginSpec); Log.error("Invalid plugin spec format: " + pluginSpec); System.exit(1); } int expected = Integer.parseInt(pluginDef[1]); pluginStartGroup.add(pluginDef[0], expected); break; case '?': System.exit(1); break; case 'P': break; case 2: // ignore --pid opt.getOptarg(); break; // port case 3: String arg = opt.getOptarg(); port = Integer.parseInt(arg); break; default: break; } } String svrName = System.getProperty("multiverse.loggername"); String runDir = System.getProperty("multiverse.rundir"); // Windows non-Cygwin only - save process ID for status script if (System.getProperty("os.name").contains("Windows") && svrName != null && runDir != null) { saveProcessID(svrName, runDir); } // parse command-line options domainServer = new DomainServer(port); domainServer.setAgentNames(agentNames); domainServer.setWorldName(worldName); domainServer.start(); pluginStartGroup.prepareDependencies(properties, worldName); domainServer.addPluginStartGroup(pluginStartGroup); pluginStartGroup.pluginAvailable("Domain", "Domain"); String timeoutStr = properties.getProperty("multiverse.startup_timeout"); int timeout = 120; if (timeoutStr != null) { timeout = Integer.parseInt(timeoutStr); } ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); ScheduledFuture<?> timeoutHandler = scheduler.schedule(new TimeoutRunnable(timeout), timeout, TimeUnit.SECONDS); javax.crypto.SecretKey domainKey = SecureTokenUtil.generateDomainKey(); // XXX Use a random keyID for now. Ideally, this would be semi-unique. long keyId = new Random().nextLong(); encodedDomainKey = Base64.encodeBytes(SecureTokenUtil.encodeDomainKey(keyId, domainKey)); Log.debug("generated domain key: " + encodedDomainKey); try { pluginStartGroup.awaitDependency("Domain"); timeoutHandler.cancel(false); String availableMessage = properties.getProperty("multiverse.world_available_message"); String availableFile = properties.getProperty("multiverse.world_available_file"); if (availableFile != null) touchFile(FileUtil.expandFileName(availableFile)); if (availableMessage != null) System.err.println("\n" + availableMessage); while (true) { Thread.sleep(10000000); } } catch (Exception ex) { Log.exception("DomainServer.main", ex); } }