node_http_server.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. //
  2. // Created by Mingliang Chen on 17/8/1.
  3. // illuspas[a]gmail.com
  4. // Copyright (c) 2018 Nodemedia. All rights reserved.
  5. //
  6. const Fs = require('fs');
  7. const path = require('path');
  8. const Http = require('http');
  9. const Https = require('https');
  10. const WebSocket = require('ws');
  11. const Express = require('express');
  12. const bodyParser = require('body-parser');
  13. const basicAuth = require('basic-auth-connect');
  14. const NodeFlvSession = require('./node_flv_session');
  15. const HTTP_PORT = 80;
  16. const HTTPS_PORT = 443;
  17. const HTTP_MEDIAROOT = './media';
  18. const Logger = require('./node_core_logger');
  19. const context = require('./node_core_ctx');
  20. const streamsRoute = require('./api/routes/streams');
  21. const serverRoute = require('./api/routes/server');
  22. const relayRoute = require('./api/routes/relay');
  23. class NodeHttpServer {
  24. constructor(config) {
  25. this.port = config.http.port || HTTP_PORT;
  26. this.mediaroot = config.http.mediaroot || HTTP_MEDIAROOT;
  27. this.config = config;
  28. let app = Express();
  29. app.use(bodyParser.json());
  30. app.use(bodyParser.urlencoded({ extended: true }));
  31. app.all('*', (req, res, next) => {
  32. res.header("Access-Control-Allow-Origin", this.config.http.allow_origin);
  33. res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With");
  34. res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
  35. res.header("Access-Control-Allow-Credentials", true);
  36. req.method === "OPTIONS" ? res.sendStatus(200) : next();
  37. });
  38. app.get('*.flv', (req, res, next) => {
  39. req.nmsConnectionType = 'http';
  40. this.onConnect(req, res);
  41. });
  42. let adminEntry = path.join(__dirname + '/public/admin/index.html');
  43. if (Fs.existsSync(adminEntry)) {
  44. app.get('/admin/*', (req, res) => {
  45. res.sendFile(adminEntry);
  46. });
  47. }
  48. if (this.config.http.api !== false) {
  49. if (this.config.auth && this.config.auth.api) {
  50. app.use(['/api/*', '/static/*', '/admin/*'], basicAuth(this.config.auth.api_user, this.config.auth.api_pass));
  51. }
  52. app.use('/api/streams', streamsRoute(context));
  53. app.use('/api/server', serverRoute(context));
  54. app.use('/api/relay', relayRoute(context));
  55. }
  56. app.use(Express.static(path.join(__dirname + '/public')));
  57. app.use(Express.static(this.mediaroot));
  58. if (config.http.webroot) {
  59. app.use(Express.static(config.http.webroot));
  60. }
  61. this.httpServer = Http.createServer(app);
  62. /**
  63. * ~ openssl genrsa -out privatekey.pem 1024
  64. * ~ openssl req -new -key privatekey.pem -out certrequest.csr
  65. * ~ openssl x509 -req -in certrequest.csr -signkey privatekey.pem -out certificate.pem
  66. */
  67. if (this.config.https) {
  68. let options = {
  69. key: Fs.readFileSync(this.config.https.key),
  70. cert: Fs.readFileSync(this.config.https.cert)
  71. };
  72. this.sport = config.https.port ? config.https.port : HTTPS_PORT;
  73. this.httpsServer = Https.createServer(options, app);
  74. }
  75. }
  76. run() {
  77. this.httpServer.listen(this.port, () => {
  78. Logger.log(`Node Media Http Server started on port: ${this.port}`);
  79. });
  80. this.httpServer.on('error', (e) => {
  81. Logger.error(`Node Media Http Server ${e}`);
  82. });
  83. this.httpServer.on('close', () => {
  84. Logger.log('Node Media Http Server Close.');
  85. });
  86. this.wsServer = new WebSocket.Server({ server: this.httpServer });
  87. this.wsServer.on('connection', (ws, req) => {
  88. req.nmsConnectionType = 'ws';
  89. this.onConnect(req, ws);
  90. });
  91. this.wsServer.on('listening', () => {
  92. Logger.log(`Node Media WebSocket Server started on port: ${this.port}`);
  93. });
  94. this.wsServer.on('error', (e) => {
  95. Logger.error(`Node Media WebSocket Server ${e}`);
  96. });
  97. if (this.httpsServer) {
  98. this.httpsServer.listen(this.sport, () => {
  99. Logger.log(`Node Media Https Server started on port: ${this.sport}`);
  100. });
  101. this.httpsServer.on('error', (e) => {
  102. Logger.error(`Node Media Https Server ${e}`);
  103. });
  104. this.httpsServer.on('close', () => {
  105. Logger.log('Node Media Https Server Close.');
  106. });
  107. this.wssServer = new WebSocket.Server({ server: this.httpsServer });
  108. this.wssServer.on('connection', (ws, req) => {
  109. req.nmsConnectionType = 'ws';
  110. this.onConnect(req, ws);
  111. });
  112. this.wssServer.on('listening', () => {
  113. Logger.log(`Node Media WebSocketSecure Server started on port: ${this.sport}`);
  114. });
  115. this.wssServer.on('error', (e) => {
  116. Logger.error(`Node Media WebSocketSecure Server ${e}`);
  117. });
  118. }
  119. context.nodeEvent.on('postPlay', (id, args) => {
  120. context.stat.accepted++;
  121. });
  122. context.nodeEvent.on('postPublish', (id, args) => {
  123. context.stat.accepted++;
  124. });
  125. context.nodeEvent.on('doneConnect', (id, args) => {
  126. let session = context.sessions.get(id);
  127. let socket = session instanceof NodeFlvSession ? session.req.socket : session.socket;
  128. context.stat.inbytes += socket.bytesRead;
  129. context.stat.outbytes += socket.bytesWritten;
  130. });
  131. }
  132. stop() {
  133. this.httpServer.close();
  134. if (this.httpsServer) {
  135. this.httpsServer.close();
  136. }
  137. context.sessions.forEach((session, id) => {
  138. if (session instanceof NodeFlvSession) {
  139. session.req.destroy();
  140. context.sessions.delete(id);
  141. }
  142. });
  143. }
  144. onConnect(req, res) {
  145. let session = new NodeFlvSession(this.config, req, res);
  146. session.run();
  147. }
  148. }
  149. module.exports = NodeHttpServer;