Skip to content
This repository
Browse code

Fleshing out chat server.

  • Loading branch information...
commit 69366723170253f1cb66d0743b7914174b675941 1 parent a67ba34
Scott González authored March 22, 2010
25  lib/channel.js
... ...
@@ -1,7 +1,14 @@
1  
-var sys = require("sys");
2  
-var Session = require("./session").Session;
  1
+var sys = require("sys"),
  2
+	Session = require("./session").Session;
3 3
 
4  
-function Channel() {
  4
+function Channel(name, options) {
  5
+	// TODO: handle invalid name and/or basePath
  6
+	options = options || {};
  7
+	this.name = name;
  8
+	this.basePath = options.basePath || ("/" + name);
  9
+	this.messageBacklog = options.messageBacklog || 200;
  10
+	this.sessionTimeout = (options.sessionTimeout || 60) * 1000;
  11
+	
5 12
 	this.messages = [];
6 13
 	this.callbacks = [];
7 14
 	this.sessions = {};
@@ -32,6 +39,11 @@ process.mixin(Channel.prototype, {
32 39
 		while (this.callbacks.length > 0) {
33 40
 			this.callbacks.shift().callback([message]);
34 41
 		}
  42
+		
  43
+		while (this.messages.length > this.messageBacklog) {
  44
+			sys.puts("shifing message");
  45
+			this.messages.shift();
  46
+		}
35 47
 	},
36 48
 	
37 49
 	query: function(since, callback) {
@@ -43,7 +55,6 @@ process.mixin(Channel.prototype, {
43 55
 				matching.push(message);
44 56
 			}
45 57
 		}
46  
-		
47 58
 		if (matching.length) {
48 59
 			callback(matching);
49 60
 		} else {
@@ -56,7 +67,7 @@ process.mixin(Channel.prototype, {
56 67
 	
57 68
 	flushCallbacks: function() {
58 69
 		var now = new Date();
59  
-		while (this.callbacks.length && now - this.callbacks[0].timestamp > 30*1000) {
  70
+		while (this.callbacks.length && now - this.callbacks[0].timestamp > this.sessionTimeout / 2) {
60 71
 			this.callbacks.shift().callback([]);
61 72
 		}
62 73
 	},
@@ -86,11 +97,11 @@ process.mixin(Channel.prototype, {
86 97
 	expireOldSessions: function() {
87 98
 		var now = new Date();
88 99
 		for (var session in this.sessions) {
89  
-			if (now - this.sessions[session].timestamp > 30 * 1000) {
  100
+			if (now - this.sessions[session].timestamp > this.sessionTimeout) {
90 101
 				this.destroySession(session);
91 102
 			}
92 103
 		}
93 104
 	}
94 105
 });
95 106
 
96  
-exports.Channel = Channel;
  107
+exports.Channel = Channel;
2  lib/router/index.js
@@ -49,7 +49,7 @@ router.createServer = function() {
49 49
 			server.listen(port, host);
50 50
 			sys.puts("Server at http://" + (host || "127.0.0.1") + ":" + port.toString() + "/");
51 51
 		},
52  
-		get: function (path, handler) {
  52
+		get: function(path, handler) {
53 53
 			getMap[path] = handler;
54 54
 		}
55 55
 	};
61  lib/server.js
@@ -4,22 +4,11 @@ var router = require("./router"),
4 4
 	qs = require("querystring"),
5 5
 	Channel = require("./channel").Channel;
6 6
 
7  
-// TODO: message backlog limit
8  
-// TODO: session timeouts
9  
-// TODO: named channels
10 7
 var servers = [];
11 8
 
12 9
 function Server() {
13  
-	var httpServer = router.createServer();
14  
-	handlers.forEach(function(handler) {
15  
-		httpServer.get(handler.path, handler.handler);
16  
-	});
17  
-	
18  
-	this.httpServer = httpServer;
19  
-	
20  
-	// TODO: don't auto-add a channel
  10
+	this.httpServer = router.createServer();
21 11
 	this.channels = [];
22  
-	this.addChannel();
23 12
 }
24 13
 
25 14
 process.mixin(Server.prototype, {
@@ -27,8 +16,20 @@ process.mixin(Server.prototype, {
27 16
 		this.httpServer.listen(port, host);
28 17
 	},
29 18
 	
30  
-	addChannel: function() {
31  
-		this.channels.push(new Channel());
  19
+	passThru: function(path, handler) {
  20
+		this.httpServer.get(path, handler);
  21
+	},
  22
+	
  23
+	addChannel: function(name, options) {
  24
+		// TODO: handle invalid channel
  25
+		var httpServer = this.httpServer,
  26
+			channel = new Channel(name, options);
  27
+		this.channels.push(channel);
  28
+		
  29
+		handlers.forEach(function(handler) {
  30
+			httpServer.get(channel.basePath + handler.path,
  31
+				handler.handler.partial(channel));
  32
+		});
32 33
 	},
33 34
 	
34 35
 	flushCallbacks: function() {
@@ -54,17 +55,16 @@ exports.createServer = function() {
54 55
 
55 56
 
56 57
 var handlers = [
57  
-	{ path: "/who", handler: function(request, response) {
  58
+	{ path: "/who", handler: function(channel, request, response) {
58 59
 		var nicks = [];
59  
-		var sessions = servers[0].channels[0].sessions;
60  
-		for (var id in sessions) {
61  
-			nicks.push(sessions[id].nick);
  60
+		for (var id in channel.sessions) {
  61
+			nicks.push(channel.sessions[id].nick);
62 62
 		}
63 63
 		response.simpleJSON(200, { nicks: nicks });
64 64
 	} },
65  
-	{ path: "/join", handler: function(request, response) {
  65
+	{ path: "/join", handler: function(channel, request, response) {
66 66
 		var nick = qs.parse(url.parse(request.url).query).nick;
67  
-		var channel = servers[0].channels[0];
  67
+		
68 68
 		if (!nick) {
69 69
 			response.simpleJSON(400, { error: "bad nick." });
70 70
 			return;
@@ -78,21 +78,21 @@ var handlers = [
78 78
 		channel.appendMessage(nick, "join");
79 79
 		response.simpleJSON(200, { id: session.id, nick: nick });
80 80
 	} },
81  
-	{ path: "/part", handler: function(request, response) {
  81
+	{ path: "/part", handler: function(channel, request, response) {
82 82
 		var id = qs.parse(url.parse(request.url).query).id;
83  
-		var channel = servers[0].channels[0];
  83
+		
84 84
 		// TODO: can we remove the check and just always call destroySession()?
85 85
 		if (id && channel.sessions[id]) {
86 86
 			channel.destroySession(id);
87 87
 		}
88 88
 		response.simpleJSON(200, {});
89 89
 	} },
90  
-	{ path: "/recv", handler: function(request, response) {
  90
+	{ path: "/recv", handler: function(channel, request, response) {
91 91
 		var query = qs.parse(url.parse(request.url).query),
92 92
 			since = query.since,
93 93
 			id = query.id,
94 94
 			session;
95  
-		var channel = servers[0].channels[0];
  95
+		
96 96
 		if (!since) {
97 97
 			response.simpleJSON(400, { error: "Must supply since parameter." });
98 98
 			return;
@@ -106,12 +106,11 @@ var handlers = [
106 106
 			response.simpleJSON(200, { messages: messages });
107 107
 		});
108 108
 	} },
109  
-	{ path: "/send", handler: function(request, response) {
  109
+	{ path: "/send", handler: function(channel, request, response) {
110 110
 		var query = qs.parse(url.parse(request.url).query),
111 111
 			id = query.id,
112 112
 			text = query.text;
113 113
 		
114  
-		var channel = servers[0].channels[0];
115 114
 		var session = channel.sessions[id];
116 115
 		if (!session || !text) {
117 116
 			response.simpleJSON(400, { error: "No such session id." });
@@ -144,3 +143,13 @@ function expireOldSessions() {
144 143
 }
145 144
 // TODO: don't expire unless we have at least one server with one channel
146 145
 expireOldSessions();
  146
+
  147
+var slice = [].slice;
  148
+Function.prototype.partial = function() {
  149
+	var fn = this,
  150
+		args = slice.call(arguments);
  151
+	
  152
+	return function() {
  153
+		return fn.apply(this, args.concat(slice.call(arguments)));
  154
+	};
  155
+};
2  lib/session.js
@@ -19,4 +19,4 @@ process.mixin(Session.prototype, {
19 19
 	} 
20 20
 });
21 21
 
22  
-exports.Session = Session;
  22
+exports.Session = Session;

0 notes on commit 6936672

Please sign in to comment.
Something went wrong with that request. Please try again.