<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>blog.freelan.org &#187; &#187; mac osx</title>
	<atom:link href="http://blog.freelan.org/tag/mac-osx/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.freelan.org</link>
	<description>De l&#039;informatique, des octets et des poneys.</description>
	<lastBuildDate>Fri, 04 Apr 2014 17:34:59 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.42</generator>
	<item>
		<title>Découverte de libsystools 2.1</title>
		<link>http://blog.freelan.org/2010/12/10/decouverte-de-libsystools-2-1/</link>
		<comments>http://blog.freelan.org/2010/12/10/decouverte-de-libsystools-2-1/#comments</comments>
		<pubDate>Fri, 10 Dec 2010 16:06:51 +0000</pubDate>
		<dc:creator><![CDATA[Julien Kauffmann]]></dc:creator>
				<category><![CDATA[Développement]]></category>
		<category><![CDATA[Systools]]></category>
		<category><![CDATA[boost]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[iconv]]></category>
		<category><![CDATA[libxml2]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mac osx]]></category>
		<category><![CDATA[openssl]]></category>
		<category><![CDATA[socket]]></category>
		<category><![CDATA[systools]]></category>
		<category><![CDATA[unix]]></category>
		<category><![CDATA[upnp]]></category>
		<category><![CDATA[windows]]></category>
		<category><![CDATA[xml]]></category>
		<category><![CDATA[xmlsec]]></category>

		<guid isPermaLink="false">http://blog.freelan.org/?p=111</guid>
		<description><![CDATA[Cette semaine, j'ai eu l'immense honneur d'effectuer la "release" de la version 2.1  de notre bibliothèque de base : libsystools. Cette version est le fruit de nombreuses heures de travail de l'équipe freelan et apporte un bon lot de nouveautés par rapport à la dernière version.

Cet article va tenter de vous faire découvrir ces nouveautés, d'expliquer certaines décisions de design et bien entendu de vous donner envie de l'essayer !]]></description>
				<content:encoded><![CDATA[<p>Cette semaine, j&#8217;ai eu l&#8217;immense honneur d&#8217;effectuer la &#8220;release&#8221; de la <a href="https://sourceforge.net/projects/libsystools/">version 2.1</a> de notre bibliothèque de base : <strong>libsystools</strong>. Cette version est le fruit de nombreuses heures de travail de l&#8217;équipe <strong>freelan</strong> et apporte un bon lot de nouveautés par rapport à la dernière version.</p>
<p>Cet article va tenter de vous faire découvrir ces nouveautés, d&#8217;expliquer certaines décisions de design et bien entendu de vous donner envie de l&#8217;essayer !</p>
<h1>Présentation</h1>
<p>Il y a 2 ans, le code de <strong>freelan</strong> commençait à être volumineux. Bon nombre de classes outils étaient écrites qui pouvaient intéresser d&#8217;autres projets. Nous avons donc décidé de rendre cet ensemble de classes autonome et c&#8217;est ainsi qu&#8217;est né <strong>libsystools</strong>.</p>
<p><strong>libsystools</strong> propose une interface C++ moderne pour un certain nombre de bibliothèques C mais aussi des classes nouvelles (notamment SmartBuffer).</p>
<p>Ses principaux domaines d&#8217;application sont :</p>
<ul>
<li>La gestion du xml (parsing, génération, modification, signature);</li>
<li>la gestion de la cryptographie (RSA, AES, SHA);</li>
<li>la gestion des certificats;</li>
<li>la gestion des ports série;</li>
<li>la gestion du SSL (TLS, DTLS);</li>
<li>la gestion du réseau (Socket, SocketAddress, SocketAddressResolver) en IPv4 <strong>et</strong> IPv6.</li>
<li>la gestion facilité de la mémoire (SmartBuffer);</li>
<li>une implémentation basique d&#8217;un client UPnP;</li>
<li>une implémentation basique d&#8217;un client HTTP;</li>
<li>une implémentation simple d&#8217;une classe de log;</li>
<li>la gestion de l&#8217;encodage (UTF-8, UTF-16, ISO-8859-1, etc.);</li>
<li>différentes méthodes pour calculer de checksum, compresser des flux, etc.</li>
</ul>
<p><strong>libsystools</strong> a été conçue dès le départ pour être extrêmement portable, qu&#8217;il s&#8217;agisse des systèmes d&#8217;exploitation ou des architectures. Elle est donc utilisable sur Windows (MinGW, Visual Studio 2010), Linux (gcc), Mac OSX (gcc), UNIX (gcc) aussi bien en 32 bits qu&#8217;en 64 bits.</p>
<p>L&#8217;ensemble de ses classes est documenté et différents exemples sont fournis qui traitent de chacun de ses domaines d&#8217;application.</p>
<p><strong>libsystools</strong> se base sur différentes bibliothèques :</p>
<ul>
<li>libxml2</li>
<li>libxmlsec1</li>
<li>openssl</li>
<li>libiconv</li>
<li>boost</li>
</ul>
<h2>Faciliter l&#8217;existant</h2>
<p>Les bibliothèques sur lesquelles se base <strong>libsystools</strong> sont bien écrites et fiables. Cependant, elles ne fournissent qu&#8217;une interface en C.</p>
<p>Lorsqu&#8217;on utilise que peu ces bibliothèques dans un projet, il est acceptable de se servir simplement de ces interfaces C. Cependant, lorsqu&#8217;un projet en fait un usage intensif, le code devient très rapidement très dur à maintenir.</p>
<p>Qui n&#8217;a jamais eu à écrire un code de ce style ?</p><pre class="crayon-plain-tag">#include &amp;lt;iostream&amp;gt;

#include &amp;lt;libfoo&amp;gt;

int main()
{
	FOOCONTEXT ctx = CreateFooContext();

	try
	{
		FOOHANDLER handler = CreateFooHandler(ctx);

		try
		{
			// Code
		}
		catch (...)
		{
			FreeFooHandler(handler);

			throw;
		}

		FreeFooHandler(handler);
	}
	catch (...)
	{
		FreeFooContext(ctx);

		throw;
	}

	FreeFooContext(ctx);

	return EXIT_SUCCESS;
}</pre><p>Bien sûr, un bon programmeur C++ simplifiera l&#8217;écriture de ce genre de code avec l&#8217;utilisation de classes conteneurs qui se chargent de libérer la ressource associée lors de leur destruction. Mais devoir refaire ce travail d&#8217;encapsulation à chaque utilisation est fastidieux, et ne règle qu&#8217;une partie du problème.</p>
<p>C&#8217;est dans cet esprit qu&#8217;on été développées les classes de <strong>libsystools</strong> : des wrappers simples, faciles à utiliser et efficaces.</p>
<p>En utilisant <strong>libsystools</strong>, le code précédent aurait plutôt ressemblé à :</p><pre class="crayon-plain-tag">#include &amp;lt;iostream&amp;gt;

#include &amp;lt;libfoo&amp;gt;

int main()
{
	FooContext ctx;
	FooHandler handler(ctx);

	// Code

	return EXIT_SUCCESS;
}</pre><p>Ce qui est bien plus lisible et maintenable, et présente l&#8217;avantage d&#8217;être &#8220;exception-safe&#8221;.</p>
<h1>Utilisation &amp; Exemples</h1>
<p>Nous pourrions exposer les différents aspects conceptuels qui ont motivé chaque décision pendant des heures et sur plusieurs pages, mais après tout, en programmation, il n&#8217;y a pas plus explicite que le code. Voici donc quelques exemples d&#8217;utilisation commentés.</p>
<h2>SmartBuffer, ou comment gérer la mémoire de façon intelligente</h2>
<p>S&#8217;il ne fallait garder qu&#8217;une seule classe, ce serait celle-ci : SmartBuffer est au coeur de <strong>libsystools</strong>. Utilisée partout, SmartBuffer représente un tableau d&#8217;octets à taille variable et dont les différentes instances peuvent partager leur mémoire.</p><pre class="crayon-plain-tag">#include &amp;lt;iostream&amp;gt;

#include &amp;lt;systools/smartbuffer.hpp&amp;gt;

int main()
{
	using systools::SmartBuffer;

	// On cr&eacute;e un buffer &agrave; partir d'une cha&icirc;ne C
	SmartBuffer buffer(&quot;Hello you&quot;);

	// On copie un buffer
	SmartBuffer copy = buffer; // copy et buffer partagent la m&ecirc;me m&eacute;moire.

	// On r&eacute;duit copy
	copy.resize(6); // copy a juste &eacute;t&eacute; r&eacute;duit, copy et buffer partagent toujours la m&ecirc;me m&eacute;moire.

	copy.append(&quot;me&quot;); // copy a &eacute;t&eacute; modifi&eacute;, copy et buffer ne partagent plus la m&ecirc;me m&eacute;moire.

	// On affiche les r&eacute;sultats
	std::cout &amp;lt;&amp;lt; &quot;buffer: &quot; &amp;lt;&amp;lt; buffer.toStdString() &amp;lt;&amp;lt; std::endl; // buffer: Hello you
	std::cout &amp;lt;&amp;lt; &quot;copy: &quot; &amp;lt;&amp;lt; copy.toStdString() &amp;lt;&amp;lt; std::endl; // copy: Hello me

	return EXIT_SUCCESS;
}

// On peut utiliser un SmartBuffer comme valeur de retour de fonction
systools::SmartBuffer getBuffer()
{
	// La m&eacute;thode-patron &quot;factory&quot; SmartBuffer::from permet de cr&eacute;er un buffer &agrave; partir de n'importe quel type.
	return systools::SmartBuffer::from&amp;lt;int&amp;gt;(4);
}</pre><p>Dans bon nombre de cas, l&#8217;utilisation de SmartBuffer permet de simplifier le code existant en remplaçant les paramètres de type :</p><pre class="crayon-plain-tag">void fonction(const char* inbuf, size_t inbuflen, char** outbuf, size_t&amp;amp; outbuflen);</pre><p>Par un simple :</p><pre class="crayon-plain-tag">SmartBuffer fonction(const SmartBuffer&amp;amp; inbuf);</pre><p>La lecture et la maintenance s&#8217;en trouvent tous deux grandement facilités.</p>
<h2>XML, les wrappers autour de libxml2</h2>
<p>Avec l&#8217;engouement de tous les domaines pour le web, il est rare aujourd&#8217;hui d&#8217;avoir du code à produire qui ne nécessite pas de manipuler du XML. En C++, plusieurs solutions existent.</p>
<p>Nous avons opté pour la libxml2 pour plusieurs raisons :</p>
<ul>
<li>C&#8217;est une bibliothèque mature, complète et quotidiennement maintenue;</li>
<li>elle est portable sur plusieurs architectures et plateformes;</li>
<li>elle s&#8217;interface très bien avec OpenSSL au sein de libxmlsec1 pour le support des signatures XML.</li>
</ul>
<p>Le module XML de libsystools se décompose en trois parties :</p>
<ul>
<li>Les éléments DOM, qui représentent de façon statique un arbre XML;</li>
<li>les &#8220;writers&#8221; qui permettent de générer du XML;</li>
<li>les objets XPath, qui permettent d&#8217;effectuer des requêtes dans les éléments DOM.</li>
</ul>
<p>Voyons un exemple d&#8217;utilisation :</p><pre class="crayon-plain-tag">#include &amp;lt;iostream&amp;gt;
#include &amp;lt;cstdlib&amp;gt;
#include &amp;lt;cstring&amp;gt;

#include &amp;lt;boost/shared_ptr.hpp&amp;gt;
#include &amp;lt;boost/foreach.hpp&amp;gt;

#include &amp;lt;systools/xml.hpp&amp;gt;
#include &amp;lt;systools/xml_document.hpp&amp;gt;
#include &amp;lt;systools/xml_node.hpp&amp;gt;
#include &amp;lt;systools/xml_xpath.hpp&amp;gt;
#include &amp;lt;systools/xml_buffer_writer.hpp&amp;gt;
#include &amp;lt;systools/xml_document_writer.hpp&amp;gt;

int main(int, char**)
{
	using namespace systools;

	// Initialization
	xml::Initializer xml;

	std::cout &amp;lt;&amp;lt; &quot;Initializing...: &quot; &amp;lt;&amp;lt; &quot;OK&quot; &amp;lt;&amp;lt; std::endl;

	try
	{
		// Generation

		xml::XmlDocumentWriter writer;

		writer.startDocument();
		writer.startElement(&quot;configuration&quot;);
		writer.writeAttribute(&quot;xmlns&quot;, &quot;namespace&quot;);
		writer.writeElement(&quot;key&quot;, &quot;value&quot;);
		writer.startElement(&quot;parent&quot;);
		writer.writeElement(&quot;child&quot;, &quot;anna&quot;);
		writer.writeElement(&quot;child&quot;, &quot;bobby&quot;);
		writer.endElement();
		writer.endDocument();

		xml::XmlDocument document = writer.getResultAsDocument();
		std::cout &amp;lt;&amp;lt; &quot;Generating XML document: &quot; &amp;lt;&amp;lt; &quot;OK&quot; &amp;lt;&amp;lt; std::endl;
		std::cout &amp;lt;&amp;lt; document.toString().toStdString() &amp;lt;&amp;lt; std::endl;

		// XPath

		xml::XPath xpath = document.xpath();

		if (!xpath.registerNamespace(&quot;fl&quot;, &quot;namespace&quot;))
		{
			std::cerr &amp;lt;&amp;lt; &quot;Warning ! Failed to register the namespace !&quot; &amp;lt;&amp;lt; std::endl;
		}

		std::list&amp;lt;xml::XmlNode&amp;gt; list = document.xpath().evaluate(&quot;/fl:configuration/fl:parent&quot;);

		if (list.size() &amp;gt; 0)
		{
			list = list.front().xpath().evaluate(&quot;fl:child&quot;);

			std::cout &amp;lt;&amp;lt; &quot;Results:&quot; &amp;lt;&amp;lt; std::endl;

			BOOST_FOREACH(const xml::XmlNode&amp;amp; node, list)
			{
				std::cout &amp;lt;&amp;lt; node.name().toStdString() &amp;lt;&amp;lt; &quot;: &quot; &amp;lt;&amp;lt; node.content().toStdString() &amp;lt;&amp;lt; std::endl;
			}
		}
	}
	catch (Exception&amp;amp; ex)
	{
		std::cout &amp;lt;&amp;lt; &quot;Exception caught: &quot; &amp;lt;&amp;lt; ex.toString() &amp;lt;&amp;lt; std::endl;
	}

	return EXIT_SUCCESS;
}</pre><p>Reprenons cet exemple point par point :</p>
<ul>
<li>Ligne 20 : nous déclarons un xml::Initializer qui existera pour toute la portée du main. Cet objet permet d&#8217;<strong>initialiser</strong> la libxml2 et de <strong>garantir sa libération</strong> au moment opportun, de façon automatique.</li>
<li>Ligne 28 : nous créons un XmlDocumentWriter. Cet objet permet une construction facilité d&#8217;un arbre XML en construisant l&#8217;un après l&#8217;autre ses différents éléments.</li>
<li>Lignes 30 à 38 : Nous créons chacun des noeuds XML. Les différentes fonctions prennent des systools::String en paramètre et supportent donc parfaitement la gestion des différents encodages.</li>
<li>Ligne 40 : Nous récupérons un arbre XML complet à partir du writer.</li>
<li>Ligne 46 : Nous récupérons l&#8217;instance XPath associé à l&#8217;arbre XML (cette instance est partagée par tous les noeuds d&#8217;un même arbre)</li>
<li>Ligne 48 : Nous associons un nom court au namespace nommé &#8220;namespace&#8221; dans l&#8217;instance XPath.</li>
<li>Ligne 53 : Nous effectuons une requête XPath sur la racine du document.</li>
<li>Ligne 57 : Nous effectuons une requête XPath sur un sous-noeud du document.</li>
</ul>
<p>La manipulation du XML est grandement facilitée. On voit que seules quelques instructions suffisent à construire un arbre, à y naviguer et à en extraire les informations utiles.</p>
<h2>Le module réseau</h2>
<p>Une autre partie importante de libsystools est son module réseau. La manipulation des différentes fonctions et structures réseau d&#8217;un système a toujours été la bête noire des programmeurs novices. Entre les spécificités propres à chaque système d&#8217;exploitation, et les fonctions dépréciées suite au prochain passage à IPv6 (ça approche, si si, croyez-moi !), il n&#8217;est pas toujours évident de produire un code propre et robuste.</p>
<p>Le module réseau de libsystools a été conçu pour résoudre cette problématique. Il propose :</p>
<ul>
<li>Une classe qui permet représenter une adresse de socket (IPv4, IPv6, etc.);</li>
<li>une classe pour effectuer des résolutions de nom ou d&#8217;adresse sur le réseau;</li>
<li>des classes Socket et SecureSocket qui encapsulent respectivement une socket classique et une socket SSL (en TLS ou DTLS);</li>
<li>une classe &#8220;Select&#8221; qui encapsule de façon objet les appels à la méthode &#8220;select()&#8221;;</li>
<li>une classe pour représenter les adresses Ethernet;</li>
<li>des outils de conversion entre adresse IP et représentation numérique.</li>
</ul>
<p>Démontrons la simplicité de son utilisation en montrant le code d&#8217;un example qui va successivement :</p>
<ol>
<li>Chercher l&#8217;adresse de socket associée à 127.0.0.1:34000 en TCP.</li>
<li>Créer une socket</li>
<li>Connecter cette socket sur le serveur TCP situé à l&#8217;adresse recherchée en 1.</li>
<li>Attendre la réception d&#8217;un message.</li>
<li>Se déconnecter et libérer la socket et toutes les ressources associées.</li>
</ol>
<p></p><pre class="crayon-plain-tag">#include &amp;lt;iostream&amp;gt;
#include &amp;lt;cstdlib&amp;gt;
#include &amp;lt;cstring&amp;gt;
#include &amp;lt;string&amp;gt;

#include &amp;lt;list&amp;gt;

#include &amp;lt;systools/network.hpp&amp;gt;
#include &amp;lt;systools/socket.hpp&amp;gt;
#include &amp;lt;systools/socket_address.hpp&amp;gt;
#include &amp;lt;systools/socket_address_resolver.hpp&amp;gt;

int main(int, char**)
{
	using namespace systools;

	network::Initializer network;

	SocketAddressResolver sar;

	try
	{
		sar.getAddrInfo(&quot;127.0.0.1&quot;, &quot;34000&quot;, IPPROTO_TCP, AF_UNSPEC);

		if (sar.size() &amp;lt;= 0)
		{
			std::cout &amp;lt;&amp;lt; &quot;No address information was returned.&quot; &amp;lt;&amp;lt; std::endl;
		} else
		{
			// Usually, one could choose to iterate trough the results and to keep only the first one to which a connection can be established.
			Socket socket(sar.front());
			SocketAddress address(sar.front());

			std::cout &amp;lt;&amp;lt; &quot;Connecting to: &quot; &amp;lt;&amp;lt; address.toNumericString() &amp;lt;&amp;lt; std::endl;

			socket.connect(address);

			SmartBuffer message;

			size_t recv_bytes = socket.recv(message);

			if (recv_bytes &amp;gt; 0)
			{
				std::cout &amp;lt;&amp;lt; &quot;Receiving message: &quot; &amp;lt;&amp;lt; std::string(message.constData(), message.size()) &amp;lt;&amp;lt; std::endl;
			}
		}
	}
	catch (Exception&amp;amp; ex)
	{
		std::cout &amp;lt;&amp;lt; &quot;Exception: &quot; &amp;lt;&amp;lt; ex.toString() &amp;lt;&amp;lt; std::endl;

		return EXIT_FAILURE;
	}

	return EXIT_SUCCESS;
}</pre><p>Pas si mal pour un code d&#8217;une cinquantaine de lignes qui gère correctement toutes les erreurs potentielles et la libération des ressources, non ?</p>
<h1>Pour conclure</h1>
<p>Vous n&#8217;avez eu ici qu&#8217;un très bref aperçu des possibilités offertes par la <strong>libsystools</strong>. Pour découvrir plus avant la bibliothèque, je vous invite à consulter sa <a href="http://www.freelan.org/doc-2.1">documentation en ligne</a>.</p>
<p>En tout cas, j&#8217;espère sincèrement que cette présentation aura attisé votre curiosité et vous aura donné envie d&#8217;essayer la bibliothèque lors de vos prochains développements. Bien entendu, si vous avez des questions générales sur la bibliothèque et des interrogations concernant son évolution future, n&#8217;hésitez pas à commenter cet article ou directement contacter l&#8217;équipe sur la <a href="mailto:libsystools-users@lists.sourceforge.net">mailing-list</a> (en anglais).</p>
<p>Bon code ! <img src="http://blog.freelan.org/wp-includes/images/smilies/icon_smile.gif" alt=":)" class="wp-smiley" /></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.freelan.org/2010/12/10/decouverte-de-libsystools-2-1/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
