text:
\chapter{Conclusion}
\label{chapter:conclusion}

    This thesis's main research objective was to determine whether the Cloud Computing advantages of OpenStack can be leveraged on embedded automotive hardware.
    The first challenge was the installation process and successful execution of OpenStack on such hardware.
    As systems like the Renesas R-Car \ac{SoC} are not intended for such usage, the installation process poses difficulties.
    Due to custom kernels and \acp{OS}, crucial packages and kernel modules for OpenStacks's functionality might not be available, leading to the necessity of an extended kernel and \ac{OS}, as described in Chapter \ref{chapter:host_and_Test_setup}.

    \noindent After a successful installation of OpenStack, two aspects were examined in order to provide a comprehensive answer to the main research question:
    First, the overhead and the impact of OpenStack were examined.
    Through performing dedicated measurements on the \ac{CPU}, memory, network, and storage as described in Chapter \ref{chapter:methodology}, the performance degradation through OpenStack as a middleware was examined.
    Summarizing the overhead results, OpenStack indeed introduces an overhead.
    However, the overhead is lower if the hardware is more powerful.
    This leads to low and acceptable overheads on the Xeon platform, while the R-Car platform suffers greater impacts.
    Especially the R-Car's big.LITTLE architecture, low memory, and low secondary storage performance, mainly lower OpenStacks performance.
    However, introducing hardware with minor changes like more \ac{CPU}-cores, faster secondary storage, or more memory could presumably suffice to achieve acceptable and Xeon-like results.\\
    Second, two advantages of Cloud Computing and OpenStack were examined in greater detail: VM distribution and VM migration.
    Both advantages can introduce benefits for the automotive area.
    Considering the VM distribution, it was found that OpenStack distributes VMs according to defined rules reliable and without errors on both tested platforms.
    As for the VM migration, also on both platforms, the live-migration was shown to happen reliably.
    However, the used ARM platform has too small resources to deliver a good performance and is therefore not suitable for such a use case, as found in Section \ref{section:usecases_application} and Figure \ref{figure:use_case_migration}.
    Although all performed tests succeeded and no wrong functionality was found, the performance was too low to enable the actual usage.
    The x86 platform, on the other hand, delivers excellent performance.
    Considering the live-migration, even using the highest possible VM configuration, it delivers very high performance, suggesting an actual in-vehicle usage.

    \noindent Concluding from all measurements performed, OpenStack is basically executable on automotive embedded hardware.
    Despite the overhead on all examined resources, OpenStack runs as stable on the R-Car SoCs as on the Xeon CPUs.
    While the overhead in some cases is non-negligible, all measurements were performed on a DevStack environment without any optimization towards better performance.
    As this thesis's scope covers only the basic functionality of an OpenStack cluster, the chosen advantages of VM distribution and migration were reliably available.
    Considering the main research question, \textbf{Is it possible to leverage the advantages of Cloud Computing on embedded hardware?}, it can be answered with a \textbf{yes}.
    Although the ARM platform shows deficient performance, it also shows that OpenStack is functional on such hardware, even with a Preempt-RT kernel patch.

    \section{Further Work and Outlook}
    \label{section:further_work}

        Gathered an answer, however, further tests are suggested to gain even more knowledge and confidence.
        Considering the performed tests, they should be extended regarding three areas:

        \begin{itemize}

             \item First and foremost, an installation without DevStack should be performed.
            Apart from unnecessary configurations and software, a better configuration of relevant settings could already improve the results.

            \item Second, the tests should be extended to a broader range of hardware, especially ARM hardware.
            Having compared a high-performance x86-based platform to an efficiency-focused big.LITTLE ARM-based SoC reduces both platforms' comparability and possibly introduces bottlenecks on the ARM platform due to insufficient resources.
            An interesting candidate would be the \textsl{NXP Layerscape LX2160A} processor\footnote{NXP LX2160A Processor: https://tinyurl.com/yxe26f2t \cite{NXP2021}} with 16 cores and no big.LITTLE architecture.
            Also, performing the test in a real-world environment with real automotive applications or benchmarks could further reveal undiscovered insights.

           \item Third and last, the OpenStack cluster should be optimized.
            The performed tests were executed on an out-of-the-box DevStack installation.
            Optimizing the cluster towards better network performance, higher computational performance, and faster storage solutions could significantly influence the results.

        \end{itemize}

        \noindent Besides extending the performed tests, also other, in this thesis not covered areas need to be studied.
        While the R-Car \acp{SoC} are running a kernel with a real-time patch, the specific real-time behavior was out of scope for this thesis.
        Proving that OpenStack and its VMs guarantee  an in-time execution of tasks and therefore provide real-time capabilities would open the possibility the execute real-time applications inside VMs.
        Through this, OpenStack could introduce even more value as a middleware.\\
        Besides handling computational tasks, today's ECUs must interact with various bus systems.
        Considering OpenStack as a middleware on multiple ECUs to execute crucial tasks inside VMs, some data exchange with, for example, sensors must happen.
        Although the Ethernet standard is already present in modern vehicles and the communication via IP-addresses is common, other bus systems will undoubtedly remain due to various factors like costs.
        As determinism, and therefore real-time capability, is also a crucial factor in some bus systems, real-time capable VMs would here as well be necessary, as well as a reliable and performant data exchange with other bus systems.\\
        Further, a topic not considered by this thesis is the usage of hardware acceleration.
        Especially with, for example, image processing or machine learning, the necessity for graphical processing units is becoming increasingly critical.
        OpenStack enables VMs the usage of GPUs via PCI-passthrough.
        Here again, the usability in terms of reliability and performance would have to be evaluated.

        \noindent Apart from the performance and possibilities of OpenStack, the actual usage and the structure of such a cluster would have to be evaluated.
        First, contrary to this thesis, in a real-world deployment of such a cluster, multiple \acp{VM} would be active concurrently.
        Due to an individual  management overhead for each \ac{VM}, the total overhead could be located in completely different dimensions.
        Second, countless different options exist how such a cluster could be organized.
        The major drawback of the cluster used throughout this thesis is the single point of failure, introduced by the core services' single presence.
        A malfunction or failure of one core service, like Neutron, or the whole controller node would lead to a non-functional cluster and, therefore, a complete failure of all \acp{VM} and their applications.
        Hence the question arises, what kind of architecture would be suitable in order to guarantee a reliable operation with efficient resource usage.
        As the core services are critical for a functional OpenStack cluster, a double presence of those services on the cluster would seem reasonable to eliminate the single point of failure.

        \noindent Looking further into a future with vehicles commonly running local private clouds, also new topics arise.
        Having entirely decoupled the software from the hardware, VMs can be executed anywhere and perform any task.
        With bigger clouds in the backend, this introduces the possibility of offloading VMs into the backend and performing the actual computing there.
        Using technologies like 5G, calculations could happen in the more powerful backend, leaving the vehicle's ECUs with as little power consumption as possible.
        This enables the inspection of the vehicle as a participant in a multiaccess edge computing cluster.
        Instead of completely offloading VMs or applications to other clouds in the backend, the vehicle could act as an edge node, preprocessing specific data locally before sending them to other networks and clouds.
        This would genuinely enable to deal with the \textsl{how} to compute, instead of the \textsl{where} to compute.

    \section{Review}
    \label{section:review}

        All initial goals of this thesis were achieved and implemented.
        An OpenStack cluster was successfully installed and executed on automotive embedded hardware.
        The knowledge gained will be used to further examine Cloud Computing and OpenStack's capabilities for in-vehicle usage. \\
        Regarding the initial schedule, it could not be totally met.
        This is mainly due to the installation process of OpenStack on the ARM platform.
        The usage of Yocto was not known in advance and therefore not considered in the initial planning.
        Because of Yocto's complexity, the unsuitability of the OpenStack recipes was only detected after four weeks.
        The discovery of using Ubuntu on the R-Car nevertheless enabled the installation of OpenStack.
        Through the usage of DevStack, the overall installation process could be accelerated and simplified.
        Still, the according kernel and ATF configuration took more time than anticipated, leading to a delayed start of the measurements.

       \noindent The execution of the measurements progressed as planned.
       However, the incomparability of the chosen platforms quickly emerged.
       The limited time frame and the unavailability of according hardware prevented the evaluation of further, more comparable platforms.
       Also, the again specific installation process on other hardware has additionally hindered other platforms' consideration.
       An earlier in-depth review, along with more time and initial tests, could have revealed this property, enabling the use of additional hardware for more confident results.

max_stars_repo_name: MaxMalinowski/BachelorThesis

max_issues_repo_name: MaxMalinowski/BachelorThesis

max_forks_repo_name: MaxMalinowski/BachelorThesis


text:
\chapter{Classes: the basics}

The basic idea behind classes is to group variables which belong together. For example, \eeClass{Vec2} has the values x and y which together make up a 2D position. Without this class, you would have to declare two separate floats to remember a position.

A software library is, for the most part, a collection of classes that work well together. The library developer provides classes which can be used to make your job easier. It would be hard to imagine a game without positions, so it makes sense that Esenthel engine provides you with a class to store such a position. In a most basic form, this class could look like this:

\begin{code}
class Vec2 {
	float x;
	float y;
}
\end{code}

When this class is defined, it can be used anywhere in your application:

\begin{code}
Vec2 pos;
Vec2 pos2 = pos; // assigns the values of pos to pos2
pos.x = 3;       // change the x value of pos
pos.y = pos2.x;  // assign the x value of pos2 to the
				 // y value of pos
\end{code}

In every application except from the small exercises we have done in the previous chapters, you should design your own classes. Almost every aspect of your program should be contained within a class. So it's about time you learn more about them.

\begin{note}
When two or more objects or variables belong together, they should be part of a class.
\end{note}

Please note that there's a difference between a class and an object. In the example above, \eeClass{Vec2} is a class, but pos and pos2 are objects of this class. You cannot use \eeClass{Vec2} as if it were an object, but you can use this class to create one:

\begin{code}
Vec2.x = 3; // wrong!
Vec2 pos;
pos.x = 3; // correct.
\end{code}

\section{Create your own class}
Imagine you need a moving circle in your application. To have a circle move at a fixed speed, you will need a variable to store this speed. It clearly belongs with the circle, but it isn't part of the Circle class provided by Esenthel because not every circle needs to move. So we create our own class:

\begin{code}
class movingCircle {
  Circle c;
  Vec2 speed;
}

// declare an object of this class
movingCirle mc;

// some code in Init()
mc.c.set(0.1, Vec2(-0.4, -0.3));
mc.speed = Vec2(0.3, 0.5);

// some code in Update()
mc.c.pos += mc.speed * Time.d();
\end{code}

Once you have a class \eeClass{movingCirle}, you can create as much moving circles as you like, all able to remember their own speed. \textit{(Although the current class can be improved a lot, which you will learn in a next chapter)}.

\begin{exercise}
\begin{enumerate}
  \item Create a container for the class \eeClass{movingCircle}. Every time you press the space bar an element should be added to the container, on a random position and with a random speed.
	\item Make sure all circles update their position in the Update function. When a circle goes outside of the screen, put it back in the middle.
	\item Expand the class \eeClass{movingCirle} with a color. Every object has a random color, to be used to draw it on the screen.
	\end{enumerate}
\end{exercise}

\begin{note}
More work will be done on this exercise in the next chapter. Save it!
\end{note}

ext: tex

max_stars_repo_name: yvanvds/EsenthelCourse

max_issues_repo_name: yvanvds/EsenthelCourse

max_forks_repo_name: yvanvds/EsenthelCourse


text:
\chapter{Exceptional ground snow per Eurocode}
\label{cha:exceptional}

% **************************** Define Graphics Path **************************
\ifpdf
    \graphicspath{{Chapter6/Figs/Raster/}{Chapter6/Figs/PDF/}{Chapter6/Figs/}}
\else
    \graphicspath{{Chapter6/Figs/Vector/}{Chapter6/Figs/}}
\fi

% **************************** Chapter Abstract ******************************
\leftskip=1cm
\noindent
\emph{The concept of exceptional ground snow load was introduced to EN 1991-1-3 based on French precedent, however, no other CEN member country has had similar provision before. Curiously, it has no quantitative definition in the standard, although this ``new action'' is governing the design of many lightweight structures. In this chapter, we critically examine the concept of exceptional ground snow load and offer a physical, statistical and reliability analysis based treatment. The analyses show that the concept of exceptional snow load provided in the related Eurocode background document is not justified statistically, either meteorologically. Reliability based definition is proposed that is generalized to other exceptional loads.  In contrast with the current definition it is believed to be founded on sound meteorological, statistical, and reliability principles. Moreover, it allows quantitative treatment opposed to the prescribing nature of the current one. The range of parameters where exceptional ground snow load should be considered is identified.}

\leftskip=0pt\rightskip=0pt

\section{Problem statement and the state of the art}
% Mirek ~ short chapter or annex!?

The joint European research effort \citep{Sanpaolesi1998}, which introduced the concept of exceptional snow action defines it as:
\begin{quote}
	``Isolated and very infrequent snowfalls where the resulting snow load is significantly greater than the loads in the general body of snow load data and its inclusion in that data set distorts the statistical analysis.''
\end{quote}

Later the report provides a working definition of exceptional snow load:
\begin{quote}
	``If the ratio of the largest load value to the characteristic load determined without the inclusion of that value is greater than 1.5 then the largest load value shall be treated as an exceptional value.''
\end{quote}

This definition is intended to be used to identify the ``isolated and very infrequent snowfalls''. However, it says nothing about how the standardized exceptional snow load model should be constructed from the identified exceptional loads. Moreover, there is a salient shortcoming of the above definition as it does not refer to any observation length. With increasing observation length the definition will almost surely identify exceptional loads, even if the sampled distribution is deliberately selected to be non-extreme. Furthermore, the definition is only related to annual maxima, this is clear from the report that considers this sole approach.

As stated in the scope and limits of this thesis (Section~\ref{sec:scope}) we focus solely on ground snow load. Hence, the snow load is to be understood as ground snow load and not snow on the roof.

\section{Solution strategy}
and here I write more \dots

\section{Results and discussion}

%\section{Extension to other random variables}
\section{Application example}

\section{Summary and conclusions}

Initial calculations show that the definition given in Eurocode background document is inappropriate; there seems to be no meteorological justification for exceptional snow; reliability based definition is proposed


text:
\chapter{ImageInput: Reading Images}
\label{chap:imageinput}
\index{Image I/O API|(}

\section{Image Input Made Simple}
\label{sec:imageinput:simple}

Here is the simplest sequence required to open an image file, find
out its resolution, and read the pixels (converting them into
8-bit values in memory, even if that's not the way they're stored in the file):

\begin{code}
        #include <OpenImageIO/imageio.h>
        using namespace OIIO;
        ...

        auto in = ImageInput::open (filename);
        if (! in)
            return;
        const ImageSpec &spec = in->spec();
        int xres = spec.width;
        int yres = spec.height;
        int channels = spec.nchannels;
        std::vector<unsigned char> pixels (xres*yres*channels);
        in->read_image (TypeDesc::UINT8, &pixels[0]);
        in->close ();
\end{code}

\noindent Here is a breakdown of what work this code is doing:

\begin{itemize}
\item Search for an ImageIO plugin that is capable of reading the file
  (\qkw{foo.jpg}), first by trying to deduce the correct plugin from the
  file extension, but if that fails, by opening every ImageIO plugin it
  can find until one will open the file without error.  When it finds
  the right plugin, it creates a subclass instance of \ImageInput that
  reads the right kind of file format, and tries to fully open the file.
  The {\cf open()} method returns a {\cf std::unique_ptr<ImageInput>} that will
  be automatically freed when it exits scope.
  \begin{code}
        auto in = ImageInput::open (filename);
  \end{code}
\item The specification, accessible as {\cf in->spec()}, contains
  vital information such as the
  dimensions of the image, number of color channels, and data type of
  the pixel values.  This is enough to allow us to allocate enough space
  for the image.
  \begin{code}
        const ImageSpec &spec = in->spec();
        int xres = spec.width;
        int yres = spec.height;
        int channels = spec.nchannels;
        std::vector<unsigned char> pixels (xres*yres*channels);
  \end{code}
  Note that in this example, we don't care what data format is used for
  the pixel data in the file --- we allocate enough space for unsigned
  8-bit integer pixel values, and will rely on \product's ability to
  convert to our requested format from the native data format of the
  file.
\item Read the entire image, hiding all details of the encoding of image
  data in the file, whether the file is scanline- or tile-based, or what
  is the native format of the data in the file (in this case, we request
  that it be automatically converted to unsigned 8-bit integers).
  \begin{code}
        in->read_image (TypeDesc::UINT8, &pixels[0]);
  \end{code}
\item Close the file.
  \begin{code}
        in->close ();
  \end{code}
\item When {\cf in} exits its scope, the \ImageInput will automatically be
  destroyed and any resources used by the plugin will be released.
\end{itemize}

\section{Advanced Image Input}
\label{sec:advancedimageinput}

Let's walk through some of the most common things you might want to do,
but that are more complex than the simple example above.

\subsection{Reading individual scanlines and tiles}
\label{sec:imageinput:scanlinestiles}

The simple example of Section~\ref{sec:imageinput:simple} read an
entire image with one call.  But sometimes you want to read a large
image a
little at a time and do not wish to retain the entire image in memory
as you process it.  \product allows you to read images
one scanline at a time or one tile at a time.

Examining the \ImageSpec reveals whether the file is scanline or
tile-oriented: a scanline image will have {\cf spec.tile_width}
and {\cf spec.tile_height} set to 0, whereas a tiled images will
have nonzero values for the tile dimensions.

\subsubsection{Reading scanlines}

Individual scanlines may be read using the \readscanline API
call:

\begin{code}
        ...
        auto in = ImageInput::open (filename);
        const ImageSpec &spec = in->spec();
        if (spec.tile_width == 0) {
            std::vector<unsigned char> scanline (spec.width*spec.channels);
            for (int y = 0;  y < yres;  ++y) {
                in->read_scanline (y, 0, TypeDesc::UINT8, &scanline[0]);
                ... process data in scanline[0..width*channels-1] ...
            }
        } else {
            ... handle tiles, or reject the file ...
        }
        in->close ();
        ...
\end{code}

The first two arguments to \readscanline specify which scanline
is being read by its vertical ($y$) scanline number (beginning with 0)
and, for volume images, its slice ($z$) number (the slice number should
be 0 for 2D non-volume images).  This is followed by a \TypeDesc
describing the data type of the pixel buffer you are supplying, and a
pointer to the pixel buffer itself.  Additional optional arguments
describe the data stride, which can be ignored for contiguous data (use
of strides is explained in Section~\ref{sec:imageinput:strides}).

Nearly all \ImageInput implementations will be most efficient reading
scanlines in strict order (starting with scanline 0, then 1, up to {\kw
  yres-1}, without skipping any).  An \ImageInput is required to accept
\readscanline requests in arbitrary order, but depending on the file
format and reader implementation, out-of-order scanline reads may be
inefficient.

There is also a {\cf read_scanlines()} function that operates similarly,
except that it takes a {\cf ybegin} and {\cf yend} that specify a range,
reading all scanlines {\cf ybegin} $\le y <$ {\cf yend}.  For most image
format readers, this is implemented as a loop over individual scanlines,
but some image format readers may be able to read a contiguous block of
scanlines more efficiently than reading each one individually.

The full descriptions of the \readscanline and {\cf read_scanlines()}
functions may be found in Section~\ref{sec:imageinput:reference}.

\subsubsection{Reading tiles}

Once you {\kw open()} an image file, you can find out if it is a tiled
image (and the tile size) by examining the \ImageSpec's {\cf
  tile_width}, {\cf tile_height}, and {\cf tile_depth} fields.
If they are zero, it's a scanline image and you should read pixels
using \readscanline, not \readtile.

\begin{code}
        ...
        auto in = ImageInput::open (filename);
        const ImageSpec &spec = in->spec();
        if (spec.tile_width == 0) {
            ... read by scanline ...
        } else {
            // Tiles
            int tilesize = spec.tile_width * spec.tile_height;
            std::vector<unsigned char> tile (tilesize * spec.channels);
            for (int y = 0;  y < yres;  y += spec.tile_height) {
                for (int x = 0;  x < xres;  x += spec.tile_width) {
                    in->read_tile (x, y, 0, TypeDesc::UINT8, &tile[0]);
                    ... process the pixels in tile[] ..
                }
            }
        }
        in->close ();
        ...
\end{code}

The first three arguments to \readtile specify which tile is
being read by the pixel coordinates of any pixel contained in the
tile: $x$ (column), $y$ (scanline), and $z$ (slice, which should always
be 0 for 2D non-volume images).  This is followed by a \TypeDesc
describing the data format of the pixel buffer you are supplying, and a
pointer to the pixel buffer.  Pixel data will be written to your buffer
in order of increasing slice, increasing
scanline within each slice, and increasing column within each scanline.
Additional optional arguments describe the data stride, which can be
ignored for contiguous data (use of strides is explained in
Section~\ref{sec:imageinput:strides}).

All \ImageInput implementations are required to support reading tiles in
arbitrary order (i.e., not in strict order of increasing $y$ rows, and
within each row, increasing $x$ column, without missing any tiles).

The full description of the \readtile function may be found
in Section~\ref{sec:imageinput:reference}.

\subsection{Converting formats}
\label{sec:imageinput:convertingformat}

The code examples of the previous sections all assumed that your
internal pixel data is stored as unsigned 8-bit integers (i.e., 0-255
range).  But \product is significantly more flexible.

You may request that the pixels be stored in any of several formats.
This is done merely by passing the {\cf read} function the data type
of your pixel buffer, as one of the enumerated type \TypeDesc.

%FIXME
%Individual file formats, and therefore \ImageInput implementations, may
%only support a subset of the formats understood by the \product library.
%Each \ImageInput plugin implementation should document which data
%formats it supports.  An individual \ImageInput implementation may
%choose to simply fail open {\kw open()}, though the recommended behavior
%is for {\kw open()} to succeed but in fact choose a data format
%supported by the file format that best preserves the precision and range
%of the originally-requested data format.

It is not required that the pixel data buffer passed to \readimage,
\readscanline, or \readtile actually be in the same data format as the
data in the file being read.  \product will automatically convert from
native data type of the file to the internal data format of your choice.
For example, the following code will open a TIFF and read pixels into
your internal buffer represented as {\cf float} values.  This will work
regardless of whether the TIFF file itself is using 8-bit, 16-bit, or
float values.

\begin{code}
        std::unique_ptr<ImageInput> in = ImageInput::open ("myfile.tif");
        const ImageSpec &spec = in->spec();
        ...
        int numpixels = spec.width * spec.height;
        float pixels = new float [numpixels * channels];
        ...
        in->read_image (TypeDesc::FLOAT, pixels);
\end{code}

\noindent Note that \readscanline and \readtile have a parameter that
works in a corresponding manner.

You can, of course, find out the native type of the file simply by
examining {\cf spec.format}.  If you wish, you may then allocate a
buffer big enough for an image of that type and request the native type
when reading, therefore eliminating any translation among types and
seeing the actual numerical values in the file.

%FIXME
%Please refer to Section~\ref{sec:imageinput:quantization} for more
%information on how values are translated among the supported data
%formats by default, and how to change the formulas by specifying
%quantization in the \ImageSpec.

\subsection{Data Strides}
\label{sec:imageinput:strides}

In the preceeding examples, we have assumed that the buffer passed to
the {\cf read} functions (i.e., the place where you want your pixels
to be stored) is \emph{contiguous}, that is:

\begin{itemize}
\item each pixel in memory consists of a number of data values equal to
  the number of channels in the file;
\item successive column pixels within a row directly follow each other in
  memory, with the first channel of pixel $x$ immediately following
  last channel of pixel $x-1$ of the same row;
\item for whole images or tiles, the data for each row
  immediately follows the previous one in memory (the first pixel of row
  $y$ immediately follows the last column of row $y-1$);
\item for 3D volumetric images, the first pixel of slice $z$ immediately
  follows the last pixel of of slice $z-1$.
\end{itemize}

Please note that this implies that \readtile will write pixel data into
your buffer so that it is contiguous in the shape of a single tile, not
just an offset into a whole image worth of pixels.

The \readscanline function takes an optional {\cf xstride} argument, and
the \readimage and \readtile functions take optional {\cf xstride},
{\cf ystride}, and {\cf zstride} values that describe the distance, in
\emph{bytes}, between successive pixel columns, rows, and slices,
respectively, of your pixel buffer.  For any of these values that are
not supplied, or are given as the special constant {\cf AutoStride},
contiguity will be assumed.

By passing different stride values, you can achieve some surprisingly
flexible functionality.  A few representative examples follow:

\begin{itemize}
\item Flip an image vertically upon reading, by using \emph{negative}
  $y$ stride:
  \begin{code}
    unsigned char pixels[spec.width * spec.height * spec.nchannels];
    int scanlinesize = spec.width * spec.nchannels * sizeof(pixels[0]);
    ...
    in->read_image (TypeDesc::UINT8,
                    (char *)pixels+(yres-1)*scanlinesize, // offset to last
                    AutoStride,                  // default x stride
                    -scanlinesize,               // special y stride
                    AutoStride);                 // default z stride
  \end{code}
\item Read a tile into its spot in a buffer whose layout matches
  a whole image of pixel data,
  rather than having a one-tile-only memory layout:
  \begin{code}
    unsigned char pixels[spec.width * spec.height * spec.nchannels];
    int pixelsize = spec.nchannels * sizeof(pixels[0]);
    int scanlinesize = xpec.width * pixelsize;
    ...
    in->read_tile (x, y, 0, TypeDesc::UINT8,
                   (char *)pixels + y*scanlinesize + x*pixelsize,
                   pixelsize,
                   scanlinesize);
  \end{code}
\end{itemize}

Please consult Section~\ref{sec:imageinput:reference} for detailed
descriptions of the stride parameters to each {\cf read} function.

\subsection{Reading metadata}
\label{sec:imageinput:metadata}

The \ImageSpec that is filled in by {\cf ImageInput::open()}
specifies all the common properties that describe an image: data format,
dimensions, number of channels, tiling.  However, there may be a variety
of additional \emph{metadata} that are present in the image file and
could be queried by your application.

The remainder of this section explains how to query additional metadata
in the \ImageSpec.  It is up to the \ImageInput to read these
from the file, if indeed the file format is able to carry additional
data.  Individual \ImageInput implementations should document which
metadata they read.

\subsubsection{Channel names}

In addition to specifying the number of color channels, the
\ImageSpec also stores the names of those channels in its {\cf
  channelnames} field, which is a {\cf vector<std::string>}.  Its length
should always be equal to the number of channels (it's the
responsibility of the \ImageInput to ensure this).

Only a few file formats (and thus \ImageInput implementations) have a
way of specifying custom channel names, so most of the time you will see
that the channel names follow the default convention of being named
\qkw{R}, \qkw{G}, \qkw{B}, and \qkw{A}, for red, green, blue, and alpha,
respectively.

Here is example code that prints the names of the channels in an image:

\begin{code}
        ImageInput *in = ImageInput::open (filename);
        const ImageSpec &spec = in->spec();
        for (int i = 0;  i < spec.nchannels;  ++i)
            std::cout << "Channel " << i << " is "
                      << spec.channelnames[i] << "\n";
\end{code}

\subsubsection{Specially-designated channels}

The \ImageSpec contains two fields, {\cf alpha_channel} and {\cf
  z_channel}, which designate which channel numbers represent alpha and
$z$ depth, if any.  If either is set to {\cf -1}, it indicates that it
is not known which channel is used for that data.

If you are doing something special with alpha or depth, it is probably
safer to respect the {\cf alpha_channel} and {\cf z_channel}
designations (if not set to {\cf -1}) rather than merely assuming that,
for example, channel 3 is always the alpha channel.

\subsubsection{Arbitrary metadata}

All other metadata found in the file will be stored in the
\ImageSpec's {\cf extra_attribs} field, which is a
\ParamValueList, which is itself essentially a vector of
\ParamValue instances.  Each \ParamValue
stores one meta-datum consisting of a name, type (specified by
a \TypeDesc), number of values, and data pointer.

If you know the name of a specific piece of metadata you want to use,
you can find it using the {\cf ImageSpec::find_attribute()}
method, which returns a pointer to the matching \ParamValue,
or {\cf NULL} if no match was found.  An optional \TypeDesc
argument can narrow the search to only parameters that match the
specified type as well as the name.  Below is an
example that looks for orientation information, expecting it to consist
of a single integer:

\begin{code}
        ImageInput *in = ImageInput::open (filename);
        const ImageSpec &spec = in->spec();
        ...
        ParamValue *p = spec.find_attribute ("Orientation", TypeInt);
        if (p) {
            int orientation = * (int *) p->data();
        } else {
            std::cout << "No integer orientation in the file\n";
        }
\end{code}

By convention, \ImageInput plugins will save all integer metadata as
32-bit integers ({\cf TypeDesc::INT} or {\cf TypeDesc::UINT}), even if the file format
dictates that a particular item is stored in the file as a 8- or 16-bit
integer.  This is just to keep client applications from having to deal
with all the types.  Since there is relatively little metadata compared
to pixel data, there's no real memory waste of promoting all integer
types to int32 metadata.  Floating-point metadata and string metadata
may also exist, of course.

For certain common types, there is an even simpler method for retrieving
the metadata:

\begin{code}
    int i = spec.get_int_attribute ("Orientation", 0);
    float f = spec.get_float_attribute ("PixelAspectRatio", 1.0f);
    std::string s = spec.get_string_attribute ("ImageDescription", "");
\end{code}

This method simply returns the value.  The second argument is the
default value to use if the attribute named is not found.  These
versions will do automatic type conversion as well --- for example,
if you ask for a float and the attribute is really an int, it will
return the proper float for it; or if the attribute is a UINT16 and
you call {\cf get_int_attribute}, it will succeed, promoting to an int.

It is also possible to step through all the metadata, item by item.
This can be accomplished using the technique of the following example:

\begin{code}
        for (size_t i = 0;  i < spec.extra_attribs.size();  ++i) {
            const ParamValue &p (spec.extra_attribs[i]);
            printf ("    \%s: ", p.name.c_str());
            if (p.type() == TypeString)
                printf ("\"\%s\"", *(const char **)p.data());
            else if (p.type() == TypeFloat)
                printf ("\%g", *(const float *)p.data());
            else if (p.type() == TypeInt)
                printf ("\%d", *(const int *)p.data());
            else if (p.type() == TypeDesc::UINT)
                printf ("\%u", *(const unsigned int *)p.data());
            else if (p.type() == TypeMatrix) {
                const float *f = (const float *)p.data();
                printf ("\%f \%f \%f \%f \%f \%f \%f \%f "
                        "\%f \%f \%f \%f \%f \%f \%f \%f",
                        f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7],
                        f[8], f[9], f[10], f[11], f[12], f[13], f[14], f[15]);
            }
            else
                printf (" <unknown data type> ");
            printf ("\n");
        }
\end{code}

Each individual \ImageInput implementation should document the names,
types, and meanings of all metadata attributes that they understand.

\subsubsection{Color space hints}

We certainly hope that you are using only modern file formats that
support high precision and extended range pixels (such as OpenEXR) and
keeping all your images in a linear color space.  But you may have to
work with file formats that dictate the use of nonlinear color values.
This is prevalent in formats that store pixels only as 8-bit values,
since 256 values are not enough to linearly represent colors without
banding artifacts in the dim values.

The {\cf ImageSpec::extra_attribs} field may store metadata that reveals
the color space the image file in the \qkw{oiio:ColorSpace}
attribute (see Section~\ref{metadata:colorspace} for explanations of
particular values).

The \ImageInput sets the \qkw{oiio:ColorSpace} metadata in a
purely advisory capacity --- the {\cf read} will not convert pixel
values among color spaces.  Many image file formats only support
nonlinear color spaces (for example, JPEG/JFIF dictates use of sRGB).
So your application should intelligently deal with gamma-corrected and
sRGB input, at the very least.

The color space hints only describe color channels.  You should assume that
alpha or depth ($z$) channels (designated by the {\cf alpha_channel} and
{\cf z_channel} fields, respectively) always represent linear values and
should never be transformed by your application.

%\subsection{Controlling quantization and encoding}
%\label{sec:imageinput:quantization}
%
%FIXME

%\subsection{Random access and repeated transmission of pixels}
%\label{sec:imageinput:randomrepeated}
%
%FIXME

\subsection{Multi-image files and MIP-maps}
\label{sec:imageinput:multiimage}
\label{sec:imageinput:mipmap}

Some image file formats support multiple discrete subimages to be stored
in one file, and/or miltiple resolutions for each image to form a
MIPmap.  When you {\cf open()} an \ImageInput, it will by default point
to the first (i.e., number 0) subimage in the file, and the highest
resolution (level 0) MIP-map level.  You can switch to viewing another
subimage or MIP-map level using the {\cf seek_subimage()} function:

\begin{code}
        ImageInput *in = ImageInput::open (filename);
        const ImageSpec &spec = in->spec();
        ...
        int subimage = 1;
        int miplevel = 0;
        if (in->seek_subimage (subimage, miplevel, spec)) {
            ...
        } else {
            ... no such subimage/miplevel ...
        }
\end{code}

The {\cf seek_subimage()} function takes three arguments: the index of
the subimage to switch to (starting with 0), the MIPmap level (starting
with 0 for the highest-resolution level), and a reference to an
\ImageSpec, into which will be stored the spec of the new
subimage/miplevel.  The {\cf seek_subimage()} function returns {\cf
  true} upon success, and {\cf false} if no such subimage or MIP level
existed.  It is legal to visit subimages and MIP levels out of order;
the \ImageInput is responsible for making it work properly.  It is also
possible to find out which subimage and MIP level is currently being
viewed, using the {\cf current_subimage()} and {\cf current_miplevel()}
functions, which return the index of the current subimage and MIP
levels, respectively.

Below is pseudocode for reading all the levels of a MIP-map (a
multi-resolution image used for texture mapping) that shows how to read
multi-image files:

\begin{code}
        auto in = ImageInput::open (filename);
        const ImageSpec &spec = in->spec();

        int num_miplevels = 0;
        while (in->seek_subimage (0, num_miplevels, spec)) {
            // Note: spec has the format of the current subimage/miplevel
            int npixels = spec.width * spec.height;
            int nchannels = spec.nchannels;
            unsigned char *pixels = new unsigned char [npixels * nchannels];
            in->read_image (TypeDesc::UINT8, pixels);

            ... do whatever you want with this level, in pixels ...

            delete [] pixels;
            ++num_miplevels;
        }
        // Note: we break out of the while loop when seek_subimage fails
        // to find a next MIP level.

        in->close ();
\end{code}

In this example, we have used \readimage, but of course \readscanline
and \readtile work as you would expect, on the current subimage and MIP
level.

\subsection{Per-channel formats}
\label{sec:imageinput:channelformats}

Some image formats allow separate per-channel data formats (for example,
{\cf half} data for colors and {\cf float} data for depth).  If you want
to read the pixels in their true native per-channel formats,
the following steps are necessary:

\begin{enumerate}
\item Check the \ImageSpec's {\cf channelformats} vector.  If non-empty,
  the channels in the file do not all have the same format.
\item When calling {\cf read_scanline}, {\cf read_scanlines},
  {\cf read_tile}, {\cf read_tiles}, or {\cf read_image},
  pass a format of {\cf TypeDesc::UNKNOWN} to indicate that
  you would like the raw data in native per-channel format of the file
  written to your {\cf data} buffer.
\end{enumerate}

For example, the following code fragment will read a 5-channel image
to an OpenEXR file, consisting of R/G/B/A channels in {\cf half} and
a Z channel in {\cf float}:

\begin{code}
        ImageInput *in = ImageInput::open (filename);
        const ImageSpec &spec = in->spec();

        // Allocate enough space
        unsigned char *pixels = new unsigned char [spec.image_bytes(true)];

        in->read_image (TypeDesc::UNKNOWN, /* use native channel formats */
                        pixels);           /* data buffer */

        if (spec.channelformats.size() > 0) {
            ... the buffer contains packed data in the native
                per-channel formats ...
        } else {
            ... the buffer contains all data per spec.format ...
        }
\end{code}

\subsection{Reading ``deep'' data}
\label{sec:imageinput:deepdata}  \index{deep data}
Some image file formats (OpenEXR only, at this time) support the concept
of ``deep'' pixels -- those containing multiple samples per pixel (and a
potentially differing number of them in each pixel).
You can tell an image is ``deep'' from its \ImageSpec: the {\cf deep}
field will be {\cf true}.

Deep files cannot be read with the usual {\cf read_scanline}, {\cf
  read_scanlines}, {\cf read_tile}, {\cf read_tiles}, {\cf read_image}
functions, due to the nature of their variable number of samples per
pixel.  Instead, \ImageInput has three special member functions used
only for reading deep data:

\begin{code}
    bool read_native_deep_scanlines (int subimage, int miplevel,
                                     int ybegin, int yend, int z,
                                     int chbegin, int chend,
                                     DeepData &deepdata);

    bool read_native_deep_tiles (int subimage, int miplevel,
                                 int xbegin, int xend, int ybegin int yend,
                                 int zbegin, int zend,
                                 int chbegin, int chend, DeepData &deepdata);

    bool read_native_deep_image (int subimage, int miplevel,
                                 DeepData &deepdata);
\end{code}

It is only possible to read ``native'' data types from deep files; that
is, there is no automatic translation into arbitrary data types as there
is for ordinary images.  All three of these functions store the
resulting deep data in a special {\cf DeepData} structure, described in
detail in Section~\ref{sec:deepdata}.

Here is an example of using these methods to read a deep image from
a file and print all its values:

\begin{code}
    auto in = ImageInput::open (filename);
    if (! in)
        return;
    const ImageSpec &spec = in->spec();
    if (spec.deep) {
        DeepData deepdata;
        in->read_native_deep_image (0, 0, deepdata);
        int p = 0;  // absolute pixel number
        for (int y = 0; y < spec.height;  ++y) {
            for (int x = 0;  x < spec.width;  ++x, ++p) {
                std::cout << "Pixel " << x << "," << y << ":\n";
                if (deepdata.samples(p) == 0)
                    std::cout << "  no samples\n";
                else
                    for (int c = 0;  c < spec.nchannels;  ++c) {
                        TypeDesc type = deepdata.channeltype(c);
                        std::cout << "  " << spec.channelnames[c] << ": ";
                        void *ptr = deepdata.pointers[p*spec.nchannels+c]
                        for (int s = 0; s < deepdata.samples(p); ++s) {
                            if (type.basetype == TypeDesc::FLOAT ||
                                type.basetype == TypeDesc::HALF)
                                std::cout << deepdata.deep_value(p, c, s) << ' ';
                            else if (type.basetype == TypeDesc::UINT32)
                                std::cout << deepdata.deep_value_uint(p, c, s) << ' ';
                        }
                        std::cout << "\n";
                    }
            }
        }
    }
    in->close ();
\end{code}

\subsection{Custom I/O proxies (and reading the file from a memory buffer)}
\label{sec:imageinput:ioproxy}
\index{reading an image file from memory buffer}
\NEW   % 1.9

Some file format readers allow you to supply a custom I/O proxy object that
can allow bypassing the usual file I/O with custom behavior, including the
ability to read the file form an in-memory buffer rather than reading from
disk.

Only some input format readers support this feature. To find out if a
particular file format supports this feature, you can create an \ImageInput
of the right type, and check if it supports the feature name \qkw{ioproxy}:

\begin{code}
    ImageInput *in = ImageInput::create (filename);
    if (! in  ||  ! in->supports ("ioproxy")) {
        ImageInput::destroy (in);
        in = nullptr;
        return;
    }
\end{code}

\ImageInput readers that support \qkw{ioproxy} will respond to a special
attribute, \qkw{oiio:ioproxy}, which passes a pointer to a {\cf
Filesystem::IOProxy*} (see \product's {\cf filesystem.h} for this type and
its subclasses). {\cf IOProxy} is an abstract type, and concrete subclasses
include {\cf IOFile} (which wraps I/O to an open {\cf FILE*}) and {\cf
IOMemReader} (which reads input from a block of memory).

Here is an example of using a proxy that reads the ``file'' from a memory
buffer:

\begin{code}
    const void *buf = ...;   // pointer to memory block
    size_t size = ...;       // length of memory block

    ImageSpec config; // ImageSpec describing input configuration options
    Filesystem::IOMemReader memreader (buf, size);  // I/O proxy object
    void *ptr = &memreader;
    config.attribute ("oiio:ioproxy", TypeDesc::PTR, &ptr);

    ImageSpec spec;
    ImageInput *in = ImageInput::open ("in.exr", spec, &config);
    in->read_image (...);
    ImageInput::destroy (in);

    // That will have read the "file" from the memory buffer
\end{code}

\subsection{Custom search paths for plugins}
\label{sec:imageinput:searchpaths}

Please see Section~\ref{sec:miscapi} for discussion
about setting the plugin search path via the {\cf attribute()} function.
For example:

\begin{code}
        std::string mysearch = "/usr/myapp/lib:${HOME}/plugins";
        OpenImageIO::attribute ("plugin_searchpath", mysearch);
        ImageInput *in = ImageInput::open (filename);
        ...
\end{code} %$

\subsection{Error checking}
\label{sec:imageinput:errors}
\index{error checking}

Nearly every \ImageInput API function returns a {\cf bool} indicating
whether the operation succeeded ({\cf true}) or failed ({\cf false}).
In the case of a failure, the \ImageInput will have saved an error
message describing in more detail what went wrong, and the latest
error message is accessible using the \ImageInput method
{\cf geterror()}, which returns the message as a {\cf std::string}.

The exceptions to this rule are static methods such as the static
{\cf ImageInput::open} and {\cf ImageInput::create}, which return
an empty pointer if it could not create an appropriate \ImageInput (and open
it, in the case of {\cf open()}.  In such a case,
since no \ImageInput is returned for which you can call its {\cf
  geterror()} function, there exists a global {\cf geterror()}
function (in the {\cf OpenImageIO} namespace) that retrieves the latest
error message resulting from a call to static {\cf open()} or {\cf create()}.

Here is another version of the simple image reading code from
Section~\ref{sec:imageinput:simple}, but this time it is fully
elaborated with error checking and reporting:

\begin{code}
        #include <OpenImageIO/imageio.h>
        using namespace OIIO;
        ...

        const char *filename = "foo.jpg";
        int xres, yres, channels;
        std::vector<unsigned char> pixels;

        auto in = ImageInput::open (filename);
        if (! in) {
            std::cerr << "Could not open " << filename
                      << ", error = " << OpenImageIO::geterror() << "\n";
            return;
        }
        const ImageSpec &spec = in->spec();
        xres = spec.width;
        yres = spec.height;
        channels = spec.nchannels;
        pixels.resize (xres*yres*channels);

        if (! in->read_image (TypeDesc::UINT8, &pixels[0])) {
            std::cerr << "Could not read pixels from " << filename
                      << ", error = " << in->geterror() << "\n";
            return;
        }

        if (! in->close ()) {
            std::cerr << "Error closing " << filename
                      << ", error = " << in->geterror() << "\n";
            return;
        }
\end{code}

\newpage
\section{\ImageInput Class Reference}
\label{sec:imageinput:reference}

\apiitem{std::unique_ptr<ImageInput> {\ce open} (const std::string \&filename, \\
\bigspc\bigspc\spc const ImageSpec *config=nullptr)}
Create an \ImageInput subclass instance that is able to read
the given file and open it. The return value is a managed unique pointer,
with an included deleter that will properly dispose the \ImageInput when
it exists its scope.  If the open fails, return an empty pointer and
set an error that can
be retrieved by {\cf OpenImageIO::geterror()}.

The {\cf config}, if not {\cf nullptr}, points to an \ImageSpec giving
requests or special instructions.  \ImageInput implementations
are free to not respond to any such requests, so the default
implementation is just to ignore config.

The {\cf open()} function will first try to make an \ImageInput
corresponding to the format implied by the file extension (for example,
\qkw{foo.tif} will try the TIFF plugin), but if one is not found or if
the inferred one does not open the file, every known \ImageInput type
will be tried until one is found that will open the file.
\apiend

\apiitem{std::unique_ptr<ImageInput> {\ce create} (const std::string \&filename, \\
\bigspc\bigspc   bool do_open=false, const ImageSpec *config=nullptr,\\
\bigspc\bigspc   string_view plugin_searchpath="")}
Create and return an \ImageInput implementation that is able
to read the given file.  If {\cf do_open} is {\cf true}, fully open it if
possible (using the optional configuration spec, if supplied),
otherwise just create the \ImageInput but don't open it.
The {\kw plugin_searchpath} parameter is an override of the searchpath,
colon-separated list of directories to search for \product plugin
DSO/DLL's (not a searchpath for the image itself!).  This will
actually just try every ImageIO plugin it can locate, until it
finds one that's able to open the file without error.  This just
creates the \ImageInput, it does not open the file.
\apiend

% \apiitem{void {\ce destroy} (ImageInput *input)}
% Destroy an \ImageInput that was created by {\cf create()} or {\cf open()}.
% The {\cf destroy()} method is just a wrapper around operator {\cf delete},
% but by being implemented within the \product DLL, it can ensure that the
% memory deallocation is done in the same DLL arena as where it was originally
% allocated. This is considered safer than a bare {\cf delete} when
% used inside ``plug-ins,'' especially on Windows systems.
% \apiend

\apiitem{const char * {\ce format_name} (void) const}
Return the name of the format implemented by this class.
\apiend

\apiitem{int {\ce supports} (string_view feature)}
\label{sec:inputsupportsfeaturelist}
Given the name of a \emph{feature}, tells if this \ImageInput  instance
supports that feature. Most queries will simply return 0 for ``doesn't
support the feature'' and nonzero for ``supports the feature,'' but it is
acceptable to have queries return other nonzero integers to indicate varying
degrees of support or limits (but those queries should be clearly documented
as such). The following features are recognized by this query:
\begin{description}
\item[\spc] \spc
\item[\rm \qkw{arbitrary_metadata}] Does the image file format allow
  metadata with arbitrary names (and either arbitrary, or a reasonable set
  of, data types)? (Versus the file format supporting only a fixed list of
  specific metadata names/values?
\item[\rm \qkw{exif}] Does the image file format support Exif camera data
  (either specifically, or via arbitrary named metadata)?
\item[\rm \qkw{iptc}] Does the image file format support IPTC data
  (either specifically, or via arbitrary named metadata)?
\item[\rm \qkw{procedural}] Might the image ``file format'' generate pixels
  procedurally, without the need for any disk file to be present?
  \end{description}
\item[\rm \qkw{ioproxy}] Does the image file format support reading
  from an {\cf IOProxy}?
\apiend

\apiitem{bool {\ce valid_file} (const std::string \&filename) const}
Return {\cf true} if the named file is a file of the type for this
\ImageInput.  The implementation will try to determine this as
efficiently as possible, in most cases much less expensively than doing
a full {\cf open()}.  Note that a file can appear to be of
the right type (i.e., {\cf valid_file()} returning {\cf true}) but still
fail a subsequent call to {\cf open()}, such as if the contents of the
file are truncated, nonsensical, or otherwise corrupted.
\apiend

\apiitem{bool {\ce open} (const std::string \&name, ImageSpec \&newspec)}
Opens the file with given name and seek to the first subimage in the
file.  Various file attributes are put in
{\kw newspec} and a copy is also saved internally to the
\ImageInput (retrievable via {\kw spec()}.  From examining
{\kw newspec} or {\kw spec()}, you can discern the resolution, if it's
tiled, number of channels, native data format, and other metadata about
the image.  Return {\kw true} if the file was found and opened okay,
otherwise {\kw false}.
\apiend

\apiitem{bool {\ce open} (const std::string \&name, ImageSpec \&newspec,\\
\bigspc  const ImageSpec \&config)}
\label{sec:inputwithconfig}

Opens the file with given name, similarly to {\cf open(name, newspec)}.
However, in this version, any non-default fields of {\cf config},
including metadata, will be taken to be configuration requests,
preferences, or hints.  The default implementation of
{\cf open (name, newspec, config)} will simply ignore {\cf config} and
calls the usual {\cf open (name, newspec)}.  But a plugin may choose to
implement this version of {\cf open} and respond in some way to the
configuration requests.  Supported configuration requests should be
documented by each plugin.
\apiend

\apiitem {const ImageSpec \& {\ce spec} (void) const}
Returns a reference to the image format specification of the
current subimage.  Note that the contents of the spec are
invalid before {\kw open()} or after {\kw close()}.
\apiend

\apiitem {ImageSpec {\ce spec} (int subimage, int miplevel=0) \\
ImageSpec {\ce spec_dimensions} (int subimage, int miplevel=0)}
\NEW % 1.9
Both of these thread-safe methods return a copy of the \ImageSpec of the
designated subimage/miplevel.

The {\cf spec()} method returns a full copy of the \ImageSpec, including all
metadata (which may be expensive).  The {\cf spec_dimensions()} method only
copies the dimension fields but none of the arbitrary named metadata (just
as with a call to {\cf ImageSpec::copy_dimensions()}), and thus is
relatively inexpensive.
\apiend

\apiitem{bool {\ce close} ()}
Closes an open image.
\apiend

\apiitem{int {\ce current_subimage} (void) const \\
int {\ce current_miplevel} (void) const}
Returns the index of the subimage and MIP level, respectively, that is
currently being read. Subimage and MIP level index numbers begin with 0.
\apiend

\apiitem{bool {\ce seek_subimage} (int subimage, int miplevel, ImageSpec \&newspec)}
Seek to the given subimage and MIP-map level within the open image file.
The first subimage in the file has index 0, and for each subimage, the
highest-resolution MIP level has index 0.  Return {\kw true} on success,
{\kw false} on failure (including that there is not a subimage or MIP
level with those indices).  The new subimage's vital statistics are put
in {\kw newspec} (and also saved internally in a way that can be
retrieved via {\kw spec()}).  The \ImageInput is expected to give the
appearance of random access to subimages and MIP levels --- in other
words, if it can't randomly seek to the given subimage or MIP level, it
should transparently close, reopen, and sequentially read through prior
subimages and levels.
\apiend

\apiitem{bool {\ce read_scanline} (int y, int z, TypeDesc format, void *data,\\
  \bigspc\spc\spc                      stride_t xstride=AutoStride)}

Read the scanline that includes pixels $(*,y,z)$ into {\kw data}
($z=0$ for non-volume images),
converting if necessary from the native data format of the file into the
{\kw format} specified.
If {\cf format} is {\cf TypeDesc::UNKNOWN}, the data will be preserved
in its native format (including per-channel formats, if applicable).
The {\kw xstride}
value gives the data spacing of adjacent pixels (in bytes).  Strides set
to the special value {\kw AutoStride} imply contiguous data, i.e., \\
  \spc {\kw xstride} $=$ {\kw spec.nchannels * spec.pixel_size()} \\
The \ImageInput is expected to give the appearance of random access
--- in other words, if it can't randomly seek to the given scanline, it
should transparently close, reopen, and sequentially read through prior
scanlines.  The base \ImageInput class has a default implementation
that calls {\kw read_native_scanline()} and then does appropriate format
conversion, so there's no reason for each format plugin to override this
method.
\apiend

\apiitem{bool {\ce read_scanline} (int y, int z, float *data)}
This simplified version of {\kw read_scanline()} reads to contiguous
float pixels.
\apiend

\apiitem{bool {\ce read_scanlines} (int subimage, int miplevel \\
  \bigspc int ybegin, int yend, int z,\\
  \bigspc int chbegin, int chend, TypeDesc format, void *data,\\
  \bigspc                      stride_t xstride=AutoStride, stride_t ystride=AutoStride)}

Read from the specified subimage and MIP level all the scanlines that
include pixels $(*,y,z)$, where $\mathit{ybegin} \le y < \mathit{yend}$, and
the given channel subset {\kw chbegin} $\le c <$ {\kw chend}, into
{\kw data}, converting if necessary from the file's native data format to
the specified buffer {\kw format}.
If {\cf format} is {\cf TypeDesc::UNKNOWN}, the data will be preserved
in its native format (including per-channel formats, if applicable).
The stride values
give the data spacing of adjacent pixels and scanlines,
respectively (measured in bytes).  Strides set to the special
value of {\kw AutoStride} imply contiguous data in the shape of
the region specified, i.e., \\
\spc {\kw xstride} $=$ {\kw spec.pixel_size() * (chend - chbegin)} \\
\spc {\kw ystride} $=$ {\kw xstride * (xend - xbegin)} \\

This function returns {\cf true} if it successfully reads the scanlines,
otherwise {\cf false} for a failure.

This function is guaranteed to be thread-safe against other concurrent calls
to the {\cf read_tiles()} or {\cf read_scanlines()} varieties that takes
explicit subimage and miplevel (but not necessarily against any other
\ImageInput methods).

\NEW % 1.9
This call was changed for \OpenImageIO 1.9 to include the explicit subimage
and miplevel parameters. The previous versions, which lacked subimage and
miplevel parameters (thus were dependent on a prior call to
{\cf seek_subimage}) are considered deprecated.
\apiend

\apiitem{bool {\ce read_tile} (int x, int y, int z, TypeDesc format,
                            void *data, \\ \bigspc stride_t xstride=AutoStride,
                            stride_t ystride=AutoStride, \\ \bigspc stride_t
                            zstride=AutoStride)}
Read the tile whose upper-left origin is $(x,y,z)$ into {\kw data}
($z=0$ for non-volume images),
converting if necessary from the native data format of the file into the
{\kw format} specified.
If {\cf format} is {\cf TypeDesc::UNKNOWN}, the data will be preserved
in its native format (including per-channel formats, if applicable).
The stride values
give the data spacing of adjacent pixels, scanlines, and volumetric
slices, respectively (measured in bytes).  Strides set to the special
value of {\kw AutoStride} imply contiguous data in the shape of a full tile,
i.e., \\
\spc {\kw xstride} $=$ {\kw spec.nchannels * spec.pixel_size()} \\
\spc {\kw ystride} $=$ {\kw xstride * spec.tile_width} \\
\spc {\kw zstride} $=$ {\kw ystride * spec.tile_height} \\
The \ImageInput is expected to give the appearance of random access
--- in other words, if it can't randomly seek to the given tile, it
should transparently close, reopen, and sequentially read through prior
tiles.  The base \ImageInput class has a default implementation
that calls {\cf read_native_tile()} and then does appropriate format conversion,
so there's no reason for each format plugin to override this method.

This function returns {\cf true} if it successfully reads the tile,
otherwise {\cf false} for a failure.
The call will fail if the image is not tiled, or if $(x,y,z)$ is not
actually a tile boundary.
\apiend

\apiitem{bool {\ce read_tile} (int x, int y, int z, float *data)}
Simple version of {\kw read_tile} that reads to contiguous float pixels.
\apiend

\apiitem{bool {\ce read_tiles} (int subimage, int miplevel, \\
         \bigspc int xbegin, int xend, int ybegin, int yend, \\
         \bigspc int zbegin, int zend, int chbegin, int chend,\\
         \bigspc TypeDesc format, void *data, \\
         \bigspc stride_t xstride=AutoStride, stride_t ystride=AutoStride, \\
         \bigspc stride_t zstride=AutoStride)}
Read the tiles bounded by {\kw xbegin} $\le x <$ {\kw xend},
{\kw ybegin} $\le y <$ {\kw yend}, {\kw zbegin} $\le z <$ {\kw zend},
and the given channel subset {\kw chbegin} $\le c <$ {\kw chend},
into {\kw data},
converting if necessary from the file's native data format into
the specified buffer {\kw format}.
If {\cf format} is {\cf TypeDesc::UNKNOWN}, the data will be preserved
in its native format (including per-channel formats, if applicable).
The stride values
give the data spacing of adjacent pixels, scanlines, and volumetric
slices, respectively (measured in bytes).  Strides set to the special
value of {\kw AutoStride} imply contiguous data in the shape of
the region specified, i.e., \\
\spc {\kw xstride} $=$ {\kw spec.pixel_size() * (chend - chbegin)} \\
\spc {\kw ystride} $=$ {\kw xstride * (xend - xbegin)} \\
\spc {\kw zstride} $=$ {\kw ystride * (yend - ybegin)} \\
The \ImageInput is expected to give the appearance of random access
--- in other words, if it can't randomly seek to the given tile, it
should transparently close, reopen, and sequentially read through prior
tiles.  The base \ImageInput class has a default implementation
that calls {\cf read_native_tiles()} and then does appropriate format conversion,
so there's no reason for each format plugin to override this method.

This function returns {\cf true} if it successfully reads the tiles,
otherwise {\cf false} for a failure.
The call will fail if the image is not tiled, or if the pixel ranges
do not fall along tile (or image) boundaries, or if it is not a valid
tile range.

This function is guaranteed to be thread-safe against other concurrent calls
to the {\cf read_tiles()} or {\cf read_scanlines()} varieties that takes
explicit subimage and miplevel (but not necessarily against any other
\ImageInput methods).

\NEW % 1.9
This call was changed for \OpenImageIO 1.9 to include the explicit subimage
and miplevel parameters. The previous versions, which lacked subimage and
miplevel parameters (thus were dependent on a prior call to
{\cf seek_subimage}) are considered deprecated.
\apiend

\apiitem{bool {\ce read_image} (TypeDesc format, void *data, \\
                             \bigspc stride_t xstride=AutoStride,
                             stride_t ystride=AutoStride, \\
                             \bigspc stride_t zstride=AutoStride, \\
                             \bigspc ProgressCallback progress_callback=NULL,\\
                             \bigspc void *progress_callback_data=NULL) \\
bool {\ce read_image} (int subimage, int miplevel, int chbegin, int chend, \\
                             \bigspc TypeDesc format, void *data, \\
                             \bigspc stride_t xstride=AutoStride,
                             stride_t ystride=AutoStride, \\
                             \bigspc stride_t zstride=AutoStride, \\
                             \bigspc ProgressCallback progress_callback=NULL,\\
                             \bigspc void *progress_callback_data=NULL)}

Read the entire image of {\kw spec.width * spec.height * spec.depth}
pixels into data (which must already be sized large enough for
the entire image) with the given strides, converting into the desired
data format.
If {\cf format} is {\cf TypeDesc::UNKNOWN}, the data will be preserved
in its native format (including per-channel formats, if applicable).
This function will automatically handle either tiles or scanlines in
the file.

Strides set to the special value of {\kw AutoStride} imply contiguous
data, i.e., \\
\spc {\kw xstride} $=$ {\kw spec.nchannels * pixel_size()} \\
\spc {\kw ystride} $=$ {\kw xstride * spec.width} \\
\spc {\kw zstride} $=$ {\kw ystride * spec.height} \\
The function will internally either call {\kw read_scanlines} or
{\kw read_tiles}, depending on whether the file is scanline- or
tile-oriented.

The version that specifies a channel range will read only
channels $[${\cf chbegin},{\cf chend}$)$ into the buffer.

Because this may be an expensive operation, a progress callback may be passed.
Periodically, it will be called as follows:\\
\begin{code}
    progress_callback (progress_callback_data, float done)
\end{code}
\noindent where \emph{done} gives the portion of the image
(between 0.0 and 1.0) that has been read thus far.

\NEW % 1.9
The version of {\cf read_image} that takes explicit subimage and
miplevel parameters is guaranteed to be thread-safe against other concurrent
calls to the {\cf read_scanlines()}, {\cf read_tiles()}, or
{\cf read_image()} varieties that take an explicit
subimage and miplevel (but not necessarily against any other \ImageInput
methods).
\apiend

\apiitem{bool {\ce read_image} (float *data)}
Simple version of {\kw read_image()} reads to contiguous float pixels.
\apiend

\apiitem{bool {\ce read_native_scanline} (int subimage, int miplevel,\\
    \bigspc int y, int z, void *data)}
The {\kw read_native_scanline()} function is just like {\kw
  read_scanline()}, except that it keeps the data in the native format
of the disk file and always reads into contiguous memory (no strides).
It's up to the user to have enough space allocated and know what to do
with the data.  IT IS EXPECTED THAT EACH FORMAT PLUGIN WILL OVERRIDE
THIS METHOD.
\apiend

\apiitem{bool {\ce read_native_scanlines} (int subimage, int miplevel,\\
    \bigspc int ybegin, int yend, int z, void *data)}
The {\kw read_native_scanlines()} function is just like
{\cf read_native_scanline}, except that it reads
a range of scanlines rather than only one scanline.  It is not necessary
for format plugins to override this method --- a default implementation
in the \ImageInput base class simply calls {\cf read_native_scanline}
for each scanline in the range.  But format plugins may optionally
override this method if there is a way to achieve higher performance by
reading multiple scanlines at once.
\apiend

\apiitem{bool {\ce read_native_scanlines} (int subimage, int miplevel,\\
    \bigspc int ybegin, int yend, int z, int chbegin, int chend, void *data)}
A variant of {\cf read_native_scanlines} that reads only a subset of
channels \\ $[${\cf chbegin},{\cf chend}$)$.
If a format reader subclass does
not override this method, the default implementation will simply
call the all-channel version of {\cf read_native_scanlines} into a
temporary buffer and copy the subset of channels.
\apiend

\apiitem{bool {\ce read_native_tile} (int subimage, int miplevel,\\
    \bigspc int x, int y, int z, void *data)}
The {\kw read_native_tile()} function is just like {\kw read_tile()},
except that it keeps the data in the native format of the disk file and
always read into contiguous memory (no strides).  It's up to the user to
have enough space allocated and know what to do with the data.  IT IS
EXPECTED THAT EACH FORMAT PLUGIN WILL OVERRIDE THIS METHOD IF IT
SUPPORTS TILED IMAGES.
\apiend

\apiitem{bool {\ce read_native_tiles} (int subimage, int miplevel,\\
    \bigspc int xbegin, int xend, int ybegin,
  int yend, \\ \bigspc int zbegin, int zend, void *data)}
The {\kw read_native_tiles()} function is just like {\kw read_tiles()},
except that it keeps the data in the native format of the disk file and
always read into contiguous memory (no strides).
If a format reader does not override this method, the default
implementation it will simply be a loop calling read_native_tile
for each tile in the block.
\apiend

\apiitem{bool {\ce read_native_tiles} (int subimage, int miplevel,\\
    \bigspc int xbegin, int xend, int ybegin, int yend, \\
    \bigspc int zbegin, int zend, int chbegin, int chend, void *data)}
A variant of {\kw read_native_tiles()} that reads only a subset of
channels \\ $[${\cf chbegin},{\cf chend}$)$.
If a format reader subclass does
not override this method, the default implementation will simply
call the all-channel version of {\cf read_native_tiles} into a
temporary buffer and copy the subset of channels.
\apiend

\apiitem{bool {\ce read_native_deep_scanlines} (int subimage, int miplevel,
 \\ \bigspc   int ybegin, int yend, int z, int chbegin, int chend, \\
 \\ bigspc     DeepData \&deepdata) \\
bool {\ce read_native_deep_tiles} (int subimage, int miplevel, \\
    \bigspc int xbegin, int xend, int ybegin, int yend, \\
    \bigspc int zbegin, int zend, int chbegin, int chend, DeepData \&deepdata) \\
bool {\ce read_native_deep_image} (int subimage, int miplevel, DeepData \&deepdata)}
Read native deep data from scanlines, tiles, or an entire image,
storing the results in {\cf deepdata} (analogously to the usual
{\cf read_scanlines}, {\cf read_tiles}, and {\cf read_image}, but with deep data).
Only channels $[${\cf chbegin},{\cf chend}$)$ will be read.
Note that for the scanline variety, the {\cf roi}'s $x$ range must specify
the complete width of the image, and the $z$ range must be a single plane.
For the tile variety, the {\cf roi} must specify a whole number of tiles.
\apiend

\apiitem{int {\ce send_to_input} (const char *format, ...)}
General message passing between client and image input server.
This is currently undefined and is reserved for future use.
\apiend

\apiitem{int {\ce send_to_client} (const char *format, ...)}
General message passing between client and image input server.
This is currently undefined and is reserved for future use.
\apiend

\apiitem{void {\ce threads} (int n) \\
int {\ce threads} () const}
\index{threads}
Get or set the threading policy for this \ImageInput, controlling the
maximum amount of parallelizing thread ``fan-out'' that might occur during
large read operations. The default of 0 means that the global
{\cf attribute("threads")} value should be used (which itself defaults to
using as many threads as cores; see Section~\ref{sec:attribute:threads}).

The main reason to change this value is to set it to 1 to indicate that the
calling thread should do all the work rather than spawning new threads. That
is probably the desired behavior in situations where the calling application
has already spawned multiple worker threads.
\apiend

\apiitem{std::string {\ce geterror} () const}
\index{error checking}
Returns the current error string describing what went wrong if
any of the public methods returned {\kw false} indicating an error.
(Hopefully the implementation plugin called {\kw error()} with a
helpful error message.)
\apiend

\index{Image I/O API|)}

\chapwidthend

max_stars_repo_name: yann-lty/oiio

max_issues_repo_name: yann-lty/oiio

max_forks_repo_name: yann-lty/oiio


text:
\section{Footprinting}

\textbf{Footprinting} consists in someone doing passive(reconnaissance) or active(scanning) information gathering about some target. This enables an attacker to create a near complete profile of an organisation’s security posture.

In our case, we will be Footprinting the following systems:

\subsection{137.74.187.100}

\subsubsection{Hacker Target - Reverse DNS \& nslookup}

Using the \href{https://hackertarget.com/reverse-dns-lookup/}{Reverse DNS Lookup} we were able to know to which domain this address belongs to:

\begin{lstlisting}
    137.74.187.100 hackthissite.org
\end{lstlisting}

\begin{figure}[ht!]
 	\centering
 	\includegraphics[width=1\linewidth]{img/nsl1.png}
 	\caption{nslookup result}
 \end{figure}

Using nslookup we were also able to perform a reverse dns search, obtaining a non-authoritative answer with the same result.

\subsubsection{dig}

Using dig, we can retrieve DNS records related to our targets IP address. By querying dig with our target it returns the following response:

\pagebreak

\begin{figure}[ht!]
 	\centering
 	\includegraphics[width=1\linewidth]{img/dig1.png}
 	\caption{dig result}
 \end{figure}

In this case, we were able to retrieve a SOA record.

\subsubsection{IP2Location.com}

Using the \href{https://www.ip2location.com/demo}{IP2Location} tool we were able to know exactly where in the world this IP address is located and we can also get a lot of information about its ISP and its ASN number.

\begin{figure}[ht!]
 	\centering
 	\includegraphics[width=0.7\linewidth]{img/ip2location137.png}
 	\caption{IP2Location result}
 \end{figure}

 Other information gathered includes:
 \begin{itemize}
    \item City Coordinates: 50°41'39"N   3°10'28"E
    \item Local Time: 28 Nov, 2020 07:55 PM (UTC +01:00)
    \item ZIP Code: 59689
    \item Elevation: 32m
    \item ASN: 16276 OVH
    \item Proxy Type: (DCH) Hosting Provider, Data Center or CDN Range
 \end{itemize}

\subsubsection{Spyse}

Using the \href{https://spyse.com/target/ip/137.74.187.100}{Spyse} tool we were able to discover open ports and technologies being used with related CVE's as well:

 \begin{itemize}
    \item Open Ports: 80 (uses http protocol) and 443
    \item Technologies Used: jQuery Ver 1.8.1
 \end{itemize}

 There were listed 6 CVE, but the free tier only shows the first 4:
 \begin{itemize}
    \item CVE-2020-11022
    \item CVE-2020-11023
    \item CVE-2020-7656
    \item CVE-2012-6708
 \end{itemize}

 \subsubsection{nmap}

Using the nmap tool we were able to scan ports on the targeted IP, as well as seeing what service is using it. Nmap was only able of doing a guess about possible Operation Systems because the fingerprint wasn't ideal. The command for running nmap with OS detection (-O) and to use the TCP SYN technique (-sS) is:

\begin{lstlisting}
     nmap -v -sS -O 137.74.187.100
\end{lstlisting}

The report that nmap returned gave us information

\begin{lstlisting}
    Nmap scan report for hackthissite.org (137.74.187.100)
    Host is up (0.040s latency).
    Not shown: 997 filtered ports
    PORT    STATE  SERVICE
    22/tcp  closed ssh
    80/tcp  open   http
    443/tcp open   https

    Device type: bridge|general purpose
    Running (JUST GUESSING): Oracle Virtualbox (98%), QEMU (93%)
    OS CPE: cpe:/o:oracle:virtualbox cpe:/a:qemu:qemu
    Aggressive OS guesses:
        - Oracle Virtualbox (98%),
        - QEMU user mode network gateway (93%)
    No exact OS matches for host (test conditions non-ideal).
    TCP Sequence Prediction: Difficulty=17 (Good luck!)
    IP ID Sequence Generation: Incremental

\end{lstlisting}

\subsubsection{Shodan}

Using the \href{https://www.shodan.io/host/137.74.187.100}{Shodan} website we were able to scan ports as before and get information about the SSL certificate. The majority of information that Shodan retrieved we already had uncovered.

\subsection{216.58.215.148}

\subsubsection{Hacker Target - Reverse DNS \& nslookup}

Using the \href{https://hackertarget.com/reverse-dns-lookup/}{Reverse DNS Lookup} we were able to know to which domain this address belongs to:

\begin{lstlisting}
    216.58.215.148 mad41s04-in-f20.1e100.net
\end{lstlisting}

\begin{figure}[ht!]
 	\centering
 	\includegraphics[width=1\linewidth]{img/nsl2.png}
 	\caption{nslookup result}
\end{figure}

Using nslookup we were also able to perform a reverse dns search, obtaining a non-authoritative answer with the same result.

\subsubsection{dig}

Using dig, we can retrieve DNS records related to our targets IP address. By querying dig with our target it returns the following response:

\begin{figure}[ht!]
 	\centering
 	\includegraphics[width=1\linewidth]{img/dig2.png}
 	\caption{dig result}
 \end{figure}

In this case, we were able to retrieve a SOA record.

\subsubsection{IP2Location.com}

Using the \href{https://www.ip2location.com/demo}{IP2Location} tool we were able to know exactly where in the world this IP address is located and we can also get a lot of information about its ISP and its ASN number.

\begin{figure}[ht!]
 	\centering
 	\includegraphics[width=0.6\linewidth]{img/ip2location216.png}
 	\caption{IP2Location result}
 \end{figure}

 \pagebreak

 Other information gathered includes:
 \begin{itemize}
    \item City Coordinates: 37°24'22"N   122°4'43"W
    \item Local 30 Nov, 2020 09:55 AM (UTC -08:00)
    \item ZIP Code: 94043
    \item Elevation: 32m
    \item ASN: 15169 Google
    \item Proxy Type: (DCH) Hosting Provider, Data Center or CDN Range
 \end{itemize}

\subsubsection{Spyse}

Using the \href{https://spyse.com/target/ip/216.58.215.148}{Spyse} tool we were able to discover only open ports, no technologies being used, nor CVE's:

 \begin{itemize}
    \item Open Ports: 80 (uses http protocol) and 443
 \end{itemize}

This site couldn't find any vulnerabilities to the given IP. Awarding a Security Score of 100, meaning it has a low security risk.

\subsubsection{nmap}

Using the nmap tool we were able to scan ports on the targeted IP, as well as seeing what service is using it. This time, Nmap was able to obtain the Operation System. The command for running nmap with OS detection (-O) and to use the TCP SYN technique (-sS) is:

\begin{lstlisting}
     nmap -v -sS -O 216.58.215.14
\end{lstlisting}

The report that nmap returned gave us information

\begin{lstlisting}
    Nmap scan report for fra21s02-in-f14.1e100.net (216.58.215.14)
    Host is up (0.0055s latency).
    Not shown: 991 filtered ports
    PORT    STATE SERVICE
    25/tcp  open  smtp
    110/tcp open  pop3
    119/tcp open  nntp
    143/tcp open  imap
    465/tcp open  smtps
    563/tcp open  snews
    587/tcp open  submission
    993/tcp open  imaps
    995/tcp open  pop3s

    Device type: bridge
    Running: Oracle Virtualbox
    OS CPE: cpe:/o:oracle:virtualbox
    OS details: Oracle Virtualbox
    TCP Sequence Prediction: Difficulty=18 (Good luck!)
    IP ID Sequence Generation: Incremental
\end{lstlisting}

\subsubsection{Shodan}

Using the \href{https://www.shodan.io/host/216.58.215.148}{Shodan} website we were able to scan ports as before, get information about the SSL certificate. The majority of information that Shodan retrieved we already had uncovered.

\subsection{45.33.32.156}

\subsubsection{Hacker Target - Reverse DNS \& nslookup}

Using the \href{https://hackertarget.com/reverse-dns-lookup/}{Reverse DNS Lookup} we were able to know to which domain this address belongs to:

\begin{lstlisting}
    45.33.32.156 scanme.nmap.org
\end{lstlisting}

\begin{figure}[ht!]
 	\centering
 	\includegraphics[width=1\linewidth]{img/nsl3.png}
 	\caption{nslookup result}
\end{figure}

Using nslookup we were also able to perform a reverse dns search, obtaining a non-authoritative answer with the same result.

\vspace{0.5cm}

\subsubsection{dig}

Using dig, we can retrieve DNS records related to our targets IP address. By querying dig with our target it returns the following response:

\begin{figure}[ht!]
 	\centering
 	\includegraphics[width=1\linewidth]{img/dig3.png}
 	\caption{dig result}
 \end{figure}

In this case, we were able to retrieve a SOA record.

\vspace{0.5cm}

\subsubsection{IP2Location.com}

Using the \href{https://www.ip2location.com/demo}{IP2Location} tool we were able to know exactly where in the world this IP address is located and we can also get a lot of information about its ISP and its ASN number.

\vspace{3cm}

\begin{figure}[ht!]
 	\centering
 	\includegraphics[width=0.7\linewidth]{img/ip2location45.png}
 	\caption{IP2Location result}
 \end{figure}

Other information gathered includes:
 \begin{itemize}
    \item City Coordinates: 37°32'54"N    121°59'19"W
    \item Local Time: 30 Nov, 2020 11:15 AM (UTC -08:00)
    \item ZIP Code: 94536
    \item Elevation: 16m
    \item ASN: 63949 Linode LLC
    \item Proxy Type: (VPN) VPN Server
 \end{itemize}

\subsubsection{Spyse}

Using the \href{https://spyse.com/target/ip/45.33.32.156}{Spyse} tool we were able to discover open ports and technologies being used with related CVE's as well:

 \begin{itemize}
    \item Open Ports: 80 (uses http protocol) and 22
    \item Technologies Used: Google AdSense, OpenSSH Ver 6.6.1p1 and Apache Ver 2.4.7
 \end{itemize}

 There were listed 6 CVE, but the free tier only shows the first 4:
 \begin{itemize}
    \item CVE-2019-0217
    \item CVE-2016-2161
    \item CVE-2015-8325
    \item CVE-2016-3115
 \end{itemize}

 We were also able to see the Banners on ports 80 and 22:

 \begin{lstlisting}
Port 80:
    HTTP/1.1 200 OK
    Date: Tue, 03 Nov 2020 21:30:32 GMT
    Server: Apache/2.4.7 (Ubuntu)
    Accept-Ranges: bytes
    Vary: Accept-Encoding
    Connection: close
    Content-Type: text/html

Port 22:
    SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.13
 \end{lstlisting}

\subsubsection{nmap}

Using the nmap tool we were able to scan ports on the targeted IP, as well as seeing what service is using it. Just like the first IP address, nmap was only able of doing a guess about possible Operation Systems, because the fingerprint wasn't ideal. The command for running nmap with OS detection (-O) and to use the TCP SYN technique (-sS) is:

\begin{lstlisting}
     nmap -v -sS -O 45.33.32.156
\end{lstlisting}

The report that nmap returned gave us information

\begin{lstlisting}
    Nmap scan report for scanme.nmap.org (45.33.32.156)
    Host is up (0.17s latency).
    Not shown: 996 closed ports
    PORT      STATE SERVICE
    22/tcp    open  ssh
    80/tcp    open  http
    9929/tcp  open  nping-echo
    31337/tcp open  Elite
    Aggressive OS guesses: Linux 5.0 - 5.4 (96%), Linux 5.4 (95%), Linux 4.15 - 5.6 (94%), Linux 5.0 - 5.3 (93%), Linux 5.1 (93%), Linux 2.6.32 - 3.13 (93%), Linux 5.0 (92%), Linux 2.6.22 - 2.6.36 (91%), Linux 3.10 - 4.11 (91%), Linux 3.10 (91%)
    No exact OS matches for host (test conditions non-ideal).
    Uptime guess: 15.079 days (since Sun Nov 15 18:01:15 2020)
    Network Distance: 20 hops
    TCP Sequence Prediction: Difficulty=264 (Good luck!)
    IP ID Sequence Generation: All zeros
\end{lstlisting}

Using nmap we discovered 2 new open ports and we use it's OS prediction to have a slight idea of the targets OS type(Linux).

\subsubsection{Shodan}

Using the \href{https://www.shodan.io/host/45.33.32.156}{Shodan} website we were able to scan ports as before, including a new one (port 123), get information about the OpenSSH, and we discovered a lot of CVE's. The majority of information that Shodan retrieved we already had uncovered.

\pagebreak

max_stars_repo_path: Ficha 3/[SSI] - Ficha 3/sections/analysis.tex

max_stars_repo_name: ribeiropdiogo/SSI

max_issues_repo_name: ribeiropdiogo/SSI

max_forks_repo_name: ribeiropdiogo/SSI