1 Describe different types of Assemblers.
Assembly language
Assembly language is converted into executable machine code by a utility program referred to as an assembler ; the conversion process is referred to as assembly, or assembling the code.
Assembly language uses a mnemonic to represent each low-level machine instruction or operation . Typical operations require one or more operands in order to form a complete instruction, and most assemblers can therefore take labels, symbols and expressions as operands to represent addresses and other constants, freeing the programmer from tedious manual calculations. Macro assemblers include a macroinstruction facility so that (parameterized) assembly language text can be represented by a name, and that name can be used to insert the expanded text into other code. Many assemblers offer additional mechanisms to facilitate program development, to control the assembly process, and to aid debugging .
Key concepts
Assembler
An assembler is a program which creates object code by translating combinations of mnemonics and syntax for operations and addressing modes into their numerical equivalents. This representation typically includes an operation code (“opcode”) as well as other control bits . [2] The assembler also calculates constant expressions and resolves symbolic names for memory locations and other entities. [3] The use of symbolic references is a key feature of assemblers, saving tedious calculations and manual address updates after program modifications. Most assemblers also include macro facilities for performing textual substitution – e.g., to generate common short sequences of instructions as inline , instead of called subroutines .
Some assemblers may also be able to perform some simple types of instruction set -specific optimizations . One concrete example of this may be the ubiquitous x86 assemblers from various vendors. Most of them are able to perform jump-instruction replacements (long jumps replaced by short or relative jumps) in any number of passes, on request. Others may even do simple rearrangement or insertion of instructions, such as some assemblers for RISC architectures that can help optimize a sensible instruction scheduling to exploit the CPU pipeline as efficiently as possible.[ citation needed]
Like early programming languages such as Fortran , Algol, Cobol and Lisp , assemblers have been available since the 1950s and the first generations of text based computer interfaces . However, assemblers came first as they are far simpler to write than compilers for high-level languages . This is because each mnemonic along with the addressing modes and operands of an instruction translates rather directly into the numeric representations of that particular instruction, without much context or analysis. There have also been several classes of translators and semi automatic code generators with properties similar to both assembly and high level languages, with speedcode as perhaps one of the better known examples.
There may be several assemblers with different syntax for a particular CPU or instruction set architecture . For instance, an instruction to add memory data to a register in a x86 -family processor might be add eax,[ebx], in original Intel syntax , whereas this would be written addl (%ebx),%eax in the AT&T syntax used by the GNU Assembler . Despite different appearances, different syntactic forms generally generate the same numeric machine code , see further below. A single assembler may also have different modes in order to support variations in syntactic forms as well as their exact semantic interpretations (such as FASM -syntax, TASM -syntax, ideal mode etc., in the special case of x86 assembly programming).
Number of passes
There are two types of assemblers based on how many passes through the source are needed to produce the executable program.
· One-pass assemblers go through the source code once. Any symbol used before it is defined will require “errata” at the end of the object code (or, at least, no earlier than the point where the symbol is defined) telling the linker or the loader to “go back” and overwrite a placeholder which had been left where the as yet undefined symbol was used.
· Multi-pass assemblers create a table with all symbols and their values in the first passes, then use the table in later passes to generate code.
In both cases, the assembler must be able to determine the size of each instruction on the initial passes in order to calculate the addresses of subsequent symbols. This means that if the size of an operation referring to an operand defined later depends on the type or distance of the operand, the assembler will make a pessimistic estimate when first encountering the operation, and if necessary pad it with one or more “ no-operation ” instructions in a later pass or the errata. In an assembler with peephole optimization , addresses may be recalculated between passes to allow replacing pessimistic code with code tailored to the exact distance from the target.
The original reason for the use of one-pass assemblers was speed of assembly – often a second pass would require rewinding and rereading a tape or rereading a deck of cards . With modern computers this has ceased to be an issue. The advantage of the multi-pass assembler is that the absence of errata makes the linking process (or the program load if the assembler directly produces executable code) faster. [4]
High-level assemblers
More sophisticated high-level assemblers provide language abstractions such as:
· Advanced control structures
· High-level procedure/function declarations and invocations
· High-level abstract data types, including structures/records, unions, classes, and sets
· Sophisticated macro processing (although available on ordinary assemblers since the late 1950s for IBM 700 series and since the 1960s for IBM/360, amongst other machines)
· Object-oriented programming features such as classes , objects , abstraction , polymorphism , and inheritance [5]
See Language design below for more details.
Assembly language
A program written in assembly language consists of a series of (mnemonic) processor instructions and meta-statements (known variously as directives, pseudo-instructions and pseudo-ops), comments and data. Assembly language instructions usually consist of an opcode mnemonic followed by a list of data, arguments or parameters. [6] These are translated by an assembler into machine language instructions that can be loaded into memory and executed.
For example, the instruction below tells an x86 / IA-32 processor to move an immediate 8-bit value into a register . The binary code for this instruction is 10110 followed by a 3-bit identifier for which register to use. The identifier for the AL register is 000, so the following machine code loads the AL register with the data 01100001. [7]
The Intel opcode 10110000 (B0) copies an 8-bit value into the AL register, while 10110001 (B1) moves it into CL and 10110010 (B2) does so into DL. Assembly language examples for these follow. [7]
MOV AL, 1h ; Load AL with immediate value 1
MOV CL, 2h ; Load CL with immediate value 2
MOV DL, 3h ; Load DL with immediate value 3
The syntax of MOV can also be more complex as the following examples show. [8]
MOV EAX, [EBX] ; Move the 4 bytes in memory at the address contained in EBX into EAX
MOV [ESI+EAX], CL ; Move the contents of CL into the byte at address ESI+EAX
In each case, the MOV mnemonic is translated directly into an opcode in the ranges 88-8E, A0-A3, B0-B8, C6 or C7 by an assembler, and the programmer does not have to know or remember which. [7]
Transforming assembly language into machine code is the job of an assembler, and the reverse can at least partially be achieved by a disassembler . Unlike high-level languages , there is usually a one-to-one correspondence between simple assembly statements and machine language instructions. However, in some cases, an assembler may providepseudoinstructions (essentially macros) which expand into several machine language instructions to provide commonly needed functionality. For example, for a machine that lacks a “branch if greater or equal” instruction, an assembler may provide a pseudoinstruction that expands to the machine’s “set if less than” and “branch if zero (on the result of the set instruction)”. Most full-featured assemblers also provide a rich macro language (discussed below) which is used by vendors and programmers to generate more complex code and data sequences.
Each computer architecture has its own machine language. Computers differ in the number and type of operations they support, in the different sizes and numbers of registers, and in the representations of data in storage. While most general-purpose computers are able to carry out essentially the same functionality, the ways they do so differ; the corresponding assembly languages reflect these differences.
Multiple sets of mnemonics or assembly-language syntax may exist for a single instruction set, typically instantiated in different assembler programs. In these cases, the most popular one is usually that supplied by the manufacturer and used in its documentation.
Language design
Basic elements
There is a large degree of diversity in the way the authors of assemblers categorize statements and in the nomenclature that they use. In particular, some describe anything other than a machine mnemonic or extended mnemonic as a pseudo-operation (pseudo-op). A typical assembly language consists of 3 types of instruction statements that are used to define program operations:
· Opcode mnemonics
· Data definitions
· Assembly directives
Opcode mnemonics and extended mnemonics
Instructions (statements) in assembly language are generally very simple, unlike those in high-level languages . Generally, a mnemonic is a symbolic name for a single executable machine language instruction (an opcode), and there is at least one opcode mnemonic defined for each machine language instruction. Each instruction typically consists of anoperation or opcode plus zero or more operands . Most instructions refer to a single value, or a pair of values. Operands can be immediate (value coded in the instruction itself), registers specified in the instruction or implied, or the addresses of data located elsewhere in storage. This is determined by the underlying processor architecture: the assembler merely reflects how this architecture works. Extended mnemonics are often used to specify a combination of an opcode with a specific operand, e.g., the System/360 assemblers use B as an extended mnemonic for BC with a mask of 15 and NOP (“NO OPeration” – do nothing for one step) for BC with a mask of 0.
Extended mnemonics are often used to support specialized uses of instructions, often for purposes not obvious from the instruction name. For example, many CPU’s do not have an explicit NOP instruction, but do have instructions that can be used for the purpose. In 8086 CPUs the instruction xchg ax,ax is used for nop, with nop being a pseudo-opcode to encode the instruction xchg ax,ax. Some disassemblers recognize this and will decode the xchg ax,ax instruction as nop. Similarly, IBM assemblers for System/360 and System/370 use the extended mnemonics NOP and NOPR for BC and BCR with zero masks. For the SPARC architecture, these are known as synthetic instructions. [9]
Some assemblers also support simple built-in macro-instructions that generate two or more machine instructions. For instance, with some Z80 assemblers the instruction ld hl,bc is recognized to generate ld l,c followed by ld h,b. [10] These are sometimes known as pseudo-opcodes.
Mnemonics are arbitrary symbols; in 1985 the IEEE published Standard 694 for a uniform set of mnemonics to be used by all assemblers. The standard has since been withdrawn.
Data directives
There are instructions used to define data elements to hold data and variables. They define the type of data, the length and the alignment of data. These instructions can also define whether the data is available to outside programs (programs assembled separately) or only to the program in which the data section is defined. Some assemblers classify these as pseudo-ops.
Assembly directives
Assembly directives, also called pseudo-opcodes, pseudo-operations or pseudo-ops, are instructions that are executed by an assembler at assembly time, not by a CPU at run time. The names of pseudo-ops often start with a dot to distinguish them from machine instructions. Pseudo-ops can make the assembly of the program dependent on parameters input by a programmer, so that one program can be assembled different ways, perhaps for different applications. Or, a pseudo-op can be used to manipulate presentation of a program to make it easier to read and maintain. Another common use of pseudo-ops is to reserve storage areas for run-time data and optionally initialize their contents to known values.
Symbolic assemblers let programmers associate arbitrary names ( labels or symbols) with memory locations and various constants. Usually, every constant and variable is given a name so instructions can reference those locations by name, thus promoting self-documenting code . In executable code, the name of each subroutine is associated with its entry point, so any calls to a subroutine can use its name. Inside subroutines, GOTO destinations are given labels. Some assemblers support local symbols which are lexically distinct from normal symbols (e.g., the use of “10$” as a GOTO destination).
Some assemblers, such as NASM provide flexible symbol management, letting programmers manage different namespaces , automatically calculate offsets within data structures , and assign labels that refer to literal values or the result of simple computations performed by the assembler. Labels can also be used to initialize constants and variables with relocatable addresses.
Assembly languages, like most other computer languages, allow comments to be added to program source code that will be ignored during assembly. Judicious commenting is essential in assembly language programs, as the meaning and purpose of a sequence of binary machine instructions can be difficult to determine. The “raw” (uncommented) assembly language generated by compilers or disassemblers is quite difficult to read when changes must be made.
Macros
Many assemblers support predefined macros, and others support programmer-defined (and repeatedly re-definable) macros involving sequences of text lines in which variables and constants are embedded. This sequence of text lines may include opcodes or directives. Once a macro has been defined its name may be used in place of a mnemonic. When the assembler processes such a statement, it replaces the statement with the text lines associated with that macro, then processes them as if they existed in the source code file (including, in some assemblers, expansion of any macros existing in the replacement text). Macros in this sense date to IBM autocoders of the 1950s.[citation needed]
This definition of “macro” is slightly different from the use of the term in other contexts, like the C programming language . C macros created through the #define directive are typically just one line, or a few lines at most. Assembler macro instructions can be lengthy “programs” by themselves, executed by interpretation by the assembler during assembly.
Since macros can have ‘short’ names but expand to several or indeed many lines of code, they can be used to make assembly language programs appear to be far shorter, requiring fewer lines of source code, as with higher level languages. They can also be used to add higher levels of structure to assembly programs, optionally introduce embedded debugging code via parameters and other similar features.
Macro assemblers often allow macros to take parameters . Some assemblers include quite sophisticated macro languages, incorporating such high-level language elements as optional parameters, symbolic variables, conditionals, string manipulation, and arithmetic operations, all usable during the execution of a given macro, and allowing macros to save context or exchange information. Thus a macro might generate numerous assembly language instructions or data definitions, based on the macro arguments. This could be used to generate record-style data structures or “unrolled” loops, for example, or could generate entire algorithms based on complex parameters. An organization using assembly language that has been heavily extended using such a macro suite can be considered to be working in a higher-level language, since such programmers are not working with a computer’s lowest-level conceptual elements.
Macros were used to customize large scale software systems for specific customers in the mainframe era and were also used by customer personnel to satisfy their employers’ needs by making specific versions of manufacturer operating systems. This was done, for example, by systems programmers working with IBM ‘s Conversational Monitor System / Virtual Machine ( VM/CMS ) and with IBM’s “real time transaction processing” add-ons, Customer Information Control System CICS , and ACP / TPF , the airline/financial system that began in the 1970s and still runs many large computer reservations systems (CRS) and credit card systems today.
It was also possible to use solely the macro processing abilities of an assembler to generate code written in completely different languages, for example, to generate a version of a program in COBOL using a pure macro assembler program containing lines of COBOL code inside assembly time operators instructing the assembler to generate arbitrary code.
This was because, as was realized in the 1960s, the concept of “macro processing” is independent of the concept of “assembly”, the former being in modern terms more word processing, text processing, than generating object code. The concept of macro processing appeared, and appears, in the C programming language, which supports “preprocessor instructions” to set variables, and make conditional tests on their values. Note that unlike certain previous macro processors inside assemblers, the C preprocessor was not Turing-complete because it lacked the ability to either loop or “go to”, the latter allowing programs to loop.
Despite the power of macro processing, it fell into disuse in many high level languages (major exceptions being C/C++ and PL/I ) while remaining a perennial for assemblers.
Macro parameter substitution is strictly by name: at macro processing time, the value of a parameter is textually substituted for its name. The most famous class of bugs resulting was the use of a parameter that itself was an expression and not a simple name when the macro writer expected a name. In the macro:
foo: macro a
load a*b
the intention was that the caller would provide the name of a variable, and the “global” variable or constant b would be used to multiply “a”. If foo is called with the parameter a-c, the macro expansion of load a-c*b occurs. To avoid any possible ambiguity, users of macro processors can parenthesize formal parameters inside macro definitions, or callers can parenthesize the input parameters. [11]
Support for structured programming
Some assemblers have incorporated structured programming elements to encode execution flow. The earliest example of this approach was in the Concept-14 macro set , originally proposed by Dr. H.D. Mills (March 1970), and implemented by Marvin Kessler at IBM’s Federal Systems Division, which extended the S/360 macro assembler with IF/ELSE/ENDIF and similar control flow blocks. [12] This was a way to reduce or eliminate the use of GOTO operations in assembly code, one of the main factors causing spaghetti code in assembly language. This approach was widely accepted in the early ’80s (the latter days of large-scale assembly language use).
A curious design was A-natural , a “stream-oriented” assembler for 8080/ Z80 processors[ citation needed ] from Whitesmiths Ltd. (developers of the Unix -like Idris operating system, and what was reported to be the first commercial C compiler ). The language was classified as an assembler, because it worked with raw machine elements such as opcodes, registers , and memory references; but it incorporated an expression syntax to indicate execution order. Parentheses and other special symbols, along with block-oriented structured programming constructs, controlled the sequence of the generated instructions. A-natural was built as the object language of a C compiler, rather than for hand-coding, but its logical syntax won some fans.
There has been little apparent demand for more sophisticated assemblers since the decline of large-scale assembly language development. [13] In spite of that, they are still being developed and applied in cases where resource constraints or peculiarities in the target system’s architecture prevent the effective use of higher-level languages. [14]
Use of assembly language
Historical perspective
Assembly languages date to the introduction of the stored-program computer . The Electronic Delay Storage Automatic Calculator (EDSAC) (1949) had an assembler called initial orders featuring one-letter mnemonics. [15] Nathaniel Rochester wrote an assembler for an IBM 701 (1954). SOAP (Symbolic Optimal Assembly Program) (1955) was an assembly language for the IBM 650 computer written by Stan Poley. [16]
Assembly languages eliminated much of the error-prone and time-consuming first-generation programming needed with the earliest computers, freeing programmers from tedium such as remembering numeric codes and calculating addresses. They were once widely used for all sorts of programming. However, by the 1980s (1990s on microcomputers ), their use had largely been supplanted by higher-level languages, in the search for improved programming productivity . Today assembly language is still used for direct hardware manipulation, access to specialized processor instructions, or to address critical performance issues. Typical uses are device drivers , low-level embedded systems , and real-time systems.
Historically, numerous programs have been written entirely in assembly language. Operating systems were entirely written in assembly language until the introduction of the Burroughs MCP (1961), which was written in Executive Systems Problem Oriented Language (ESPOL), an Algol dialect. Many commercial applications were written in assembly language as well, including a large amount of the IBM mainframe software written by large corporations. COBOL , FORTRAN and some PL/I eventually displaced much of this work, although a number of large organizations retained assembly-language application infrastructures well into the 1990s.
Most early microcomputers relied on hand-coded assembly language, including most operating systems and large applications. This was because these systems had severe resource constraints, imposed idiosyncratic memory and display architectures, and provided limited, buggy system services. Perhaps more important was the lack of first-class high-level language compilers suitable for microcomputer use. A psychological factor may have also played a role: the first generation of microcomputer programmers retained a hobbyist, “wires and pliers” attitude.
In a more commercial context, the biggest reasons for using assembly language were minimal bloat (size), minimal overhead, greater speed, and reliability.
Typical examples of large assembly language programs from this time are IBM PC DOS operating systems and early applications such as the spreadsheet program Lotus 1-2-3 . Even into the 1990s, most console video games were written in assembly, including most games for the Mega Drive/Genesis and the Super Nintendo Entertainment System .[ citation needed ] According to some[ who? ] industry insiders, the assembly language was the best computer language to use to get the best performance out of the Sega Saturn , a console that was notoriously challenging to develop and program games for. [17] The arcade game NBA Jam (1993) is another example.
Assembly language has long been the primary development language for many popular home computers of the 1980s and 1990s (such as the Sinclair ZX Spectrum , Commodore 64 , Commodore Amiga , and Atari ST ). This was in large part because interpreted BASIC dialects on these systems offered insufficient execution speed, as well as insufficient facilities to take full advantage of the available hardware on these systems. Some systems even have an integrated development environment (IDE) with highly advanced debugging and macro facilities.
The Assembler for the VIC-20 was written by Don French and published by French Silk. At 1,639 bytes in length, its author believes it is the smallest symbolic assembler ever written. The assembler supported the usual symbolic addressing and the definition of character strings or hex strings. It also allowed address expressions which could be combined with addition , subtraction , multiplication , division , logical AND , logical OR , and exponentiation operators. [18]
Current usage
There have always been debates over the usefulness and performance of assembly language relative to high-level languages. Assembly language has specific niche uses where it is important; see below. Assembler can be used to optimize for speed or optimize for size. In the case of speed optimization, modern optimizing compilers are claimed[19] to render high-level languages into code that can run as fast as hand-written assembly, despite the counter-examples that can be found. [20] [21] [22] The complexity of modern processors and memory sub-systems makes effective optimization increasingly difficult for compilers, as well as assembly programmers. [23] [24] Moreover, increasing processor performance has meant that most CPUs sit idle most of the time, [25] with delays caused by predictable bottlenecks such as cache misses, I/O operations and paging . This has made raw code execution speed a non-issue for many programmers.
There are some situations in which developers might choose to use assembly language:
· A stand-alone executable of compact size is required that must execute without recourse to the run-time components or libraries associated with a high-level language; this is perhaps the most common situation. For example, firmware for telephones, automobile fuel and ignition systems, air-conditioning control systems, security systems, and sensors.
· Code that must interact directly with the hardware, for example in device drivers and interrupt handlers .
· Programs that need to use processor-specific instructions not implemented in a compiler. A common example is the bitwise rotation instruction at the core of many encryption algorithms.
· Programs that create vectorized functions for programs in higher-level languages such as C. In the higher-level language this is sometimes aided by compiler intrinsic functions which map directly to SIMD mnemonics, but nevertheless result in a one-to-one assembly conversion specific for the given vector processor.
· Programs requiring extreme optimization, for example an inner loop in a processor-intensive algorithm. Game programmers take advantage of the abilities of hardware features in systems, enabling games to run faster. Also large scientific simulations require highly optimized algorithms, e.g. linear algebra with BLAS [20] [26] or discrete cosine transformation (e.g. SIMD assembly version from x264 [27] )
· Situations where no high-level language exists, on a new or specialized processor, for example.
· Programs that need precise timing such as
· real-time programs such as simulations, flight navigation systems, and medical equipment. For example, in a fly-by-wire system, telemetry must be interpreted and acted upon within strict time constraints. Such systems must eliminate sources of unpredictable delays, which may be created by (some) interpreted languages, automatic garbage collection , paging operations, or preemptive multitasking . However, some higher-level languages incorporate run-time components and operating system interfaces that can introduce such delays. Choosing assembly or lower-level languages for such systems gives programmers greater visibility and control over processing details.
· cryptographic algorithms that must always take strictly the same time to execute, preventing timing attacks .
· Situations where complete control over the environment is required, in extremely high security situations where nothing can be taken for granted .
· Computer viruses , bootloaders, certain device drivers , or other items very close to the hardware or low-level operating system.
· Instruction set simulators for monitoring, tracing and debugging where additional overhead is kept to a minimum
· Reverse-engineering and modifying program files such as
· existing binaries that may or may not have originally been written in a high-level language, for example when trying to recreate programs for which source code is not available or has been lost, or cracking copy protection of proprietary software.
· Video games (also termed ROM hacking ), which is possible via several methods. The most widely employed is altering program code at the assembly language level.
· Self-modifying code , to which assembly language lends itself well.
· Games and other software for graphing calculators . [28]
Assembly language is still taught in most computer science and electronic engineering programs. Although few programmers today regularly work with assembly language as a tool, the underlying concepts remain very important. Such fundamental topics as binary arithmetic , memory allocation , stack processing , character set encoding, interruptprocessing, and compiler design would be hard to study in detail without a grasp of how a computer operates at the hardware level. Since a computer’s behavior is fundamentally defined by its instruction set, the logical way to learn such concepts is to study an assembly language. Most modern computers have similar instruction sets. Therefore, studying a single assembly language is sufficient to learn: I) the basic concepts; II) to recognize situations where the use of assembly language might be appropriate; and III) to see how efficient executable code can be created from high-level languages. [29] This is analogous to children needing to learn the basic arithmetic operations (e.g., long division), although calculators are widely used for all except the most trivial calculations.
Typical applications
· Assembly language is typically used in a system’s boot code, the low-level code that initializes and tests the system hardware prior to booting the operating system and is often stored in ROM . ( BIOS on IBM-compatible PC systems and CP/M is an example.)
· Some compilers translate high-level languages into assembly first before fully compiling, allowing the assembly code to be viewed for debugging and optimization purposes.
· Relatively low-level languages, such as C , allow the programmer to embed assembly language directly in the source code. Programs using such facilities, such as the Linux kernel , can then construct abstractions using different assembly language on each hardware platform. The system’s portable code can then use these processor-specific components through a uniform interface.
· Assembly language is useful in reverse engineering . Many programs are distributed only in machine code form which is straightforward to translate into assembly language, but more difficult to translate into a higher-level language. Tools such as the Interactive Disassembler make extensive use of disassembly for such a purpose.
· Assemblers can be used to generate blocks of data, with no high-level language overhead, from formatted and commented source code, to be used by other code.[ citation needed ]
.
2 What is Language Processor? Explain about the two Language
processing activities.
By a language processor, we mean a program that processes programs written in a programming language (source language). All or part of a language processor is a language translator, which translates the program from the source language into machine code, assembly language, or some other language. The machine code can be for an actual computer or for a virtual (hypothetical) computer. If it is for a virtual computer, then a simulator for the virtual computer is needed in order to execute the translated program.
If a language processor is a translator that produces machine or assembly code as output (in object code or executable code) then it is called a compiler. If the language processor executes the translated program (output from the translator) then it is called an interpreter.
In a typical programming language implementation, source program components (files or modules) are first translated into machine language to produce components called object modules or object files. Following the translation step, a linkage editor (or linker) combines multiple object components for a program with components from libraries to produce an executable program. This can occur either as an intermediate step, or in some cases it may occur as the program executes, loading each component as it is needed. The execution of a program may be done by an actual computer or by a simulator for a virtual computer.
Program components in languages such as C are normally compiled into object files, which are combined into an executable file by a linkage editor or linking loader. The linkage editor adjusts addresses as needed when it combines the object modules, and it also puts in the addresses where a module references a location in another module (such as for a function call). If an executable file is produced, then there will also be a loader program that loads an executable file into memory so that it can execute. The loader may also do some final adjustments on addresses to correspond to the actual locations in memory where the executing program will reside.
Explain language processing activities with suitable diagrams.
Language processing activities arise to bridge the ideas of software designer with actual execution on the computer system. Due to the differences between the manners in which a software designer describes the ideas concerning the behavior of software and the manner in which these ideas are implemented in a computer system. The designer expresses the ideas in terms related to the application domain of the software. To implement these ideas, their description has to be interpreted in terms related to the execution domain of the computer system. We use the term semantics to represent the rules of meaning of a domain, and the term semantic gap to represent the difference between the semantics of two domains. The fundamental language processing activities can be divided into those that bridge the specification gap and those that bridge the execution gap.
· Program Generation Activities
· Program Execution Activities
A program generation activity aims at automatic generation of a program. The source language is a specification language of an application domain and the target language is typically a procedure oriented PL. A program execution activity, organizes this execution of a program written in a PL on a computer system. Its source language could be a procedure-oriented language or a problem oriented language.
o Program Generation
The program generator is a software system which accepts the specification of a program to be generated, and generates a program in the target PL. We call this the program generator domain. The specification gap is now the gap between the application domain and the program generator domain. This gap is smaller than the gap between the application domain and the target PL domain.
Reduction in the specification gap increases the reliability of the generated program. Since the generator domain is close to the application domain, it is easy for the designer or programmer to write the specification of the program to be generated.
Fig. 1.3: Program generator domain
The harder task of bridging the gap to the PL domain is performed by the generator. This would be performed while implementing the generator. To test an application generated by using the generator, it is necessary to only verify the correctness of the specification input to the program generator. This is a much simpler task than verifying correctness of the generated program. This task can be further simplified by providing a good diagnostic (i.e. error indication) capability in the program generator, which would detect inconsistencies in the specification.
It is more economical to develop a program generator than to develop a problem-oriented language. This is because a problem oriented language suffers a very large execution gap between the PL domain and the execution domain, whereas the program generator has a smaller semantic gap to the target PL domain, j which is the domain of a standard procedure oriented language. The execution gap between the target PL domain and the execution domain is bridged by the compiler or interpreter for the PL.
o Program Execution
Two popular models for program execution are
· Translation
· Interpretation
Program Translation
Program translation model bridges the execution gap by translating a program written in a PL, called thesource program (SP), into an equivalent program in the machine or assembly language of the computer system, called the target program (TP).
What is an assembly languageExplain its basic features. State the
advantage and disadvantages of coding in assembly language.
Assembly language
Sometimes referred to as assembly or ASL, assembly language is a low-levelprogramming language used to interface with computer hardware. Assembly language uses structured commands as substitutions for numbers allowing humans to more easily read the code versus looking at binary. Although easier to read than binary, assembly language is a difficult language and is usually substituted for a higher language such as C. Below is an example of assembly language in a debug routine.
mov ax,4C00h int 21h
· See the debug routines page for other examples of low-level assembly code and additional information about what each routine does.
Assembly Language. Its Advantages And Disadvantages.
Assembly Language : It is the first step to improve the programming structure. You should know that computer can handle numbers and letter. Therefore some combination of letters can be used to substitute for number of machine codes. The set of symbols and letters forms the Assembly Language and a translator program is required to translate the Assembly Language to machine language. This translator program is called `Assembler’. It is considered to be a second-generation language. Advantages Assembly Language: 1.The symbolic programming of Assembly Language is easier to understand and saves a lot of time and effort of the programmer. 2.It is easier to correct errors and modify program instructions. 3.Assembly Language has the same efficiency of execution as the machine level language. Because this is one-to-one translator between assembly language program and its corresponding machine language program. Disadvantages Assembly Language: 1.One of the major disadvantages is that assembly language is machine dependent. A program written for one computer might not run in other computers with different hardware configuration.
List and explain the various issues which must be considered to make
your drivers portable across CPU architectures.
3 Understanding CPU and Bus Issues That Influence Device Driver Design
This chapter discusses design issues related to writing device drivers that can operate on multiple CPU and bus architectures. The issues relate specifically to the Alpha CPU architecture and to bus architectures that Digital implements (EISA, ISA, PCI, and TURBOchannel). However, these issues might be applicable to other CPU and bus architectures. The chapter begins with a discussion of the CPU issues that influence device driver design and concludes with a summary of the bus issues that you need to consider when designing your device drivers.
3.1 CPU Issues That Influence Device Driver Design
Whenever possible, you should design a device driver so that it can accommodate peripheral devices that operate on more then one CPU architecture. You need to consider the following issues to make your drivers portable across CPU architectures:
· Control status register (CSR) access
· I/O copy operation
· Direct memory access (DMA) operation
· Memory mapping
· 64-bit versus 32-bit
· Memory barriers
The discussion centers around 64-bit Alpha CPU platforms and 32-bit CPU platforms, but the topics may be applicable to other CPU architectures. The following sections discuss each of these issues.
3.1.1 Control Status Register Issues
Many device drivers based on the UNIX operating system access a device’s control status register (CSR) addresses directly through a device register structure. This method involves declaring a device register structure that describes the device’s characteristics, which include a device’s control status register. After declaring the device register structure, the driver accesses the device’s CSR addresses through the member that maps to it.
There are some CPU architectures that do not allow you to access the device CSR addresses directly. If you want to write your device driver to operate on both types of CPU architectures, you can write one device driver with the appropriate conditional compilation statements. You can also avoid the potentially confusing proliferation of conditional compilation statements by using the CSR I/O access kernel interfaces provided by Digital UNIX to read from and write to the device’s CSR addresses. Because the CSR I/O access interfaces are designed to be CPU hardware independent, their use not only simplifies the readability of the driver, but also makes the driver more portable across different CPU architectures and different CPU types within the same architecture.
Section 7.1.9 shows how the /dev/none driver uses the CSR I/O access kernel interfaces read_io_port and write_io_port to read from and write to the device’s CSR addresses. See Section 7.1.10 to learn how to build your own macros based on the read and write macros that Digital provides.
Device drivers operating on Alpha CPUs must access the device registers by defining device register offsets and passing them as arguments to the I/O access interfaces.
3.1.2 I/O Copy Operation Issues
I/O copy operations can differ markedly from one device driver to another because of the differences in CPU architectures. Using techniques other than the generic kernel interfaces that Digital provides for performing I/O copy operations, you would probably not be able to write one device driver that operates on more than one CPU architecture or more than one CPU type within the same architecture.
To provide portability when performing I/O copy operations, Digital UNIX provides generic kernel interfaces to the system-level interfaces required by device drivers to perform an I/O copy operation. Because these I/O copy interfaces are designed to be CPU hardware independent, their use makes the driver more portable across different CPU architectures and more than one CPU type within the same architecture.
Section 18.5.1 shows you how to call these I/O copy operation interfaces.
3.1.3 Direct Memory Access Operation Issues
Direct memory access (DMA) operations can differ markedly from one device driver to another because of the DMA hardware support features for buses on Alpha systems and because of the diversity of the buses themselves. Using the current techniques for performing DMA, you would probably not be able to write one device driver that operates on more than one CPU architecture or more than one CPU type within the same architecture.
To provide portability with regard to DMA operations, Digital UNIX provides generic kernel interfaces to the system-level interfaces required by device drivers to perform a DMA operation. These generic interfaces are typically called “mapping interfaces.” This is because their historical background is to acquire the hardware and software resources needed to map contiguous I/O bus addresses and accesses into discontiguous system memory addresses and accesses. Because these interfaces are designed to be CPU hardware independent, their use makes the driver more portable across different CPU architectures and more than one CPU type within the same architecture.
Section 18.6 shows you how to use these mapping interfaces to achieve device driver portability across different CPU architectures.
3.1.4 Memory Mapping Issues
Many device drivers based on the UNIX operating system provide a memory map section to handle applications that make use of the mmap system call. An application calls mmap to map a character device’s memory into user address space. Some CPU architectures, including the Alpha architecture, do not support an application’s use of the mmap system call. If your device driver operates only on CPUs that support the mmap feature, you can continue writing a memory map section. If, however, you want the device driver to operate on CPUs that do not support the mmap feature, you should design the device driver so that it uses something other than a memory map section.
3.1.5 32-Bit Versus 64-Bit Issues
This section describes issues related to declaring data types for 32-bit and 64-bit CPU architectures. By paying careful attention to data types, you can make your device drivers work on both 32-bit and 64-bit systems.Table 3-1 lists the C compiler data types and bit sizes for 32-bit CPUs and the Alpha 64-bit CPUs.
Table 3-1: C Compiler Data Types and Bit Sizes
C Type | 32-Bit Data Size | Alpha 64-Bit Data Size |
short | 16 bits | 16 bits |
int | 32 bits | 32 bits |
long | 32 bits | 64 bits |
* (pointer) | 32 bits | 64 bits |
long long | 64 bits | 64 bits |
char | 8 bits | 8 bits |
The following sections describe some common declaration situations:
· Declaring 32-bit variables
· Declaring 32-bit and 64-bit variables
· Declaring arguments to C interfaces (functions)
· Declaring register variables
· Performing bit operations on constants
· Using NULL and zero (0) values
· Modifying type char
· Declaring bit fields
· Using printf formats
· Using mb and wbflush
· Using the volatile compiler keyword
Note
The /usr/sys/include/io/common/iotypes.h file defines constants used for 64-bit conversions. See Writing Device Drivers: Reference for a description of the contents of this file.
3.1.5.1 Declaring 32-Bit Variables
Declare any variable that you want to be 32 bits in size as type int, not type long. The size of variables declared as type int is 32 bits on both 32-bit systems and the 64-bit Alpha systems.
Look at any variables declared as type int in your existing device drivers to determine if they hold an address. On Alpha systems, sizeof (int) is not equal to sizeof (char *).
In your existing device drivers, also look at any variable declared as type long. If it must be 32 bits in size, you have to change the variable declaration to type int.
3.1.5.2 Declaring 32-Bit and 64-Bit Variables
If a variable should be 32 bits in size on a 32-bit system and 64 bits in size on a 64-bit Alpha system, declare it as type long.
3.1.5.3 Declaring Arguments to C Functions
Be aware of arguments to C interfaces (functions) where the argument is not explicitly declared and typed. You should explicitly declare the formal parameters to C interfaces; otherwise, their sizes may not match up with the calling program. The default size is type int, which truncates 64-bit addresses.
3.1.5.4 Declaring Register Variables
When you declare variables with the register keyword, the compiler defaults its size to that of type int. For example:
register somevariable;
Remember that these variable declarations also default to type int. For example:
unsigned somevariable;
Thus, if you want the variable to be 32 bits in size on both 32-bit systems and 64-bit Alpha systems, the above declarations are correct. However, if you want the variable to be 32 bits in size on a 32-bit system and 64 bits in size on a 64-bit Alpha system, declare the variables explicitly, using the type long.
3.1.5.5 Performing Bit Operations on Constants
By default, constants are 32-bit quantities. When you perform shift or bit operations on constants, the compiler gives 32-bit results. If you want a 64-bit result, you must follow the constant with an L. Otherwise, you get a 32-bit result. For example, the following is a left shift operation that uses the L:
long foo, bar;
foo = 1L << bar;
3.1.5.6 Using NULL and Zero Values
Explain briefly about Android Architecture Libraries.
Android Architecture
February 3, 2015 Android 35 Comments
If you are an Android user, you may know how to carry out the basic functions such as making a call, sending a text message, changing the system settings, install or remove apps etc. Well! Every Android user knows these, but is it enough for you as a developer? Of course Not! So, what else things do we need to know for being successful developers? I’ll explain. We should know all the key concepts of Android OS. That is the nuts and bolts of the Android OS. Here we will explore the Android architecture in detail. By the term Android architecture, I mean the building blocks of the Android OS.
Android Architecture Diagram:
Before you start looking at the diagram, keep these points in your mind.
1. Android OS is made of different layers of software.
2. Each layer provides different services to the layer just above it.
3. Together it will make the OS, middle ware and applications.
Now look at the diagram:
So, the layers we referred to in the top are:
1. Linux Kernel
2. Libraries
3. Android Run time
4. Application Framework
5. Android Apps
The app that we develop will go to the Android Apps layer.
Now we will look at each of these layers in detail:
1. Linux Kernel
The basic layer is the Linux Kernel. The whole Android OS is built on top of the Linux Kernel with some further architectural changes. Please don’t get confused by the terms Linux and Linux Kernel. The term Kernel means the core of any Operating System. By saying Android is based upon Linux Kernel, it doesn’t mean that it is another Linux distribution. It is not like that. It simply means, Android at its core is Linux. But you can’t run any linux packages on Android. It is a totally different OS. It is this Linux kernel that interacts with the hardware and it contains all the essential hardware drivers. Drivers are programs that control and communicate with the hardware. For example, consider the Bluetooth function. All devices has a Bluetooth hardware in it. Therefore the kernel must include a Bluetooth driver to communicate with the Bluetooth hardware. The Linux kernel also acts as an abstraction layer between the hardware and other software layers. As the Android is built on a most popular and proven foundation, the porting of Android to variety of hardware became a relatively painless task.
2. Libraries
The next layer is the Android’s native libraries. It is this layer that enables the device to handle different types of data. These libraries are written in c or c++ language and are specific for a particular hardware.
Some of the important native libraries include the following:
Surface Manager: It is used for compositing window manager with off-screen buffering. Off-screen buffering means the apps can’t directly draw into the screen, instead the drawings go to the off-screen buffer. There it is combined with other drawings and form the final screen the user will see. This off screen buffer is the reason behind the transparency of windows.
Media framework: Media framework provides different media codecs allowing the recording and playback of different media formats
SQLite: SQLite is the database engine used in android for data storage purposes
WebKit: It is the browser engine used to display HTML content
OpenGL: Used to render 2D or 3D graphics content to the screen
3. Android Runtime
Android Runtime consists of Dalvik Virtual machine and Core Java libraries.
Dalvik Virtual Machine
It is a type of JVM used in android devices to run apps and is optimized for low processing power and low memory environments. Unlike the JVM, the Dalvik Virtual Machine doesn’t run .class files, instead it runs .dex files. .dex files are built from .class file at the time of compilation and provides hifger efficiency in low resource environments. The Dalvik VM allows multiple instance of Virtual machine to be created simultaneously providing security, isolation, memory management and threading support.
ART
Google has introduced a new virtual machine known as ART (Android Runtime) in their newer releases of Android. In Lollipop, the Dalvik Virtual Machine is completely replaced by ART. ART has many advantages over Dalvik VM such as AOT (Ahead Of Time) compilation and improved garbage collection which boost the performance of apps significantly.
Core Java Libraries
These are different from Java SE and Java ME libraries. However these libraries provides most of the functionalities defined in the Java SE libraries.
4. Application Framework
These are the blocks that our applications directly interacts with. These programs manage the basic functions of phone like resource management, voice call management etc. As a developer, you just consider these are some basic tools with which we are building our applications.
Important blocks of Application framework are:
Activity Manager: Manages the activity life cycle of applications
Content Providers: Manage the data sharing between applications
Telephony Manager: Manages all voice calls. We use telephony manager if we want to access voice calls in our application.
Location Manager: Location management, using GPS or cell tower
Resource Manager: Manage the various types of resources we use in our Application
5. Applications
Applications are the top layer in the Android architecture and this is where our applications are gonna fit into. Several standard applications comes pre-installed with every device, such as:
· SMS client app
· Dialer
· Web browser
· Contact manager
As a developer we are able to write an app which replace any existing system app. That is, you are not limited in accessing any particular feature. You are practically limitless and can whatever you want to do with the android (as long as the users of your app permits it). Thus Android is opening endless opportunities to the developer. ⇐Back to The Index of Android Development Tutorial
Stay tuned to EazyTutz for all future updates.
Did this tutorial on Android Architecture help you? or did I miss any important point? What do you think? Suggestions, queries, criticism or whatever. I’d love to hear from you. Please add a comment below.
Write the Steps for UPnP device addressing with proper flowchart
UPnP Client Support Overview
Over time, installing, configuring and troubleshooting networks have arguably become easier. This is a necessary outcome required to support networking in the absence of a dedicated information technology group, as is more often the case as smaller networks are being deployed in small businesses and home environments.
Also over the last several years, there has been an increase in the number of devices supporting digital information exchange such as the cell phone, PDA and Tablet devices, and even the television. Devices that are not traditionally computing devices are adding computer technology for various reasons, including to process the digital data formats becoming more popular. Non-traditional devices that now include computing technology vary widely, from the thermostat to the stereo system. A decrease in the cost of implementing computing and networking technology has perpetuated itself and allowed the addition of intelligence, and in some cases reliable networking, into many devices in use today.
The next step in this evolution (which has already begun) is to transparently connect these devices together. This enables new capabilities such as remote control and monitoring, sharing of digital data, and converging data from multiple devices and locations. Doing this requires a common set of standards and protocols for communicating. This is part of what UPnP offers.
While Windows might not be required, a system running Windows with UPnP support can serve several purposes in this new network of devices, including that of central controller and gateway.
The protocols and requirements for UPnP are discussed in detail in documents and specifications found on the UPnP Forum Website. In this article we will discuss the implementation of UPnP on the Windows platform.
UPnP is built on existing protocols and technologies. For example, UPnP uses TCP/IP, UDP/IP, and HTTP protocols as a base. In addition to these base protocols, several other protocols build on top of these to implement the various “steps” or phases of UPnP networking.
A UPnP network defines several component types and their responsibilities as shown in figure 1. These components include control points, devices and services. Control points are considered the clients in a UPnP network and control devices and services. On the Windows platform, these control points are usually applications written to control specific types of devices or services.
Figure 1: Components of a UPnP network and their relation.
Devices are logical containers for a service or set of services, and possibly for other devices. Devices and services are identified partially by their type, which defines their minimum capabilities.
Windows can participate in the UPnP network and make UPnP enabled devices and services that are connected to the network available to the user of the Windows system. Windows can also serve as a platform for building and running control point applications to control UPnP connected devices and services. The Internet Connection Sharing (ICS) service uses UPnP to announce the availability of the service to other computers on the network, which are running UPnP clients.
Windows might be a host for multiple control point applications concurrently. Many different individuals and companies might write these applications. The Windows support architecture for these applications should minimize a developer’s need to write code that would be common to all UPnP applications. Including much of the common code in Windows will reduce the effort required to implement as well as improve the stability of the system.
The Steps in UPnP Networking
To implement architecture for UPnP support in Windows, support for the steps in UPnP networking must be provided.
· Addressing – Addressing, sometimes called step ‘0’ in UPnP networking, is a common requirement for any device participating in a network; obtaining a network layer address for the device. The TCP/IP (and UDP) and DHCP components of the Windows networking stack provide the addressing support. Addressing can be accomplished through DHCP assigned addresses, or lacking DHCP support in the network, through automatically assigned IP addresses or AutoIP.
· Discovery – UPnP discovery enables control points to locate interesting devices on a network. Devices periodically announce their presence and respond when requested with announcements for their UPnP defined device and service types. Control points may solicit device and service announcements. These capabilities are defined in UPnP as using unicast and multicast variants of the HTTP protocol. Discovery also leverages methods and headers defined in two other protocols, Simple Service Discovery Protocol (SSDP) and Generic Event Notification Architecture (GENA). Only a portion of GENA is used and it may not be used in a future version of UPnP.
For Windows to support UPnP control points from a discovery point of view, Windows must provide interfaces for a control point to instigate searches for devices or services based on device and service types. Devices can be added to the network at any time (announce themselves) and refresh announcements periodically. They can also leave the network, with or without notification. The Windows discovery interfaces allow notification of changes in a device’s presence and for arrival notification of new devices.
In short, to support discovery, Windows must provide interfaces for multiple dynamic control points and devices, manage these instances, and implement the GENA and SSDP protocols.
· Description – Through discovery, enough information is provided about the devices on the network to determine whether the sought after device is available and choose which device to use amongst several similar devices. Once this decision is made, more information is necessary to access and control the devices and their services. A detailed description of the device is needed. In UPnP, this device description is an Extensible Markup Language (XML) document whose format is defined by the UPnP Forum. The description contains a wealth of information about a device and its service(s) (service descriptions are referenced in device descriptions), including information needed to exercise the device as described in the subsequent steps in UPnP networking.
Windows must then support description for the control point (client) application. A control point application must be able to request, receive and parse XML description documents through the architecture implemented. All of this document management can be built on standard HTTP methods.
· Control – Once a description is retrieved for a device and its services, a control point can request actions be performed on those services by calling exposed methods called actions. The service description contains information on what actions can be requested along with the parameters associated with those actions. The result of calling one of these actions is a kind of remote procedure call interface to UPnP services. Action requests and responses are formatted using the Simple Object Access Protocol (SOAP). Similar to action, UPnP Control also defines how control points can query state variables exposed by a service, but this capability is being depreciated in favor of generic service actions to retrieve state variables. SOAP is also used for this purpose.
A Windows implementation of UPnP must support control of network devices for control point applications. The control point application is the action requestor. The implementation will need to translate these method requests from the application into SOAP requests to the device over the network. The return parameters and results must be parsed and presented to the application.
· Eventing – UPnP Services may contain variables that reflect the state of the service while it is running. The service can publish updates to these variables when they change, and control points can request notification of these changes by subscribing to the service. Notifications are sent using GENA methods.
An interface must be provided for the control point to request subscription to a particular service on the network and register a callback. The implementation would then convert that request into a protocol request to the service for subscription. State variable changes sent to the implementation as GENA notifications would then need to be passed to the registered callback.
· Presentation – This last step in UPnP networking can be used to provide an HTML based user interface for a device. This interface can then be used to control or view device status. A presentation URL is provided as part of the device description for this purpose.
For control point support, the elements of the description document would be provided as described under description above. Standard HTTP interfaces and methods can then be used to retrieve a device presentation page.
See UPnP in Action
UPnP is designed to make networking simple, and this includes easily finding new devices when they are added to your network. If you are running a UPnP enabled operating system, such as Windows ME or Windows XP, new UPnP devices added to the network can be made to automatically appear in My Network Places.
Note: In Windows XP (and Windows ME) this capability is not enabled by default since this will cause unnecessary network traffic in networks that cannot benefit from UPnP. Additionally, enhancements might be made to how and where discovered devices are displayed to make locating them simpler.
In Windows XP the current UI component that enables display of UPnP devices in My Network Places can be installed as an optional networking component (all of UPnP is an optional component in Windows ME). To install the UI component:
1. Go to Start->Control Panel->Network Connections
2. In Network Connections, select Advanced->Optional Networking Components
3. Select Networking Services and click Details
4. Check the box for Universal Plug and Play
5. Click Ok, and then Next in the Windows Components dialog to finish installing the UPnP UI.
You can now see if any UPnP enabled devices exist on your network by opening My Network Places on the desktop. If there are UPnP devices on your local network, they will appear here with a generic icon based on the device type. You can invoke the device from here through its presentation page.
In order to see this behavior you will need to have a UPnP device on the network. There are a couple of options here. The first option is to use the sample device provided in The UPnP Device Development Kit. This sample device can run on Windows 2000 with IIS or on Windows XP if you stop the SSDP Service. Stopping the service is required because the sample device and SSDP use the same ports, creating a conflict. The sample device requires a second machine running one of these platforms. The UPnP DDK can be downloaded from:
http://www.microsoft.com/hwdev/tech/nonpc/UPnP/default.asp
Another option is to purchase a UPnP enabled device. These devices will become available in the near future. Internet gateway devices like Windows XP’s Internet Connection Sharing (ICS) may support NAT Traversal and Firewall configuration using UPnP, but these devices are not designed to appear in My Network Places.
UPnP Client Support Architecture
Much of what we need to implement UPnP on Windows is available through the standard protocol stacks and components like TCP/IP and HTTP. On top of these components, support for the protocols used by UPnP, such as SSDP and GENA, must be added. Interfaces into these protocols must be defined for use by control point applications. The architecture must be designed so that it supports and manages multiple control point applications running at once.
The Windows UPnP implementation can be described by two complimentary architectures. First there is a component architecture describing the software components making up the UPnP implementation and how these components interface with the rest of the operating system. There is also COM Architecture for these components, which will help in understanding the interaction of these components and applications built on them. First we will discuss the component architecture and then the COM architecture.
Component Architecture
Figure 2 is a diagram of the components that implement the client side (control point) support for UPnP in Windows XP. Included are the other networking components these components interact with. The UPnP specific components and their responsibilities are described below.
Figure 2: Universal Plug and Play Client components in Windows XP. UPnP specific components colored white.
The components shown in figure 2 serve the following purposes.
upnp.dll – This DLL exposes the Windows UPnP API and COM object interfaces for control point applications as described in the UPnP Development Kit and platform SDK. Requests requiring discovery invoke the SSDP protocol and so are passed along to ssdpapi.dll. Control requests and responses, are SOAP messages and take a different path, through the XML Document Object Model (XMLDOM) interfaces provided by msxml.dll and the WinInet interfaces. The XML DOM interfaces are also used elsewhere as required to manage XML documents. XML DOM is implemented such that it uses the WinInet API when network access is required. Upnp.dll also uses a few utility interfaces provided by urlmon.dll such as CoInternetCombineUrl. Upnp.dll is loaded into every UPnP application.
ssdpapi.dll – This DLL exposes SSDP APIs and is used by upnp.dll to process discovery requests for the client. Applications use the Device Finder COM object to cause search messages to be sent on the network. Device finder calls into upnp.dll result in calls into ssdpapi.dll and eventually to Windows Sockets to send the search message(s) on the network. Ssdpapi.dll also implements a search timer and is loaded into every UPnP application. Ssdpapi.dll interfaces with ssdpsrv.dll for the device cache, notification of device announcements, event notification, and so on.
ssdpsrv.dll – This DLL (called ssdpsrv.exe in Windows ME) implements the SSDP Discovery Service as a Windows service. The discovery cache is maintained here and accessed (both for query and update) through RPC. Ssdpsrv manages receipt of device presence announcements; updating its cache and passing these notifications along to clients with outstanding search requests. This component also takes care of event subscriptions for clients that open services. The SSDP Discovery service accepts registration of event callbacks from clients, turns these into subscription requests and monitors for the event notifications; passing them along to the registered callbacks. Ssdpsrv.dll interfaces with the network through both Windows Sockets and the WinInet interface.
upnpui.dll (not shown) – This DLL is responsible for the shell interface for UPnP. Upnpui.dll is not installed by default and must be installed as an optional networking component. Upnpui.dll is a shell extension that is loaded by explorer on logon (if it is installed). Since it is also a UPnP application, it loads upnp.dll and ssdpapi.dll. It is responsible for the display of UPnP devices in My Network Places. To accomplish this, upnpui.dll will register with and be called by Windows Explorer. This DLL also manages the taskbar notification area.
UPnP COM Architecture
The COM object architecture for the support of control point applications is shown in Figure 3.
Figure 3: COM Interfaces to support UPnP Clients
Not shown in figure 3 are the callback interfaces a developer must implement if asynchronous searches or description document loads are used, or if event notifications are to be received from a service. The interfaces shown in the diagram are those implemented in Windows.
To leverage UPnP, a control point application must first create an instance of the Device Finder. The Device Finder object can then be used to perform synchronous or asynchronous searches for devices. Depending upon the search method used, the result will be communicated as a device collection or a single device object. A device collection can be parsed for individual device objects. Device objects can also be retrieved through methods exposed by the Description Document interface.
Once a device object is obtained, the control point can use this object’s methods to obtain properties of a particular device. This includes the ability to retrieve a service collection, and from there retrieve individual service objects. Once a service object is obtained, its methods can be used to request event notification and invoke control actions.
Methods called on these objects may result in requests to the various other components described in the component architecture earlier in this chapter. Note from the diagram that the COM architecture is implemented in upnp.dll.
UPnP Client Support Initialization and Operation
This section covers the operation of the components discussed above. We will discuss how and when these components are involved in various operations performed by UPnP control point applications or hosted devices. We will first discuss how and when each component is initialized and then discuss the involvement of these components in several UPnP operations.
UPnP Client Support Initialization
This section covers the initialization of the UPnP components.
SSDP Discovery Service (SSDPSRV) Initialization
The SSDP Discovery Service runs as a demand start service in Windows XP. This means that the service will be automatically started whenever the SSDPAPI initialization function is called. The responsibilities of this component include:
· Maintains a cache of devices available on the network by listening for announcements and through updates based on client searches.
· Manages event subscriptions for clients by sending subscribe and re-subscribe requests periodically and dispatching incoming event notifications.
The other UPnP components can then leverage SSDPSRV for these services. The SSDP client API, for example, checks the device cache (using RPC) before sending a search request and will update the cache with the results of each search.
The default installation of Windows XP will install UPnP and set the SSDP Discovery Service (SSDPSRV) to start on-demand. The first thing SSDPSRV will do when started is register a service control handler with the service control manager – a normal thing for services to do – to handle service control requests such as requests to stop or start the service.
The SSDP Discovery service then proceeds to initialize, taking the following steps.
The service creates a timer queue (using CreateTimerQueue()) for use by the service. The service will create timers on this queue for various purposes including:
· Sending device announcements for hosted devices
· Re-sending device removal notifications (SSDP byebye messages)
· Expiring cache contents based on SSDP Cache Control
· Event Subscription renewal for clients
· Sending client search responses
The service then initializes a list of network interfaces available on the system. This list is consulted as a list of available interfaces to be used by Internet Connection Firewall (ICF) and Internet Connection Sharing (ICS) when they utilize UPnP to provide their services such as port mapping and NAT traversal. For security reasons ICS does not use UPnP on the external (Internet) interface.
An event is created that will be signaled when there is a change in the interfaces. A wait thread from the thread pool is directed to wait on this event with a callback that will rebuild the IP addresses in the interface list. The event is used in a call to the Internet Protocol Helper (IPHelper) API NotifyAddrChange, and will be signaled when an interface to IP address mapping changes on the system, triggering the callback to update the IP address list. Another IPHelper API, GetAdaptersInfo, is used to populate the list, both initially and upon change.
The service then initializes two linked lists, one for valid distinct networks on this computer and one for open connections to peer systems. These lists will be populated and used later.
The service will then initialize its Windows Sockets interface. To do this, a call is made to WSAStartup, requesting version 2.0; requiring version 1.1. If the version negotiation succeeds, the service will initialize a socket address structure containing the standard destination address for SSDP discovery requests – 239.255.255.250:1900. This will be used as the remote address when discovery messages need to be sent by the service. A socket is opened for receipt of event notifications, bound to the wildcard local address and event port (5000). This socket will be listened on and used as a template to accept TCP connections for eventing purposes.
The SSDP Discovery service exposes interfaces for clients of the service through RPC, and therefore has to initialize its RPC server side. This portion of the service initialization is done next.
A manual reset event is created for use in synchronizing shutdown of the service. The main thread will wait on this event, which will be signaled when the service is shutdown.
The RPC server side then registers with RPC, specifying local procedure calls as its protocol sequence, by calling RpcServerUseProtSeqEp. This means local applications and services can access the service, but it will be unavailable to remote systems. The RPC server then registers its interface with RpcServerRegisterIf. The service makes methods available through RPC for device publication, event and device notification, device cache management, and specific support for ICS as a hosted device.
The service then populates the linked list of networks created earlier. This is done using a Windows Sockets Ioctl call, SIO_ADDRESS_LIST_QUERY, to retrieve the valid list of IP addresses on the machine. The list is parsed to remove invalid addresses such as NULL, 0 or non-IP addresses. The addresses remaining are placed in protocol specific socket address structures and added to an SSDP Network structure that also contains the network state and an open socket for that network. The socket that is stored in this structure is opened next, and set to join the SSDP multicast group for sending and receiving. If no valid networks are on the list, at minimum the loopback address is added. These “networks” are then stored on the valid network linked list for this machine. This list is used later on to determine which networks to listen or send on.
At this point the RPC server side will listen for incoming RPC calls by calling RpcServerListen. The server is now ready for a client to connect.
The service then creates an object to handle the processing of data received from the network. This object includes two events, one to signal new work and one to signal service shutdown, and a thread. The thread is created and set to run a routine to process incoming data. The thread waits on both events, and if the new work event is signaled, processes the received data. If the shutdown event is signaled, the thread will complete.
The service will create a hidden window from which to receive and dispatch window messages. This is primarily used to process incoming Windows Sockets messages. This window handle is then used in a call to WSAAsyncSelect specifying FD_READ as the event of interest for each network in the list of networks populated earlier. The message specified to be posted to the service’s window indicates a SSDP message was received. The effect is the service is set up to listen on all networks for incoming SSDP messages.
Next, The socket created for event notifications is initialized further. A listen is posted on this socket followed by a WSAAsyncSelect with a message indicating that TCP data (or a connection) has been received. The registered events of interest for select on this socket are FD_ACCEPT, FD_CONNECT, FD_READ, and FD_CLOSE.
The service needs to be aware of any changes to the available interfaces in the interface list or the associated IP addresses. If this occurs, among other things the network list will need to be recalculated, the sockets recreated, and the select calls reposted. To accomplish this the service will create an additional event, have a thread pool thread wait on this event with a callback routine, and call NotifyAddrChange (IPHelper API) with the event. When and if the event is signaled, the callback will rebuild the network list, recreate the sockets and repost the listens and selects.
Finally, the service control manager’s status for the service is updated to ‘running’ status through a call to SetServiceStatus and the main thread is sent to execute the process’s message loop for the service.
Now that the service is running, several threads have been created or are performing various tasks. The Main thread is running a message loop, two threads are waiting on address change notification, a thread is waiting in the Receive Data Manager for the Work event to be signaled so incoming data can be processed, and an RPC thread is waiting for incoming client API calls.
SSDP Client (UPNP.DLL, SSDPAPI.DLL) Initialization
When an application uses the UPnP client APIs, UPNP.DLL and SSDPAPI.DLL will be loaded into that applications address space. These are the UPnP client (control point) DLLs. As discussed earlier, UPNP.DLL implements the COM interfaces and leverages the SSDP Client API exposed by SSDPAPI.DLL for SSDP network activity. UPNP.DLL also uses APIs and Interfaces exposed by URLMON.DLL and MSXML.DLL as shown in the architecture diagram above. How these are used will be discussed further in the appropriate sections below.
Initialization of UPNP.DLL takes place when the COM objects implemented by UPNP.DLL are instantiated by an application, the first usually being a Device Finder object. Since this is done in the process of a UPnP client operation, the initialization that takes place will be discussed in the appropriate section below (along with the action that causes this initialization).
SSDPAPI.DLL (the SSDP Client) will prepare for calls to its API from any client of the API. One such client is UPNP.DLL. Initialization of the SSDP Client API is started through a call to the exposed interface SsdpStartup (which must be matched by a call to SsdpCleanup). SsdpStartup initializes the global state for the SSDP Client and must be done before any APIs are called. Some of the initialization may only be useful for specific clients. When startup is called, the following steps are taken.
An internal routine to initialize the RPC Client (that uses the RPC Server interfaces in SSDPSRV) is called. In this routine, the RPC protocol sequence is configured to LRPC and the endpoint configured to the SSDPSRV endpoint. Before actually binding to the server, several other steps are taken.
A linked list is created for storage of client notification registrations, along with a mutex to protect access to this list. This list can later be populated and actual notifications matched to a requesting client. Next a timer queue is created using CreateTimerQueue for timers used to timeout SSDP Search requests.
The SSDP Client API will use the network directly through Windows Sockets when sending search requests and receiving responses. To prepare for this, WSAStartup is called and an address structure allocated containing the destination address and port (239.255.255.250/1900) for SSDP requests.
The SSDP Client API creates a couple of synchronization objects for internal thread synchronization. First it creates an Event that will be signaled when a notification loop thread has been created for this client. Other notification threads wait on this event to ensure no calls are made to receive notifications until after the thread that will look for those notifications is started. This will be discussed further when registration for notifications are discussed. The second synchronization object can be acquired for shared or exclusive access and is used to ensure that the callback registered for a notification is not called until the registration completes. To accomplish this, the registration process acquires the object shared and the callback will attempt to get exclusive access – and must wait until the shared access is released.
Finally the SSDP Client calls RpcStringBindingCompose and RpcBindingFromStringBinding to obtain a binding for RPC calls to SSDPSRV.
At this point, the SSDP Client API has:
· Created a RPC binding handle to the SSDP Discovery Service
· Initialized a list for outstanding notification callbacks
· Created a queue for timers to time out search requests
· Initialized two thread synchronization objects.
UPnP Client Support Operation
To get a clearer idea of how the various UPnP components interact, we will take a high level view of what happens during various UPnP operations. A UPnP Client implemented on Windows XP (or Windows ME) has all of the COM objects and interfaces necessary find and control UPnP devices. Applications can be scripts embedded in HTML, Visual Basic programs and C++ programs.
In this section we will talk about how UPnP handles client requests to find a device, retrieve the device description, subscribe to service events and control a service. Examples of performing each of these operations using both Visual Basic and C++ are included in the Windows XP SDK, so that is not described here. Rather we will discuss the effects on the UPnP implementation.
Finding a Device
The first thing a client application must do when locating available devices is to create a Device Finder COM object. The Device Finder can then be used to instigate synchronous or asynchronous searches. When the Device Finder is allocated, several steps are taken to initialize for the searches expected to come.
A linked list is created to store the finder and associated information for later location. The list will actually be used when processing a find request. The finder object is implemented in upnp.dll, but needs the services of the SSDP components. The newly allocated finder will call into the SSDPAPI client DLL at SsdpStartup to initialize the DLL as described in the initialization section.
Now that the client has a device finder interface to use, the search can be conducted either synchronously or asynchronously. For an asynchronous search a Device Finder Callback object must be provided and the call will return immediately to the client. This object must implement either the IUPnPDeviceFinderCallback interface or the IDispatch interface. The callback object’s methods will be used to indicate any results to the client, finally indicating when the search is complete. After the initial search completes, the callback remains in place and is called again for new announcements of device comings and goings. This continues until the asynchronous search is cancelled.
With the synchronous search request no callback is required from the client, but the UPnP implementation will allocate a callback object of its own and turn this into an asynchronous search. When the final search complete is indicated to UPnP for this synchronous request, the asynchronous search is canceled and the results returned. Because both searches result in an asynchronous search, we discuss how UPnP implements the asynchronous search.
When CreateAsyncFind is called, a private device finder callback object is allocated for the use of UPnP and placed on the device finder list. This object is initialized to contain the search specifics including the resource identifier being searched for, a timer queue for timers pertaining to this search request, and a pointer to the interface to be called with search results (the client provided callback object).
The private callback object then registers its private callback helpers in the global interface table. The search state is set to ‘initialized’ and a cookie to identify this search is returned to the client.
To instigate the search the client must use the StartAsyncSearch method. The cookie returned from CreateAsyncFind is passed as a parameter to this call and is used to locate the appropriate callback object on the device finder list. A check is then made to insure we are initialized and that the search has not already started.
At this point the search state is set to ‘started’ and a call is made into SSDPAPI to start the search. This call includes parameters identifying the type of search, a Boolean value indicating a search should be forced for this request (hit the network), a callback routine (global to UPnP.DLL), and a pointer to the private callback object as a context. A handle is returned from this call and stored with the private callback object.
SSDPAPI will allocate an object to represent the search request, a separate object to manage possibly multiple search requests from this client, and a list to store the currently active search requests (on which this request is stored). An event is created to signal the completion of the request. The SSDP search request is composed based upon the information passed. Windows Sockets and IPHelper are then used to create a list of the available interfaces on the system, open a socket on each of these interfaces for sending search requests and then store this socket along with other information about the interface on a list. The loopback interface is included on this list.
The search state is set to ‘discovering’ and the search is begun. The first thing the SSDP client API does is make a RPC call to check the cache of announcements maintained by the SSDP Discovery service. This cache check is passed to the SSDP Discovery service using RPC. The service maintains a list of devices for which it has received SSDP announcements through listening for SSDP alive or byebye notifications or through updates resulting from clients search requests. The list is adjusted when network interfaces change.
After checking the local cache for any cached entries matching the search request, the devices returned are added to a list of the found devices. The network is then checked by accessing Windows Sockets directly (using sendto on the sockets created during initialization) to send search requests out of all available interfaces. A timer is set for 3 seconds (default) to time out the search and try again (for 3 retries).
A sockets select call is then used to monitor each socket for FD_READ capability. If select returns because of a read capable socket, an ioctl is used to check the amount of data to read, and recvfrom is called on that socket with the appropriate size buffer to retrieve the SSDP response. The response is parsed and compared to the responses we already have on the list of found devices. If this response is unique, it is placed on the list. The response is also forwarded to the SSDP Discovery service in a request to update the service’s cache.
Since a response has been received, several other things happen. The device finder receives a call at its private callback (in UPNP.DLL) indicating that a new device has been found. MSXML (XML DOM) and WinInet are used to asynchronously load a description document for this device based on the location specified in the response received. This load is performed asynchronously and when the document has been completely loaded the original client’s DeviceAdded callback method is invoked with the new Device Object representing the found device.
As part of the loading process, a description document object is created to manage the device object(s) that might be created to represent the found device. The description document will contain a pointer to the root device object, which will contain pointers to any child device objects or service objects. The description document is parsed to retrieve the XML data and store this information in the appropriate nested device and service objects. This data includes the properties stored in an array for easy access later when a method is called on the device object by the client.
After all of the retries complete and the responses received are compiled onto the response list, the private internal callback is invoked again with an indication that the search is done. The callback has a couple of responsibilities for the search is done case.
The original request was an asynchronous request (remember, even if we called one of the synchronous methods) and the active search phase is over. We still want to be notified of device comings and goings until we cancel the request with a CancelAsyncFind call. To arrange callback when devices come or go on the network based on announcements, the device finder registers to receive notifications. Notifications are covered later in this chapter when we discuss what occurs when a callback is registered to subscribe to service events. Note that any synchronous search requests that are turned into asynchronous requests by the device finder internally do not persist beyond the return of the synchronous call. Rather they are canceled when the search completes internally.
Finally the internal callback calls the SearchComplete method for the asynchronous callback object. Asynchronous searches are no longer in active search mode, but the callbacks are now registered to receive notifications of device comings and goings through SSDP notifications.
Retrieving and Parsing Device Descriptions
After the search completes, the client has access to individual device objects representing devices that match the search criteria. For a search by UDN request, this is a single device object. For a search by type, this is a device collection which must be further parsed to retrieve an individual object. The Item method for the device collection can be used to do this given a specific UDN. To accomplish this, the implementation simply walks through the device object collection, retrieving the UDN from the stored properties (the same way the client application would, with the UniqueDeviceName method) and comparing it to the specified UDN. If we have a match, the device object is returned.
With a device object, the client application has access, through its methods, to all of the properties of the device description. These were loaded into an easily accessible array in the object as discussed previously. If the client application requests child devices, a device collection can be retrieved from the parent device object and it becomes an iterative process.
Retrieving a Service Object
When the device tree was parsed and stored by the UPnP client implementation, the services were also enumerated and added to a list attached to the device. The client application can use the Services method on the device object to retrieve this list of services. This service collection can be parsed to locate a particular service and retrieve a service object.
When UPnP receives the request to retrieve the service object, it will search the list of services for the device to find a matching service ID. If a match is found additional steps are taken. First the URLs for this service (for the description document, control and eventing) are checked for validity. The service description is loaded synchronously using WinInet and the XML DOM interfaces. The next step is to create a service object to represent this service.
In creating the service object, the description for the service is parsed for state variables and a table is created to contain information on these variables. This table includes the variable name, the data type, and default value and an indication whether the variable must be remotely queried (based on whether events are sent for this variable). An action table is also created that contains an array of structures representing the actions supported by the service, including the input and output arguments as well as the return value. These tables and the other information (control URL, Eventing URL, etc.) are copied into the service object returned.
One last step is taken before the service object is returned to the caller. The service is initialized for eventing by the UPnP implementation. A private callback interface is created by UPnP that references this service object. This private interface is stored on the global interface table for the service object. If there are evented variables for the service, the eventing URL is used register for notifications of property changes for the service. This notification allows UPnP to keep its service state table up to date and execute any callbacks registered by clients. Regardless how many callbacks are registered through this service object, only one is registered by the UPnP client with the remote service. The registration proceeds to the SSDP Discovery service just like the registration for device comings and goings previously discussed. We will discuss these registrations next.
Registering a Callback
Once a service object has been retrieved, the client application can use the methods exposed by that object for various things. This includes querying state variables or invoking actions, which will be discussed later, as well as registering a callback to be notified of changes in the state of the service or service state variables.
This callback registration is accomplished through the service object’s AddCallback method. A client uses this method to register a service callback to receive notification of service state changes. Prior to this, when the service object was retrieved, the UPnP client DLL registered for notifications from this service. The client’s callback will be added to the global interface table for the object along with any other state change callbacks registered. When the callback registered by the UPnP client DLL is executed, the callback interfaces stored in the global interface table are walked and called in turn to receive notification of this change.
Whether the registration for notification is instigated by the device finder (for device notifications) or through the service object (for events), the result is a call into the SSDP Client API, and eventually into the SSDP Discovery service. The request includes the type of notification – either “Alive” (for device notifications) or “Property Change” (for service state changes). Also included are the device type or UDN from an asynchronous device search, the event URL for event notifications, the callback for either the device finder or service, and a context to indicate the original source of the request (the search request or the service object).
The SSDP client API forwards this request to the SSDP Discovery service using RPC. Before this happens, several things occur. A structure is allocated that is populated with all of the information about the registration. This includes place to store a handle that will be returned by the service as a way for it to recognize the registration for later deregistration. A handle to this structure is eventually returned to the caller of the SSDP API (the UPnP Client DLL) as its handle to the registration.
Next a check is made to determine if this is the first time a call to register a notification has been made. If this is the case, a notification message loop thread needs to be created. To start this message loop, first a semaphore is created. A thread is then created that calls into the SSDP Discovery (using RPC) service to retrieve notifications. This thread will wait on the semaphore to be signaled. The semaphore will be signaled once for each new notification that is received, allowing the thread to wake and process the message.
Once this notification loop thread has been created, the notification registration can continue. A call is made into the service for this, and depending upon the notification type (alive or property change), the service will process the request differently. For either type request, the semaphore is passed to the service and stored with the request object created. The semaphore can then be located when a notification is received matching the request and released to allow the notification loop thread to run and process the request.
If the request is for device notifications (alive) the information about the notification (including the callback interface) is stored on a list of active alive callbacks. A pointer to this structure on the list of device notifications is returned as the server’s handle to the client API. This is stored along with the other information in a structure representing the registration and a handle to this structure returned to the caller of the SSDP API (The UPnP DLL). The UPnP DLL will use the handle later when calling to deregister the notification if the asynchronous find is canceled or the application shutdown.
The path a registration for property change notification takes is slightly different. In this case we aren’t just waiting for new things to appear and announce themselves, but we actually have to subscribe to the service on the network.
To do this, the SSDP Discovery service uses the WinInet API to create a connection to the service’s event URL and send the subscription request. The return form the remote service will contain a subscription ID and timeout, which are stored in a structure with the rest of the information about this registration. A timer is set on the service’s timer queue to timeout this notification request (based on 65% of the timeout time for the subscription). When this timer fires, a re-subscription request will be sent to the service using the returned subscription ID. The response to the re-subscription request will contain the same subscription ID and a timeout time which may or may not be the same as the time received in the subscription response. The timer is restarted to be 65% of this returned timeout time.
As with the device notification registration, the event notification registration is stored on a list in the service and a handle returned to the client for removing the subscription later. The socket created for event notifications during initialization is used to receive TCP connections for devices submitting notifications.
When Event Notifications Arrive
During initialization the SSDP Discovery Service posted a WSAAsyncSelect call on the socket it created for receiving notifications. A handle to the service’s hidden window and a message indicating receipt of TCP data were specified in this call. When such a message arrives, the service’s Window process will determine the reason for the message – what caused the select to fire, a connection ready to be accepted, closed, or receive data? From this the next step is determined.
If a close message is received, closesocket is called and the connection is removed from a list of open connection the service maintains. If a new connection request has arrived, accept is called and a new connection allocated to manage the new connection. The event server portion of the SSDP Discovery service maintains a linked list of its open connections, storing information such as the peer socket handle and a pre-prepared SSDP message for that connection.
If the message indicates data is available to be read on the socket, a receive buffer is allocated based on the amount of data available (determined via ioctlsocket) and recvfrom called to populate the buffer. All of the available information about the received data, including the socket it was received on; the remote socket address; and the data itself, is copied into a structure and passed as a context in a work item to a worker thread.
When this work item is processed, a check is made to validate the open connection exists on the list of maintained open connections, and the received data is processed. The message is parsed to verify that it is indeed in the expected format and the headers are verified to be complete and valid. The information in the request is copied into a structure used for processing the data further and passed along for further processing (still in the service).
This processing includes checking whether there is a client application interested in this particular event by checking for a match based on the subscription ID and other header values. If there is a client interested in this event the notification request object is retrieved and a pending notification list allocated and added to the object. The semaphore associated with this notification request is then released. If this is actually an incoming discovery notification, and there are clients subscribed to that service, the discovery cache is updated.
Releasing the semaphore causes the notification loop thread to be released (discussed earlier). This loop uses the semaphore as a context to locate the client request and return from the RPC call with the received message.
Preparation is made for the callback into the original client for each event pending, by copying the callback information into a callback structure and incrementing the number of callbacks to be made. Then for each callback, the client registered callback is invoked – this is the callback registered by the UPnP client DLL.
The UPnP client DLL callback will validate the sequence numbers on the event notification and if invalid, re-subscribe to the service. Otherwise, the message is converted to an XML DOM document and parsed to update the state table being kept for the service and call the actual client application registered callback. The client callbacks are located through the service objects global interface table as described during the registration section.
Action (Control) Requests
A client application will use the service object’s InvokeAction method to execute a control request against the service. Control requests, like state variable queries, use SOAP. Because of this they are very much alike in how they are implemented and share code.
This method first does a thorough check of the passed in values – are there the correct number of input variables for this request? Are the output parameters for the output variables and return value correct and writable? To perform these checks, and to execute the action request, the action table maintained for the service object must be parsed to retrieve the structure associated with this action request.
A SOAP request is created, built and executed for this request. WinInet is used for the network interaction required to process this request. The request is sent asynchronously using the control URL from the service object. When the request completes, the results are parsed from the response. If the request was successful, the output parameters and return value are returned to the client application.
Troubleshooting UPnP Client Support
The workings of UPnP are mostly invisible to the user – either the network connected devices and services are available to the control point applications or they are not. If network connectivity is available, such as file and printer sharing, the UPnP devices will likely also be there. Where issues outside of network connectivity and normal network troubleshooting come in is during design and testing of a UPnP device or control point application.
So there are two different types of issues:
· Device or Control Point development issues
· Device and service discovery and usage issues
Device and Control Point development issues are generally solved before the product ships, whether that product is a UPnP device or a control point application. During the development, many of the same issues may arise as are seen by a consumer in a live deployment. Here are some things to try when encountering device discovery issues. These steps are for Windows XP – the process might vary when using a Windows ME computer as the device client.
1. Verify connectivity first.
As with any networking issue, physical connectivity issues are the most common. Connectivity can be verified several ways. First, physical connectivity to the network should be examined. In a home network environment, the device might be connected to the same or different network media than the client.
If the two components are connected to different media, for example one is connected to Ethernet and the other to Wireless, check to see that the two networks are connected together. This could be accomplished using the Network Bridge in Windows XP, or through some other bridging device. How this is tested is dependent on the network configuration and media involved. One possible way of checking this level of connectivity is whether the client can see other devices on the same medium as the target device.
If the two components are on the same physical media, connectivity does not require a network bridge. Some mediums have a visual indication of connectivity that can be checked. For example, Ethernet on twisted pair cabling has green link integrity light to indicate the cable is connected and dependable. Once again, access to other devices on the same media is an indication of connectivity.
If physical connectivity appears to be okay, network protocol connectivity should be checked. This can also be done several ways, but since UPnP requires TCP/IP, the “ping” utility is a simple mechanism. Ping can be run from the Windows XP client and targeted at the device, using the IP address of the device. Determining the IP address of the device is device dependent (some devices may have a way to display this information).
In networks that use UPnP, the address may also be configured using Dynamic Host Configuration Protocol (DHCP). For example, if ICS is being used to share an internet connection, the DHCP server in ICS will assign addresses in the reserved private IP address range of 192.168.0.x. The addresses in this range could be tried to see if any elicit a response [***This is lame. Is there an easier way?]
Because SSDP Discovery uses a multicast frame with TTL of 4, you should also pay attention to the TTL returned by the ping (tracert can also be used for this purpose) command. If the ping succeeds, and the TTL is 255 (indicating the destination is found on this subnet) you can proceed with the assumption network connectivity exists. If you find that more than one hop exists between the device and client, put them on the same hub and test again.
2. Verify the SSDP Discovery Service is running on the Windows XP client and that there are no events in the System log related to it failing.
The SSDP Discovery Service is required as described above in order to detect or search for devices. A simple way to find out if the service is running is to type:
net start <enter>
at the command prompt and look for “SSDP Discovery Service.” If the service is not running, type:
net start “SSDP Discovery Service”<enter>
This should start the service.
The System event log can be checked in event viewer through Control Panel | Administrative Tools | Event Viewer.
3. If you know what port is being used by the device service, you can use telnet to connect to that port and verify HTTP functionality.
If you get the following then the device is not providing access to the XML description (or is doing it on a different port):
Connecting To <computername or IP>…Could not open connection to the host, on port XXX.
No connection could be made because the target machine actively refused it.
Note: If you are trying to troubleshoot the connectivity to a UPnP enabled Internet Gateway device like ICS, this mechanism may not work.
If you can’t get a connection using telnet, there may be a problem with the device, it may be incorrectly configured, or using a port other than the port you are trying. Stop and check these possibilities by locally checking the device configuration.
Another way to detect that the device is working is to check for an icon in My Network Place (remember that the UI component must be installed). If the icon is present, discovery and description are working. If there is no icon, it could indicate a problem but may be because the device does not provide a presentation page (optional).
4. At this point more advanced troubleshooting may be required.
This might involve using Network Monitor or the netcap.exe utility to capture network traffic generated by a UPnP request. The resulting capture could then be examined to verify the SSDP frames are constructed properly, and that the appropriate UPnP traffic was exchanged.
The netcap.exe utility is available on the Windows XP product CD in the \support\tools directory. To read the capture created you will need Network Monitor. Network Monitor is available with Windows Server products or with Microsoft Systems Management Server. A temporary version can also be requested from Microsoft Product Support Services who can provide assistance in analyzing network traces.
In this case particular attention should be paid to the SSDP Response frame to check the Description URL (found in the Location field of this frame). Also check the Description Request (the frame is an HTTP GET for the XML description document) and the Description Response (HTTP Response that passes the XML to the client). If the description request is not sent, or is sent improperly there may be a problem with the SSDP Discovery Service on the client machine, or with the format of the SSDP exchange.
All of the above has verified that the discovery and description traffic is getting to the client machine. The next step would be to figure out what’s happening on the local machine once the data arrives. Several things could be going on, including:
· A corrupt XML document is causing a problem for the client machine
· The SSDP Discovery service is malfunctioning during enumeration
· The UUID for the device conflicts with another, previously discovered device
Microsoft Product Support Services (PSS) could be contacted to assist in this effort.
Summary
The Universal Plug and Play support provided in Windows XP helps make networking a variety of devices together a simple task. As this standard develops and more devices are created supporting the standard protocols used, controlling or monitoring any device from anywhere else in the network will be taken for granted. As the Microsoft Windows platform evolves, support for the devices, services and applications will be expanded and enhanced.
References
For more information on the UPnP Forum and UPnP specifications and standards, visit the UPnP Forum website at http://www.upnp.org.
Information on XML DOM, URLMON, WinInet, and the IP Helper APIs can be found in the Platform SDK, part of the MSDN Library. For more information on the MSDN Library, see http://msdn.microsoft.com
This is a chapter of the SOHO Networking section, part of the Inside Windows Networking series.