Use a local PeerJS server.

pull/1/head
Alex Kern 11 years ago
parent 22ecf9cb12
commit 3da3b2d443

@ -3,9 +3,7 @@ import alt from '../alt';
export default alt.createActions(class DownloadActions { export default alt.createActions(class DownloadActions {
constructor() { constructor() {
this.generateActions( this.generateActions(
'beginDownload',
'requestDownload', 'requestDownload',
'cancelDownlaod',
'setDownloadInfo' 'setDownloadInfo'
) )
} }

@ -3,7 +3,7 @@ import alt from '../alt';
export default alt.createActions(class PeerActions { export default alt.createActions(class PeerActions {
constructor() { constructor() {
this.generateActions( this.generateActions(
'setPeerID' 'peerConnected'
) )
} }
}) })

@ -53,19 +53,15 @@ export default class App extends React.Component {
render() { render() {
if (this.state.readyToUpload) { if (this.state.readyToUpload) {
return ( return <div>
<div> <FileDescription file={this.state.uploadFile} />
<FileDescription file={this.state.uploadFile} /> <Tempalink token={this.state.uploadToken} />
<Tempalink token={this.state.uploadToken} /> </div>;
</div>
);
} else if (this.state.readyToDownload) { } else if (this.state.readyToDownload) {
return ( return <div>
<div> <FileDescription file={this.state.downloadFile} />
<FileDescription file={this.state.downloadFile} /> <button onClick={this.downloadFile.bind(this)}>Download</button>
<button onClick={this.downloadFile.bind(this)}>Download</button> </div>;
</div>
);
} else { } else {
return <DropZone onDrop={this.uploadFile.bind(this)} />; return <DropZone onDrop={this.uploadFile.bind(this)} />;
} }

@ -14,13 +14,11 @@ export default class DropZone extends React.Component {
} }
render() { render() {
return ( return <div className="drop-zone"
<div className="drop-zone" onDragOver={this.dragOver.bind(this)}
onDragOver={this.dragOver.bind(this)} onDrop={this.drop.bind(this)}>
onDrop={this.drop.bind(this)}> Drop a file here.
Drop a file here. </div>;
</div>
);
} }
} }

@ -3,13 +3,11 @@ import React from 'react';
export default class FileDescription extends React.Component { export default class FileDescription extends React.Component {
render() { render() {
return ( return <div className="file-description">
<div className="file-description"> <span className="file-name">{this.props.file.name}</span>
<span className="file-name">{this.props.file.name}</span> <span className="file-size">{this.props.file.size}</span>
<span className="file-size">{this.props.file.size}</span> <span className="file-type">{this.props.file.type}</span>
<span className="file-type">{this.props.file.type}</span> </div>;
</div>
);
} }
} }

@ -4,9 +4,7 @@ export default class Tempalink extends React.Component {
render() { render() {
var url = window.location.origin + '/d/' + this.props.token; var url = window.location.origin + '/d/' + this.props.token;
return ( return <a href={url} className="tempalink">{url}</a>;
<a href={url} className="tempalink">{url}</a>
);
} }
} }

@ -1,13 +0,0 @@
import DownloadActions from './actions/DownloadActions';
import Peer from 'peerjs';
import PeerActions from './actions/PeerActions';
var peer = module.exports = new Peer({ key: '8w3x9m637e0o1or' });
peer.on('open', function () {
PeerActions.setPeerID(peer.id);
});
peer.on('connection', function (conn) {
DownloadActions.beginDownload(conn);
});

@ -25,21 +25,17 @@ export default alt.createStore(class DownloadStore {
this.bindActions(DownloadActions); this.bindActions(DownloadActions);
this.bindActions(PeerActions); this.bindActions(PeerActions);
this.conn = null;
this.token = null; this.token = null;
this.file = null; this.file = null;
this.status = new DownloadStatus(); this.status = new DownloadStatus();
} }
onSetPeerID() {
this.waitFor(PeerStore.dispatchToken);
if (this.status.isOffline() && this.token) this.status.set('ready');
}
onSetDownloadInfo(info) { onSetDownloadInfo(info) {
if (!this.status.isOffline()) return;
this.status.set('ready');
this.token = info.token; this.token = info.token;
this.file = new DownloadFile(info.name, info.size, info.type); this.file = new DownloadFile(info.name, info.size, info.type);
if (this.status.isOffline() && PeerStore.getPeerID()) this.status.set('ready');
} }
onRequestDownload() { onRequestDownload() {
@ -52,11 +48,10 @@ export default alt.createStore(class DownloadStore {
}); });
} }
onBeginDownload(conn) { onPeerConnected(conn) {
if (!this.status.isRequesting()) return; if (!this.status.isRequesting()) return;
this.status.set('downloading'); this.status.set('downloading');
this.conn = conn;
let chunkSize = conn.metadata.chunkSize; let chunkSize = conn.metadata.chunkSize;
let i = 0; let i = 0;
@ -78,20 +73,9 @@ export default alt.createStore(class DownloadStore {
conn.on('close', () => { conn.on('close', () => {
if (!this.status.isDownloading()) return; if (!this.status.isDownloading()) return;
this._cancel(); this.status.set('cancelled');
this.file.clearPackets();
}); });
} }
onCancelDownload() {
if (!this.status.isRequesting() && !this.status.isDownloading()) return;
this._cancel();
}
_cancel() {
this.status.set('cancelled');
if (this.conn) this.conn.close();
this.conn = null;
this.file.clearPackets();
}
}) })

@ -1,19 +1,30 @@
import Peer from 'peerjs';
import PeerActions from '../actions/PeerActions'; import PeerActions from '../actions/PeerActions';
import alt from '../alt'; import alt from '../alt';
import uuid from 'node-uuid';
export default alt.createStore(class PeerStore { let id = uuid.v4();
let peer = new Peer(id, {
host: window.location.hostname,
port: window.location.port,
path: '/peer'
});
constructor() { peer.on('connection', (conn) => {
this.bindActions(PeerActions); PeerActions.peerConnected(conn);
this.peerID = null; });
}
export default alt.createStore(class PeerStore {
onSetPeerID(id) { static connect(peerID, metadata) {
this.peerID = id; return peer.connect(peerID, {
reliable: true,
metadata: metadata
});
} }
static getPeerID() { static getPeerID() {
return this.getState().peerID; return id;
} }
}) })

@ -1,10 +1,8 @@
import PeerActions from '../actions/PeerActions';
import PeerStore from './PeerStore'; import PeerStore from './PeerStore';
import Status from '../Status'; import Status from '../Status';
import UploadActions from '../actions/UploadActions'; import UploadActions from '../actions/UploadActions';
import UploadFile from '../UploadFile'; import UploadFile from '../UploadFile';
import alt from '../alt'; import alt from '../alt';
import peer from '../peer';
import socket from '../socket'; import socket from '../socket';
const chunkSize = 32; const chunkSize = 32;
@ -12,7 +10,6 @@ const chunkSize = 32;
class UploadStatus extends Status { class UploadStatus extends Status {
constructor() { constructor() {
super([ super([
'offline',
'ready', 'ready',
'processing', 'processing',
'uploading' 'uploading'
@ -23,17 +20,12 @@ class UploadStatus extends Status {
export default alt.createStore(class UploadStore { export default alt.createStore(class UploadStore {
constructor() { constructor() {
this.bindActions(PeerActions);
this.bindActions(UploadActions); this.bindActions(UploadActions);
this.status = new UploadStatus();
this.token = null; this.token = null;
this.file = null; this.file = null;
this.status = new UploadStatus(); this.downloaders = [];
}
onSetPeerID(id) {
this.waitFor(PeerStore.dispatchToken);
if (this.status.isOffline()) this.status.set('ready');
} }
onUploadFile(file) { onUploadFile(file) {
@ -54,33 +46,26 @@ export default alt.createStore(class UploadStore {
onSendToDownloader(peerID) { onSendToDownloader(peerID) {
if (!this.status.isUploading()) return; if (!this.status.isUploading()) return;
this.downloaders.push(peerID); // TODO
let file = this.file; let conn = PeerStore.connect(peerID, {
let conn = peer.connect(peerID, { chunkSize: chunkSize
reliable: true,
metadata: { chunkSize: chunkSize }
}); });
conn.on('open', function () { let totalPackets = this.file.countPackets();
let i = 0;
let packets = file.countPackets();
let packet = 0;
function sendNextChunk() { let sendNextChunk = () => {
for (let i = 0; i < chunkSize; i++) { for (let j = 0; i < totalPackets && j < chunkSize; i++, j++) {
if (packet >= packets) break; let packet = this.file.getPacket(i);
let b = file.getPacket(packet); conn.send(packet);
conn.send(b);
packet++;
}
} }
}
conn.on('data', function (data) { conn.on('open', () => { sendNextChunk(); });
if (data === 'more') sendNextChunk();
});
sendNextChunk();
conn.on('data', (data) => {
if (data === 'more') sendNextChunk();
}); });
} }

@ -5,8 +5,8 @@
"main": "server/index.js", "main": "server/index.js",
"scripts": { "scripts": {
"start": "node server/index.js", "start": "node server/index.js",
"build": "./node_modules/.bin/browserify -d -o static/app.js -t babelify -t reactify client/index.js", "build": "./node_modules/.bin/browserify -d -o static/app.js -t babelify client/index.js",
"watch": "./node_modules/.bin/watchify -d -o static/app.js -t babelify -t reactify client/index.js" "watch": "./node_modules/.bin/watchify -d -o static/app.js -t babelify client/index.js"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -19,18 +19,19 @@
}, },
"homepage": "https://github.com/kern/webdrop", "homepage": "https://github.com/kern/webdrop",
"dependencies": { "dependencies": {
"alt": "^0.14.4",
"bases": "^0.2.1", "bases": "^0.2.1",
"ejs": "^2.3.1", "ejs": "^2.3.1",
"express": "^4.12.0", "express": "^4.12.0",
"peerjs": "^0.3.14", "peer": "^0.2.8",
"socket.io": "^1.3.5" "socket.io": "^1.3.5"
}, },
"devDependencies": { "devDependencies": {
"alt": "^0.14.4",
"babelify": "^5.0.4", "babelify": "^5.0.4",
"node-uuid": "^1.4.3",
"peerjs": "^0.3.14",
"browserify": "^9.0.3", "browserify": "^9.0.3",
"react": "^0.13.0", "react": "^0.13.0",
"reactify": "^1.1.0",
"socket.io-client": "^1.3.5", "socket.io-client": "^1.3.5",
"watchify": "^2.4.0" "watchify": "^2.4.0"
}, },

@ -2,6 +2,7 @@ var Upload = require('./Upload');
var express = require('express'); var express = require('express');
var http = require('http'); var http = require('http');
var path = require('path'); var path = require('path');
var peer = require('peer');
var routes = require('./routes'); var routes = require('./routes');
var socketIO = require('socket.io'); var socketIO = require('socket.io');
@ -17,7 +18,9 @@ server.listen(process.env.PORT || 3000, function () {
app.set('view engine', 'ejs'); app.set('view engine', 'ejs');
app.set('views', path.resolve(__dirname, '../views')); app.set('views', path.resolve(__dirname, '../views'));
app.use(routes); app.use(routes);
app.use('/peer', peer.ExpressPeerServer(server));
io.on('connection', function (socket) { io.on('connection', function (socket) {

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save