This is an automated email from the ASF dual-hosted git repository. git-site-role pushed a commit to branch asf-site in repository https://gitbox.apache.org/repos/asf/mina-site.git
The following commit(s) were added to refs/heads/asf-site by this push: new 254aa1aee Updated site from master (362229b8d1a5369a73b162b16e7d50742e00407a) 254aa1aee is described below commit 254aa1aee6f2726fac699be31553530d7f9d324e Author: jenkins <bui...@apache.org> AuthorDate: Sun Apr 28 04:18:57 2024 +0000 Updated site from master (362229b8d1a5369a73b162b16e7d50742e00407a) --- content/contributors.html | 2 +- .../documentation/ch6-internals/ch6-internals.html | 171 ++++++++++++++++++++- content/index.xml | 9 +- content/mina-project/index.xml | 7 +- .../ch1-getting-started/ch1.1-nio-overview.html | 6 +- .../ch1-getting-started/ch1.2-why-mina.html | 8 +- .../ch1-getting-started/ch1.3-features.html | 2 +- .../ch1-getting-started/ch1.4-first-steps.html | 10 +- .../ch2-basics/ch2.1-application-architecture.html | 14 +- .../ch2-basics/ch2.1.1-server-architecture.html | 2 +- .../ch2-basics/ch2.2-sample-tcp-server.html | 2 +- .../userguide/ch4-session/ch4-session.html | 15 +- .../userguide/ch5-filters/ch5.19-ssl-filter.html | 56 +++++-- content/sitemap.xml | 26 ++-- 14 files changed, 269 insertions(+), 61 deletions(-) diff --git a/content/contributors.html b/content/contributors.html index d7c2c2aca..8a17df1dd 100644 --- a/content/contributors.html +++ b/content/contributors.html @@ -101,6 +101,7 @@ <li>Alex Karasulu (akarasulu)</li> <li>Ashish Paliwal (apaliwal)</li> <li>Emmanuel Lécharny (elecharny)</li> +<li>Gary D. Gregory (ggregory)</li> <li><strong>Guillaume Nodet</strong> (gnodet) (chairman)</li> <li>Jean-François Maury (jeffmaury)</li> <li>Jeff Genender (jgenender)</li> @@ -119,7 +120,6 @@ <li>Bogdan Pistol (bogdan)</li> <li>David Latorre (dlat)</li> <li><a href="http://tedorg.free.fr/en/main.php">Edouard De Oliveira</a> (edeoliveira)</li> -<li>Gary D. Gregory (ggregory)</li> <li>Michael Jakl (mjakl)</li> <li>Mike Mahonay (foodmike)</li> <li>Raphaël P. Barazzutti (rbarazzutti)</li> diff --git a/content/ftpserver-project/documentation/ch6-internals/ch6-internals.html b/content/ftpserver-project/documentation/ch6-internals/ch6-internals.html index deb12b7fb..c04731081 100644 --- a/content/ftpserver-project/documentation/ch6-internals/ch6-internals.html +++ b/content/ftpserver-project/documentation/ch6-internals/ch6-internals.html @@ -147,9 +147,9 @@ '--| FtpServerContext | '----------------' ^ - | .-------------------------. + | .-----------------------. '--| DefaultFtpServerContext | - '-------------------------' + '-----------------------' </code></pre><h3 id="messageresourcefactory-and-messageresource">MessageResourceFactory and MessageResource</h3> <p>The <strong>MessageResourceFactory</strong> is used to create the <strong>MessageResource</strong> instance which will be an instance of the <strong>DefaultMessageResource</strong> class).</p> @@ -174,7 +174,7 @@ </ul> </li> </ul> -<h2 id="commandfactory">Commandfactory</h2> +<h2 id="commandfactory">CommandFactory</h2> <p>This factory creates a <strong>Map</strong> which contains the <em>Command</em> instances associated with the command name. The current version support those commands:</p> <table> <thead> @@ -433,6 +433,171 @@ <li><em>DbUserManagerFactory</em> which takes the information relative to the user from a <strong>SQL</strong> Database</li> <li><em>PropertiesUserManagerFactory</em> which takes the information relative to the user from properties file</li> </ul> +<p>The <em>User</em> class contain information about the users:</p> +<ul> +<li><em>ftpserver.user.{username}.homedirectory</em>: Path to the home directory for the user, based on the file system implementation used</li> +<li><em>ftpserver.user.{username}.userpassword</em>: The password for the user. Can be in clear text, MD5 hash or salted SHA hash based on the configuration on the user manager</li> +<li><em>ftpserver.user.{username}.enableflag</em>: true if the user is enabled, false otherwise</li> +<li><em>ftpserver.user.{username}.writepermission</em>: true if the user is allowed to upload files and create directories, false otherwise</li> +<li><em>ftpserver.user.{username}.idletime</em>: The number of seconds the user is allowed to be idle before disconnected. 0 disables the idle timeout</li> +<li><em>ftpserver.user.{username}.maxloginnumber</em>: The maximum number of concurrent logins by the user. 0 disables the check.</li> +<li><em>ftpserver.user.{username}.maxloginperip</em>: The maximum number of concurrent logins from the same IP address by the user. 0 disables the check.</li> +<li><em>ftpserver.user.{username}.uploadrate</em>: The maximum number of bytes per second the user is allowed to upload files. 0 disables the check.</li> +<li><em>ftpserver.user.{username}.downloadrate</em>: The maximum number of bytes per second the user is allowed to download files. 0 disables the check.</li> +</ul> +<p>Here is an exemple of file containing some users:</p> +<pre><code>ftpserver.user.admin.homedirectory=./test-tmp/ftproot +ftpserver.user.admin.userpassword=admin +ftpserver.user.admin.enableflag=true +ftpserver.user.admin.writepermission=true +ftpserver.user.admin.idletime=0 +ftpserver.user.admin.maxloginnumber=0 +ftpserver.user.admin.maxloginperip=0 +ftpserver.user.admin.uploadrate=0 +ftpserver.user.admin.downloadrate=0 + +</code></pre><p>In any case, we use a <em>UserManager</em> instance to manage the users once read by one of the two previous factories.</p> +<h3 id="usermanager">UserManager</h3> +<p>The hierarchy is the following:</p> +<pre><code class="language-goat" data-lang="goat"> + .-----------. + | UserManager | + '-----------' + ^ + | .-------------------. + '--| AbstractUserManager | + '-------------------' + ^ + | .-------------. + +--| DbUserManager | + | '-------------' + | + | .---------------------. + '--| PropertiesUserManager | + '---------------------' +</code></pre><p>Those classes are used to get the <strong>User</strong> information. The <strong>User</strong> class stores the following data:</p> +<ul> +<li><em>authorities</em>: The user’s permissions. One of <em>WritePermission</em>, <em>TransferRatePermission</em> and <em>ConcurrentLoginPermission</em></li> +<li><em>homeDir</em>: The user’s home directory</li> +<li><em>isEnabled</em>: A flag set to <em>true</em> if teh user is enabled</li> +<li><em>maxIdleTimeSec</em>: The maximum time the user can remain iddle (default to infinite)</li> +<li><em>name</em>: The user’s name</li> +<li><em>password</em>: The hashed user’s password</li> +</ul> +<p>The <em>User</em> interface is used to expose the available methods. The class hierarchy is:</p> +<pre><code class="language-goat" data-lang="goat"> + .----. + | User | + '----' + ^ + | .--------. + '--| BaseUser | + '--------' +</code></pre><p>As the users are stored either in a property file or in a SQL Database, we need a way to manage those users. There is a class that can bbe used to add users in those containes: the <em>AddUser</em> class. Otherwise, the <em>UserManager</em> instance can be used to delete or get users from their container. Creating a user programatically can be done either with the <em>UserFactory</em> or by instanciating a <em>BaseUser</em> class.</p> +<h3 id="filesystemfactory">FileSystemFactory</h3> +<p>This factory will be used to create the directory the user will access. The factory will be used later.</p> +<h3 id="ftpletcontainer">FtpletContainer</h3> +<p>The <em>FtpletCinainer</em> is holding all the <em>Ftplet</em> elements in a <em>HashMap</em>.</p> +<p>A <em>Ftplet</em> is a piece of code that get executed before or after a command, and before and after a connection.</p> +<p>Here is the class hierarchy:</p> +<pre><code class="language-goat" data-lang="goat"> + .------. + | Ftplet | + '------' + ^ + | .---------------. + '--| FtpletContainer | + '---------------' + ^ + | .----------------------. + '--| DefaultFtpletContainer | + '----------------------' +</code></pre><h3 id="ftpstatistics">FtpStatistics</h3> +<p>This is used to store statistics about the FtpServer usage. The class hierarchy is teh following:</p> +<pre><code class="language-goat" data-lang="goat"> + .-------------. + | FtpStatistics | + '-------------' + ^ + | .-------------------. + '--| ServerFtpStatistics | + '-------------------' + ^ + | .--------------------. + '--| DefaultFtpStatistics | + '--------------------' +</code></pre><p>The <em>FtpStatistics</em> contains all the getters, the <em>ServerFtpStatistics</em> contains all the setters.</p> +<p>The following values are followed:</p> +<ul> +<li><em>startTime</em></li> +<li><em>uploadCount</em></li> +<li><em>downloadCount</em></li> +<li><em>deleteCount</em></li> +<li><em>mkdirCount</em></li> +<li><em>rmdirCount</em></li> +<li><em>currLogins</em></li> +<li><em>totalLogins</em></li> +<li><em>totalFailedLogins</em></li> +<li><em>currAnonLogins</em></li> +<li><em>totalAnonLogins</em></li> +<li><em>currConnections</em></li> +<li><em>totalConnections</em></li> +<li><em>bytesUpload</em></li> +<li><em>bytesDownload</em></li> +</ul> +<p>The methods are called by the <em>Command</em> instances.</p> +<h3 id="connectionconfigfactory">ConnectionConfigFactory</h3> +<p>This class create a <em>ConnectionConfig</em> instance.</p> +<p>It manages the following server parameters:</p> +<ul> +<li><em>maxLogins</em></li> +<li><em>anonymousLoginEnabled</em></li> +<li><em>maxAnonymousLogins</em></li> +<li><em>maxLoginFailures</em></li> +<li><em>loginFailureDelay</em></li> +<li><em>maxThreads</em></li> +</ul> +<p>By default, the server configuration will allow 3 fails login attempts, insert a 500ms delay between each attempt, allow 10 concurrent users, allow 10 anonymous users, and do not limit the number of threads dedicated for command processing.</p> +<h3 id="listeners">Listeners</h3> +<p>The <em>Listeners</em> are used to manage communications with the users. We keep a <em>Map</em> of created listeners. Those listeners are created by a <em>ListenerFactory</em>.</p> +<p>The <em>ListenerFactory</em> class contains a <em>DataConnectionConfiguration</em> instance which is created by a <em>DataConnectionConfigurationFactory</em> factory class.</p> +<p>The class hierarchy is the following:</p> +<pre><code class="language-goat" data-lang="goat"> + .--------. + | Listener | + '--------' + ^ + | .----------------. + '--| AbstractListener | + '----------------' + ^ + | .-----------. + '--| NioListener | + '-----------' +</code></pre><p>The <em>NioListener</em> class is responsible for all the TCP communication with the user. It depends on <strong>MINA</strong> <em>SocketAcceptor</em>_ class.</p> +<p>The <em>AbstractListener</em> class</p> +<p>The <em>SocketAcceptor</em> instance is declared with the following parameters:</p> +<ul> +<li><em>ReuseAddress</em> is set to true</li> +<li>The read buffer size is set to 2048</li> +<li>The receive buffer size is set to 512</li> +<li>The idle time is set to 300 seconds</li> +<li>The service chain contains, in this order from server to handler: +<ul> +<li>An optional <em>SslFilter</em></li> +<li>A <em>MdcInjectionFilter</em></li> +<li>An optional <em>MinaSessionFilter</em></li> +<li>A <em>ExecutorFilter</em></li> +<li>A <em>ProtocolCodecFilter</em>: The decoder is a simple instance of a <em>TextLineDecoder</em>. The encoder is an instance of a <em>FtpResponseEncoder</em>.</li> +<li>A <em>MdcInjectionFilter</em></li> +<li>A <em>FtpLoggingFilter</em></li> +</ul> +</li> +</ul> +<p>A <em>Listener</em> instance can be created through a call to the <em>ListenerFactory.createListener()</em> method, it should not be created directly. This method instanciate a <em>NioListener</em> after having chekced that the provided server name is valid.</p> +<p>Internally, it creates a <em>FtpHandler</em> instances, which is used to handle all the incoming <em>FTP</em> requests.</p> +<p>The instanciated <em>listener</em> will be added to the map of listeners, as <em>default</em>.</p> +<p>The server factory has been created, we now have to create the server and to start it.</p> diff --git a/content/index.xml b/content/index.xml index 0dbb1cdae..e3a054c40 100644 --- a/content/index.xml +++ b/content/index.xml @@ -26,7 +26,8 @@ First of all, it's good to know that MINA is written on top of NIO 1. A new <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate> <guid>https://mina.apache.org/mina-project/userguide/ch1-getting-started/ch1.2-why-mina.html</guid> - <description>Why MINA ? Writing network applications are generally seen as a burden and perceived as low level development. It is an area which is not frequently studied or known by developers, either because it has been studied in school a long time ago and everything has been forgotten, or because the complexity of the network layer is frequently hidden by higher level layers, so you never get deep into it.</description> + <description>Why MINA? Writing network applications are generally seen as a burden and perceived as low level development. It is an area which is not frequently studied or known by developers, either because it has been studied in school a long time ago and everything has been forgotten, or because the complexity of the network layer is frequently hidden by higher level layers, so you never get deep into it. +Added to that (when it comes to asynchronous IO) an extra layer of complexity comes into play: time.</description> </item> <item> @@ -66,8 +67,8 @@ In the chapters to come we shall discuss about MINA Core constructs and advanced <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate> <guid>https://mina.apache.org/mina-project/userguide/ch2-basics/ch2.1-application-architecture.html</guid> - <description>2.1.1 - Server Architecture 2.1.2 - Client Architecture 2.1 - MINA based Application Architecture It&rsquo;s the question most asked : &lsquo;How does a MINA based application look like&rsquo;? In this article lets see what&rsquo;s the architecture of MINA based application. Have tried to gather the information from presentations based on MINA. -A Bird&rsquo;s Eye View : + <description>2.1.1 - Server Architecture 2.1.2 - Client Architecture 2.1 - MINA based Application Architecture It&rsquo;s the question most asked: &lsquo;How does a MINA based application look like&rsquo;? In this article lets see what&rsquo;s the architecture of MINA based application. Have tried to gather the information from presentations based on MINA. +A Bird&rsquo;s Eye View: Here, we can see that MINA is the glue between your application (be it a client or a server) and the underlying network layer, which can be based on TCP, UDP, in-VM communication or even a RS-232C serial protocol for a client.</description> </item> @@ -450,7 +451,7 @@ Getting the Binary Distributions Description Download Link SHA256 hashes SHA5 <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate> <guid>https://mina.apache.org/contributors.html</guid> - <description>Project Management Committee Alex Karasulu (akarasulu) Ashish Paliwal (apaliwal) Emmanuel L&eacute;charny (elecharny) Guillaume Nodet (gnodet) (chairman) Jean-Fran&ccedil;ois Maury (jeffmaury) Jeff Genender (jgenender) Jonathan Valliere (johnnyv) Julien Vermillard (jvermillard) Lyor Goldstein (lgoldstein) Maarten Bosteels (maarten) Mark Webb (mwebb) Niklas Gustavsson (ngn) Thomas Wolf (twolf) Committers Alan Cabrera (adc) Bobby Powers (bpowers) Bogdan Pistol [...] + <description>Project Management Committee Alex Karasulu (akarasulu) Ashish Paliwal (apaliwal) Emmanuel L&eacute;charny (elecharny) Gary D. Gregory (ggregory) Guillaume Nodet (gnodet) (chairman) Jean-Fran&ccedil;ois Maury (jeffmaury) Jeff Genender (jgenender) Jonathan Valliere (johnnyv) Julien Vermillard (jvermillard) Lyor Goldstein (lgoldstein) Maarten Bosteels (maarten) Mark Webb (mwebb) Niklas Gustavsson (ngn) Thomas Wolf (twolf) Committers Alan Cabrera (adc) Bobby Pow [...] </item> <item> diff --git a/content/mina-project/index.xml b/content/mina-project/index.xml index 5331f9e8f..ef1ed826d 100644 --- a/content/mina-project/index.xml +++ b/content/mina-project/index.xml @@ -26,7 +26,8 @@ First of all, it's good to know that MINA is written on top of NIO 1. A new <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate> <guid>https://mina.apache.org/mina-project/userguide/ch1-getting-started/ch1.2-why-mina.html</guid> - <description>Why MINA ? Writing network applications are generally seen as a burden and perceived as low level development. It is an area which is not frequently studied or known by developers, either because it has been studied in school a long time ago and everything has been forgotten, or because the complexity of the network layer is frequently hidden by higher level layers, so you never get deep into it.</description> + <description>Why MINA? Writing network applications are generally seen as a burden and perceived as low level development. It is an area which is not frequently studied or known by developers, either because it has been studied in school a long time ago and everything has been forgotten, or because the complexity of the network layer is frequently hidden by higher level layers, so you never get deep into it. +Added to that (when it comes to asynchronous IO) an extra layer of complexity comes into play: time.</description> </item> <item> @@ -66,8 +67,8 @@ In the chapters to come we shall discuss about MINA Core constructs and advanced <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate> <guid>https://mina.apache.org/mina-project/userguide/ch2-basics/ch2.1-application-architecture.html</guid> - <description>2.1.1 - Server Architecture 2.1.2 - Client Architecture 2.1 - MINA based Application Architecture It&rsquo;s the question most asked : &lsquo;How does a MINA based application look like&rsquo;? In this article lets see what&rsquo;s the architecture of MINA based application. Have tried to gather the information from presentations based on MINA. -A Bird&rsquo;s Eye View : + <description>2.1.1 - Server Architecture 2.1.2 - Client Architecture 2.1 - MINA based Application Architecture It&rsquo;s the question most asked: &lsquo;How does a MINA based application look like&rsquo;? In this article lets see what&rsquo;s the architecture of MINA based application. Have tried to gather the information from presentations based on MINA. +A Bird&rsquo;s Eye View: Here, we can see that MINA is the glue between your application (be it a client or a server) and the underlying network layer, which can be based on TCP, UDP, in-VM communication or even a RS-232C serial protocol for a client.</description> </item> diff --git a/content/mina-project/userguide/ch1-getting-started/ch1.1-nio-overview.html b/content/mina-project/userguide/ch1-getting-started/ch1.1-nio-overview.html index c2e677477..80adc3242 100644 --- a/content/mina-project/userguide/ch1-getting-started/ch1.1-nio-overview.html +++ b/content/mina-project/userguide/ch1-getting-started/ch1.1-nio-overview.html @@ -163,9 +163,9 @@ <p>We are mostly interested in the <em>Channels</em>, <em>Selectors</em> and <em>Buffers</em> parts in the <strong>MINA</strong> framework, except that we want to hide those elements to the user.</p> <p>This user guide will thus focus on everything built on top of those internal components.</p> <h1 id="nio-vs-bio">NIO vs BIO</h1> -<p>It’s important to understand the difference between those two APIs. <strong>BIO</strong>, or <strong>Blocking</strong> <strong>IO</strong>, relies on plain sockets used in a blocking mode : when you read, write or do whatever operation on a socket, the called operation will block the caller until the operation is completed.</p> -<p>In some cases, it’s critical to be able to call the operation, and to expect the called operation to inform the caller when the operation is done : the caller can then do something else in the mean time.</p> -<p>This is also where <strong>NIO</strong> offers a better way to handle <strong>IO</strong> when you have numerous connected sockets : you dn’t have to create a specific thread for each connection, you can just use a few threads to do the same job.</p> +<p>It’s important to understand the difference between those two APIs. <strong>BIO</strong>, or <strong>Blocking</strong> <strong>IO</strong>, relies on plain sockets used in a blocking mode: when you read, write or do whatever operation on a socket, the called operation will block the caller until the operation is completed.</p> +<p>In some cases, it’s critical to be able to call the operation, and to expect the called operation to inform the caller when the operation is done: the caller can then do something else in the mean time.</p> +<p>This is also where <strong>NIO</strong> offers a better way to handle <strong>IO</strong> when you have numerous connected sockets: you don’t have to create a specific thread for each connection, you can just use a few threads to do the same job.</p> <p>If you want to get more information about what covers <strong>NIO</strong>, there is a lot of good articles around the web, and a few books covering this matter.</p> diff --git a/content/mina-project/userguide/ch1-getting-started/ch1.2-why-mina.html b/content/mina-project/userguide/ch1-getting-started/ch1.2-why-mina.html index c7441866b..0b96c9b91 100644 --- a/content/mina-project/userguide/ch1-getting-started/ch1.2-why-mina.html +++ b/content/mina-project/userguide/ch1-getting-started/ch1.2-why-mina.html @@ -144,17 +144,17 @@ - <h1 id="why-mina-">Why MINA ?</h1> + <h1 id="why-mina">Why MINA?</h1> <p>Writing network applications are generally seen as a burden and perceived as low level development. It is an area which is not frequently studied or known by developers, either because it has been studied in school a long time ago and everything has been forgotten, or because the complexity of the network layer is frequently hidden by higher level layers, so you never get deep into it.</p> <p>Added to that (when it comes to asynchronous IO) an extra layer of complexity comes into play: time.</p> -<p>The big difference between <strong>BIO</strong> (Blocking IO) and <strong>NIO</strong> (Non-Blocking IO) is that in <strong>BIO</strong>, you send a request, and you wait until you get the response. On the server side, it means one thread wil be associated with any incoming connection, so you won’t have to deal with the complexity of multiplexing the connections. In <strong>NIO</strong>, on the other hand, you have to deal with the synchronous nature of a non-blocking system, w [...] +<p>The big difference between <strong>BIO</strong> (Blocking IO) and <strong>NIO</strong> (Non-Blocking IO) is that in <strong>BIO</strong>, you send a request, and you wait until you get the response. On the server side, it means one thread will be associated with any incoming connection, so you won’t have to deal with the complexity of multiplexing the connections. In <strong>NIO</strong>, on the other hand, you have to deal with the synchronous nature of a non-blocking system, [...] <h2 id="the-need-of-a-framework">The need of a framework</h2> <p>Considering those differences, and the fact that most of the applications are usually expecting a blocking mode when invoking the network layer, the best solution is to hide this aspect by writing a framework that mimics a blocking mode. This is what <strong>MINA</strong> does!</p> <p>But <strong>MINA</strong> does more. It provides a common IO vision to an application that needs to communicate over <strong>TCP</strong>, <strong>UDP</strong> or whatever mechanism. If we consider only <strong>TCP</strong> and <strong>UDP</strong>, one is a connected protocol (<strong>TCP</strong>) where the other is connectionless (<strong>UDP</strong>). <strong>MINA</strong> masks this difference, and makes you focus on the two parts that are important for your application: the app [...] <p>*<strong>MINA</strong> does not only handle <strong>TCP</strong> and <strong>UDP</strong>, it also offers a layer on top of serial communication (<strong>RSC232</strong>), over <strong>VmpPipe</strong> or <strong>APR</strong>.</p> <p>Last but not least, <strong>MINA</strong> is a network framework that has been specifically designed to work on both the client side and server side. Writing a server makes it critical to have a scalable system, which is tunable to fit the server needs, in terms of performance and memory usage. This is what <strong>MINA</strong> is good for, making it easy to develop you server.</p> -<h2 id="when-to-use-mina-">When to use MINA ?</h2> -<p>This is a interesting question! <strong>MINA</strong> does not expect to be the best possible choice in all cases. There are a few elements to take into account when considering using <strong>MINA</strong>. Let’s list them:</p> +<h2 id="when-to-use-mina">When to use MINA?</h2> +<p>This is an interesting question! <strong>MINA</strong> does not expect to be the best possible choice in all cases. There are a few elements to take into account when considering using <strong>MINA</strong>. Let’s list them:</p> <ul> <li> <p>Ease of use diff --git a/content/mina-project/userguide/ch1-getting-started/ch1.3-features.html b/content/mina-project/userguide/ch1-getting-started/ch1.3-features.html index e2300bb55..0c5faa00f 100644 --- a/content/mina-project/userguide/ch1-getting-started/ch1.3-features.html +++ b/content/mina-project/userguide/ch1-getting-started/ch1.3-features.html @@ -172,7 +172,7 @@ <li>Out-of-the-box SSL · TLS · StartTLS support using Java 5 SSLEngine</li> <li>Overload shielding & traffic throttling</li> <li>Unit testability using mock objects</li> -<li>JMX managability</li> +<li>JMX manageability</li> <li>Stream-based I/O support via StreamIoHandler</li> <li>Integration with well known containers such as PicoContainer and Spring</li> <li>Smooth migration from Netty, an ancestor of Apache MINA.</li> diff --git a/content/mina-project/userguide/ch1-getting-started/ch1.4-first-steps.html b/content/mina-project/userguide/ch1-getting-started/ch1.4-first-steps.html index 34bdf1f18..61255beee 100644 --- a/content/mina-project/userguide/ch1-getting-started/ch1.4-first-steps.html +++ b/content/mina-project/userguide/ch1-getting-started/ch1.4-first-steps.html @@ -149,13 +149,13 @@ <p>The first thing you have to do is to setup your environment when you want to use <strong>MINA</strong> in your application. We will describe what you need to install and how to run a <strong>MINA</strong> program. Nothing fancy, just a first taste of <strong>MINA</strong>…</p> <h2 id="download">Download</h2> <p>First, you have to download the latest <strong>MINA</strong> release from <a href="../../downloads_2_0.html">MINA 2.0 Downloads Section</a> or <a href="../../downloads_2_1.html">MINA 2.1 Downloads Section</a>. Just take the latest version, unless you have very good reasons not to do so…</p> -<p>Generally speaking, if you are going to use <strong>Maven</strong> to build your project, you won’t even have to download anything, as soon as you will depend on a repository which already contains the <strong>MINA</strong> libraries : you just tell your <strong>Maven</strong> poms that you want to use the <strong>MINA</strong> jars you need.</p> +<p>Generally speaking, if you are going to use <strong>Maven</strong> to build your project, you won’t even have to download anything, as soon as you will depend on a repository which already contains the <strong>MINA</strong> libraries: you just tell your <strong>Maven</strong> poms that you want to use the <strong>MINA</strong> jars you need.</p> <h2 id="whats-inside">What’s inside</h2> <p>After the download is complete, extract the content of <em>tar.gz</em> or <em>zip</em> file to local hard drive. The downloaded compressed file has following contents</p> -<p>On UNIX system, type :</p> +<p>On UNIX system, type:</p> <pre><code>$ tar xzpf apache-mina-2.0.7-tar.gz </code></pre> -<p>In the <em>apache-mina-2.0.7</em> directory, you will get :</p> +<p>In the <em>apache-mina-2.0.7</em> directory, you will get:</p> <pre><code> | +- dist +- docs @@ -177,7 +177,7 @@ <p>Additional to these, the base directory has couple of license and notice files</p> <h1 id="running-your-first-mina-program">Running your first MINA program</h1> <p>Well, we have downloaded the release, let’s run our first <strong>MINA</strong> example, shipped with the release.</p> -<p>Put the following jars in the classpath</p> +<p>Put the following jars in the class path</p> <ul> <li>mina-core-2.0.7.jar</li> <li>mina-example-2.0.7.jar</li> @@ -197,7 +197,7 @@ For instance, <em>slf4j-log4j12.jar</em> and <em>log4j-1.3.x.jar</em> can not be If you don’t need a logging framework you can use <em>slf4j-nop.jar</em> for no logging or <em>slf4j-simple.jar</em> for very basic logging.</p> </div> -<p>On the command prompt, issue the following command :</p> +<p>On the command prompt, issue the following command:</p> <pre><code>$ java org.apache.mina.example.gettingstarted.timeserver.MinaTimeServer </code></pre> <p>This shall start the server. Now telnet and see the program in action</p> diff --git a/content/mina-project/userguide/ch2-basics/ch2.1-application-architecture.html b/content/mina-project/userguide/ch2-basics/ch2.1-application-architecture.html index c173ff992..ff5048c19 100644 --- a/content/mina-project/userguide/ch2-basics/ch2.1-application-architecture.html +++ b/content/mina-project/userguide/ch2-basics/ch2.1-application-architecture.html @@ -149,12 +149,12 @@ <li><a href="ch2.1.2-client-architecture.html">2.1.2 - Client Architecture</a></li> </ul> <h1 id="21----mina-based-application-architecture">2.1 - MINA based Application Architecture</h1> -<p>It’s the question most asked : ‘How does a <strong>MINA</strong> based application look like’? In this article lets see what’s the architecture of MINA based application. Have tried to gather the information from presentations based on <strong>MINA</strong>.</p> -<p>A Bird’s Eye View :</p> +<p>It’s the question most asked: ‘How does a <strong>MINA</strong> based application look like’? In this article lets see what’s the architecture of MINA based application. Have tried to gather the information from presentations based on <strong>MINA</strong>.</p> +<p>A Bird’s Eye View:</p> <p><img src="/assets/img/mina/apparch_small.png" alt=""></p> <p>Here, we can see that <strong>MINA</strong> is the glue between your application (be it a client or a server) and the underlying network layer, which can be based on TCP, UDP, in-VM communication or even a RS-232C serial protocol for a client.</p> -<p>You just have to design your application on top of MINA without having to handle all the complexity of the newtork layer.</p> -<p>Lets take a deeper dive into the details now. The following image shows a bit more the internal of <strong>MINA</strong>, and what are each of the <strong>MINA</strong> components doing :</p> +<p>You just have to design your application on top of MINA without having to handle all the complexity of the network layer.</p> +<p>Lets take a deeper dive into the details now. The following image shows a bit more the internal of <strong>MINA</strong>, and what are each of the <strong>MINA</strong> components doing:</p> <p><img src="/assets/img/mina/mina_app_arch.png" alt=""></p> <p>(The image is from Emmanuel Lécharny presentation <a href="/assets/pdfs/Mina_in_real_life_ASEU-2009.pdf">MINA in real life (ApacheCon EU 2009)</a>)</p> <p>Broadly, MINA based applications are divided into 3 layers</p> @@ -163,14 +163,14 @@ <li>I/O Filter Chain - Filters/Transforms bytes into desired Data Structures and vice-versa</li> <li>I/O Handler - Here resides the actual business logic</li> </ul> -<p>So, in order to create a MINA based Application, you have to :</p> +<p>So, in order to create a MINA based Application, you have to:</p> <ol> -<li>Create an I/O service - Choose from already available Services (*Acceptor) or create your own</li> +<li>Create an I/O service - Choose from already available Services (<em>Acceptor</em>) or create your own</li> <li>Create a Filter Chain - Choose from already existing Filters or create a custom Filter for transforming request/response</li> <li>Create an I/O Handler - Write business logic, on handling different messages</li> </ol> <p>This is pretty much it.</p> -<p>You can get a bit deeper by reading those two pages :</p> +<p>You can get a bit deeper by reading those two pages:</p> <ul> <li><a href="ch2.1.1-server-architecture.html">2.1.1 - Server Architecture</a></li> <li><a href="ch2.1.2-client-architecture.html">2.1.2 - Client Architecture</a></li> diff --git a/content/mina-project/userguide/ch2-basics/ch2.1.1-server-architecture.html b/content/mina-project/userguide/ch2-basics/ch2.1.1-server-architecture.html index 15410b162..e18172c43 100644 --- a/content/mina-project/userguide/ch2-basics/ch2.1.1-server-architecture.html +++ b/content/mina-project/userguide/ch2-basics/ch2.1.1-server-architecture.html @@ -154,7 +154,7 @@ <li>Finally the packet or converted object lands in <code>IOHandler</code>. <code>IOHandler</code>s can be used to fulfill business needs.</li> </ul> <h2 id="session-creation">Session creation</h2> -<p>Whenever a client connects on a MINA server, we will create a new session to store persistent data into it. Even if the protocol is not connected, this session will be created. The following schema shows how <strong>MINA</strong> handles incoming connections :</p> +<p>Whenever a client connects on a MINA server, we will create a new session to store persistent data into it. Even if the protocol is not connected, this session will be created. The following schema shows how <strong>MINA</strong> handles incoming connections:</p> <p><img src="/assets/img/mina/incoming-connections.png" alt="Incoming connections handling"></p> <h2 id="incoming-messages-processing">Incoming messages processing</h2> <p>We will now explain how <strong>MINA</strong> processes incoming messages.</p> diff --git a/content/mina-project/userguide/ch2-basics/ch2.2-sample-tcp-server.html b/content/mina-project/userguide/ch2-basics/ch2.2-sample-tcp-server.html index 2fced0bc3..527eb5c6b 100644 --- a/content/mina-project/userguide/ch2-basics/ch2.2-sample-tcp-server.html +++ b/content/mina-project/userguide/ch2-basics/ch2.2-sample-tcp-server.html @@ -177,7 +177,7 @@ IoAcceptor acceptor <span style="color:#666">=</span> <span style="color:#a2f;font-weight:bold">new</span> NioSocketAcceptor<span style="color:#666">(</span><span style="color:#666">)</span><span style="color:#666">;</span> <span style="color:#666">}</span> <span style="color:#666">}</span> -</code></pre></div><p>With the NioSocketAcceptor class in place, we can go ahead and define the handler class and bind the NioSocketAcceptor to a port :</p> +</code></pre></div><p>With the NioSocketAcceptor class in place, we can go ahead and define the handler class and bind the NioSocketAcceptor to a port:</p> <div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#a2f;font-weight:bold">import</span> <span style="color:#00f;font-weight:bold">java.net.InetSocketAddress</span><span style="color:#666">;</span> <span style="color:#a2f;font-weight:bold">import</span> <span style="color:#00f;font-weight:bold">org.apache.mina.core.service.IoAcceptor</span><span style="color:#666">;</span> diff --git a/content/mina-project/userguide/ch4-session/ch4-session.html b/content/mina-project/userguide/ch4-session/ch4-session.html index 7be7785f0..52b8159eb 100644 --- a/content/mina-project/userguide/ch4-session/ch4-session.html +++ b/content/mina-project/userguide/ch4-session/ch4-session.html @@ -160,6 +160,7 @@ It is critical to understand that due to the asynchrnous very nature of NIO, rea <h2 id="session-state">Session state</h2> <p>A session has a state, which will evolve during time.</p> <ul> +<li>Created : the session has just been created</li> <li>Connected : the session has been created and is available</li> <li>Idle : the session hasn’t processed any request for at least a period of time (this period is configurable) <ul> @@ -168,7 +169,10 @@ It is critical to understand that due to the asynchrnous very nature of NIO, rea <li>Idle for both : no read nor write for a period of time</li> </ul> </li> +<li>Secured : the TLS layer has been initialised</li> +<li>Unsecured : The TLS layer has been shut down</li> <li>Closing : the session is being closed (the remaining messages are being flushed, cleaning up is not terminated)</li> +<li>Input closed : the input part of the socket has been closed</li> <li>Closed : The session is now closed, nothing else can be done to revive it. This is actually not a real state : when teh session is closed, it’s removed.</li> </ul> <p>The following state diagram exposes all the possible states and transitions :</p> @@ -177,8 +181,17 @@ It is critical to understand that due to the asynchrnous very nature of NIO, rea <p>Session status :</p> <ul> <li>isActive() : tells if the session is valid (it might mean different things depending on the implementation)</li> +<li>isBothIdle() : tells if the session is idling on reads and writes</li> <li>isClosing() : tells if the session is already being closed</li> <li>isConnected() : tells if the session is active (ie, not in the closing mode)</li> +<li>isIdle( idling status ) : tells if the session is idling on a specific state (read or write)</li> +<li>isReadIdle() : tells if the session is idling on reads</li> +<li>isReadSuspended() : tells if the session is not allowed to read messsages</li> +<li>isScheduledForFlush() : tells if the session has pending messages that are to be written</li> +<li>isSecured() : tells if teh TLS layer is active and initialized</li> +<li>isServer() : tells if the session is on the server side</li> +<li>isWriteIdle() : tells if the session is idling on writes</li> +<li>isWriteSuspended() : tells if the session is not allowed to write messsages</li> </ul> <h2 id="opening-a-session">Opening a session</h2> <p>Actually, there is nothing you have to do : it’s automatic ! Every time a remote peer connect to a server, the server will create a new connection. On the client side, every time you connect to a server, a session will be created.</p> @@ -198,7 +211,7 @@ session <span style="color:#666">=</span> connectionFuture<span style="color:#66 session <span style="color:#666">=</span> connector<span style="color:#666">.</span><span style="color:#b44">connect</span><span style="color:#666">(</span>address<span style="color:#666">)</span><span style="color:#666">.</span><span style="color:#b44">getSession</span><span style="color:#666">(</span><span style="color:#666">)</span><span style="color:#666">;</span> <span style="color:#666">.</span><span style="color:#666">.</span><span style="color:#666">.</span> </code></pre></div><h2 id="initialization">Initialization</h2> -<p>When a new session is created, it has to be initialized. This is done using the default IoService configuration, bt you can update this configuration later on. Actually, when the session is created, we internally create a copy of the default IoService configuration that is stored within the session, and this is this configuration instance that will be used (and that can be modified).</p> +<p>When a new session is created, it has to be initialized. This is done using the default IoService configuration, but you can update this configuration later on. Actually, when the session is created, we internally create a copy of the default IoService configuration that is stored within the session, and this is this configuration instance that will be used (and that can be modified).</p> <p>This initialization will also starts the statistics counters, create the Attributes container, associate a write queue to to the session (this is where the messages will be enqueued until they have been sent), and ultimately, would you have provided a specific task to do during this phase, it will call it.</p> <h2 id="closing-a-session">Closing a session</h2> <p>A session can be closed in 4 ways, two of which are explicit :</p> diff --git a/content/mina-project/userguide/ch5-filters/ch5.19-ssl-filter.html b/content/mina-project/userguide/ch5-filters/ch5.19-ssl-filter.html index ca26cbe95..92ee85e53 100644 --- a/content/mina-project/userguide/ch5-filters/ch5.19-ssl-filter.html +++ b/content/mina-project/userguide/ch5-filters/ch5.19-ssl-filter.html @@ -151,7 +151,7 @@ <p>The thing to remember is that the <strong>TLS</strong> protocol works in two steps:</p> <ul> <li>First there is a negociation part (the <em>Handshake</em>)</li> -<li>Then once the <em>Handshake</em> is completed, all the data will be encrypted before being sent.</li> +<li>Then once the <em>Handshake</em> is completed, all the data will be encrypted before being sent, and decryptd when received.</li> </ul> <p>We just have to add the filter in the chain like this:</p> <pre><code> ... @@ -160,24 +160,52 @@ chain.addFirst("sslFilter", sslFilter); ... -</code></pre><p>The <em>chain</em> is the instance of <strong>IoFilterChainBuilder</strong> class that is associated with either the <em>Connector</em> or the <em>Acceptor</em> instances (wether we are using a client or a server).</p> +</code></pre><p>The <em>chain</em> is the instance of <strong>IoFilterChainBuilder</strong> class that is associated with either the <em>Connector</em> or the <em>Acceptor</em> instances (wether we are using a client or a server). It will be used when a connection is set to define the filter chain this connected session will use.</p> <div class="note" markdown="1"> -Usually the **SSLFilyter** is always set at the first position in the chain. The rationnal is that it will receive and send encrypted data, so there is little use of having a functionnal filter between the head of the chain and the **SslFilter**. However, if such a filter is to be used, make sure it does not interfere with the data being exchanged with the remote peer. +Usually the **SSLFilter** is always set at the first position in the chain. The rationnal is that it will receive and send encrypted data, so there is little use of having a functionnal filter between the head of the chain and the **SslFilter**. However, if such a filter is to be used, make sure it does not interfere with the data being exchanged with the remote peer. </div> -<p>The missing part here is the <em>sslContext</em> which has to be defined. It’s an instande of the <strong>SSLContext</strong> class, where you define a <strong>TrustManager</strong>, a <strong>KeyManager</strong> and a <strong>Securerandom</strong>.</p> +<p>The missing part here is the <em>sslContext</em> which has to be defined. It’s an instance of the <strong>SSLContext</strong> class, where you define a <strong>TrustManager</strong>, a <strong>KeyManager</strong> and a <strong>Securerandom</strong>.</p> <div class="note" markdown="1"> This part is strandard Java security. You'll find plenty of pages on internet explaining you to set up a proper _SSLContext_ instance. </div> +<p>The filter can be added either <em>before</em> the connection has been established, or <em>after</em> the connection has been established. +In the first case, it’s easy, the filter initialisation will be done when the connection is created. The second is a bit more complex, as we will have to deal with ongoing messages.</p> +<h3 id="initialization">Initialization</h3> +<p>When a connection is created, the filter chain is created, and the <strong>SslFilter</strong> is added to this chain, which intializes it. The filter’s <em>onPreAdd</em> method is called, which will only check if the filter has already been added (we can’t have the <strong>SslFilter</strong> twice in the chain).</p> +<p>The filter’s <em>onPostAdd</em> method is then called, and if the <em>autostart</em> flag is set to <em>true</em> and the session is connected (which should be the case…), then the <em>onConnected</em> method is called.</p> +<div class="note" markdown="1"> + The _autostart_ flag can be set when creating the **SslFilter**. It indicates that the filter will be initialized immediatly on a new connection. Otherwise the filter will be initialized later on when the session will have been opened. +</div> +<p>The <strong>SslHandler</strong> will then be created, which will contain a newly created <strong>SslEngine</strong>. This is the place where the <strong>TLS</strong> parameters will be set:</p> +<ul> +<li>The authentication <strong>WANT</strong> or <strong>NEED</strong> flags</li> +<li>The cipher suite</li> +<li>The enabled protocols</li> +<li>The endpoint identification algorithms</li> +<li>and finally the flag indicating if it’s for a server or a client</li> +</ul> +<p>All those flags are optionnal but the last one.</p> +<p>The newly created <strong>SslHandler</strong> instance will be added into the session’s attributes, under the <em>org.apache.mina.filter.ssl.SslHandler.handler@<ID></em> key (The <strong>ID</strong> part is unique).</p> +<p>Last, not least, the <strong>SslHandler</strong> instance is opened. If we are on the client side, the <strong>TLS</strong> <em>Handshake</em> will be started, otherwise a flag will be set to indicate we are expecting a <em>Handshake</em> on the server side.</p> +<p>We are all set and ready for the <em>Handshake</em> to be processed!</p> <h3 id="handshake">Handshake</h3> -<p>The <strong>Handshake</strong> is automatically initiated by the server when the connection is created. The <strong>SslFilter</strong> has a <em>onPostAdd</em> method which create a <strong>SSLEngine</strong> instance based on the provided <strong>SSLContext</strong>.</p> -<p>It sets the <strong>SSLEngine</strong> characteristics:</p> +<p>The <em>Handshake</em> must be done as soon as the <strong>TLS</strong> layer is activated. It’s initiated by the client, which must send a <em>CLIENT_HELLO</em> message (see the <a href="https://tls13.xargs.org/#client-hello">Client Hello</a> description), but the server must be ready to accept this message.</p> +<p>We will consider two use cases: the <strong>Client</strong> side and the <strong>Server</strong> side (as <strong>Mina</strong> can handle both sides, but could work with a peer written using a different implementation)</p> +<h4 id="initial-handshake-message">Initial Handshake message</h4> +<p>The first <em>Handshake</em> message to be processed is the <strong>CLIENT HELLO</strong> <strong>TLS</strong> message.</p> +<h5 id="server-side">Server side</h5> +<p>The <em>Handshake</em> is initiated by a <strong>CLIENT_HELLO</strong> <strong>TLS</strong> request which is sent by the client, the server is waiting for it. There starts a serie of <strong>TLS</strong> messages exchanged between the cleint and the server, at the end of which the session is secured, and data can be exchanged encrypted.</p> +<p>What is important to note here is that during the <em>Handshake</em> exchanges, no application data can be sent, and the <strong>SslFilter</strong> is handling the whole process, before returning the hand to the application. That means messages emitted by the application will be stacked until the session is secured.</p> +<h5 id="client-side">Client side</h5> +<p>The client is the initiator of the <em>Handshake</em> exchange. The difference with the server is that the client <strong>SSLhandler</strong> will generate the inital <em>Handshake</em> message (<strong>CLIENT HELLO</strong>) and send it to the server</p> +<h4 id="follow-up-handshake-messages">Follow up Handshake messages</h4> +<p>Once the <em>Handshake</em> has been initiated, the dance keeps going until the <em>Handshake</em> is either done or fails:</p> <ul> -<li>Whether the client authentication is requested or required (<em>needClientAuth</em> and <em>wantClientAuth</em> flags)</li> -<li>Sets the enabled cipher suites</li> -<li>Sets the enabled protocols</li> +<li>The client sends <em>Handshake</em> requests</li> +<li>The server sends <em>Handshake</em> responses</li> </ul> -<p>Last, not least, the <strong>CLIENT_HELLO</strong> <strong>TLS</strong> request is sent by the client side, the server is waiting for it. There starts a serie of <strong>TLS</strong> messages exchanged between the cleint and the server, at teh end of which the session is secured, and data can be exchanged encrypted.</p> -<p>What is important to note here is that during the <strong>Handshake</strong> exchanges, no application data can be sent, and the <strong>SslFilter</strong> is handling the whole process, before returning the hand to the application.</p> +<p>This dance can use many steps.</p> +<p>It ends with both side send a <em>finished</em> message, and has verified that it’s valid.</p> <h3 id="session-secured">Session secured</h3> <p>The application is informed that the session is secured:</p> <ul> @@ -195,12 +223,12 @@ Usually the **SSLFilyter** is always set at the first position in the chain. The <li><a href="https://datatracker.ietf.org/doc/html/rfc4642"><strong>NNTP</strong></a></li> <li><a href="https://datatracker.ietf.org/doc/html/rfc4513"><strong>LDAP</strong></a></li> </ul> -<p>The way it works is that at some point of a clear text established connection, the client sends a <strong>STARTLS</strong> command, which forces the <strong>TLS</strong> handshake to start to establish a secured connection. When the secured connection is established, the client and the server exchanges will be encrypted.</p> +<p>The way it works is that at some point of a clear text established connection, the client sends a <strong>STARTLS</strong> command, which forces the <strong>TLS</strong> <em>Handshake</em> to start to establish a secured connection. When the secured connection is established, the client and the server exchanges will be encrypted.</p> <p>Now, that is a bit tricky to implement, because both the client <em>and</em> the server must block the exchange of messages during the establishement of the <strong>TLS</strong> session. As the client is the initiator of the command, it’s easy, but on the server side, we must pass a response to the original command <strong>in clear text</strong> informing the client that the command has been received and processed.</p> <pre><code>(C) The client sends a **StartTLS** command (S) The server receives the command, initialize the **TLS** layer, and send back a response to the client, bypassing the **TLS** layer. -(C) The client received the server response to the command, and setup the **TLS** layer, and initiates the **TLS** handshake -(S/C) The Handshake is processed +(C) The client received the server response to the command, and setup the **TLS** layer, and initiates the **TLS** _Handshake_ +(S/C) The _Handshake_ is processed (S/C) The session is secured on both side (S/C) at this point, every message exchanged are encrypted. </code></pre> diff --git a/content/sitemap.xml b/content/sitemap.xml index 2491ff887..18e49b4b4 100644 --- a/content/sitemap.xml +++ b/content/sitemap.xml @@ -4,22 +4,22 @@ <url> <loc>https://mina.apache.org/mina-project/userguide/ch1-getting-started/ch1.1-nio-overview.html</loc> - <lastmod>2020-02-24T11:41:02+01:00</lastmod> + <lastmod>2024-04-28T06:15:39+02:00</lastmod> </url> <url> <loc>https://mina.apache.org/mina-project/userguide/ch1-getting-started/ch1.2-why-mina.html</loc> - <lastmod>2020-02-24T11:41:02+01:00</lastmod> + <lastmod>2024-04-28T06:15:39+02:00</lastmod> </url> <url> <loc>https://mina.apache.org/mina-project/userguide/ch1-getting-started/ch1.3-features.html</loc> - <lastmod>2020-02-27T13:50:48+01:00</lastmod> + <lastmod>2024-04-28T06:15:39+02:00</lastmod> </url> <url> <loc>https://mina.apache.org/mina-project/userguide/ch1-getting-started/ch1.4-first-steps.html</loc> - <lastmod>2020-02-24T11:41:02+01:00</lastmod> + <lastmod>2024-04-28T06:15:39+02:00</lastmod> </url> <url> @@ -29,12 +29,12 @@ <url> <loc>https://mina.apache.org/mina-project/userguide/ch2-basics/ch2.1-application-architecture.html</loc> - <lastmod>2020-02-27T13:50:48+01:00</lastmod> + <lastmod>2024-04-28T06:15:39+02:00</lastmod> </url> <url> <loc>https://mina.apache.org/mina-project/userguide/ch2-basics/ch2.1.1-server-architecture.html</loc> - <lastmod>2020-02-24T11:41:02+01:00</lastmod> + <lastmod>2024-04-28T06:15:39+02:00</lastmod> </url> <url> @@ -44,7 +44,7 @@ <url> <loc>https://mina.apache.org/mina-project/userguide/ch2-basics/ch2.2-sample-tcp-server.html</loc> - <lastmod>2020-02-27T13:50:48+01:00</lastmod> + <lastmod>2024-04-28T06:15:39+02:00</lastmod> </url> <url> @@ -149,7 +149,7 @@ <url> <loc>https://mina.apache.org/mina-project/userguide/ch5-filters/ch5.19-ssl-filter.html</loc> - <lastmod>2023-06-04T07:12:06+02:00</lastmod> + <lastmod>2024-04-28T06:15:39+02:00</lastmod> </url> <url> @@ -224,7 +224,7 @@ <url> <loc>https://mina.apache.org/contributors.html</loc> - <lastmod>2023-07-04T22:40:54+02:00</lastmod> + <lastmod>2024-04-28T06:14:56+02:00</lastmod> </url> <url> @@ -559,7 +559,7 @@ <url> <loc>https://mina.apache.org/mina-project/userguide/ch4-session/ch4-session.html</loc> - <lastmod>2020-02-27T13:50:48+01:00</lastmod> + <lastmod>2024-04-28T06:15:39+02:00</lastmod> </url> <url> @@ -569,7 +569,7 @@ <url> <loc>https://mina.apache.org/ftpserver-project/documentation/ch6-internals/ch6-internals.html</loc> - <lastmod>2023-07-03T15:48:21+02:00</lastmod> + <lastmod>2024-04-28T06:17:22+02:00</lastmod> </url> <url> @@ -819,7 +819,7 @@ <url> <loc>https://mina.apache.org/ftpserver-project.html</loc> - <lastmod>2023-07-03T15:48:21+02:00</lastmod> + <lastmod>2024-04-28T06:17:22+02:00</lastmod> </url> <url> @@ -899,7 +899,7 @@ <url> <loc>https://mina.apache.org/mina-project.html</loc> - <lastmod>2023-09-12T10:28:07+02:00</lastmod> + <lastmod>2024-04-28T06:15:39+02:00</lastmod> </url> <url>