Showing posts with label web. Show all posts
Showing posts with label web. Show all posts

Sending file through WebRTC

Introduction


Back in 2016, I’ve worked on an application called ShareTC that allowed users to share their files through their web browser using the WebRTC technology. The application was working well but the promise was to be able to share files without any server. The first version used PeerJS, a library allowing you to implement WebRTC data channel for file sharing easily with the drawback needing a server for what is called the signaling process. Thus, I’ve made some improvement to the project to allow user to share their files without even using a signaling server.
For those who are no interested by the technical implementation you can directly have a look to the demo on GitHub.

Migration


Originally, the project was barebone native JavaScript but I decided to upgrade the project to Angular 8, because exchanging the signaling configuration is a little complex, I needed some framework for easy DOM manipulation.

Because this is a side project, I didn’t want to recreate a component library so I used the @angular/material library for the forms and user feedbacks.

I also used @angular/flex-layout to easily define the layout, knowing that the application design is really basic as it is not the primary intent of the demonstration.

How it works


So, the interesting part now, the application will try to create a data channel between the sender and the receiver, using WebRTC. The protocol needs to know to whom it should send the data, this is named peer discovery, and it can be done automatically through what is called a signaling server, a server where you exchange your configuration to begin the communication and this is the component that I wanted to remove. For the manual configuration we use the Session Description Protocol (or SDP).




But because the network is a little complex, in some cases, you’ll need a Session Traversal Utilities for NAT (or STUN) server. This is used when you’re exchanging a file from behind a Network Address Translation (or NAT) firewall. There are some public servers available for this like:
-    stun.services.mozilla.com
-    stun.l.google.com:19302




In some other cases the communication channel will be blocked by firewalls. In this case you can eventually use a Traversal Using Relays around NAT (or TURN) server that will work as a Data relay between you and the peer. They are expensive and only necessary if you’re behind a blocking firewall so I didn’t integrate a solution for that 😊



So, what do we do is, we generate the sender configuration SDP, that you will need to share with the receiver. Then he’ll be able to generate his SDP configuration, that you’ll need to import in order to create the communication channel. Then you’ll be able to send the file using Datagram Transport Layer Security (or DTLS) which is a secure communication channel.

How to make it happen


Now that you have the WebRTC communication scheme in mind, let’s see some interesting parts of the project. You might want to have the code open to better understand this part by accessing the project repository flyersweb/sharetc.

First, I chose to use the great feross/simple-peer library for WebRTC communication channel. To use the library we had to add some polyfills (check polyfills.ts) to the project for the global, process and buffer objects like this:

(window as any).global = window;
(window as any).process = {
    nextTick: setImmediate,
    env: { DEBUG: undefined },
};
(window as any).global.Buffer = (window as any).global.Buffer || require('buffer').Buffer;

If you’re using typescript you also might have to add the node declarations for native modules by modifying your tsconfig.app.json file with:

"types": [
  "node"
],

I’ve also decided to compress SDP configuration using LZ-based compression so it is easier to share. This is why the configurations will look more like this:

 N4IgLgngDgpiBcID2AzFMBOIA0IDOAJlAiAG4C8ADADobUB2S5AtkgF4CWANlwIYB0ggCoAJAJIBlAPqSpEgCIAFAIIAlIcoC0Adkr89ARgAEBgEwAWSuYCcZ7dZsAOc6e2Ptpo5SNiAcj8VzL30Qmjp6PHJNWgYwKi8Y+l5yPBh6AgwYAGNSROSUDnoAc0woDEKweDwAC15NUwBWADYjJuV4JoaO63gAZgAxeEcm+ABRAGF4bXN4W3h5Qf7JxvhzLoNBptGxyYbt0ZGG9tH5eGVtpp63eH7KVZ7lRzGDeHG769M7+Rf5O4AhUZ5chFDBIACuUHgfwAqr55AAZUYJcLJZh4DgETSpZi8ehgDhZeAAdQAshIjAAqRLMci8KBQLgE3j4pD0IwNRyOUwtaFKAD08iE8IkfIk4yEiiMAHcYAAjDBgLKaAjM3hZWr0egwLiJLLkPwBILWPTG-iNfgGXqOIFZXEEDHMmDwbzGXmS0xmUyNRrmXomPR6UwWhpGXraXq2IyQKBGapIPBgG12h1gJ1+4xCcbugyUBoNCzmez+kJBgwh6xR6Cx+NgKNZKDRmBGNX40gwJPpFNO4yupQmJrDXOmYZ+02m82WxzszncysxvAYFBcAAeRgwvAIGWLgeDa6gSAVofDtiBqXSmRyQLSmNQmltnZVqbwQIJME0UClBCm9m0TVzsosUwshgbRZRgdx7GaAhZQIT4slMFAAJfYDNDBFB1yKeAGmsD0DHA3ogWYDFnVPGAwAheAWygXg8GfFEUiyMAoHfA9KgaSgOMI3hl00ZgYFo3gSixDg2G7Shw2mAwuQI8IQAAXyAA

But by decompressing it you’ll get a valid SDP signal message.

And finally, in order to send and download the file we use the JavaScript File API so we can send it through the data channel. Thing is, the data will be stored as an ArrayBuffer so we generate a download link through a Blob for the file to be downloaded with the name file.dat as shown in the download component.

To exchange messages through the communication data channel we also need to convert the ArrayBuffer to string by using this function:

function ab2str(buf: ArrayBuffer): string {
  return String.fromCharCode.apply(null, new Uint16Array(buf));
}

You can check how it is used in the upload component.

The demo


Because you have to exchange the SDP configuration and create the data channel before sending the file, the application is a little more complex to grasp. So to use the demo application you’ll need to:

1. Send your sender configuration
2. Receiver will enter your configuration and hit connect (it connects to sender)
3. The receiver will the share his generated configuration with you the sender
4. Then the sender hit connect to create the data channel
5. The duplex stream is up and running

You can access it by accessing https://flyersweb.github.io/sharetc.

Conclusion


This was a long road to have the application that I wanted. To allow users to share their file securely without any server, but I’m really happy to have achieved it besides the network complexity and thanks to the projects that make using WebRTC each day easier.

You can check the project source code on the github repository flyersweb/sharetc and give me a tip so that I can buy me a coffee to work more on this 😊

FrontEnd Bootstrap

Hi,

I've just published my front-end developments setup on Github to let you guys play with it and make some tries.

The bootstrap comes with a Grunt script to generate outputs and is based on Typescript on the javascript side and Sass on the styling part. I also shipped the Angular framework and the Twitter bootstrap styling in it.

You can go directly to the project page if you do not want to get more details about why I chose this setup.

So, let me explain a little why I chose this setup and why this is my personal opinion of course…

First of all, on the javascript programming side I've chosen Typescript. It allows you to transform pure javascript programming through the superset and to declare strong typed variables. This last point is the most interesting, imagine that you have a thousand lines of code of pure javascript (the size of a real web application in production) that you've made 2 years ago and that you need to edit because of a hidden bug causing a BSoD in all main browsers… Having weak typed variables don't really allows you to ensure that they contains what they should contain and moreover you have to read all preceding source code to double check the expected variable type… Thanks to typescript you doesn't have this problem, you can explicitly declare your variables and simplify the source code maintenance. The other main superset used in the market is Coffeescript. Coffee script looks very good too, the only reason I haven't chosen this other option is for the syntax. I'm more used to Java/C# like programming but I think that Coffeescript will please all Ruby coders.

In order to speed up the coding process, I also like the Angular framework for his straight forward programmatic style. Integrating directly the view in the HTML DOM and the testing framework is a win to win brilliant concept. There is a LOT of others framework based on the MVC model but after using Backbone, Maria and Ember the easy and fast prototyping allowed with Angular conquered me.

On the Styling side, I used Sass as the superset of CSS. Why using a superset of CSS ? It allows you to define reusable blocks, variables and to define operations in different units. This is the main reasons I like to use Sass but the other most known CSS extension known as LESS is also a great alternative.
You can check both options and stick with the one you like the most. For me, it also was a syntax based decision.

I've also included the Twitter bootstrap package that help a lot to design web applications thanks to the predefined grid and components.

I'll let you clone, fork, try and test the bootstrap and I hope that it will please you as mush as myself :)

Have fun.

The Ultimate Flexbox Cheat Sheet

Flexbox is a brand, spankin' new CSS layout module with suprisingly good browser support! Say goodbye to float frustration and hello to a brave new world of easy vertical centering, re-ordering elements and dynamically growing and shrinking layouts.

http://www.sketchingwithcss.com/samplechapter/cheatsheet.html

Why MySQL ?

Hi,

I didn't get a lot of time lastely to post on the Blog. Got a lot of work and tried a lot of new stuff (yeah).

One of these new tool that I used is the MariaDB, the opensource fork of MySQL when Oracle bought it. So I made a try for a new project that we'll need to code.

MariaDB was so easy to install and I double checked MySQL compatibility and it looks like that they are almost the same, event the binaries used in MariaDB bundle use the same executables names !!!

The project is maintained by almost the same team that developed the base engine, this could be a mark of quality because they know the project really well. So I checked online and seen that some benchmarks show that MariaDB in a lot of cases works better than MySQL !!!

So I told myself, "Why still using MySQL maintained by a company that I don't have in my heart that shows lower performances and not go to an opensource project developed and maintained by the original team ?". And just one reason was making sense : habit. I was so used to use this database that I've never took the time to check others alternatives. Habits kills innovation, when you get used to a technology you should make a break and try new alternatives because sometimes we make choices without thinking and our customaries make all the work.

This is the lesson of the day then : have a try to new technologies and make your own mind about it before getting used to the easy choice of habits.

Have a nice week end and I hope that my advice will not be in vain :)

Google AppEngine Thoughts

Introduction


For sometimes now i've been working on Google AppEngine platform.

I've made different production back-ends and web services for professional applications. Thus i've been facing lot of problem resolution on AppEngine and after using the Google App Engine i want to share my experience on this particular platform.

First of all, I think Google make really great software and face lot of problem resolution before every one in the world. They've made an awesome map platform, mail platform, mobile platform and office software platform and others.

So it will be obvious that if they made such great applications, we, App Engine developers, would benefit such improvements in our development platform. That's why we oriented ourselves to this host media.

Data Store


Google App Engine offers an API in Java, Python and Go for developing applications. I mostly use the Python version.

The API offers lot of services from email sending to task queuing.

But like all Information System, we need a data store to save all needed data by our application. This is the datastore. Google use a proprietary datastore for storing those informations.

This database system is supposed to be optimized for cluster saving and data accessing who is particularly suited for cloud computing.

It is called Big Tables and is based on NoSQL specifications and so on it is not a relational database. So no many to many relations or on delete cascade.

Thankfully, it is possible to simulate such comportment using ReferenceProperty and/or Parent-child relationship.

Map Reduce algorithm


The BigTable database is based on the Map Reduce algorithm to order its internal data. This is certainly due to the usage of GFS for storing data.

MapReduce algorithm is very useful in distributed environment to speed up filtering and treatment of data. The drawback of this method is that it is really applicable only using background tasking.

Moreover, the MapReduce algorithm prevent performance introduced by common database system features such as B-trees and hash partitioning.

Like in Filesystems, MapReduce have proven his limitation and like it is said in this wired article that Google too has decided to migrate its infrastructures on another filesystem called Colossus.

So we should think that Google is going to apply those changes to the Google App Engine too soon or later. But for the moment, using BigTable lead sometimes to really bad performances for realtime data accessing on some applications.

That's why you should rely on the memcache API when you have such a scenario in some of your project... for the moment.

Alternatives


Other option can be to use another Cloud Computing based hoster. Like Amazon, Yahoo or a more opensource option like OpenShift.

Some of those systems use opensource technology. The one that I like are Apache Hadoop for filesystem or MongoDB for database. It offers good performances and scalability and it offers the necessary flexibility in development that is needed on a lot of projects.

H.264 Decoder in javascript

Une performance impressionnante de la part de Michael Bebenita qui a eu l'idée de convertir le code en C du décodeur vidéo H.264 de Android en Javascript. Bien sûr le script est encore en phase de test mais donne des résultats intéressant. En effet le script tourne aux alentours des 20 FPS sous la nightly build de Firefox. Malheureusement les résultats ne sont vraiment pas les mêmes sur les versions stables de Chrome ou Firefox. Le script s'appel Broadway et il est prévu d'utiliser WebGL pour tirer partie de la puissance du GPU.

Vous pouvez accéder à la démonstration à cette adresse : devongovett.github.com/Broadway.

New CSS 3 in 3D

Bonjour à tous,

Aujourd'hui nous allons nous intéresser à une nouvelle feature intégrée dans CSS 3. Il s'agit des transformations 3D qui ont été intégrées dans le moteur Web WebKit.

Cette nouvelle feature permet de simuler de la 3D ( ce n'est pas de la vrai 3D comme WebGL ) pour des rendus vraiment sympas.

Hakim El Hattab a réalisé une démonstration de cette feature destinée aux appareils mobiles. J'ai modifié cette démonstration pour qu'elle prenne en charge les navigateurs PC basés sur WebKit tels que Safari ou Google Chrome.

Alors comment cela fonctionne-t-il me demanderait vous ? Et bien c'est assez simple, dans un premier temps on réalise un cube à l'aide de la propriété CSS -webkit-transform de cette manière :
#back {
width: 600px;
height: 500px;
background: rgba(0,100,120,1);
text-align: center;
-webkit-transform: translateZ(-49px); // on place le fond à -49
}

#front {
width: 600px;
height: 500px;
background: url('../stripe.png') no-repeat bottom;
-webkit-transform: translateZ(50px); // on place le premier plan à 50
}

#wall-left {
height: 500px;
width: 100px;
left: 0px;

background: #bbb;
// le mur gauche est placé sur l'axe X puis tourné sur l'axe Y de 90 degrés
-webkit-transform: translateX(-50px) rotate3d(0, 50, 0, 90deg);
}

#wall-right {
height: 500px;
width: 100px;
right: 0px;
background: #bbb;
// on fait de même pour le mur droit en inversant l'angle de rotation
-webkit-transform: translateX(50px) rotate3d(0, 50, 0, -90deg);
}

#wall-top {
height: 100px;
width: 600px;
top: 0px;
background: #999;
-webkit-transform: translateY(-50px) rotate3d(50, 0, 0, 90deg);
}

#wall-bottom {
height: 100px;
width: 600px;
bottom: 0px;
background: #999;
-webkit-transform: translateY(50px) rotate3d(50, 0, 0, -90deg);
}


La propriété -webkit-transform permet de spécifier un ensemble de transformations sur les couleurs, la rotation, la taille mais aussi le placement de l'élément. Une fois que l'on a notre belle boîte en CSS 3, il faut faire en sorte que cette boîte se déforme par rapport aux mouvements de la souris.

Pour cela nous utilisons la propriété -webkit-perspective-origin qui nous permet de définir l'origine de l'effet de perspective définit par -webkit-perspective. Cette propriété nous permet de définir la profondeur de champs et le point de vu pour un effet de perspective. Celui-ci est calculé automatiquement par le moteur WebKit pour nous :D.

Nous calculons donc les coordonnées de l'origine du point de vu de la perspective et appliquons les modifications de coordonnées à l'aide d'une boucle de cette façon :
function onMouseMove( event ) {
perspective.tx = Math.round( ( event.clientX / window.innerWidth ) * 100 );
perspective.ty = Math.round( ( event.clientY / window.innerHeight ) * 100 );
};

function update() {
// Interpolate towards the target perspective
perspective.cx += ( perspective.tx - perspective.cx ) * 0.1;
perspective.cy += ( perspective.ty - perspective.cy ) * 0.1;

// Apply the current perspective
world.style.webkitPerspectiveOrigin = perspective.cx + '% ' + perspective.cy + '%';
world.style.perspectiveOrigin = perspective.cx + '% ' + perspective.cy + '%';

// Rinse, repeat
setTimeout( update, 1000 / 30 );
}

Et voilà notre cube 3D qui s'oriente en fonction de la souris fonctionne. Enfin presque, dans certains cas il faut penser à placer les murs au-dessus ou au-dessous des autres éléments à l'aide de la propriété z-index.

Pour les appareils mobiles (iPhone / iPad en l'occurence) la tâche est un peu plus complexe. Nous pouvons accéder au gyroscope  à l'aide de la propriété accelerationIncludingGravity ce qui permet de savoir comment est penché notre appareil. Puis il nous faut détecter l'orientation l'appareil (portrait ou paysage) ce qui se fait par le biais de la propriété window.orientation qui sera égale à 90 ou 0.

A l'aide de ces informations nous pouvons alors placer notre point d'origine d'effet de perspective ainsi :
function onMotionChange( event ) {
if ( orientation ) {
var beta = -event.accelerationIncludingGravity.z;
var gamma = -event.accelerationIncludingGravity.y;
}else {
var beta = -event.accelerationIncludingGravity.z;
var gamma = -event.accelerationIncludingGravity.x;
}

perspective.tx = ( ( gamma / 5 ) + 0.5 ) * 100;
perspective.ty = ( ( beta / 5 ) - 0.5 ) * 100;

event.preventDefault();
}


A noter l'utilisation de la fonction preventDefault() qui permets de surcharger la fonction de base de l'évènement. Ainsi vous pouvez modifier le comportement par default de l'évènement lors de la rotation de l'appareil.

C'est ainsi que se termine cet article sur cette fonctionnalité plutôt intéressante du CSS 3. WebKit a également une page dédiée aux transformations 3D.

Compression Gzip

Bonjour, bonjour,

Ca fait un petit moment que j'ai pas eu le temps de poster sur mon blog, j'ai donc décidé de me racheter

Introduction

Courant Mars, Google a mis en production une nouvelle version de son site comme vous avez été nombreux à le voir. Ce changement inclus également une modification de l'algorithme d'indexation de Google. En effet, l'algorithme appelé MayDay a été mis en place suivi, plus récemment, par l'algorithme Caffeine.

Ces modifications de l'indexation ont eu des effets sur le référencement de nombreux sites car Google a modifié ses critères de classement. De nouveaux critères entres maintenant en jeu. Parmi ceux-là il y a maintenant la vitesse de réponse du serveur.

Nous allons voir aujourd'hui comment améliorer ce critère à l'aide d'un technique de compression à la volée.

Module Gzip/Deflate

La compression des données à la volée permet de diminuer la taille des données transférées entre votre navigateur et le serveur. En effet, grâce à cette technique, votre navigateur reçoit les données HTML compressée par Gzip et les décompresse pour les afficher.

Cette technique peut vous premettre de gagner jusqu'à 8 secondes de temps de réponse. Le seul bémol de cette technique est qu'elle nécessite un serveur d'assez bonne qualité puisque le processeur est plus utilisé.

Pour activer Gzip, rien de plus simple installez mod_deflate pour Apache 2.x et mod_gzip pour Apache 1.x.

Activez ensuite le module dans votre httpd.conf : LoadModule deflate_module modules/mod_deflate.so

Et ajoutez la règle suivante dans le : AddOutputFilterByType DEFLATE text/html. Ce qui compressera les fichiers HTML.

Vous pouvez également ajouter des règles pour d'autres types de fichiers comme les MP3 ou PDF mais sachez qu'il peut y avoir des incompatibilités avec ces formats.

PHP Zlib

Vous pouvez également activer ce module grâce à PHP. Vous aurez besoin avant tout que l'extension Zlib de PHP soit installée.

Ajoutez le code suivant en tout début de page : ob_start("ob_gzhandler");

Le handler ob_gzhandler est un alias facilitant l'activation de la compression gzip. L'inconvénient de cette technique est le même que précédemment, cela aura pour effet d'utiliser plus le processeur de votre serveur.

Autre optimisation

Vous pouvez également forcer le taux de rafraîchissement du cache de vos visiteurs grâce à l'entête Expires. Ainsi vos visiteurs ne chargeront vos images que lors de leur première visite. Le point négatif de ce dispositif est que le client doit vider son cache pour que son navigateur prenne en compte les modifications que vous avez apportées.

L'entête Expires prend comme argument une date d'expiration. Si la date est antérieure à la date courante, le cache sera mis à jour. Attention, les dates supérieures à un an par rapport à la date courante ne sont pas conseillées.

En Php pour utiliser l'entête Expires, rien de plus simple, vous utilisez la fonction header : header("Expires: ".gmdate('D, d M Y H:i:s', time()+(60*60*24).' GMT'); .

Nous définissons donc une date d'expiration de 60 secondes * 60 minutes * 24 heures soit 1 journée. Ainsi durant une journée vos visiteurs ne mettrons pas à jour leur cache.

Conclusion

Il existe de nombreuses techniques d'optimisation du temps de réponse de votre serveur web. On peut citer l'optimisation des fichiers CSS et JavaScript mais aussi l'optimisation de vos requêtes SQL.

De nombreux développeur oublient de prendre ce paramètre en compte lors du développement d'un site internet or ces optimisations deviennent de plus en plus indispensables aux vues des exigences des moteurs de recherche actuels.

Voilà, voilà, sur ce je vous souhaite une très bonne soirée.

A+, Flyers.

Réalisation du site Pharma Equipment



Participation dans le cadre d'un projet tutoré à la réalisation du site de l'entreprise Pharma Equipment, achat/vente de machines pharmaceutiques.

Webdesign cr3e



Dans le cadre d'un projet de cours, nous devions refaire le webdesign du site www.cr3e.com en reprenant les éléments graphiques de l'écologie et de la construction.

Webdesign du site Burning Man




Dans le cadre d'un projet d'étude, j'ai réalisé le design du site Burning Man sur le thème "Metropolis"

Most seen