UNPKG

ndn-js

Version:

A JavaScript client library for Named Data Networking

535 lines (477 loc) 23.3 kB
/* * Copyright (C) 2014-2019 Regents of the University of California. * @author: Zhehao Wang * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * A copy of the GNU Lesser General Public License is in the file COPYING. */ var Face = require('../..').Face; var Name = require('../..').Name; var Blob = require('../..').Blob; var Interest = require('../..').Interest; var Data = require('../..').Data; var SafeBag = require('../..').SafeBag; var KeyChain = require('../..').KeyChain; var KeyType = require('../..').KeyType; var ChronoSync2013 = require('../..').ChronoSync2013; var UnixTransport = require('../..').UnixTransport; var DEFAULT_RSA_PUBLIC_KEY_DER = new Buffer([ 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xb8, 0x09, 0xa7, 0x59, 0x82, 0x84, 0xec, 0x4f, 0x06, 0xfa, 0x1c, 0xb2, 0xe1, 0x38, 0x93, 0x53, 0xbb, 0x7d, 0xd4, 0xac, 0x88, 0x1a, 0xf8, 0x25, 0x11, 0xe4, 0xfa, 0x1d, 0x61, 0x24, 0x5b, 0x82, 0xca, 0xcd, 0x72, 0xce, 0xdb, 0x66, 0xb5, 0x8d, 0x54, 0xbd, 0xfb, 0x23, 0xfd, 0xe8, 0x8e, 0xaf, 0xa7, 0xb3, 0x79, 0xbe, 0x94, 0xb5, 0xb7, 0xba, 0x17, 0xb6, 0x05, 0xae, 0xce, 0x43, 0xbe, 0x3b, 0xce, 0x6e, 0xea, 0x07, 0xdb, 0xbf, 0x0a, 0x7e, 0xeb, 0xbc, 0xc9, 0x7b, 0x62, 0x3c, 0xf5, 0xe1, 0xce, 0xe1, 0xd9, 0x8d, 0x9c, 0xfe, 0x1f, 0xc7, 0xf8, 0xfb, 0x59, 0xc0, 0x94, 0x0b, 0x2c, 0xd9, 0x7d, 0xbc, 0x96, 0xeb, 0xb8, 0x79, 0x22, 0x8a, 0x2e, 0xa0, 0x12, 0x1d, 0x42, 0x07, 0xb6, 0x5d, 0xdb, 0xe1, 0xf6, 0xb1, 0x5d, 0x7b, 0x1f, 0x54, 0x52, 0x1c, 0xa3, 0x11, 0x9b, 0xf9, 0xeb, 0xbe, 0xb3, 0x95, 0xca, 0xa5, 0x87, 0x3f, 0x31, 0x18, 0x1a, 0xc9, 0x99, 0x01, 0xec, 0xaa, 0x90, 0xfd, 0x8a, 0x36, 0x35, 0x5e, 0x12, 0x81, 0xbe, 0x84, 0x88, 0xa1, 0x0d, 0x19, 0x2a, 0x4a, 0x66, 0xc1, 0x59, 0x3c, 0x41, 0x83, 0x3d, 0x3d, 0xb8, 0xd4, 0xab, 0x34, 0x90, 0x06, 0x3e, 0x1a, 0x61, 0x74, 0xbe, 0x04, 0xf5, 0x7a, 0x69, 0x1b, 0x9d, 0x56, 0xfc, 0x83, 0xb7, 0x60, 0xc1, 0x5e, 0x9d, 0x85, 0x34, 0xfd, 0x02, 0x1a, 0xba, 0x2c, 0x09, 0x72, 0xa7, 0x4a, 0x5e, 0x18, 0xbf, 0xc0, 0x58, 0xa7, 0x49, 0x34, 0x46, 0x61, 0x59, 0x0e, 0xe2, 0x6e, 0x9e, 0xd2, 0xdb, 0xfd, 0x72, 0x2f, 0x3c, 0x47, 0xcc, 0x5f, 0x99, 0x62, 0xee, 0x0d, 0xf3, 0x1f, 0x30, 0x25, 0x20, 0x92, 0x15, 0x4b, 0x04, 0xfe, 0x15, 0x19, 0x1d, 0xdc, 0x7e, 0x5c, 0x10, 0x21, 0x52, 0x21, 0x91, 0x54, 0x60, 0x8b, 0x92, 0x41, 0x02, 0x03, 0x01, 0x00, 0x01 ]); // Use an unencrypted PKCS #8 PrivateKeyInfo. var DEFAULT_RSA_PRIVATE_KEY_DER = new Buffer([ 0x30, 0x82, 0x04, 0xbf, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x04, 0xa9, 0x30, 0x82, 0x04, 0xa5, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xb8, 0x09, 0xa7, 0x59, 0x82, 0x84, 0xec, 0x4f, 0x06, 0xfa, 0x1c, 0xb2, 0xe1, 0x38, 0x93, 0x53, 0xbb, 0x7d, 0xd4, 0xac, 0x88, 0x1a, 0xf8, 0x25, 0x11, 0xe4, 0xfa, 0x1d, 0x61, 0x24, 0x5b, 0x82, 0xca, 0xcd, 0x72, 0xce, 0xdb, 0x66, 0xb5, 0x8d, 0x54, 0xbd, 0xfb, 0x23, 0xfd, 0xe8, 0x8e, 0xaf, 0xa7, 0xb3, 0x79, 0xbe, 0x94, 0xb5, 0xb7, 0xba, 0x17, 0xb6, 0x05, 0xae, 0xce, 0x43, 0xbe, 0x3b, 0xce, 0x6e, 0xea, 0x07, 0xdb, 0xbf, 0x0a, 0x7e, 0xeb, 0xbc, 0xc9, 0x7b, 0x62, 0x3c, 0xf5, 0xe1, 0xce, 0xe1, 0xd9, 0x8d, 0x9c, 0xfe, 0x1f, 0xc7, 0xf8, 0xfb, 0x59, 0xc0, 0x94, 0x0b, 0x2c, 0xd9, 0x7d, 0xbc, 0x96, 0xeb, 0xb8, 0x79, 0x22, 0x8a, 0x2e, 0xa0, 0x12, 0x1d, 0x42, 0x07, 0xb6, 0x5d, 0xdb, 0xe1, 0xf6, 0xb1, 0x5d, 0x7b, 0x1f, 0x54, 0x52, 0x1c, 0xa3, 0x11, 0x9b, 0xf9, 0xeb, 0xbe, 0xb3, 0x95, 0xca, 0xa5, 0x87, 0x3f, 0x31, 0x18, 0x1a, 0xc9, 0x99, 0x01, 0xec, 0xaa, 0x90, 0xfd, 0x8a, 0x36, 0x35, 0x5e, 0x12, 0x81, 0xbe, 0x84, 0x88, 0xa1, 0x0d, 0x19, 0x2a, 0x4a, 0x66, 0xc1, 0x59, 0x3c, 0x41, 0x83, 0x3d, 0x3d, 0xb8, 0xd4, 0xab, 0x34, 0x90, 0x06, 0x3e, 0x1a, 0x61, 0x74, 0xbe, 0x04, 0xf5, 0x7a, 0x69, 0x1b, 0x9d, 0x56, 0xfc, 0x83, 0xb7, 0x60, 0xc1, 0x5e, 0x9d, 0x85, 0x34, 0xfd, 0x02, 0x1a, 0xba, 0x2c, 0x09, 0x72, 0xa7, 0x4a, 0x5e, 0x18, 0xbf, 0xc0, 0x58, 0xa7, 0x49, 0x34, 0x46, 0x61, 0x59, 0x0e, 0xe2, 0x6e, 0x9e, 0xd2, 0xdb, 0xfd, 0x72, 0x2f, 0x3c, 0x47, 0xcc, 0x5f, 0x99, 0x62, 0xee, 0x0d, 0xf3, 0x1f, 0x30, 0x25, 0x20, 0x92, 0x15, 0x4b, 0x04, 0xfe, 0x15, 0x19, 0x1d, 0xdc, 0x7e, 0x5c, 0x10, 0x21, 0x52, 0x21, 0x91, 0x54, 0x60, 0x8b, 0x92, 0x41, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x01, 0x00, 0x8a, 0x05, 0xfb, 0x73, 0x7f, 0x16, 0xaf, 0x9f, 0xa9, 0x4c, 0xe5, 0x3f, 0x26, 0xf8, 0x66, 0x4d, 0xd2, 0xfc, 0xd1, 0x06, 0xc0, 0x60, 0xf1, 0x9f, 0xe3, 0xa6, 0xc6, 0x0a, 0x48, 0xb3, 0x9a, 0xca, 0x21, 0xcd, 0x29, 0x80, 0x88, 0x3d, 0xa4, 0x85, 0xa5, 0x7b, 0x82, 0x21, 0x81, 0x28, 0xeb, 0xf2, 0x43, 0x24, 0xb0, 0x76, 0xc5, 0x52, 0xef, 0xc2, 0xea, 0x4b, 0x82, 0x41, 0x92, 0xc2, 0x6d, 0xa6, 0xae, 0xf0, 0xb2, 0x26, 0x48, 0xa1, 0x23, 0x7f, 0x02, 0xcf, 0xa8, 0x90, 0x17, 0xa2, 0x3e, 0x8a, 0x26, 0xbd, 0x6d, 0x8a, 0xee, 0xa6, 0x0c, 0x31, 0xce, 0xc2, 0xbb, 0x92, 0x59, 0xb5, 0x73, 0xe2, 0x7d, 0x91, 0x75, 0xe2, 0xbd, 0x8c, 0x63, 0xe2, 0x1c, 0x8b, 0xc2, 0x6a, 0x1c, 0xfe, 0x69, 0xc0, 0x44, 0xcb, 0x58, 0x57, 0xb7, 0x13, 0x42, 0xf0, 0xdb, 0x50, 0x4c, 0xe0, 0x45, 0x09, 0x8f, 0xca, 0x45, 0x8a, 0x06, 0xfe, 0x98, 0xd1, 0x22, 0xf5, 0x5a, 0x9a, 0xdf, 0x89, 0x17, 0xca, 0x20, 0xcc, 0x12, 0xa9, 0x09, 0x3d, 0xd5, 0xf7, 0xe3, 0xeb, 0x08, 0x4a, 0xc4, 0x12, 0xc0, 0xb9, 0x47, 0x6c, 0x79, 0x50, 0x66, 0xa3, 0xf8, 0xaf, 0x2c, 0xfa, 0xb4, 0x6b, 0xec, 0x03, 0xad, 0xcb, 0xda, 0x24, 0x0c, 0x52, 0x07, 0x87, 0x88, 0xc0, 0x21, 0xf3, 0x02, 0xe8, 0x24, 0x44, 0x0f, 0xcd, 0xa0, 0xad, 0x2f, 0x1b, 0x79, 0xab, 0x6b, 0x49, 0x4a, 0xe6, 0x3b, 0xd0, 0xad, 0xc3, 0x48, 0xb9, 0xf7, 0xf1, 0x34, 0x09, 0xeb, 0x7a, 0xc0, 0xd5, 0x0d, 0x39, 0xd8, 0x45, 0xce, 0x36, 0x7a, 0xd8, 0xde, 0x3c, 0xb0, 0x21, 0x96, 0x97, 0x8a, 0xff, 0x8b, 0x23, 0x60, 0x4f, 0xf0, 0x3d, 0xd7, 0x8f, 0xf3, 0x2c, 0xcb, 0x1d, 0x48, 0x3f, 0x86, 0xc4, 0xa9, 0x00, 0xf2, 0x23, 0x2d, 0x72, 0x4d, 0x66, 0xa5, 0x01, 0x02, 0x81, 0x81, 0x00, 0xdc, 0x4f, 0x99, 0x44, 0x0d, 0x7f, 0x59, 0x46, 0x1e, 0x8f, 0xe7, 0x2d, 0x8d, 0xdd, 0x54, 0xc0, 0xf7, 0xfa, 0x46, 0x0d, 0x9d, 0x35, 0x03, 0xf1, 0x7c, 0x12, 0xf3, 0x5a, 0x9d, 0x83, 0xcf, 0xdd, 0x37, 0x21, 0x7c, 0xb7, 0xee, 0xc3, 0x39, 0xd2, 0x75, 0x8f, 0xb2, 0x2d, 0x6f, 0xec, 0xc6, 0x03, 0x55, 0xd7, 0x00, 0x67, 0xd3, 0x9b, 0xa2, 0x68, 0x50, 0x6f, 0x9e, 0x28, 0xa4, 0x76, 0x39, 0x2b, 0xb2, 0x65, 0xcc, 0x72, 0x82, 0x93, 0xa0, 0xcf, 0x10, 0x05, 0x6a, 0x75, 0xca, 0x85, 0x35, 0x99, 0xb0, 0xa6, 0xc6, 0xef, 0x4c, 0x4d, 0x99, 0x7d, 0x2c, 0x38, 0x01, 0x21, 0xb5, 0x31, 0xac, 0x80, 0x54, 0xc4, 0x18, 0x4b, 0xfd, 0xef, 0xb3, 0x30, 0x22, 0x51, 0x5a, 0xea, 0x7d, 0x9b, 0xb2, 0x9d, 0xcb, 0xba, 0x3f, 0xc0, 0x1a, 0x6b, 0xcd, 0xb0, 0xe6, 0x2f, 0x04, 0x33, 0xd7, 0x3a, 0x49, 0x71, 0x02, 0x81, 0x81, 0x00, 0xd5, 0xd9, 0xc9, 0x70, 0x1a, 0x13, 0xb3, 0x39, 0x24, 0x02, 0xee, 0xb0, 0xbb, 0x84, 0x17, 0x12, 0xc6, 0xbd, 0x65, 0x73, 0xe9, 0x34, 0x5d, 0x43, 0xff, 0xdc, 0xf8, 0x55, 0xaf, 0x2a, 0xb9, 0xe1, 0xfa, 0x71, 0x65, 0x4e, 0x50, 0x0f, 0xa4, 0x3b, 0xe5, 0x68, 0xf2, 0x49, 0x71, 0xaf, 0x15, 0x88, 0xd7, 0xaf, 0xc4, 0x9d, 0x94, 0x84, 0x6b, 0x5b, 0x10, 0xd5, 0xc0, 0xaa, 0x0c, 0x13, 0x62, 0x99, 0xc0, 0x8b, 0xfc, 0x90, 0x0f, 0x87, 0x40, 0x4d, 0x58, 0x88, 0xbd, 0xe2, 0xba, 0x3e, 0x7e, 0x2d, 0xd7, 0x69, 0xa9, 0x3c, 0x09, 0x64, 0x31, 0xb6, 0xcc, 0x4d, 0x1f, 0x23, 0xb6, 0x9e, 0x65, 0xd6, 0x81, 0xdc, 0x85, 0xcc, 0x1e, 0xf1, 0x0b, 0x84, 0x38, 0xab, 0x93, 0x5f, 0x9f, 0x92, 0x4e, 0x93, 0x46, 0x95, 0x6b, 0x3e, 0xb6, 0xc3, 0x1b, 0xd7, 0x69, 0xa1, 0x0a, 0x97, 0x37, 0x78, 0xed, 0xd1, 0x02, 0x81, 0x80, 0x33, 0x18, 0xc3, 0x13, 0x65, 0x8e, 0x03, 0xc6, 0x9f, 0x90, 0x00, 0xae, 0x30, 0x19, 0x05, 0x6f, 0x3c, 0x14, 0x6f, 0xea, 0xf8, 0x6b, 0x33, 0x5e, 0xee, 0xc7, 0xf6, 0x69, 0x2d, 0xdf, 0x44, 0x76, 0xaa, 0x32, 0xba, 0x1a, 0x6e, 0xe6, 0x18, 0xa3, 0x17, 0x61, 0x1c, 0x92, 0x2d, 0x43, 0x5d, 0x29, 0xa8, 0xdf, 0x14, 0xd8, 0xff, 0xdb, 0x38, 0xef, 0xb8, 0xb8, 0x2a, 0x96, 0x82, 0x8e, 0x68, 0xf4, 0x19, 0x8c, 0x42, 0xbe, 0xcc, 0x4a, 0x31, 0x21, 0xd5, 0x35, 0x6c, 0x5b, 0xa5, 0x7c, 0xff, 0xd1, 0x85, 0x87, 0x28, 0xdc, 0x97, 0x75, 0xe8, 0x03, 0x80, 0x1d, 0xfd, 0x25, 0x34, 0x41, 0x31, 0x21, 0x12, 0x87, 0xe8, 0x9a, 0xb7, 0x6a, 0xc0, 0xc4, 0x89, 0x31, 0x15, 0x45, 0x0d, 0x9c, 0xee, 0xf0, 0x6a, 0x2f, 0xe8, 0x59, 0x45, 0xc7, 0x7b, 0x0d, 0x6c, 0x55, 0xbb, 0x43, 0xca, 0xc7, 0x5a, 0x01, 0x02, 0x81, 0x81, 0x00, 0xab, 0xf4, 0xd5, 0xcf, 0x78, 0x88, 0x82, 0xc2, 0xdd, 0xbc, 0x25, 0xe6, 0xa2, 0xc1, 0xd2, 0x33, 0xdc, 0xef, 0x0a, 0x97, 0x2b, 0xdc, 0x59, 0x6a, 0x86, 0x61, 0x4e, 0xa6, 0xc7, 0x95, 0x99, 0xa6, 0xa6, 0x55, 0x6c, 0x5a, 0x8e, 0x72, 0x25, 0x63, 0xac, 0x52, 0xb9, 0x10, 0x69, 0x83, 0x99, 0xd3, 0x51, 0x6c, 0x1a, 0xb3, 0x83, 0x6a, 0xff, 0x50, 0x58, 0xb7, 0x28, 0x97, 0x13, 0xe2, 0xba, 0x94, 0x5b, 0x89, 0xb4, 0xea, 0xba, 0x31, 0xcd, 0x78, 0xe4, 0x4a, 0x00, 0x36, 0x42, 0x00, 0x62, 0x41, 0xc6, 0x47, 0x46, 0x37, 0xea, 0x6d, 0x50, 0xb4, 0x66, 0x8f, 0x55, 0x0c, 0xc8, 0x99, 0x91, 0xd5, 0xec, 0xd2, 0x40, 0x1c, 0x24, 0x7d, 0x3a, 0xff, 0x74, 0xfa, 0x32, 0x24, 0xe0, 0x11, 0x2b, 0x71, 0xad, 0x7e, 0x14, 0xa0, 0x77, 0x21, 0x68, 0x4f, 0xcc, 0xb6, 0x1b, 0xe8, 0x00, 0x49, 0x13, 0x21, 0x02, 0x81, 0x81, 0x00, 0xb6, 0x18, 0x73, 0x59, 0x2c, 0x4f, 0x92, 0xac, 0xa2, 0x2e, 0x5f, 0xb6, 0xbe, 0x78, 0x5d, 0x47, 0x71, 0x04, 0x92, 0xf0, 0xd7, 0xe8, 0xc5, 0x7a, 0x84, 0x6b, 0xb8, 0xb4, 0x30, 0x1f, 0xd8, 0x0d, 0x58, 0xd0, 0x64, 0x80, 0xa7, 0x21, 0x1a, 0x48, 0x00, 0x37, 0xd6, 0x19, 0x71, 0xbb, 0x91, 0x20, 0x9d, 0xe2, 0xc3, 0xec, 0xdb, 0x36, 0x1c, 0xca, 0x48, 0x7d, 0x03, 0x32, 0x74, 0x1e, 0x65, 0x73, 0x02, 0x90, 0x73, 0xd8, 0x3f, 0xb5, 0x52, 0x35, 0x79, 0x1c, 0xee, 0x93, 0xa3, 0x32, 0x8b, 0xed, 0x89, 0x98, 0xf1, 0x0c, 0xd8, 0x12, 0xf2, 0x89, 0x7f, 0x32, 0x23, 0xec, 0x67, 0x66, 0x52, 0x83, 0x89, 0x99, 0x5e, 0x42, 0x2b, 0x42, 0x4b, 0x84, 0x50, 0x1b, 0x3e, 0x47, 0x6d, 0x74, 0xfb, 0xd1, 0xa6, 0x10, 0x20, 0x6c, 0x6e, 0xbe, 0x44, 0x3f, 0xb9, 0xfe, 0xbc, 0x8d, 0xda, 0xcb, 0xea, 0x8f ]); var ChronoChat = function(screenName, chatRoom, hubPrefix, face, keyChain, certificateName) { this.screen_name = screenName; this.chatroom = chatRoom; this.maxmsgcachelength = 100; this.isRecoverySyncState = true; this.sync_lifetime = 5000.0; this.face = face; this.keyChain = keyChain; this.certificateName = certificateName; this.chat_prefix = (new Name(hubPrefix)).append(this.chatroom).append(this.getRandomString()); this.roster = []; this.msgcache = []; //console.log("The local chat prefix " + this.chat_prefix.toUri() + " ***"); var session = (new Date()).getTime(); session = parseInt(session/1000); this.usrname = this.screen_name + session; this.ChatMessage = require('./test-chrono-chat-protobuf.js').ChatMessage; if (this.screen_name == "" || this.chatroom == "") { console.log("input usrname and chatroom"); } else { console.log(this.screen_name + ", welcome to chatroom " + this.chatroom + "!"); this.sync = new ChronoSync2013(this.sendInterest.bind(this), this.initial.bind(this), this.chat_prefix, (new Name("/ndn/broadcast/ChronoChat-0.3")).append(this.chatroom), session, face, keyChain, certificateName, this.sync_lifetime, this.onRegisterFailed.bind(this)); face.registerPrefix(this.chat_prefix, this.onInterest.bind(this), this.onRegisterFailed.bind(this)); } }; /** * Send the data packet which contains the user's message * @param {Name} Interest name prefix * @param {Interest} The interest * @param {Face} The face * @param {number} interestFilterId * @param {InterestFilter} filter */ ChronoChat.prototype.onInterest = function (prefix, interest, face, interestFilterId, filter) { var content = {}; // chat_prefix should really be saved as a name, not a URI string. var chatPrefixSize = new Name(this.chat_prefix).size(); var seq = parseInt(interest.getName().get(chatPrefixSize + 1).toEscapedString()); for (var i = this.msgcache.length - 1 ; i >= 0; i--) { if (this.msgcache[i].seqno == seq) { if(this.msgcache[i].msgtype != 'CHAT') content = new this.ChatMessage({from:this.screen_name, to:this.chatroom, type:this.msgcache[i].msgtype, timestamp:parseInt(this.msgcache[i].time/1000)}); else content = new this.ChatMessage({from:this.screen_name, to:this.chatroom, type:this.msgcache[i].msgtype, data:this.msgcache[i].msg, timestamp:parseInt(this.msgcache[i].time/1000)}); break; } } if (content.from != null) { var str = new Uint8Array(content.toArrayBuffer()); var co = new Data(interest.getName()); co.setContent(str); this.keyChain.sign(co); try { face.putData(co); } catch (e) { console.log(e.toString()); } } }; ChronoChat.prototype.onRegisterFailed = function(prefix) { }; ChronoChat.prototype.initial = function() { var timeout = new Interest(new Name("/local/timeout")); timeout.setInterestLifetimeMilliseconds(60000); this.face.expressInterest(timeout, this.dummyOnData, this.heartbeat.bind(this)); if (this.roster.indexOf(this.usrname) == -1) { this.roster.push(this.usrname); //console.log("*** Local member " + this.usrname + " joins. ***"); this.messageCacheAppend('JOIN', 'xxx'); } }; /** * This onData is passed as onData for timeout interest in initial, which means it * should not be called under any circumstances. */ ChronoChat.prototype.dummyOnData = function(interest, co) { console.log("*** dummyOndata called, name: " + interest.getName().toUri() + " ***"); }; /** * Send a Chat interest to fetch chat messages after the user gets the Sync data packet * @param {SyncStates[]} The array of sync states * @param {bool} if it's in recovery state */ ChronoChat.prototype.sendInterest = function(syncStates, isRecovery) { this.isRecoverySyncState = isRecovery; var sendList = []; // of String var sessionNoList = []; // of number var sequenceNoList = []; // of number for (var j = 0; j < syncStates.length; j++) { var syncState = syncStates[j]; var nameComponents = new Name(syncState.getDataPrefix()); var tempName = nameComponents.get(-1).toEscapedString(); var sessionNo = syncState.getSessionNo(); if (tempName != this.screen_name) { var index = -1; for (var k = 0; k < sendList.length; ++k) { if (sendList[k] == syncState.getDataPrefix()) { index = k; break; } } if (index != -1) { sessionNoList[index] = sessionNo; sequenceNoList[index] = syncState.getSequenceNo(); } else { sendList.push(syncState.getDataPrefix()); sessionNoList.push(sessionNo); sequenceNoList.push(syncState.getSequenceNo()); } } } for (var i = 0; i < sendList.length; ++i) { var uri = sendList[i] + "/" + sessionNoList[i] + "/" + sequenceNoList[i]; var interest = new Interest(new Name(uri)); interest.setInterestLifetimeMilliseconds(this.sync_lifetime); this.face.expressInterest(interest, this.onData.bind(this), this.chatTimeout.bind(this)); } }; /** * Process the incoming data * @param {Interest} interest * @param {Data} co */ ChronoChat.prototype.onData = function(interest, co) { var arr = new Uint8Array(co.getContent().size()); arr.set(co.getContent().buf()); var content = this.ChatMessage.decode(arr.buffer); var temp = (new Date()).getTime(); if (temp - content.timestamp * 1000 < 120000) { var t = (new Date(content.timestamp * 1000)).toLocaleTimeString(); var name = content.from; // chat_prefix should be saved as a name, not a URI string. var prefix = co.getName().getPrefix(-2).toUri(); var session = parseInt((co.getName().get(-2)).toEscapedString()); var seqno = parseInt((co.getName().get(-1)).toEscapedString()); var l = 0; //update roster while (l < this.roster.length) { var name_t = this.roster[l].substring(0,this.roster[l].length-10); var session_t = this.roster[l].substring(this.roster[l].length-10,this.roster[l].length); if (name != name_t && content.type != 2) l++; else{ if(name == name_t && session > session_t){ this.roster[l] = name + session; } break; } } if(l == this.roster.length) { this.roster.push(name + session); console.log("JOIN: " + name + session); } var timeout = new Interest(new Name("/local/timeout")); timeout.setInterestLifetimeMilliseconds(120000); this.face.expressInterest(timeout, this.dummyOnData, this.alive.bind(this, timeout, seqno, name, session, prefix)); //if (content.type == 0 && this.isRecoverySyncState == false && content.from != this.screen_name){ // Note: the original logic does not display old data; // But what if an ordinary application data interest gets answered after entering recovery state? if (content.type == 0 && content.from != this.screen_name){ console.log(content.from + ": " + content.data); } else if (content.type == 2) { //leave message var n = this.roster.indexOf(name + session); if(n != -1 && name != this.screen_name) { this.roster.splice(n,1); for(var i = 0; i<this.roster.length; i++) { var name_t = this.roster[i].substring(0,this.roster[i].length - 10); } var d = new Date(content.timestamp * 1000); var t = d.toLocaleTimeString(); } } } }; /** * No chat data coming back. * @param {Interest} */ ChronoChat.prototype.chatTimeout = function(interest) { }; /** * * @param {Interest} */ ChronoChat.prototype.heartbeat = function(interest) { // Based on ndn-cpp library approach if (this.msgcache.length == 0) { // Is it possible that this gets executed? this.messageCacheAppend("JOIN", "xxx"); } this.sync.publishNextSequenceNo(); this.messageCacheAppend("HELLO", "xxx"); // Making a timeout interest for heartbeat... var timeout = new Interest(new Name("/local/timeout")); timeout.setInterestLifetimeMilliseconds(60000); //console.log("*** Chat heartbeat expressed interest with name: " + timeout.getName().toUri() + " ***"); this.face.expressInterest(timeout, this.dummyOnData, this.heartbeat.bind(this)); }; /** * This is called after a timeout to check if the user with prefix has a newer sequence * number than the given temp_seq. If not, assume the user is idle and remove from the * roster and print a leave message. * This method has an interest argument because we use it as the onTimeout for * Face.expressInterest. * @param {Interest} * @param {int} * @param {string} * @param {int} * @param {string} */ ChronoChat.prototype.alive = function(interest, temp_seq, name, session, prefix) { //console.log("check alive"); var index_n = this.sync.digest_tree.find(prefix, session); var n = this.roster.indexOf(name + session); if (index_n != -1 && n != -1) { var seq = this.sync.digest_tree.digestnode[index_n].seqno.seq; if (temp_seq == seq) { this.roster.splice(n,1); console.log(name+" leave"); var d = new Date(); var t = d.toLocaleTimeString(); // records the time of leaving } } }; /** * @param {string} */ ChronoChat.prototype.sendMessage = function(chatmsg) { if (this.msgcache.length == 0) this.messageCacheAppend("JOIN", "xxx"); if (chatmsg != "") { this.sync.publishNextSequenceNo(); this.messageCacheAppend("CHAT", chatmsg); // Display chat message } } /** * Append a new CachedMessage to msgcache, using given messageType and message, * the sequence number from this.sync.getSequenceNo() and the current time. * Also remove elements from the front of the cache as needed to keep the size to * this.maxmsgcachelength. */ ChronoChat.prototype.messageCacheAppend = function(messageType, message) { var d = new Date(); var t = d.getTime(); this.msgcache.push(new ChronoChat.CachedMessage(this.sync.usrseq, messageType, message, t)); while (this.msgcache.length > this.maxmsgcachelength) { this.msgcache.shift(); } }; ChronoChat.prototype.getRandomString = function() { var seed = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789'; var result = ''; for (var i = 0; i < 10; i++) { var pos = Math.floor(Math.random() * seed.length); result += seed[pos]; } return result; }; // Embedded class CachedMessage; defining class with its constructor ChronoChat.CachedMessage = function (seqno, msgtype, msg, time) { this.seqno = seqno; this.msgtype = msgtype; this.msg = msg; this.time = time; }; ChronoChat.CachedMessage.prototype.getSequenceNo = function() { return this.seqno; }; ChronoChat.CachedMessage.prototype.getMessageType = function() { return this.msgtype; }; ChronoChat.CachedMessage.prototype.getMessage = function() { return this.msg; }; /** * @return MillisecondsSince1970 */ ChronoChat.CachedMessage.prototype.getTime = function() { return this.time; }; function getRandomNameString() { var seed = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM'; var result = ''; for (var i = 0; i < 3; i++) { var pos = Math.floor(Math.random() * seed.length); result += seed[pos]; } return result; }; // initiateChat() also sends random chat messages so that we don't need input from node JS function initiateChat() { // Silence the warning from Interest wire encode. Interest.setDefaultCanBePrefix(true); var hubPrefix = "ndn/edu/ucla/remap"; var screenName = getRandomNameString(); // chatroom is the name inputted by the user var chatroom = "ndnchat"; var face = new Face(new UnixTransport()); // Set up the KeyChain. var keyChain = new KeyChain("pib-memory:", "tpm-memory:"); // This puts the public key in the pibImpl used by the SelfVerifyPolicyManager. keyChain.importSafeBag(new SafeBag (new Name("/testname/KEY/123"), new Blob(DEFAULT_RSA_PRIVATE_KEY_DER, false), new Blob(DEFAULT_RSA_PUBLIC_KEY_DER, false))); face.setCommandSigningInfo(keyChain, keyChain.getDefaultCertificateName()); var chronoChat = new ChronoChat (screenName, chatroom, hubPrefix, face, keyChain, keyChain.getDefaultCertificateName()); // Send random test chat message at a fixed interval var num = 0; setInterval( function(){ var chatMsg = screenName + num; chronoChat.sendMessage(chatMsg); console.log(screenName + ": " + chatMsg); num ++; }, 2000); } initiateChat();