-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclient.js
More file actions
148 lines (117 loc) · 3.74 KB
/
client.js
File metadata and controls
148 lines (117 loc) · 3.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
function NowHs (server, port, readyCallback) {
this.socket = new WebSocket("ws://" + server + ":" + port);
this.socket.onopen = function () {
console.log("Socket opened");
};
var self = this;
this.currentFunId = 0;
// TODO deal with int overflow
this.genFunId = function () {
return self.currentFunId++;
};
this.callbacks = {};
this.socket.onmessage = function (msg) {
var msgJSON = JSON.parse(msg.data);
var functions = msgJSON[0];
var schemas = msgJSON[1];
// set up schemas
// first put in dummies
self.schemas = {};
for (var i in schemas) {
self.schemas[schemas[i].schemaName] = {};
}
// now create the schemas
for (var i in schemas) {
var fields = schemas[i].schemaFields;
var schema = self.schemas[schemas[i].schemaName];
for (var j in fields) {
schema[fields[j][0]] = self.createSchemaField (fields[j][1]);
}
}
// now for the functions
// first set up schemafields for the arguments
self.funcSchFields = {}
for (var i in functions) {
self.funcSchFields[functions[i].functionName] = []
for (var j in functions[i].functionArgTypes) {
self.funcSchFields[functions[i].functionName][j]
= self.createSchemaField (functions[i].functionArgTypes[j]);
}
}
// now set up wrapper functions
for (var i in functions) {
// using raw name for interface but qualified name internally
self[functions[i].functionNameRaw] = function (fun, schemaFields) { // closure needed
return function () {
// check arguments
if (arguments.length - 1 !== schemaFields.length) {
throw "Arity mismatch: " + schemaFields.length + " arguments + callback expected";
}
for (var arg = 0; arg < arguments.length - 1; arg++) {
jsschema.checkField (schemaFields[arg], arguments[arg]);
}
if (typeof arguments[arguments.length - 1] !== "function") {
throw "Last argument should be a callback function";
}
var functionCall = {
cFunName : fun.functionName,
cFunId : self.genFunId (),
cFunArgs : Array.prototype.slice.call (arguments, 0, arguments.length - 1) // retarded javascript
};
var jsn = JSON.stringify ({ ClientFCall: functionCall });
self.socket.send (jsn);
// TODO: FIGURE OUT asynchronous calls (generate hash for each fcall?)
var func = arguments[arguments.length - 1]; // freaking scoped arguments wtf javascript
self.callbacks[functionCall.cFunId] = func;
self.socket.onmessage = function (msg) {
var res = JSON.parse (msg.data);
// res = {
// type: "ServerFunctionReturn"
// value: {
// sFunId: [generated with genFunId at call]
// sRetVal: [callback data]
// }
// }
switch (res.type) {
case "ServerFunctionReturn":
self.callbacks[res.value.sFunId](res.value.sRetVal);
delete self.callbacks[res.value.sFunId];
break;
default:
console.error ("unhandled response type " + res.type);
}
};
}
} (functions[i], self.funcSchFields[functions[i].functionName]);
}
if (typeof readyCallback === "function") {
readyCallback ();
}
};
// returns primitive type or reference to schema
this.primOrSchema = function (obj) {
switch (obj.type) {
case "Prim":
return obj.value;
case "SchemaName":
return this.schemas[obj.value];
default:
throw ("Cannot happen" + obj.type);
}
};
this.createSchemaField = function (schFieldDesc) {
switch (schFieldDesc[0]) {
case "Required":
return jsschema.required (this.primOrSchema (schFieldDesc[1]));
break;
case "Optional":
return jsschema.optional (this.primOrSchema (schFieldDesc[1]));
break;
case "Repeated":
return jsschema.repeated (this.primOrSchema (schFieldDesc[1]));
break;
default:
throw ("Cannot happen: " + schFieldDesc[0]);
}
};
}