diff --git a/example/example.html b/example/example.html
new file mode 100644
index 0000000..71d3a2b
--- /dev/null
+++ b/example/example.html
@@ -0,0 +1,28 @@
+
+
+
+
+
+ Wormhole test
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/example/example.js b/example/example.js
new file mode 100644
index 0000000..bf83724
--- /dev/null
+++ b/example/example.js
@@ -0,0 +1,3 @@
+const Wormhole = require('../index');
+
+const wormhole = new Wormhole({ urls: [ '/hello' ] });
\ No newline at end of file
diff --git a/index.js b/index.js
index e69de29..c843d41 100644
--- a/index.js
+++ b/index.js
@@ -0,0 +1,58 @@
+const http = require('http');
+
+const { createLog } = require('./lib/logger');
+const handshake = require('./lib/handshake');
+const constants = require('./lib/constants');
+const Socket = require('./lib/Socket');
+
+const handshakeLog = createLog([ 'Wormhole', 'Handshake' ]);
+
+class Wormhole {
+ constructor({ urls=[ '/bruh' ], port=8080 }) {
+ this._urls = urls;
+ this._port = port;
+
+ this._httpServer = http.createServer((req, res) => {
+ if (req.method === 'GET' && req.url && this._urls.includes(req.url)) {
+ handshakeLog(`Got connection request to ${req.url} on port ${this._port}`);
+
+ const failConnection = (status=400) => {
+ res.writeHead(status);
+ res.end();
+
+ console.trace();
+ };
+
+ const websocketKey = req.headers['sec-websocket-key'];
+ const upgradeHeader = req.headers['upgrade'];
+ const websocketVersion = req.headers['sec-websocket-version'];
+
+ if (upgradeHeader !== constants.upgradeHeaderRequirement) return failConnection();
+ if (websocketVersion !== constants.websocketVersionRequirement) return failConnection();
+
+ const websocketAccept = handshake.generateWebsocketAcceptValue(websocketKey);
+
+ handshakeLog(websocketKey, websocketAccept);
+
+ if (websocketAccept) {
+ res.writeHead(101, {
+ 'Upgrade': 'websocket',
+ 'Connection': 'Upgrade',
+ 'Sec-WebSocket-Accept': websocketAccept
+ });
+ res.end();
+
+ const socket = new Socket({ socket: res.socket, initalState: 'CONNECTED' });
+
+ return true;
+ }
+
+ return failConnection();
+ }
+ });
+
+ this._httpServer.listen(port);
+ }
+}
+
+module.exports = Wormhole;
\ No newline at end of file
diff --git a/lib/Socket.js b/lib/Socket.js
new file mode 100644
index 0000000..4e248a3
--- /dev/null
+++ b/lib/Socket.js
@@ -0,0 +1,12 @@
+class Socket {
+ constructor({ initialState='CONNECTING', socket }) {
+ this._state = initialState;
+ this._socket = socket;
+
+ this._socket.on('data', (e) => {
+ console.log(e.toString());
+ });
+ }
+}
+
+module.exports = Socket;
\ No newline at end of file
diff --git a/lib/constants.js b/lib/constants.js
new file mode 100644
index 0000000..1830419
--- /dev/null
+++ b/lib/constants.js
@@ -0,0 +1,5 @@
+module.exports = {
+ handshakeGUID: '258EAFA5-E914-47DA-95CA-C5AB0DC85B11',
+ upgradeHeaderRequirement: 'websocket',
+ websocketVersionRequirement: '13'
+}
\ No newline at end of file
diff --git a/lib/handshake.js b/lib/handshake.js
new file mode 100644
index 0000000..f6abb61
--- /dev/null
+++ b/lib/handshake.js
@@ -0,0 +1,17 @@
+const crypto = require('crypto');
+
+const { handshakeGUID } = require('./constants');
+
+const generateWebsocketAcceptValue = (websocketKey) => {
+ if (typeof websocketKey !== 'string' || typeof handshakeGUID !== 'string') {
+ // TODO: maybe throw error?
+ return;
+ }
+
+ const concatenated = websocketKey + handshakeGUID;
+ const sha1HashedInBase64 = crypto.createHash('sha1').update(concatenated, 'binary').digest('base64');
+
+ return sha1HashedInBase64;
+};
+
+module.exports = { generateWebsocketAcceptValue };
\ No newline at end of file
diff --git a/lib/logger.js b/lib/logger.js
new file mode 100644
index 0000000..9dad21c
--- /dev/null
+++ b/lib/logger.js
@@ -0,0 +1,16 @@
+const logDebug = true;
+
+module.exports = {
+ createLog: (components) => (...args) => {
+ let compString = '';
+ for (const i in components) {
+ const component = components[i];
+ if (i >= (components.length - 1)) {
+ compString += `[${component}]`;
+ } else {
+ compString += `[${component}] `;
+ }
+ }
+ logDebug && console.log(compString, ...args);
+ }
+};
\ No newline at end of file