1
/* Copyright (C) 2000-2005 Thomas Bopp, Thorsten Hampel, Ludger Merkens
3
* This program is free software; you can redistribute it and/or modify
4
* it under the terms of the GNU General Public License as published by
5
* the Free Software Foundation; either version 2 of the License, or
6
* (at your option) any later version.
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU General Public License for more details.
13
* You should have received a copy of the GNU General Public License
14
* along with this program; if not, write to the Free Software
15
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
* $Id: client_base.pike,v 1.3 2006/10/03 13:02:07 astra Exp $
20
constant cvs_version="$Id: client_base.pike,v 1.3 2006/10/03 13:02:07 astra Exp $";
22
inherit "kernel/socket";
23
inherit "net/coal/binary";
32
#define DEBUG_CLIENT(s, args...) werror(s+"\n", args)
34
#define DEBUG_CLIENT(s, args...)
37
private static mapping mObjects; // objects
38
private static string sLastPacket; // last package while communicating
39
private static int iOID; // the object id of the current object
40
private static int iTID; // the current transaction id
41
private static int iWaitTID;
42
static mapping mVariables; // session variables
44
static int __connected;
45
static int __downloadBytes;
47
static function downloadStore;
48
static mapping mEvents;
50
private static mixed miResult;
51
private static int miCommand;
53
static Thread.Mutex cmd_mutex = Thread.Mutex();
54
static Thread.Condition cmd_cond = Thread.Condition();
55
static Thread.Queue resultQueue = Thread.Queue();
56
static Thread.Queue cmdQueue = Thread.Queue();
57
static object cmd_lock;
59
string connected_server;
64
private static int oID;
65
private static string identifier = 0;
66
private static int cl = 0;
67
private static int(0..1) nowait;
68
private static mapping(string:function) functions=([]);
74
int get_object_class() {
77
int id = set_object(oID);
78
mixed res = send_command(COAL_COMMAND, ({ "get_object_class" }));
87
string get_identifier() {
88
if ( !stringp(identifier) ) {
90
int id = set_object(oID);
91
identifier = send_command(COAL_COMMAND, ({ "get_identifier" }));
103
return 1; // PSTAT_SAVE_OK
106
int no_wait(void|int(0..1) _nowait)
108
if(!zero_type(_nowait) && nowait == !_nowait)
117
string function_name(function fun)
119
return search(functions, fun);
125
catch{ describe=`->("describe")(); };
126
return sprintf("%s:%d/%s", connected_server, connected_port, describe);
129
function `->(string fun)
136
functions[fun]=lambda(mixed|void ... args) {
137
return send_cmd(oID, fun, args, nowait);
139
return functions[fun];
150
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
153
int set_object(int|object|string id)
158
if ( objectp(mVariables[id]) )
159
iOID = mVariables[id]->get_object_id();
161
iOID = mVariables[id];
163
else if ( objectp(id) )
164
iOID = id->get_object_id();
175
* @author Thomas Bopp (astra@upb.de)
178
static object find_obj(int id)
180
if ( !mObjects[id] ) {
181
mObjects[id] = SteamObj(id);
182
//werror("Created:"+master()->describe_object(mObjects[id])+"\n");
187
object find_object(int id) { return find_obj(id); }
195
* @author Thomas Bopp (astra@upb.de)
198
int connect_server(string server, int port)
212
if ( connect(server, port) ) {
213
MESSAGE("Connected to " + server + ":"+port +"\n");
214
connected_server=server;
216
__last_response = time(); // timestamp of last response
218
set_buffer(65536, "r");
219
set_buffer(65536, "w");
221
thread_create(read_thread);
222
thread_create(handle_commands);
232
static int write(string str)
234
__last_response = time();
238
static void handle_command(string func, mixed args) { }
240
void handle_commands()
243
while ( res = cmdQueue->read() ) {
245
if ( arrayp(res[1]) ) {
247
handle_command(res[1][0], res[1][1]);
250
werror("Fatal error while calling command: %O\n", err);
257
void read_callback(object id, string data)
259
__last_response = time();
261
if ( functionp(downloadStore) ) {
265
__downloadBytes -= strlen(data);
266
if ( __downloadBytes <= 0 ) {
268
downloadStore = 0; // download finished
273
if ( __downloadBytes > 0 ) {
274
if ( __downloadBytes <= strlen(sLastPacket) )
275
resultQueue->write(sLastPacket);
279
res = receive_binary(sLastPacket);
280
while ( arrayp(res) ) {
284
if ( cmd == COAL_EVENT ) {
285
DEBUG_CLIENT("Event %O", res[1]);
287
DEBUG_CLIENT("RCVD Package(%d): Waiting for %d\n", tid, iWaitTID);
288
sLastPacket = res[2];
289
if ( tid == iWaitTID ) {
291
miCommand = res[0][1];
292
resultQueue->write(miResult);
294
else if ( cmd == COAL_COMMAND ) {
295
cmdQueue->write(res);
297
res = receive_binary(sLastPacket);
301
string download(int bytes, void|function store)
303
// actually the last command should have been the upload response,
304
// so there shouldnt be anything on the line except events
305
// which should have been already processed
306
// everything else should be download data
308
__downloadBytes = bytes;
310
if ( functionp(store) ) {
311
data = copy_value(sLastPacket[..bytes]);
312
__downloadBytes -= strlen(data);
313
if ( strlen(data) > 0 )
315
if ( __downloadBytes <= 0 ) {
319
downloadStore = store;
324
if ( strlen(sLastPacket) >= bytes ) {
325
data = copy_value(sLastPacket[..bytes]);
326
if ( bytes > strlen(sLastPacket) )
327
sLastPacket = sLastPacket[bytes+1..];
334
miResult = resultQueue->read();
335
data = copy_value(sLastPacket[..bytes]);
336
if ( strlen(sLastPacket) > bytes )
337
sLastPacket = sLastPacket[bytes+1..];
349
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
352
void handle_error(mixed err)
362
* @author Thomas Bopp (astra@upb.de)
365
mixed send_command(int cmd, array(mixed) args, int|void no_wait)
367
if ( !no_wait ) iWaitTID = iTID;
371
string msg = coal_compose(iTID++, cmd, iOID, 0, args);
372
string nmsg = copy_value(msg);
375
if ( no_wait ) return 0;
377
mixed result = resultQueue->read();
378
if ( miCommand == COAL_ERROR ) {
379
handle_error(result);
384
void subscribe_event(object obj, int eid, function callback)
386
int oid = set_object(obj);
387
send_command(COAL_SUBSCRIBE, ({ eid }) );
388
mEvents[eid] = callback;
392
mixed send_cmd(object|int obj, string func, mixed|void args, void|int no_wait)
394
int oid = set_object(obj);
395
if ( zero_type(args) )
397
else if ( !arrayp(args) )
400
mixed res = send_command(COAL_COMMAND, ({ func, args }), no_wait);
406
login(string name, string pw, int features, string|void cname, int|void novars)
408
if ( !stringp(cname) )
409
cname = "steam-pike";
413
loginData =send_command(COAL_LOGIN, ({ name, pw, cname, features, __id }));
416
send_command(COAL_LOGIN,({ name, pw, cname,CLIENT_FEATURES_ALL, __id}));
418
if ( arrayp(loginData) && sizeof(loginData) >= 9 ) {
419
mVariables["user"] = iOID;
420
foreach ( indices(loginData[8]), string key ) {
421
mVariables[key] = loginData[8][key];
423
mVariables["rootroom"] = loginData[6];
426
foreach ( values(loginData[9]), object cl ) {
427
set_object(cl->get_object_id());
428
mVariables[send_cmd(cl,"get_identifier")] = cl;
436
mixed get_variable(string key)
438
return mVariables[key];
444
write(coal_compose(0, COAL_LOGOUT, 0, 0, 0));
450
resultQueue->write("");
455
void write_error2file(mixed|string err, int recursive) {
457
Stdio.File error_file;
459
array(string) directory;
463
directory = get_dir(path);
466
tmp_found=Stdio.exist(path+"/install_error."+file_counter);
468
file_counter = file_counter + 1;
476
file_counter = file_counter -1;
477
error_file=Stdio.File (path+"/install_error."+file_counter ,"cwa");
479
error_file->write(err);
482
foreach(err, mixed error){
483
if ( stringp(error) || intp(error) )
484
error_file->write((string)error);
485
else if ( objectp(error) )
486
error_file->write("<object...>\n");
487
else if ( arrayp(error) ){
488
write_error2file(error,1);