~ubuntu-branches/ubuntu/wily/steam/wily

« back to all changes in this revision

Viewing changes to client/client_base.pike

  • Committer: Package Import Robot
  • Author(s): Felix Geyer
  • Date: 2013-10-29 19:51:18 UTC
  • mfrom: (1.1.4) (0.1.4 trusty-proposed)
  • Revision ID: package-import@ubuntu.com-20131029195118-b9bxciz5hwx5z459
Tags: 1:1.0.0.39-2ubuntu1
Add an epoch to the version number as there was an unrelated steam package
in the archive with a higher version number.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2000-2005  Thomas Bopp, Thorsten Hampel, Ludger Merkens
2
 
 *
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.
7
 
 *
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.
12
 
 *
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
16
 
 * 
17
 
 * $Id: client_base.pike,v 1.3 2006/10/03 13:02:07 astra Exp $
18
 
 */
19
 
 
20
 
constant cvs_version="$Id: client_base.pike,v 1.3 2006/10/03 13:02:07 astra Exp $";
21
 
 
22
 
inherit "kernel/socket";
23
 
inherit "net/coal/binary";
24
 
 
25
 
#include <coal.h>
26
 
#include <macros.h>
27
 
#include <client.h>
28
 
 
29
 
#undef CLIENT_DEBUG
30
 
 
31
 
#ifdef CLIENT_DEBUG
32
 
#define DEBUG_CLIENT(s, args...) werror(s+"\n", args)
33
 
#else
34
 
#define DEBUG_CLIENT(s, args...)
35
 
#endif
36
 
 
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
43
 
        static array           aEvents;
44
 
        static int         __connected;
45
 
        static int     __downloadBytes;
46
 
               int     __last_response;
47
 
        static function  downloadStore;
48
 
        static mapping         mEvents;
49
 
 
50
 
private static mixed          miResult;
51
 
private static int           miCommand;
52
 
 
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;
58
 
 
59
 
string connected_server;
60
 
int connected_port;
61
 
 
62
 
class SteamObj 
63
 
{
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=([]);
69
 
  
70
 
  int get_object_id() {
71
 
    return oID;
72
 
  }
73
 
 
74
 
  int get_object_class() {
75
 
    if ( cl == 0 ) {
76
 
      int wid = iWaitTID;
77
 
      int id = set_object(oID);
78
 
      mixed res = send_command(COAL_COMMAND, ({ "get_object_class" }));
79
 
      if ( intp(res) )
80
 
          cl = res;
81
 
      set_object(id);
82
 
      iWaitTID = wid;
83
 
    }
84
 
    return cl;
85
 
  }
86
 
 
87
 
  string get_identifier() {
88
 
    if ( !stringp(identifier) ) {
89
 
      int wid = iWaitTID;
90
 
      int id = set_object(oID);
91
 
      identifier = send_command(COAL_COMMAND, ({ "get_identifier" }));
92
 
      set_object(id);
93
 
      iWaitTID = wid;
94
 
    }
95
 
    return identifier;
96
 
  }
97
 
 
98
 
  void create(int id) {
99
 
    oID = id;
100
 
  }
101
 
 
102
 
  int status() {
103
 
    return 1; // PSTAT_SAVE_OK
104
 
  }
105
 
 
106
 
  int no_wait(void|int(0..1) _nowait)
107
 
  {
108
 
    if(!zero_type(_nowait) && nowait == !_nowait)
109
 
    {
110
 
      nowait=!!_nowait;
111
 
      return !nowait;
112
 
    }
113
 
    else
114
 
      return nowait;
115
 
  }
116
 
 
117
 
  string function_name(function fun)
118
 
  {
119
 
    return search(functions, fun);
120
 
  }
121
 
 
122
 
  string _sprintf()
123
 
  {
124
 
    string describe="";
125
 
    catch{ describe=`->("describe")(); };
126
 
    return sprintf("%s:%d/%s", connected_server, connected_port, describe);
127
 
  }
128
 
 
129
 
  function `->(string fun) 
130
 
  {
131
 
    if(::`->(fun))
132
 
      return ::`->(fun);
133
 
    else
134
 
    {
135
 
      if(!functions->fun)
136
 
        functions[fun]=lambda(mixed|void ... args) { 
137
 
                         return send_cmd(oID, fun, args, nowait); 
138
 
                       };
139
 
      return functions[fun];
140
 
    }
141
 
  }
142
 
};
143
 
 
144
 
 
145
 
/**
146
 
 *
147
 
 *  
148
 
 * @param 
149
 
 * @return 
150
 
 * @author <a href="mailto:astra@upb.de">Thomas Bopp</a>) 
151
 
 * @see 
152
 
 */
153
 
int set_object(int|object|string id)
154
 
{
155
 
    int oldID = iOID;
156
 
 
157
 
    if ( stringp(id) ) {
158
 
        if ( objectp(mVariables[id]) )
159
 
            iOID = mVariables[id]->get_object_id();
160
 
        else
161
 
            iOID = mVariables[id];
162
 
    }
163
 
    else if ( objectp(id) )
164
 
        iOID = id->get_object_id();
165
 
    else
166
 
        iOID = id;
167
 
    return oldID;
168
 
}
169
 
 
170
 
/**
171
 
 *
172
 
 *  
173
 
 * @param 
174
 
 * @return 
175
 
 * @author Thomas Bopp (astra@upb.de) 
176
 
 * @see 
177
 
 */
178
 
static object find_obj(int id)
179
 
{
180
 
    if ( !mObjects[id] ) {
181
 
        mObjects[id] = SteamObj(id);
182
 
        //werror("Created:"+master()->describe_object(mObjects[id])+"\n");
183
 
    }
184
 
    return mObjects[id];
185
 
}
186
 
 
187
 
object find_object(int id) { return find_obj(id); }
188
 
 
189
 
 
190
 
/**
191
 
 *
192
 
 *  
193
 
 * @param 
194
 
 * @return 
195
 
 * @author Thomas Bopp (astra@upb.de) 
196
 
 * @see 
197
 
 */
198
 
int connect_server(string server, int port)
199
 
{
200
 
    iTID = 1;
201
 
    iOID = 0;
202
 
 
203
 
    sLastPacket     = "";
204
 
    __downloadBytes =  0;
205
 
    mVariables      = ([ ]);
206
 
    mObjects        = ([ ]);
207
 
    aEvents         = ({ });
208
 
    mEvents         = ([ ]);
209
 
    
210
 
    open_socket();
211
 
    set_blocking();
212
 
    if ( connect(server, port) ) {
213
 
        MESSAGE("Connected to " + server + ":"+port +"\n");
214
 
        connected_server=server;
215
 
        connected_port=port;
216
 
        __last_response = time(); // timestamp of last response 
217
 
        __connected = 1;
218
 
        set_buffer(65536, "r");
219
 
        set_buffer(65536, "w");
220
 
        set_blocking();
221
 
        thread_create(read_thread);
222
 
        thread_create(handle_commands);
223
 
        return 1;
224
 
    }
225
 
    return 0;
226
 
}
227
 
 
228
 
void create()
229
 
{
230
 
}
231
 
 
232
 
static int write(string str)
233
 
{
234
 
    __last_response = time();
235
 
    return ::write(str);
236
 
}
237
 
 
238
 
static void handle_command(string func, mixed args) { }
239
 
 
240
 
void handle_commands() 
241
 
{
242
 
  mixed res;
243
 
  while ( res = cmdQueue->read() ) {
244
 
      if ( arrayp(res) ) {
245
 
        if ( arrayp(res[1]) ) {
246
 
          mixed err = catch {
247
 
            handle_command(res[1][0], res[1][1]);
248
 
          };
249
 
          if ( err != 0 )
250
 
            werror("Fatal error while calling command: %O\n", err);
251
 
        }
252
 
      }
253
 
  }
254
 
}
255
 
 
256
 
 
257
 
void read_callback(object id, string data)
258
 
{
259
 
    __last_response = time();
260
 
    
261
 
    if ( functionp(downloadStore) ) {
262
 
        mixed err = catch {
263
 
            downloadStore(data);
264
 
        };
265
 
        __downloadBytes -= strlen(data);
266
 
        if ( __downloadBytes <= 0 ) {
267
 
            downloadStore(0);
268
 
            downloadStore = 0; // download finished
269
 
        }
270
 
        return;
271
 
    }
272
 
    sLastPacket += data;
273
 
    if ( __downloadBytes > 0 ) {
274
 
        if ( __downloadBytes <= strlen(sLastPacket) )
275
 
            resultQueue->write(sLastPacket);
276
 
        return;
277
 
    }
278
 
    mixed res;
279
 
    res = receive_binary(sLastPacket);
280
 
    while ( arrayp(res) ) {
281
 
        int tid = res[0][0];
282
 
        int cmd = res[0][1];
283
 
        
284
 
        if ( cmd == COAL_EVENT ) {
285
 
            DEBUG_CLIENT("Event %O", res[1]);
286
 
        }
287
 
        DEBUG_CLIENT("RCVD Package(%d): Waiting for %d\n", tid, iWaitTID);
288
 
        sLastPacket = res[2];
289
 
        if ( tid == iWaitTID ) {
290
 
            miResult = res[1];
291
 
            miCommand = res[0][1];
292
 
            resultQueue->write(miResult);
293
 
        }
294
 
        else if ( cmd == COAL_COMMAND ) {
295
 
            cmdQueue->write(res);
296
 
        }
297
 
        res = receive_binary(sLastPacket);
298
 
    }
299
 
}
300
 
 
301
 
string download(int bytes, void|function store) 
302
 
{
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
307
 
    string data;
308
 
    __downloadBytes = bytes;
309
 
 
310
 
    if ( functionp(store) ) {
311
 
        data = copy_value(sLastPacket[..bytes]);
312
 
        __downloadBytes -= strlen(data);
313
 
        if ( strlen(data) > 0 )
314
 
            store(data);
315
 
        if ( __downloadBytes <= 0 ) {
316
 
            store(0);
317
 
            return "";
318
 
        }
319
 
        downloadStore = store;
320
 
        return "";
321
 
    }
322
 
    downloadStore = 0;
323
 
 
324
 
    if ( strlen(sLastPacket) >= bytes ) {
325
 
        data = copy_value(sLastPacket[..bytes]);
326
 
        if ( bytes > strlen(sLastPacket) )
327
 
            sLastPacket = sLastPacket[bytes+1..];
328
 
        else
329
 
            sLastPacket = "";
330
 
        __downloadBytes = 0;
331
 
        return data;
332
 
    }
333
 
 
334
 
    miResult = resultQueue->read();
335
 
    data = copy_value(sLastPacket[..bytes]);
336
 
    if ( strlen(sLastPacket) > bytes )
337
 
        sLastPacket = sLastPacket[bytes+1..];
338
 
    else
339
 
        sLastPacket = "";
340
 
    __downloadBytes = 0;
341
 
    return data;
342
 
}
343
 
 
344
 
/**
345
 
 *
346
 
 *  
347
 
 * @param 
348
 
 * @return 
349
 
 * @author <a href="mailto:astra@upb.de">Thomas Bopp</a>) 
350
 
 * @see 
351
 
 */
352
 
void handle_error(mixed err)
353
 
{
354
 
    throw(err);
355
 
}
356
 
 
357
 
/**
358
 
 *
359
 
 *  
360
 
 * @param 
361
 
 * @return 
362
 
 * @author Thomas Bopp (astra@upb.de) 
363
 
 * @see 
364
 
 */
365
 
mixed send_command(int cmd, array(mixed) args, int|void no_wait)
366
 
{
367
 
    if ( !no_wait ) iWaitTID = iTID;
368
 
    aEvents  = ({ });
369
 
 
370
 
    
371
 
    string msg = coal_compose(iTID++, cmd, iOID, 0, args);
372
 
    string nmsg = copy_value(msg);
373
 
 
374
 
    send_message(nmsg);
375
 
    if ( no_wait ) return 0;
376
 
     
377
 
    mixed result = resultQueue->read();
378
 
    if ( miCommand == COAL_ERROR ) {
379
 
        handle_error(result);
380
 
    }
381
 
    return result;
382
 
}
383
 
 
384
 
void subscribe_event(object obj, int eid, function callback)
385
 
{
386
 
  int oid = set_object(obj);
387
 
  send_command(COAL_SUBSCRIBE, ({ eid }) );
388
 
  mEvents[eid] = callback;
389
 
  set_object(oid);
390
 
}
391
 
 
392
 
mixed send_cmd(object|int obj, string func, mixed|void args, void|int no_wait)
393
 
{
394
 
    int oid = set_object(obj);
395
 
    if ( zero_type(args) )
396
 
        args = ({ });
397
 
    else if ( !arrayp(args) )
398
 
        args = ({ args });
399
 
    
400
 
    mixed res = send_command(COAL_COMMAND, ({ func, args }), no_wait);
401
 
    set_object(oid);
402
 
    return res;
403
 
}
404
 
 
405
 
mixed 
406
 
login(string name, string pw, int features, string|void cname, int|void novars)
407
 
{
408
 
    if ( !stringp(cname) )
409
 
        cname = "steam-pike";
410
 
    
411
 
    mixed loginData;
412
 
    if ( features != 0 )
413
 
        loginData =send_command(COAL_LOGIN, ({ name, pw, cname, features, __id }));
414
 
    else
415
 
        loginData =
416
 
            send_command(COAL_LOGIN,({ name, pw, cname,CLIENT_FEATURES_ALL, __id}));
417
 
    
418
 
    if ( arrayp(loginData) && sizeof(loginData) >= 9 ) {
419
 
        mVariables["user"] = iOID;
420
 
        foreach ( indices(loginData[8]), string key ) {
421
 
            mVariables[key] = loginData[8][key];
422
 
        }
423
 
        mVariables["rootroom"] = loginData[6];
424
 
        sLastPacket = "";
425
 
        if ( novars != 1 ) {
426
 
            foreach ( values(loginData[9]), object cl ) {
427
 
                set_object(cl->get_object_id());
428
 
                mVariables[send_cmd(cl,"get_identifier")] = cl;
429
 
            }
430
 
        }
431
 
        return name;
432
 
    }
433
 
    return 0;
434
 
}
435
 
 
436
 
mixed get_variable(string key)
437
 
{
438
 
  return mVariables[key];
439
 
}
440
 
 
441
 
mixed logout()
442
 
{
443
 
    __connected = 0;
444
 
    write(coal_compose(0, COAL_LOGOUT, 0, 0, 0));
445
 
}
446
 
 
447
 
 
448
 
void was_closed()
449
 
{
450
 
    resultQueue->write("");
451
 
    ::was_closed();
452
 
}
453
 
 
454
 
 
455
 
void write_error2file(mixed|string err, int recursive) {
456
 
 
457
 
    Stdio.File error_file;
458
 
    string             path;
459
 
    array(string) directory;
460
 
    int file_counter =0;
461
 
    int found=0;
462
 
    path = getcwd();
463
 
    directory = get_dir(path);
464
 
    while (found==0){
465
 
        int tmp_found=1;
466
 
        tmp_found=Stdio.exist(path+"/install_error."+file_counter);
467
 
        if (tmp_found==1){
468
 
            file_counter = file_counter + 1;
469
 
        }
470
 
        else{
471
 
            found = 1;
472
 
        }
473
 
    }
474
 
 
475
 
    if (recursive==1)
476
 
        file_counter = file_counter -1;
477
 
    error_file=Stdio.File (path+"/install_error."+file_counter ,"cwa");
478
 
    if (stringp (err)){
479
 
        error_file->write(err);
480
 
    }
481
 
    if(arrayp(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);
489
 
            }
490
 
        }
491
 
    }
492
 
    if (recursive!=0)
493
 
        error_file->close();
494
 
}