1 /* Copyright (C) 2000-2004 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.1 2008/03/31 13:39:57 exodusd Exp $
19 inherit "kernel/socket";
20 inherit "net/coal/binary";
24 class client_base : public socket,binary{
31 private mapping mObjects; // objects
32 private string sLastPacket; // last package while communicating
33 private int iOID; // the object id of the current object
34 private int iTID; // the current transaction id
36 mapping mVariables; // session variables
41 function downloadStore;
43 private mixed miResult;
44 private int miCommand;
47 Thread.Mutex cmd_mutex = Thread.Mutex();
48 Thread.Mutex newmut = Thread.Mutex();
49 Thread.Condition cmd_cond = Thread.Condition();
50 Thread.Queue resultQueue = Thread.Queue();
51 Thread.MutexKey newmutkey;
52 Thread.Condition th = Thread.Condition();
55 string connected_server;
62 private string identifier = 0;
64 private int(0..1) nowait;
65 private mapping(string:function) functions=([]);
71 object get_environment() {
72 return send_command(COAL_COMMAND, ({ "get_environment" }));
75 int get_object_class() {
78 int id = set_object(oID);
79 mixed res = send_command(COAL_COMMAND, ({ "get_object_class" }));
88 return 1; //PSTAT_SAVE_OK
91 string get_identifier() {
92 if ( !stringp(identifier) ) {
94 int id = set_object(oID);
95 identifier = send_command(COAL_COMMAND, ({ "get_identifier" }));
102 void create(int id) {
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);
124 mixed result = catch {
125 if(this_object()->__indices)
126 return this_object()->__indices();
135 catch{ describe=`->("describe")(); };
137 if ( stringp(connected_server) ) format += "%s:";
138 else format += "%O:";
139 if ( intp(connected_port) ) format += "%d/";
140 else format += "%O/";
141 if ( stringp(describe) ) format += "%s";
143 return sprintf( format, connected_server, connected_port, describe );
146 function `->(string fun)
152 if ( fun == "exec_code" )
154 else if ( fun == "serialize_coal" )
157 functions[fun]=lambda(mixed|void ... args)
159 return send_cmd(oID, fun, args, nowait);
161 return functions[fun];
164 function find_function(string fun) {
166 functions[fun]=lambda(mixed|void ... args)
168 return send_cmd(oID, fun, args, nowait);
170 return functions[fun];
182 int set_object(int|object id)
187 iOID = id->get_object_id();
201 object find_obj(int id)
203 if ( !mObjects[id] ) {
204 mObjects[id] = SteamObj(id);
205 //werror("Created:"+master()->describe_object(mObjects[id])+"\n");
212 object find_object(int id) { return find_obj(id); }
222 int connect_server(string server, int port)
235 if ( connect(server, port) ) {
236 MESSAGE("Connected to " + server + ":"+port +"\n");
237 connected_server=server;
239 __last_response = time(); // timestamp of last response
241 set_buffer(65536, "r");
242 set_buffer(65536, "w");
244 thread_create(read_thread);
255 int write(string str)
257 __last_response = time();
271 void read_callback(object id, string data)
273 __last_response = time();
275 if ( functionp(downloadStore) ) {
279 __downloadBytes -= strlen(data);
280 if ( __downloadBytes <= 0 ) {
282 downloadStore = 0; // download finished
287 if ( __downloadBytes > 0 ) {
288 if ( __downloadBytes <= strlen(sLastPacket) )
289 resultQueue->write(sLastPacket);
293 mixed res = receive_binary(sLastPacket);
298 sLastPacket = res[2];
299 if ( tid == iWaitTID ) {
301 miCommand = res[0][1];
302 resultQueue->write(miResult);
307 string download(int bytes, void|function store)
309 // actually the last command should have been the upload response,
310 // so there shouldnt be anything on the line except events
311 // which should have been already processed
312 // everything else should be download data
314 __downloadBytes = bytes;
316 if ( functionp(store) ) {
317 data = copy_value(sLastPacket[..bytes]);
318 __downloadBytes -= strlen(data);
319 if ( strlen(data) > 0 )
321 if ( __downloadBytes <= 0 ) {
325 downloadStore = store;
330 if ( strlen(sLastPacket) >= bytes ) {
331 data = copy_value(sLastPacket[..bytes]);
332 if ( bytes > strlen(sLastPacket) )
333 sLastPacket = sLastPacket[bytes+1..];
340 miResult = resultQueue->read();
341 data = copy_value(sLastPacket[..bytes]);
342 if ( strlen(sLastPacket) > bytes )
343 sLastPacket = sLastPacket[bytes+1..];
357 void handle_error(mixed err)
369 mixed send_command(int cmd, array args, int|void no_wait)
371 // newmutkey = newmut->lock(1);
372 if ( !no_wait ) iWaitTID = iTID;
375 string msg = coal_compose(iTID++, cmd, iOID, 0, args);
376 string nmsg = copy_value(msg);
379 if ( no_wait ) return 0;
382 Thread.Thread(check_thread);
383 result = resultQueue->read();
386 if ( miCommand == COAL_ERROR ) {
387 handle_error(result);
394 int start_time = time();
395 th->wait(cmd_mutex->lock(), 10);
396 if((time()-start_time) >=10){
397 resultQueue->write("sTeam connection lost.");
410 mixed send_cmd(object|int obj, string func, mixed|void args, void|int no_wait)
412 int oid = set_object(obj);
413 if ( zero_type(args) )
415 else if ( !arrayp(args) )
418 mixed res = send_command(COAL_COMMAND, ({ func, args }), no_wait);
431 login(string name, string pw, int features, string|void cname, int|void novars)
433 if ( !stringp(cname) )
434 cname = "steam-pike";
438 loginData =send_command(COAL_LOGIN, ({ name, pw, cname, features, __id }));
441 send_command(COAL_LOGIN,({ name, pw, cname,CLIENT_FEATURES_ALL, __id}));
443 if ( arrayp(loginData) && sizeof(loginData) >= 9 ) {
444 mVariables["user"] = iOID;
445 foreach ( indices(loginData[8]), string key ) {
446 mVariables[key] = loginData[8][key];
448 mVariables["rootroom"] = loginData[6];
451 foreach ( values(loginData[9]), object cl ) {
452 set_object(cl->get_object_id());
453 mVariables[send_cmd(cl,"get_identifier")] = cl;
463 werror("logout()!!!\n\n");
465 write(coal_compose(0, COAL_LOGOUT, 0, 0, 0));
471 resultQueue->write("");
476 void write_error2file(mixed|string err, int recursive) {
478 Stdio.File error_file;
484 directory = get_dir(path);
487 tmp_found=Stdio.exist(path+"/install_error."+file_counter);
489 file_counter = file_counter + 1;
497 file_counter = file_counter -1;
498 error_file=Stdio.File (path+"/install_error."+file_counter ,"cwa");
500 error_file->write(err);
503 foreach(err, mixed error){
504 if ( stringp(error) || intp(error) )
505 error_file->write((string)error);
506 else if ( objectp(error) )
507 error_file->write("<object...>\n");
508 else if ( arrayp(error) ){
509 write_error2file(error,1);