forked from marccampbell/node-autocomplete
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request marccampbell#3 from georgeye/master
server code
- Loading branch information
Showing
3 changed files
with
288 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
var config = {}; | ||
|
||
config.maxFiles = 1; | ||
config.filePrefix = "confFile"; | ||
config.fileSuffix = ".conf"; | ||
config.fileLocation = "./"; | ||
config.logFile = './trace.log'; | ||
config.logLevel = 3; | ||
|
||
module.exports = config; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,175 @@ | ||
module.exports = require('./lib/autocomplete'); | ||
var net = require('net'), sys = require('sys'), fs = require('fs'), lazy = require('lazy'); | ||
var winston = require('winston'); | ||
var parser = require("./lib/message"); | ||
var autocomplete = require('./lib/autocomplete'); | ||
var config = require('./config'); | ||
|
||
//initialized logging (winston) | ||
winston.add(winston.transports.File, { filename: config.logFile}); | ||
winston.remove(winston.transports.Console); | ||
var a = autocomplete.connectAutocomplete(); | ||
|
||
initServer(config, a); | ||
|
||
var server = net.createServer(function (stream) { | ||
stream.setEncoding("utf8"); | ||
stream.on("connect", initStream); | ||
stream.on("data", handleReceive); | ||
stream.on("end", function () { | ||
stream.end(); | ||
logInfo('stream end, closing'); | ||
}); | ||
|
||
stream.on("error", function(error) { | ||
logError(error); | ||
stream.end(); | ||
}); | ||
}); | ||
server.listen(5050, "127.0.0.1"); | ||
// }); | ||
|
||
function handleReceive(data) { | ||
// console.log('received ' + data.length + ' bytes of data'); | ||
this.myRequest.inBuffer = this.myRequest.inBuffer + data; | ||
// console.log('total length=' + this.myRequest.inBuffer.length); | ||
for(; ;) { | ||
var rc = parser.parse(this.myRequest); | ||
if(rc) { | ||
logDebug('read a request, start to handle'); | ||
// start to handle payload | ||
var payload = this.myRequest.inBuffer.substr(this.myRequest.headerLength+4, this.myRequest.contentLength); | ||
//logDebug('received content:' + payload); | ||
var jPayload = JSON.parse(payload); | ||
if(jPayload.method === 'add') { | ||
//handle add | ||
processAdd(jPayload); | ||
} | ||
else if(jPayload.method === 'remove') { | ||
//handle remove | ||
processRemove(jPayload); | ||
} | ||
else if(jPayload.method === 'search') { | ||
processSearch(jPayload, this); | ||
} | ||
resetStream(this.myRequest); | ||
} | ||
else if(this.myRequest.needRead) { | ||
break; | ||
} | ||
else { | ||
logError("in error, close the stream"); | ||
this.end(); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
function initStream() { | ||
this.myRequest = new Object; | ||
this.myRequest.inBuffer = ""; | ||
this.myRequest.contentLength = 0; | ||
this.myRequest.needRead = true; | ||
this.myRequest.headerReceived = false; | ||
this.myRequest.headerLength = 0; | ||
this.myRequest.requestId = ""; | ||
//console.log("a new connection\n"); | ||
// sys.puts(sys.inspect(socket, false)); | ||
} | ||
|
||
function processAdd(data) { | ||
logInfo('in add operation'); | ||
var items = data.data; | ||
for(var i = 0; i < items.length; i++) { | ||
if(items[i].key.length > 0 && items[i].value) { | ||
// console.log('add item:' + items[i]); | ||
a.addElement(items[i]); | ||
} | ||
else if(item[i].key.length > 0 && !items[i].value) { | ||
// console.log('add item:' + items[i].key); | ||
a.addElement(items[i].key); | ||
} | ||
} | ||
} | ||
|
||
function processRemove(data) { | ||
logInfo('in remove operation'); | ||
var items = data.data; | ||
for(var i = 0; i < items.length; i++) { | ||
if(items[i].key.length > 0) { | ||
logInfo('remove item:' + items[i].key); | ||
a.removeElement(items[i].key); | ||
} | ||
} | ||
} | ||
|
||
function processSearch(data, socket ) { | ||
logInfo('in search operation'); | ||
var results = []; | ||
var items = data.data; | ||
if(items.length > 0) { | ||
results = a.search(data.data[0].key); | ||
} | ||
// send resutls back | ||
var response = new Object(); | ||
response.method = 'search'; | ||
response.data = results.slice(0,20); //only return 20 items | ||
var jresp = JSON.stringify(response); | ||
var wire ='Content-Length:' + jresp.length + '\r\n'; | ||
wire = wire + 'Request-Id:' + socket.myRequest.requestId + '\r\n\r\n' + jresp; | ||
//logDebug("total lenght is:" + wire.length); | ||
//logDebug(wire); | ||
socket.write(wire); | ||
} | ||
|
||
function resetStream(request) { | ||
// move remaining data to the front | ||
request.inBuffer = request.inBuffer.substr(request.headerLength+4 + request.contentLength); | ||
request.headerLength = 0; | ||
request.contentLength = 0; | ||
request.needRead = true; | ||
request.headerReceived = false; | ||
request.requestId = ""; | ||
} | ||
|
||
function initServer(config, AutoComplete) { | ||
for(var i = 0; i < config.maxFiles; i++) { | ||
var fileName = config.fileLocation + config.filePrefix + i + config.fileSuffix; | ||
// console.log('file name=' + fileName); | ||
new lazy(fs.createReadStream(fileName)) | ||
.lines | ||
.forEach(function(line) { | ||
var kv = line.toString().split(':'); | ||
//console.log('add key/value: ' + kv); | ||
if(kv.length > 1) { | ||
var item = new Object(); | ||
item.key = kv[0]; | ||
item.value = kv[1]; | ||
AutoComplete.addElement(item); | ||
} | ||
else { | ||
AutoComplete.addElement(kv[0]); | ||
} | ||
} | ||
); | ||
} | ||
} | ||
|
||
function logInfo(log) { | ||
if(config.logLevel >= 4) { | ||
var current = new Date(); | ||
winston.info(current + ': ' + log); | ||
} | ||
} | ||
function logDebug(log) { | ||
if(config.logLevel >=5) { | ||
var current = new Date(); | ||
winston.debug(current + ': ' + log); | ||
} | ||
} | ||
function logError(log) { | ||
if(config.logLevel >= 2) { | ||
var current = new Date(); | ||
winston.error(current + ': ' + log); | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
|
||
exports.parse = function(request) { | ||
var MAXHEADERLENGTH = 100; | ||
//check if request header is received | ||
var rc = false; | ||
//console.log('in parser'); | ||
if(request.headerReceived) { // to get the content then | ||
if(request.inBuffer.length >= (request.headerLength + request.contentLength + 4)) { | ||
rc = true; | ||
request.needRead = false; | ||
} | ||
else { | ||
request.needRead = true; | ||
} | ||
} | ||
else { | ||
var index = -1; | ||
// console.log('try to get header'); | ||
index = request.inBuffer.indexOf("\r\n\r\n"); | ||
if(index != -1) { | ||
// console.log('header received'); | ||
request.headerReceived = true; | ||
request.headerLength = index; | ||
var rc1 = parseHeader(request); | ||
// check if content is received | ||
if(rc1) { | ||
// console.log('contentLenght=' + request.contentLength + ' requestId=' + request.requestId); | ||
// console.log('total message Len:' + request.inBuffer.length + ' contentLenght=' + request.contentLength + ' requestHeaderLength=' + request.headerLength); | ||
if(request.inBuffer.length >= (request.headerLength + request.contentLength + 4)) { | ||
rc = true; | ||
request.needRead = false; | ||
} | ||
else { | ||
request.needRead = true; | ||
} | ||
} | ||
else { // something wrong in header | ||
request.needRead = false; | ||
rc = false; | ||
} | ||
} | ||
else { | ||
if(request.inBuffer.length > MAXHEADERLENGTH) { // must be bad request | ||
rc = false; | ||
request.needRead = false; | ||
} | ||
else { | ||
request.needRead = true; | ||
} | ||
// console.log('need to read more'); | ||
} | ||
} | ||
return rc; | ||
}; | ||
|
||
function parseHeader(request) { | ||
var rc = true; | ||
var subHeaders = request.inBuffer.split("\r\n"); | ||
request.contentLength = getContentLength(subHeaders); | ||
request.requestId = getRequestId(subHeaders); | ||
if(request.contentLength == 0 || request.requestId == "") { | ||
rc = false; | ||
} | ||
return rc; | ||
} | ||
|
||
function getContentLength(headers) { | ||
var index = -1, i =0; | ||
var length = 0; | ||
for(i = 0; i < headers.length; i++) { | ||
if(headers[i].indexOf("Content-Length") != -1) { | ||
var subString = headers[i].split(":"); | ||
if(subString.length == 2) { | ||
length = parseInt(subString[1]); | ||
if(isNaN(length)) { | ||
length = 0; | ||
} | ||
} | ||
break; | ||
} | ||
} | ||
//console.log('contentLength:' + length); | ||
return length; | ||
} | ||
|
||
function getRequestId(headers) { | ||
var i =0; | ||
var requestId = ""; | ||
for(i = 0; i < headers.length; i++) { | ||
if(headers[i].indexOf("Request-Id") != -1) { | ||
var subString = headers[i].split(":"); | ||
if(subString.length == 2) { | ||
//remove leading and trailing whitespace | ||
requestId = subString[1].replace(/^\s+|\s+$/g, '') ; | ||
} | ||
break; | ||
} | ||
} | ||
//console.log('requestid:' + requestId); | ||
return requestId; | ||
} | ||
|
||
|