DEV Community

Cover image for How One Developer Recreated AirDrop Using Just JavaScript
Abdisalan
Abdisalan

Posted on

How One Developer Recreated AirDrop Using Just JavaScript

Have you ever used AirDrop on iPhone or Mac?

Okay, If you haven't then can you imagine seamlessly sharing files between phones or a laptop at the tap of a button?

SnapDrop.net, created by Robin Linus, lets you directly share files between any device with a browser. Doesn't matter if it's between iPhone and Android or a tablet with a PC.

And no uploading to and downloading from the cloud needed. 😲

So how the heck does it work?

After analyzing it line by line, I figured out its brilliant architecture. In this post I'll show you how it works.

Use This New Technology

Knowing this technology could set you apart from other engineers who haven't yet explored what it has to offer.

This awesome technology is WebRTC (Web Real-Time Communication) and it only came out a few years ago. Its data channel enables SnapDrop to send bytes (even audio and video!) directly from one peer to another.

(Think of a peer as a device, like your phone or laptop)

However, WebRTC can't connect two users without some help. It needs a signaling server, in other words, something to discover other peers and show it how to connect.

WebRTC is Impossible To Use Without This

Diagram of Architecture. NodeJS Server connected to a phone and computer over websockets. Phone and computer are connected with WebRTC

ICE (Interactive Connectivity Establishment) is how a computer can draw a map from the internet to itself when it doesn't have a public IP address. This is due to NAT (Network Address Translation) that happens between your router and computer.

Once the map has been made, you'll have find some way for these two devices to share their maps with each other. SnapDrop does this through a NodeJS server that communicates between each peer using WebSockets — another awesome protocol.

Now you're probably thinking, is this secure?

Okay, But How Do You Secure This Thing?

WebRTC in transit encrypts its data by default. That's cool and all but you also probably don't want to be sharing files with random people.

SnapDrop only shares the ICE between two computers with the same IP address — meaning they're on the same network/wifi.

It does this by creating rooms for each IP address and differentiates devices by generating a unique id.

/* Code to handle joining peers from the server */
_joinRoom(peer) {
    // if room doesn't exist, create it
    if (!this._rooms[peer.ip]) {
      this._rooms[peer.ip] = {};
    }

    // add this peer to room
    this._rooms[peer.ip][peer.id] = peer;
}
Enter fullscreen mode Exit fullscreen mode

You might not want to use this app while on public wifi since then anyone could send files to you. But in this pandemic, who's going outside anyway? 🤷‍♀️

The code snippet above makes an interesting choice by storing the peers in an object on the server class. Normally you would expect a database to be used but this might be to simplify things and the app probably doesn't have a lot of traffic.

A Familiar User Interface and User Experience

SnapDrop Site with icons for 2 computers and a phone

The style is almost exactly like AirDrop. Each device has a fun name and an icon to help distinguish each peer. Not only that but its also a progressive web app which gives it a few nice features like:

  • Feels like a native app
  • Notifications
  • Live Updates

What If The Device Doesn't Support WebRTC?

By now most devices/browsers support WebRTC but in the event that they don't, SnapDrop has a fallback! In this case it uses the already established WebSocket connection to send the file data.

However, this is less efficient and less secure because the data needs to first go to the server and before it reaches its final destination.

if (window.isRtcSupported && peer.rtcSupported) {
    this.peers[peer.id] = new RTCPeer(this._server, peer.id);
} else {
    this.peers[peer.id] = new WSPeer(this._server, peer.id);
}
Enter fullscreen mode Exit fullscreen mode

Event-Driven Code Style

The code base is completely event-driven. You use this style when you want to decouple services from each other and allow processing as actions occur.

This compliments WebRTC and WebSockets because they're also event-driven. When a message comes in, or a new peer joins, or a file wants to be sent — that's an event.

It's really tough to follow at first because its not a linear process. Here's the class for registering and firing events.

class Events {
    static fire(type, detail) {
        window.dispatchEvent(new CustomEvent(type, { detail: detail }));
    }
    static on(type, callback) {
        return window.addEventListener(type, callback, false);
    }
}
Enter fullscreen mode Exit fullscreen mode

Which lets you write event-driven code like this

Events.on('signal', e => this._onMessage(e.detail));
Events.on('peers', e => this._onPeers(e.detail));
Events.on('files-selected', e => this._onFilesSelected(e.detail));
Events.on('send-text', e => this._onSendText(e.detail));
Events.on('peer-left', e => this._onPeerLeft(e.detail));
Enter fullscreen mode Exit fullscreen mode

Check Out The Code Yourself

I hope you learned something today! If you want to explore the code for yourself, here's the github repository. https://github.com/RobinLinus/snapdrop

The creator was also kind enough to create a docker compose file so that you could run and host this yourself. I wonder how many people are running their own SnapDrop instance?

Thanks for Reading!

What do you think of this type of blog post? I feel like I had to write about it because this project taught me a few valuable lessons. Leave comment below and I'll get back to everyone!

See you in the next one ✌

P.S. Support SnapDrop

Wow! Didn’t think this would be so popular! 10,000+ of you have seen this article!

Please consider supporting the project because it is free and has NO ADs and NO data collection.

Link here: https://github.com/RobinLinus/snapdrop#support-the-snapdrop-community

Discussion (54)

Collapse
braydentw profile image
Brayden W ⚡️

Wow, this is so cool! I use my iPhone and Windows laptop a lot so this is a super efficient solution. 👍

Collapse
abdisalan_js profile image
Abdisalan Author

Same! Its so useful for sharing photos 🤩

Collapse
barca00 profile image
barca00

Very interesting post. I always wondered how does airdrop work and this post sums in short all the answers.

Collapse
abdisalan_js profile image
Abdisalan Author

AirDrop uses a proprietary HTTP based protocol over WiFi! Kinda similar but different from WebRTC. SnapDrop was just clever enough to use WebRTC for the same effect.

Collapse
crimsonmed profile image
Médéric Burlet

Thanks a lot for the interesting topic! Loved reading through it.
I had two questions:

Doesn't airdrop use Bluetooth and Wi-Fi instead of webrtc?

Did you inspire yourself from send-anywhere.com/ as this is a korean startup that uses webrtc to transfer files from device to device directly. I figure this is closer to what you built than airdrop.

Collapse
abdisalan_js profile image
Abdisalan Author

Interesting I’ve never heard of them but that’s a cool product!

Collapse
ur5us profile image
Juri Hahn

Not to complain about the software but as Joseph Buchma pointed out there’s sharedrop.io/ which is also open source github.com/cowbell/sharedrop and much older, started about 6 years ago.

Collapse
abdisalan_js profile image
Abdisalan Author

So what? No one is allowed to do this once it’s been done once? This project is also open source

Collapse
ur5us profile image
Juri Hahn

Relax dude! If we put your title in context, especially the part “How One Developer […]” it just sounds dishonest due to lack of giving credit where credit’s due.

Thread Thread
abdisalan_js profile image
Abdisalan Author

Apologies that my words came off that way! I’m merely challenging your complaint that someone already made a similar project before. 😊

Thread Thread
ur5us profile image
Juri Hahn

Hence why I started with “Not to complain about the software […]”. I just found your title presumptuous given an older implementation also written in JavaScript exists, albeit using EmberJS. Both repos also have multiple committers as opposed to one. I just challenged one particular aspect of your otherwise interesting post because I felt that it didn’t need to be this way. For me personally, it somewhat detracts from the otherwise good content because I’ve known about and used ShareDrop for a long time.

Thread Thread
abdisalan_js profile image
Abdisalan Author

Thanks for taking the time to give constructive feedback!

Collapse
chaycek profile image
challey17

super interesting, great article!

Collapse
abdisalan_js profile image
Abdisalan Author

Thank you! 🤩

Collapse
shostarsson profile image
Rémi Lavedrine

That's a great discovery.

I love Airdrop. Nevertheless as a Linux user myself, I often face limitations to it. :-)
I am using shredrop.io to replace airdrop but I am going to give snapdrop a try.
WebRTC is a great peace of technology so it's nice to know that snapdrop relies on it.

Thanks again for sharing it and explaining it.
Great job.

Collapse
vaibhavkhulbe profile image
Vaibhav Khulbe

That's amazing! I will surely use it 💯

Collapse
abdisalan_js profile image
Abdisalan Author

It’s been a critical part of my workflow for the last week, Happy to share this awesome tool!

Collapse
yum profile image
Antariksh Verma

JavaScript and Material Design have just outdone themselves! Congrats on this app!

Collapse
abdisalan_js profile image
Abdisalan Author

They really have! I didn’t make the app though just to be clear 😅 I figured out the architecture and wanted to share that

Collapse
micahlt profile image
Micah Lindley

I've been an avid Snapdrop fan for about three years now, and I've never been happier. It's fast, simple, and works on any device. Great article!

Collapse
abdisalan_js profile image
Abdisalan Author

Thanks! Loving it too! I just discovered it one week ago 😄

Collapse
gadrawingz profile image
Gad Iradufasha

Awesomely terrible!

Collapse
boxpiperapp profile image
BOX PIPER

Great work man!

Collapse
abdisalan_js profile image
Abdisalan Author

Thank you! 🙏🏾

Collapse
ben profile image
Ben Halpern

🤯

Collapse
dario_wd_coding profile image
Dario Presutti

Very very intersting thanks to share!

Collapse
sefrem profile image
sefrem

With Telegram you could also transfer files between different platforms and if you are already using at as messenger you dont' need to install any additional apps.

Collapse
marlonanthony profile image
Marlon Decosta

Super cool! Thanks for writing this up. I'm def checking this out later.

Collapse
gerardocrdena14 profile image
Gerardo Cárdenas

This technology opens a world of many solutions... as the one written by Brayden W.
I really motivated with this technology.

Collapse
josephbuchma profile image
Joseph Buchma

Good work!
What are main differences compared to sharedrop.io/ ?

Collapse
jonrandy profile image
Jon Randy

This app is 5 years old. Interesting it suddenly appears here

Collapse
abdisalan_js profile image
Abdisalan Author

Yup! I found it a week ago when I wanted to airdrop my stuff from my iPhone to windows PC. It felt like magic so I had to figure out how it worked and share it 😊

Collapse
phongduong profile image
Phong Duong

Great. Thank you

Collapse
gotheer profile image
gotheer

Thanks for writing this post.
Webrtc is not the only technology which can offer same fonctionalities on the browser.

Collapse
abdisalan_js profile image
Abdisalan Author

Thanks! What other protocol offers peer to peer file sharing?

Collapse
gotheer profile image
gotheer

Maybe this link can help:
w3c.github.io/webrtc-quic/

Collapse
eissorcercode99 profile image
The EisSorcer

Omg Thank you for this brilliance! Well explained

Collapse
abdisalan_js profile image
Abdisalan Author

Thanks! 😁 Just sharing what I found interesting

Collapse
mdirshaddev profile image
Md Irshad Dev

SO cool bro

Collapse
andrewbaisden profile image
Andrew Baisden

Good read thanks for posting.

Collapse
ronaldohoch profile image
Ronaldo Hoch

Awesome!

Collapse
codemonkey51 profile image
Codemonkey51

Thanks for the overview of this project!

Collapse
ganes1410 profile image
Ganesh R

Awesome use of WerbRTC. Great work 👍

Collapse
abdisalan_js profile image
Abdisalan Author

Just to be clear, I didn't make this 😅 I just thought it was super cool and wanted to know how it worked, then it became a blog post haha

Collapse
moopet profile image
Ben Sinclair

That's... actually pretty cool.

Collapse
abdisalan_js profile image
Abdisalan Author

🔥🔥🔥 Yup 🔥🔥🔥

Collapse
mikaoelitiana profile image
Mika Andrianarijaona

Great job !!

Collapse
abdisalan_js profile image
Abdisalan Author

Thank you!! 🙏🏾

Collapse
hassam7 profile image
Hassam Ali

Is it possible to use this on local network which is not connected to internet?

Collapse
abdisalan_js profile image
Abdisalan Author

Theoretically yes! I think you can go offline after the devices share their ice. I haven’t tested this though😅
You could also figure out a way to share the ice while offline, maybe copy from one computer and paste to the other?

Collapse
wassimbj profile image
Wassim Ben Jdida

why doesnt it use websocket directly ? great article btw

Collapse
abdisalan_js profile image
Abdisalan Author

Thanks! Web sockets are slower and have to send the data to the server so it’s costs more bandwidth.