예제 #1
0
		/// <summary> This is the core routine for decoding incoming messages and deciding what should be
		/// done with them.  We have registered ourself with DProtocol to be notified when any
		/// incoming messages have been received.
		/// 
		/// It is important to note that we should not rely on the contents of the message
		/// since it may be reused after we exit this method.
		/// </summary>
		public virtual void  messageArrived(DMessage msg, DProtocol which)
		{
			/* at this point we just open up a big switch statement and walk through all possible cases */
			int type = msg.Type;
			//		System.out.println("manager msg = "+DMessage.inTypeName(type));
			
			switch (type)
			{
				
				case DMessage.InVersion: 
				{
                    long ver = msg.getDWord();
					m_playerVersion = (int) ver;
					break;
				}
				
				
				case DMessage.InErrorExecLimit: 
				{
					handleFaultEvent(new RecursionLimitFault());
					break;
				}
				
				
				case DMessage.InErrorWith: 
				{
					handleFaultEvent(new InvalidWithFault());
					break;
				}
				
				
				case DMessage.InErrorProtoLimit: 
				{
					handleFaultEvent(new ProtoLimitFault());
					break;
				}
				
				
				case DMessage.InErrorURLOpen: 
				{
                    String url = msg.getString();
					handleFaultEvent(new InvalidURLFault(url));
					break;
				}
				
				
				case DMessage.InErrorTarget: 
				{
                    String name = msg.getString();
					handleFaultEvent(new InvalidTargetFault(name));
					break;
				}
				
				
				case DMessage.InErrorException: 
				{
                    long offset = msg.getDWord();
					// As of FP9, the player will also send the "toString()" message
					// of the exception.  But for backward compatibility with older
					// players, we won't assume that that is there.
					String exceptionMessage;
					if (msg.Remaining > 0)
                        exceptionMessage = msg.getString();
					else
						exceptionMessage = ""; //$NON-NLS-1$
					handleFaultEvent(new ExceptionFault(exceptionMessage));
					break;
				}
				
				
				case DMessage.InErrorStackUnderflow: 
				{
                    long offset = msg.getDWord();
					handleFaultEvent(new StackUnderFlowFault());
					break;
				}
				
				
				case DMessage.InErrorZeroDivide: 
				{
                    long offset = msg.getDWord();
					handleFaultEvent(new DivideByZeroFault());
					break;
				}
				
				
				case DMessage.InErrorScriptStuck: 
				{
					handleFaultEvent(new ScriptTimeoutFault());
					break;
				}
				
				
				case DMessage.InErrorConsole: 
				{
                    String s = msg.getString();
					handleFaultEvent(new ConsoleErrorFault(s));
					break;
				}
				
				
				case DMessage.InTrace: 
				{
                    String text = msg.getString();
					addEvent(new TraceEvent(text));
					break;
				}
				
				
				case DMessage.InSquelch: 
				{
                    long state = msg.getDWord();
					m_squelchEnabled = (state != 0)?true:false;
					break;
				}
				
				
				case DMessage.InParam: 
				{
                    String name = msg.getString();
                    String value = msg.getString();
					
					// here's where we get movie = URL and password which I'm not sure what to do with?
					//				System.out.println(name+"="+value);
					m_parms[name] = value;
					
					// if string is a "movie", then this is a URL
					if (name.StartsWith("movie"))
					//$NON-NLS-1$
						m_uri = convertToURI(value);
					break;
				}
				
				
				case DMessage.InPlaceObject: 
				{
                    long objId = msg.getDWord();
					String path = msg.getString();
					//				m_bag.placeObject((int)objId, path);
					break;
				}
				
				
				case DMessage.InSetProperty: 
				{
                    long objId = msg.getDWord();
					int item = msg.getWord();
                    String value = msg.getString();
					break;
				}
				
				
				case DMessage.InNewObject: 
				{
                    long objId = msg.getDWord();
					break;
				}
				
				
				case DMessage.InRemoveObject: 
				{
                    long objId = msg.getDWord();
					//				m_bag.removeObject((int)objId);
					break;
				}
				
				
				case DMessage.InSetVariable: 
				{
                    long objId = msg.getDWord();
                    String name = msg.getString();
					int dType = msg.getWord();
                    int flags = (int)msg.getDWord();
                    String value = msg.getString();
					
					//				m_bag.createVariable((int)objId, name, dType, flags, value);
					break;
				}
				
				
				case DMessage.InDeleteVariable: 
				{
                    long objId = msg.getDWord();
                    String name = msg.getString();
					//				m_bag.deleteVariable((int)objId, name);
					break;
				}
				
				
				case DMessage.InScript: 
				{
                    int module = (int)msg.getDWord();
                    int bitmap = (int)msg.getDWord();
                    String name = msg.getString(); // in "basepath;package;filename" format
                    String text = msg.getString();
					int swfIndex = - 1;
					
					/* new in flash player 9: player tells us what swf this is for */
					if (msg.Remaining >= 4)
                        swfIndex = (int)msg.getDWord();
					
					lock (m_source)
					{
						// create new source file
						if (putSource(swfIndex, module, bitmap, name, text))
						{
							// have we changed the list since last query
							if (!m_sourceListModified)
								addEvent(new FileListModifiedEvent());
							
							m_sourceListModified = true; /* current source list is stale */
						}
					}
					break;
				}
				
				
				case DMessage.InRemoveScript: 
				{
                    long module = msg.getDWord();
					lock (m_source)
					{
						if (removeSource((int) module))
						{
							// have we changed the list since last query
							if (!m_sourceListModified)
								addEvent(new FileListModifiedEvent());
							
							m_sourceListModified = true; /* current source list is stale */
						}
					}
					break;
				}
				
				
				case DMessage.InAskBreakpoints: 
				{
					// the player has just loaded a swf and we know the player
					// has halted, waiting for us to continue.  The only caveat
					// is that it looks like it still does a number of things in
					// the background which take a few seconds to complete.
					if (m_suspendInfo == null)
						m_suspendInfo = new DSuspendInfo(SuspendReason.ScriptLoaded, 0, 0, 0, 0);
					break;
				}
				
				
				case DMessage.InBreakAt: 
				{
                    long bp = msg.getDWord();
                    long id = msg.getDWord();
                    String stack = msg.getString();
					//				System.out.println(msg.getInTypeName()+",bp="+(bp&0xffff)+":"+(bp>>16)+",id="+id+",stack=\n"+stack);
					
					//System.out.println("InBreakAt");
					
					int module = DLocation.decodeFile(bp);
					int line = DLocation.decodeLine(bp);
					addEvent(new BreakEvent(module, line));
					break;
				}
				
				
				case DMessage.InContinue: 
				{
					/* we are running again so trash all our variable contents */
					continuing();
					break;
				}
				
				
				case DMessage.InSetLocalVariables: 
				{
                    long objId = msg.getDWord();
					//				m_bag.markObjectLocal((int)objId, true);
					break;
				}
				
				
				case DMessage.InSetBreakpoint: 
				{
                    long count = msg.getDWord();
					while (count-- > 0)
					{
                        long bp = msg.getDWord();
						
						int fileId = DLocation.decodeFile(bp);
						int line = DLocation.decodeLine(bp);
						
						DModule file = getSource(fileId);
						DLocation l = new DLocation(file, line);
						
						if (file != null)
							addBreakpoint((int) bp, l);
					}
					break;
				}
				
				
				case DMessage.InNumScript: 
				{
					/* lets us know how many scripts there are */
                    int num = (int)msg.getDWord();
					DSwfInfo swf;
					
					/*
					* New as of flash player 9: another dword indicating which swf this is for.
					* That means we don't have to guess whether this is for an old SWF
					* which has just had some more modules loaded, or for a new SWF!
					*/
					if (msg.Remaining >= 4)
					{
                        int swfIndex = (int)msg.getDWord();
						swf = getOrCreateSwfInfo(swfIndex);
						m_lastSwfInfo = swf;
					}
					else
					{
						/* This is not flash player 9 (or it is an early build of fp9).
						*
						* We use this message as a trigger that a new swf has been loaded, so make sure
						* we are ready to accept the scripts.
						*/
						swf = ActiveSwfInfo;
					}
					
					// It is NOT an error for the player to have sent us a new,
					// different sourceExpectedCount from whatever we had before!
					// In fact, this happens all the time, whenever a SWF has more
					// than one ABC.
					swf.SourceExpectedCount = num;
					break;
				}
				
				
				case DMessage.InRemoveBreakpoint: 
				{
                    long count = msg.getDWord();
					while (count-- > 0)
					{
                        long bp = msg.getDWord();
						removeBreakpoint((int) bp);
					}
					break;
				}
				
				
				case DMessage.InBreakAtExt: 
				{
                    long bp = msg.getDWord();
                    long num = msg.getDWord();
					
					//				System.out.println(msg.getInTypeName()+",bp="+(bp&0xffff)+":"+(bp>>16));
					/* we have stack info to store away */
					clearFrames(); // just in case
					int depth = 0;
					while (num-- > 0)
					{
                        long bpi = msg.getDWord();
                        long id = msg.getDWord();
                        String stack = msg.getString();
						int module = DLocation.decodeFile(bpi);
						int line = DLocation.decodeLine(bpi);
						DModule m = getSource(module);
						DStackContext c = new DStackContext(module, line, m, (int) id, stack, depth);
						// If addFrame() returns false, that means it chose to ignore this
						// frame, so we do NOT want to increment our depth for the next
						// time through the loop.  If it returns true, then we do want to.
						if (addFrame(c))
							++depth;
						//					System.out.println("   this="+id+",@"+(bpi&0xffff)+":"+(bpi>>16)+",stack="+stack);
					}
					mapOldFramesToNew();
					break;
				}
				
				
				case DMessage.InFrame: 
				{
					// For InFrame the first element is really our frame id
					DValue frame = null;
					DVariable child = null;
					System.Collections.ArrayList v = new System.Collections.ArrayList();
					System.Collections.ArrayList registers = new System.Collections.ArrayList();

                    int depth = (int)msg.getDWord(); // depth of frame
					
					// make sure we have a valid depth
					if (depth > - 1)
					{
						// first thing is number of registers
                        int num = (int)msg.getDWord();
						for (int i = 0; i < num; i++)
							registers.Add(extractRegister(msg, i + 1));
					}
					
					int currentArg = - 1;
					bool gettingScopeChain = false;
					
					// then our frame itself
					while (msg.Remaining > 0)
					{
                        long frameId = msg.getDWord();
						
						if (frame == null)
						{
							frame = getOrCreateValue(frameId);
							extractVariable(msg); // put the rest of the info in the trash
						}
						else
						{
							child = extractVariable(msg);
							if (currentArg == - 1 && child.getName().Equals(ARGUMENTS_MARKER))
							{
								currentArg = 0;
								gettingScopeChain = false;
							}
							else if (child.getName().Equals(SCOPE_CHAIN_MARKER))
							{
								currentArg = - 1;
								gettingScopeChain = true;
							}
							else if (currentArg >= 0)
							{
								// work around a compiler bug: If the variable's name is "undefined",
								// then change its name to "_argN", where "N" is the argument index,
								// e.g. _arg1, _arg2, etc.
								++currentArg;
								if (child.getName().Equals("undefined"))
								//$NON-NLS-1$
									child.setName("_arg" + currentArg); //$NON-NLS-1$
							}
							
							// All args and locals get added as "children" of
							// the frame; but scope chain entries do not.
							if (!gettingScopeChain)
								addVariableMember(frameId, child);
							
							// Everything gets added to the ordered list of
							// variables that came in.
							v.Add(child);
						}
					}
					
					// let's transfer our newly gained knowledge into the stack context
					if (depth == 0)
						populateRootNode(frame, v);
					else
						populateFrame(depth, v);
					
					break;
				}
				
				
				case DMessage.InOption: 
				{
                    String s = msg.getString();
                    String v = msg.getString();
					m_options[s] = v;
					break;
				}
				
				
				case DMessage.InGetVariable: 
				{
					// For InGetVariable the first element is the original entity we requested
					DValue parent = null;
					DVariable child = null;
					String definingClass = null;
					int level = 0;
					int highestLevelWithMembers = - 1;
					System.Collections.IList classes = new System.Collections.ArrayList();
					
					while (msg.Remaining > 0)
					{
                        long parentId = msg.getDWord();
						
						// build or get parent node
						if (parent == null)
						{
                            String name = msg.getString();
							
							// pull the contents of the node which normally are disposed of except if we did a 0,name call
							m_lastInGetVariable = extractVariable(msg, name);
							
							parent = getOrCreateValue(parentId);
						}
						else
						{
							// extract the child and add it to the parent.
							child = extractVariable(msg);
							if (showMember(child))
							{
								if (child.isAttributeSet(VariableAttribute.IS_DYNAMIC))
								{
									// Dynamic attributes always come in marked as a member of
									// class "Object"; but to the user, it makes more sense to
									// consider them as members of the topmost class.
									if (classes.Count > 0)
									{
										child.setDefiningClass(0, (String) classes[0]);
										highestLevelWithMembers = Math.Max(highestLevelWithMembers, 0);
									}
								}
								else
								{
									child.setDefiningClass(level, definingClass);
									if (definingClass != null)
									{
										highestLevelWithMembers = Math.Max(highestLevelWithMembers, level);
									}
								}
								addVariableMember(parent.Id, child);
							}
							else
							{
								if (isTraits(child))
								{
									definingClass = child.QualifiedName;
									level = classes.Count;
									
									// If the traits name end with "$", then it represents a class object --
									// in other words, the variables inside it are static variables of that
									// class.  In that case, we need to juggle the information.  For example,
									// if we are told that a variable is a member of "MyClass$", we actually
									// store it into the information for "MyClass".
									if (definingClass.EndsWith("$"))
									{
										//$NON-NLS-1$
										String classWithoutDollar = definingClass.Substring(0, (definingClass.Length - 1) - (0));
										int indexOfClass = classes.IndexOf(classWithoutDollar);
										if (indexOfClass != - 1)
										{
											level = indexOfClass;
											definingClass = classWithoutDollar;
										}
									}
									
									// It wasn't static -- so, add this class to the end of the list of classes
									if (level == classes.Count)
									{
										classes.Add(definingClass);
									}
								}
							}
						}
					}
					
					if (parent != null && parent.getClassHierarchy(true) == null)
					{
                        String[] classesArray = new String[classes.Count];
                        int index = 0;

                        foreach (String className in classes)
                        {
                            classesArray[index++] = className;
                        }

						parent.setClassHierarchy(classesArray, highestLevelWithMembers + 1);
					}
					
					break;
				}
				
				
				case DMessage.InWatch: 
				// for AS2; sends 16-bit ID field
				case DMessage.InWatch2:  // for AS3; sends 32-bit ID field
					{
						// This message is sent whenever a watchpoint is added
						// modified or removed.
						//
						// For an addition, flags will be non-zero and
						// success will be true.
						//
						// For a modification flags  will be non-zero.
						// and oldFlags will be non-zero and success
						// will be true.  Additionally oldFlags will not
						// be equal to flags.
						//
						// For a removal flags will be zero.  oldFlags
						// will be non-zero.
						//
						// flags identifies the type of watchpoint added,
						// see WatchKind.
						//
						// success indicates whether the operation was successful
						//
						// request.   It will be associated with the watchpoint.
                        int success = msg.getWord();
                        int oldFlags = msg.getWord();
                        int oldTag = msg.getWord();
                        int flags = msg.getWord();
                        int tag = msg.getWord();
						// for AS2, the ID came in above as a Word.  For AS3, the above value is
						// bogus, and it has been sent again as a DWord.
                        int id = (int)((type == DMessage.InWatch2) ? msg.getDWord() : msg.getWord());
                        String name = msg.getString();
						
						if (success != 0)
						{
							if (flags == 0)
							{
								removeWatchpoint(oldTag);
							}
							else
							{
								// modification or addition is the same to us
								// a new watch is created and added into the table
								// while any old entry if it exists is removed.
								removeWatchpoint(oldTag);
								DWatch w = new DWatch(id, name, flags, tag);
								addWatchpoint(w);
							}
						}
						break;
					}
				
				
				case DMessage.InGetSwf: 
				{
					// we only house the swf temporarily, PlayerSession then
					// pieces it back into swfinfo record.  Also, we don't
					// send any extra data in the message so that we need not
					// copy the bytes.
					m_swf = msg.Data;
					break;
				}
				
				
				case DMessage.InGetSwd: 
				{
					// we only house the swd temporarily, PlayerSession then
					// pieces it back into swfinfo record.
					m_swd = msg.Data;
					break;
				}
				
				
				case DMessage.InBreakReason: 
					{
						// the id map 1-1 with out SuspendReason interface constants
                        int suspendReason = msg.getWord();
                        int suspendPlayer = msg.getWord(); // item index of player
                        int breakOffset = (int)msg.getDWord(); // current script offset
                        int prevBreakOffset = (int)msg.getDWord(); // prev script offset
                        int nextBreakOffset = (int)msg.getDWord(); // next script offset
						m_suspendInfo = new DSuspendInfo(suspendReason, suspendPlayer, breakOffset, prevBreakOffset, nextBreakOffset);
						
						// augment the current frame with this information.  It
						// should work ok since we only get this message after a
						// InBreakAtExt message
						try
						{
							DStackContext c = getFrame(0);
							c.Offset = breakOffset;
							c.SwfIndex = suspendPlayer;
						}
						catch (Exception e)
						{
							if (Trace.error)
							{
								Trace.trace("Oh my god, gag me with a spoon...getFrame(0) call failed"); //$NON-NLS-1$
                                Console.Error.Write(e.StackTrace);
                                Console.Error.Flush();
                            }
						}
						break;
					}
					
					// obtain raw action script byte codes
				
				case DMessage.InGetActions: 
					{
                        int item = msg.getWord();
                        int rsvd = msg.getWord();
                        int at = (int)msg.getDWord();
                        int len = (int)msg.getDWord();
						int i = 0;
						
						m_actions = (len <= 0)?null:new byte[len];
						while (len-- > 0)
                            m_actions[i++] = (byte)msg.getByte();
						
						break;
					}
					
					// obtain data about a SWF
				
				case DMessage.InSwfInfo: 
					{
                        int count = msg.getWord();
						for (int i = 0; i < count; i++)
						{
                            long index = msg.getDWord();
                            long id = msg.getDWord();
							
							// get it
							DSwfInfo info = getOrCreateSwfInfo((int) index);
							
							// remember which was last seen
							m_lastSwfInfo = info;
							
							if (id != 0)
							{
                                bool debugComing = (msg.getByte() == 0) ? false : true;
                                byte vmVersion = (byte)msg.getByte(); // AS vm version number (1 = avm+, 0 == avm-)
                                int rsvd1 = msg.getWord();

                                long swfSize = msg.getDWord();
                                long swdSize = msg.getDWord();
                                long scriptCount = msg.getDWord();
                                long offsetCount = msg.getDWord();
                                long breakpointCount = msg.getDWord();

                                long port = msg.getDWord();
                                String path = msg.getString();
                                String url = msg.getString();
                                String host = msg.getString();
								
								// now we read in the swd debugging map (which provides
								// local to global mappings of the script ids
                                long num = msg.getDWord();
								IntMap local2global = new IntMap();
								int minId = Int32.MaxValue;
								int maxId = Int32.MinValue;
								for (int j = 0; j < num; j++)
								{
                                    long local = msg.getDWord();
                                    long global = msg.getDWord();
									local2global.put((int) local, (Int32) global);
									minId = ((int) global < minId)?(int) global:minId;
									maxId = ((int) global > maxId)?(int) global:maxId;
								}
								
								// If its a new record then the swf size would have been unknown at creation time
								bool justCreated = (info.SwfSize == 0);
								
								// if we are a avm+ engine then we don't wait for the swd to load
								if (vmVersion > 0)
								{
									debugComing = false;
									info.VmVersion = vmVersion;
									info.setPopulated(); // added by mmorearty on 9/5/05 for RSL debugging
								}
								
								// update this swfinfo with the lastest data
								info.freshen(id, path, url, host, port, debugComing, swfSize, swdSize, breakpointCount, offsetCount, scriptCount, local2global, minId, maxId);
								// now tie any scripts that have been loaded into this swfinfo object
								tieScriptsToSwf(info);
								
								// notify if its newly created
								if (justCreated)
									addEvent(new SwfLoadedEvent(id, (int) index, path, url, host, port, swfSize));
							}
							else
							{
								// note our state before marking it
								bool alreadyUnloaded = info.isUnloaded();
								
								// clear it out
								info.setUnloaded();
								
								// notify if this information is new.
								if (!alreadyUnloaded)
									addEvent(new SwfUnloadedEvent(info.Id, info.Path, (int) index));
							}
							//					System.out.println("[SWFLOAD] Loaded "+path+", size="+swfSize+", scripts="+scriptCount);
						}
						break;
					}
					
					// obtain the constant pool of some player
				
				case DMessage.InConstantPool: 
					{
                        int item = msg.getWord();
                        int count = (int)msg.getDWord();
						
						String[] pool = new String[count];
						for (int i = 0; i < count; i++)
						{
                            long id = msg.getDWord();
							DVariable var = extractVariable(msg);
							
							// we only need the contents of the variable
							pool[i] = var.getValue().ValueAsString;
						}
						m_lastConstantPool = pool;
						break;
					}
					
					// obtain one or more function name line number mappings.
				
				case DMessage.InGetFncNames: 
				{
                    long id = msg.getDWord(); // module id
                    long count = msg.getDWord(); // number of entries
					
					// get the DModule
					DModule m = getSource((int) id);
					if (m != null)
					{
						for (int i = 0; i < count; i++)
						{
                            int offset = (int)msg.getDWord();
                            int firstLine = (int)msg.getDWord();
                            int lastLine = (int)msg.getDWord();
                            String name = msg.getString();
							
							// now add the entries
							m.addLineFunctionInfo(offset, firstLine, lastLine, name);
						}
					}
					break;
				}
				
				
				default: 
				{
					break;
				}
				
			}
		}
예제 #2
0
		/// <summary> Frame stack management related stuff</summary>
		/// <returns> true if we added this frame; false if we ignored it
		/// </returns>
		internal virtual bool addFrame(DStackContext ds)
		{
			m_frames.Add(ds);
			return true;
		}