Skip to content

Commit eceb772

Browse files
authored
Merge pull request #98 from JoyStream/development
dev to master - release v0.1.0
2 parents 01bdb02 + d213c44 commit eceb772

43 files changed

Lines changed: 5067 additions & 1422 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.travis.yml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1-
language: node_js
21
dist: trusty
2+
sudo: false
3+
language: node_js
34
node_js:
4-
- "node"
5+
- "7"
6+
os:
7+
- osx
8+
- linux
59
addons:
610
apt:
711
sources:
@@ -10,6 +14,5 @@ addons:
1014
- cmake
1115
- cmake-data
1216
before_install:
13-
- "pip install --user conan"
14-
- "conan remote add joystream https://conan.joystream.co:9300 True"
15-
- "conan user travis -p trav444 -r=joystream"
17+
- if [ "$TRAVIS_OS_NAME" = osx ]; then pip install conan; else pip install --user conan; fi
18+
- "conan remote add joystream https://api.bintray.com/conan/joystream/joystream True"

CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
cmake_minimum_required(VERSION 2.8)
1+
cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
22

33
project (JoyStreamAddon)
44

@@ -19,3 +19,8 @@ file(GLOB_RECURSE JOYSTREAM_SOURCE_FILES "src/*.cpp")
1919
add_library(JoyStreamAddon SHARED ${JOYSTREAM_SOURCE_FILES})
2020
set_target_properties(JoyStreamAddon PROPERTIES PREFIX "" SUFFIX ".node")
2121
target_link_libraries(JoyStreamAddon ${CONAN_LIBS} ${CMAKE_JS_LIB})
22+
23+
IF(MSVC)
24+
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
25+
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
26+
ENDIF(MSVC)

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2015-2017 JoyStream AS
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.

README.md

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,46 @@
1-
# Joystream Node
1+
# JoyStream Node
22

3-
Repository containing the joystream bindings and the javascript wrapper library
3+
[![npm package](https://nodei.co/npm/joystream-node.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/joystream-node/)
44

5-
## Getting Started:
5+
`joystream-node` is the core javascript library for the JoyStream payment protocol over BitTorrent.
66

7-
Clone repo :
87
```
9-
$ git clone https://github.com/JoyStream/joystream-node
8+
conan remote add joystream https://api.bintray.com/conan/joystream/joystream True
9+
10+
npm install joystream-node
1011
```
1112

12-
Install dependencies and build node module:
13+
## Dependencies
14+
The module is a nodejs native c++ addon and needs to be compiled from source. The build tools required are:
15+
16+
- [git](https://git-scm.com/)
17+
- [node-js](https://nodejs.org)
18+
- [node-gyp](https://github.com/nodejs/node-gyp)
19+
- CMake (minimum version 3.1 for support of CMAKE_CXX_STANDARD variable)
20+
- python2 + pip
21+
- [Conan](https://www.conan.io/downloads) C/C++ package manager
22+
23+
Follow [instruction in node-gyp readme](https://github.com/nodejs/node-gyp) for setting up a compiler toolchain for your platform.
24+
25+
The module depends on multiple c++ packages which will be fetched and built using conan.
26+
27+
After installing conan add the JoyStream conan repository:
1328
```
14-
$ npm install
29+
conan remote add joystream https://api.bintray.com/conan/joystream/joystream True
1530
```
1631

17-
## To build module for a specific runtime use node-gyp
32+
If building on windows install npm v4.6.1 (build fails with newer versions of npm)
33+
```
34+
npm install -g npm@4.6.1
35+
```
1836

19-
building for electron for example:
2037

38+
Installing joystream-node:
2139
```
22-
$ node-gyp rebuild --target=1.6.2 --arch=x64 --dist-url=https://atom.io/download/electron
40+
npm install joystream-node
2341
```
42+
43+
## License
44+
45+
JoyStream node library is released under the terms of the MIT license.
46+
See [LICENSE](LICENCE) for more information.

build.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,21 @@ function getRuntimeAndVersion() {
6060
function conanInstall(options) {
6161
console.log('conan install with options:', options)
6262

63+
// node-gyp sets MAKEFLAGS env var that looks like: "r -- BUILDTYPE=Release"
64+
// -r make flags is causing build issue for openssl and zlib on OSX
65+
// BUILDTYPE=Debug/Release is redundant (it is set in BUILDTYPE env var)
66+
// so just clearing the flag here
67+
process.env.MAKEFLAGS=''
68+
6369
var args = ['install', '.', '--build=missing']
6470
args.push("-oruntime=" + options.runtime)
6571
args.push("-oruntime_version=" + options.runtime_version)
6672

73+
if (process.platform === 'win32') {
74+
args.push("-scompiler=Visual Studio")
75+
args.push("-scompiler.runtime=MT")
76+
}
77+
6778
var mapping = {
6879
'x64' : 'x86_64',
6980
'ia32' : 'x86'

conanfile.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,19 @@
11
from conans import ConanFile
22

3-
class JoyStreamNodeNPMConan(ConanFile):
3+
class JoyStreamNode(ConanFile):
44
settings = "os", "compiler", "build_type", "arch"
5-
requires = "LibtorrentNode/1.1.1@joystream/stable", "Extension/0.1@joystream/stable"
5+
requires = ("Libtorrent/1.1.1@joystream/stable",
6+
"LibtorrentNode/0.0.6@joystream/stable",
7+
"CoinCore/0.1.2@joystream/stable",
8+
"Common/0.1.2@joystream/stable",
9+
"PaymentChannel/0.1.2@joystream/stable",
10+
"ProtocolWire/0.1.2@joystream/stable",
11+
"ProtocolStateMachine/0.1.2@joystream/stable",
12+
"ProtocolSession/0.1.4@joystream/stable",
13+
"Extension/0.1.6@joystream/stable",
14+
"Boost/1.60.0@lasote/stable",
15+
"OpenSSL/1.0.2j@lasote/stable")
16+
617
generators = "cmake"
718

819
options = {

examples/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
purchase/buyer/
22
purchase/seller/
3+
4+
dht/buyer/
5+
dht/seller/

examples/basic/basic.js

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
const Session = require('../../').Session
22
const TorrentInfo = require('../../').TorrentInfo
3-
const _ = require('lodash')
43

54
console.log('====== Starting basic.js example ======')
65

76
// start a joystream session
8-
var session = new Session()
7+
var session = new Session({port: 6881})
98

109
let addTorrentParams = {
1110
ti: new TorrentInfo(__dirname + '/../../test/sintel.torrent'),
@@ -18,13 +17,38 @@ session.addTorrent(addTorrentParams, (err, torrent) => {
1817

1918
console.log(torrent)
2019

21-
session.removeTorrent(torrent.handle.infoHash(), (err, result) => {
20+
torrent.on('pieceFinished', (pieceIndex) => {
21+
console.log('WE HAVE PIECE : ', pieceIndex)
22+
})
23+
24+
torrent.on('state_changed', () => {
25+
26+
var status = torrent.status()
27+
28+
console.log(status)
29+
30+
if (status.state === 5 || status.state === 3) {
31+
var havePiece = torrent.handle.havePiece(0)
32+
33+
var torrentInfo = torrent.handle.torrentFile()
34+
var fileStorage = torrentInfo.files()
35+
36+
if (havePiece) {
37+
console.log('asking for piece !')
38+
torrent.handle.readPiece(0)
39+
} else {
40+
console.log('We dont have piece')
41+
}
42+
}
43+
})
44+
45+
/*session.removeTorrent(torrent.infoHash, (err, result) => {
2246
if (!err) {
2347
console.log('====== Torrent Sintel Removed ======')
2448
} else {
2549
console.error(err)
2650
}
27-
})
51+
})*/
2852
} else {
2953
console.error(err)
3054
}

examples/buyer/buyer.js

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
'use strict'
2+
3+
const Session = require('../../').Session
4+
const TorrentInfo = require('../../').TorrentInfo
5+
const path = require('path')
6+
const areTermsMatching = require('../../lib/utils').areTermsMatching
7+
const ConnectionInnerState = require('../../').ConnectionInnerState
8+
const TorrentState = require('../../').TorrentState
9+
const LibtorrentInteraction = require('../../').LibtorrentInteraction
10+
11+
const torrentPath = path.join(__dirname, '/../../test/sfc.torrent')
12+
const sintelTorrentPath = path.join(__dirname, '/../../test/sintel.torrent')
13+
14+
var buyerSession = new Session({
15+
port: 6881
16+
})
17+
18+
let addTorrentParamsBuyer = {
19+
ti: new TorrentInfo(torrentPath),
20+
savePath: path.join(__dirname, '/downloads/')
21+
}
22+
23+
function letsBuy (torrent) {
24+
console.log('torrent in downloading state, going to buy mode')
25+
// 100, 5, 1, 20000
26+
const buyerTerms = {
27+
maxPrice: 100,
28+
maxLock: 5,
29+
minNumberOfSellers: 1,
30+
maxContractFeePerKb: 20000
31+
}
32+
33+
let lookingForSeller = false
34+
35+
torrent.toBuyMode(buyerTerms, (err) => {
36+
if (err) {
37+
return console.log(err)
38+
}
39+
40+
torrent.startPlugin(function (err) {
41+
if(err) {
42+
return console.log(err)
43+
}
44+
45+
console.log('We are in buying mode')
46+
lookingForSeller = true
47+
})
48+
})
49+
50+
// Wait for one suitable seller and start downloading
51+
torrent.on('peerPluginStatusUpdates', function (peerStatuses) {
52+
if (!lookingForSeller) return
53+
54+
console.log('looking for seller')
55+
56+
const connection = pickSuitableSeller(peerStatuses, buyerTerms)
57+
58+
if (!connection) return
59+
60+
console.log('found a suitable seller', connection)
61+
62+
// Stop looking for seller
63+
lookingForSeller = false
64+
65+
const pid = connection.pid
66+
const sellerTerms = connection.announcedModeAndTermsFromPeer.seller.terms
67+
68+
let setup = makeContractAndDownloadInfoMap(pid, sellerTerms)
69+
70+
torrent.startDownloading(setup.contract, setup.map, function (err) {
71+
if (err) {
72+
console.log(err)
73+
lookingForSeller = true
74+
return
75+
}
76+
console.log('Started Downloading From Seller')
77+
})
78+
})
79+
}
80+
81+
function makeContractAndDownloadInfoMap (pid, sellerTerms) {
82+
// Fake contract
83+
const contract = Buffer.from('01000000017b1eabe0209b1fe794124575ef807057c77ada2138ae4fa8d6c4de0398a14f3f00000000494830450221008949f0cb400094ad2b5eb399d59d01c14d73d8fe6e96df1a7150deb388ab8935022079656090d7f6bac4c9a94e0aad311a4268e082a725f8aeae0573fb12ff866a5f01ffffffff01f0ca052a010000001976a914cbc20a7664f2f69e5355aa427045bc15e7c6c77288ac00000000', 'hex')
84+
85+
// Download info map for one seller
86+
const map = new Map()
87+
88+
map.set(pid, {
89+
index: 0,
90+
value: 100000,
91+
sellerTerms: sellerTerms,
92+
buyerContractSk: Buffer.from('0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20', 'hex'),
93+
buyerFinalPkHash: new Buffer(20)
94+
})
95+
96+
return {contract, map}
97+
}
98+
99+
function pickSuitableSeller (peerStatuses, buyerTerms) {
100+
for (var i in peerStatuses) {
101+
const status = peerStatuses[i]
102+
103+
if (!status.connection) continue
104+
105+
//console.log(status.connection.announcedModeAndTermsFromPeer)
106+
107+
// connection must be in PerparingContract state
108+
if (status.connection.innerState !== ConnectionInnerState.PreparingContract) {
109+
console.log('not in preparing contract status')
110+
continue
111+
}
112+
113+
try {
114+
// lazy checking for seller, if peer is not a seller this will throw..
115+
const sellerTerms = status.connection.announcedModeAndTermsFromPeer.seller.terms
116+
console.log(sellerTerms)
117+
if (areTermsMatching(buyerTerms, sellerTerms)) {
118+
return status.connection
119+
}
120+
121+
} catch (e) { console.log(e) }
122+
}
123+
124+
return null
125+
}
126+
127+
buyerSession.addTorrent(addTorrentParamsBuyer, (err, torrent) => {
128+
if (err) {
129+
return console.log(err)
130+
}
131+
132+
console.log(torrent)
133+
134+
torrent.setLibtorrentInteraction(LibtorrentInteraction.BlockUploadingAndDownloading)
135+
136+
// Wait for libtorrent state to be downloading
137+
waitForState(torrent, TorrentState.downloading, function () {
138+
letsBuy(torrent)
139+
})
140+
141+
// Wait for libtorrent state to be seeding which means we already
142+
// have it and it doesn't make sense to try to buy it, or we completed downloading it
143+
waitForState(torrent, TorrentState.seeding, function () {
144+
console.log('Torrent downloaded, exiting')
145+
process.exit()
146+
})
147+
})
148+
149+
function waitForState (torrent, targetState, callback) {
150+
function checkState () {
151+
if (torrent.status().state === targetState) {
152+
torrent.removeListener('state_changed', checkState)
153+
callback()
154+
}
155+
}
156+
157+
if (torrent.status().state === targetState) {
158+
callback()
159+
} else {
160+
torrent.on('state_changed', checkState)
161+
}
162+
}

examples/dht/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# DHT example
2+
3+
Show how to update dht.

0 commit comments

Comments
 (0)