~profzoom/ubuntu/quantal/wmaker/bug-1079925

« back to all changes in this revision

Viewing changes to WINGs/Examples/server.c

  • Committer: Bazaar Package Importer
  • Author(s): Marcelo E. Magallon
  • Date: 2004-11-10 14:05:30 UTC
  • Revision ID: james.westby@ubuntu.com-20041110140530-qpd66b5lm38x7apk
Tags: upstream-0.91.0
ImportĀ upstreamĀ versionĀ 0.91.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  WINGs server.c: example how to create a network server using WMConnection
 
3
 *
 
4
 *  Copyright (c) 2001-2003 Dan Pascu
 
5
 *
 
6
 */
 
7
 
 
8
 
 
9
#include <stdio.h>
 
10
#include <stdlib.h>
 
11
#include <unistd.h>
 
12
#include <string.h>
 
13
 
 
14
#include <WINGs/WINGs.h>
 
15
 
 
16
 
 
17
#define _(P)         P
 
18
#define MAXCMD_SIZE  512
 
19
 
 
20
 
 
21
char *SEConnectionShouldBeRemovedNotification = "SEConnectionShouldBeRemovedNotification";
 
22
 
 
23
 
 
24
 
 
25
 
 
26
static void didReceiveInput(ConnectionDelegate *self, WMConnection *cPtr);
 
27
 
 
28
static void connectionDidDie(ConnectionDelegate *self, WMConnection *cPtr);
 
29
 
 
30
static void connectionDidTimeout(ConnectionDelegate *self, WMConnection *cPtr);
 
31
 
 
32
 
 
33
extern char *SEConnectionShouldBeRemovedNotification;
 
34
 
 
35
static WMUserDefaults *timeDB = NULL;
 
36
static char *ServerAddress = NULL;
 
37
static char *ServerPort = NULL;
 
38
static WMArray *allowedHostList = NULL;
 
39
static WMArray *clientConnections = NULL;
 
40
static WMConnection *serverPtr = NULL;
 
41
 
 
42
 
 
43
 
 
44
static ConnectionDelegate socketDelegate = {
 
45
    NULL,                 /* client data */
 
46
    NULL,                 /* canResumeSending */
 
47
    NULL,                 /* didCatchException */
 
48
    connectionDidDie,     /* didDie */
 
49
    NULL,                 /* didInitialize */
 
50
    didReceiveInput,      /* didReceiveInput */
 
51
    connectionDidTimeout  /* didTimeout */
 
52
};
 
53
 
 
54
 
 
55
 
 
56
void
 
57
wAbort(Bool foo)
 
58
{
 
59
    exit(1);
 
60
}
 
61
 
 
62
 
 
63
static void
 
64
printHelp(char *progname)
 
65
{
 
66
    printf(_("usage: %s [options]\n\n"), progname);
 
67
    puts(_(" --help                             print this message"));
 
68
    puts(_(" --listen [address:]port    only listen on the specified address/port"));
 
69
    puts(_(" --allow host1[,host2...]   only allow connections from listed hosts\n"));
 
70
    puts(_(" By default server listens on all interfaces and port 34567, unless"
 
71
           " something\nelse is specified with the --listen option. If address is"
 
72
           " omitted or the keyword\n'Any' is used, it will listen on all interfaces else"
 
73
           " only on the specified one.\n\nFor example --listen localhost: will"
 
74
           " listen on the default port 34567, but only\non connections comming"
 
75
           " in through the loopback interface.\n\n Also by default the server"
 
76
           " listens to incoming connections from any host,\nunless a list of"
 
77
           " hosts is given with the --allow option, in which case it will\nreject"
 
78
           " connections not comming from those hosts.\nThe list of hosts is comma"
 
79
           " separated and should NOT contain ANY spaces."));
 
80
}
 
81
 
 
82
 
 
83
static void
 
84
enqueueConnectionForRemoval(WMConnection *cPtr)
 
85
{
 
86
    WMNotification *notif;
 
87
 
 
88
    /*don't release notif here. it will be released by queue after processing */
 
89
    notif = WMCreateNotification(SEConnectionShouldBeRemovedNotification,
 
90
                                 cPtr, NULL);
 
91
    WMEnqueueNotification(WMGetDefaultNotificationQueue(), notif, WMPostASAP);
 
92
}
 
93
 
 
94
 
 
95
static int
 
96
sendMessage(WMConnection *cPtr, char *message)
 
97
{
 
98
    WMData *aData;
 
99
    int res;
 
100
 
 
101
    if (WMGetConnectionState(cPtr)!=WCConnected)
 
102
        return -1;
 
103
 
 
104
    aData = WMCreateDataWithBytes(message, strlen(message));
 
105
    res = WMSendConnectionData(cPtr, aData);
 
106
    WMReleaseData(aData);
 
107
 
 
108
    return res;
 
109
}
 
110
 
 
111
 
 
112
static Bool
 
113
enqueueMessage(WMConnection *cPtr, char *message)
 
114
{
 
115
    WMData *aData;
 
116
    Bool res;
 
117
 
 
118
    if (WMGetConnectionState(cPtr)!=WCConnected)
 
119
        return False;
 
120
 
 
121
    aData = WMCreateDataWithBytes(message, strlen(message));
 
122
    res = WMEnqueueConnectionData(cPtr, aData);
 
123
    WMReleaseData(aData);
 
124
 
 
125
    return res;
 
126
}
 
127
 
 
128
 
 
129
static unsigned char*
 
130
findDelimiter(unsigned char *data, unsigned const char *endPtr)
 
131
{
 
132
    wassertrv(data < endPtr, NULL);
 
133
 
 
134
    while (data<endPtr && *data!='\n' && *data!='\r' && *data!=';' && *data!='\0')
 
135
        data++;
 
136
 
 
137
    if (data < endPtr)
 
138
        return data;
 
139
 
 
140
    return NULL;
 
141
}
 
142
 
 
143
 
 
144
static WMArray*
 
145
getAvailableMessages(WMConnection *cPtr)
 
146
{
 
147
    char *ptr, *crtPos, *buffer;
 
148
    const char *bytes, *endPtr;
 
149
    WMData *aData, *receivedData, *holdData;
 
150
    WMRange range;
 
151
    WMArray *messages;
 
152
    int length;
 
153
 
 
154
    receivedData = WMGetConnectionAvailableData(cPtr);
 
155
    if (!receivedData)
 
156
        return NULL;
 
157
    if ((length=WMGetDataLength(receivedData))==0) {
 
158
        WMReleaseData(receivedData);
 
159
        return NULL;
 
160
    }
 
161
 
 
162
    holdData = (WMData*)WMGetConnectionClientData(cPtr);
 
163
    if (holdData) {
 
164
        WMAppendData(holdData, receivedData);
 
165
        WMReleaseData(receivedData);
 
166
        WMSetConnectionClientData(cPtr, NULL);
 
167
        aData = holdData;
 
168
    } else {
 
169
        aData = receivedData;
 
170
    }
 
171
 
 
172
    length = WMGetDataLength(aData);
 
173
    bytes = (char*)WMDataBytes(aData);
 
174
    endPtr = bytes + length;
 
175
 
 
176
    messages = WMCreateArrayWithDestructor(1, wfree);
 
177
    crtPos = (char*)bytes;
 
178
    while (crtPos<endPtr && (ptr = findDelimiter(crtPos, endPtr))!=NULL) {
 
179
        range.position = (crtPos - bytes);
 
180
        range.count = (ptr - crtPos);
 
181
        if (range.count > MAXCMD_SIZE) {
 
182
            /* Hmmm... The message is too long. Possibly that someone is
 
183
             * flooding us, or there is a dumb client which do not know
 
184
             * who is talking to. */
 
185
            sendMessage(cPtr, "Command too long\n\r");
 
186
            WMFreeArray(messages);
 
187
            WMReleaseData(aData);
 
188
            WMCloseConnection(cPtr);
 
189
            enqueueConnectionForRemoval(cPtr);
 
190
            return NULL;
 
191
        }
 
192
        buffer = wmalloc(range.count+1);
 
193
        WMGetDataBytesWithRange(aData, buffer, range);
 
194
        buffer[range.count] = '\0';
 
195
        WMAddToArray(messages, buffer);
 
196
        crtPos = ptr;
 
197
        while (crtPos<endPtr && (*crtPos=='\n' || *crtPos=='\r' ||
 
198
                                 *crtPos=='\t' || *crtPos=='\0' ||
 
199
                                 *crtPos==';' || *crtPos==' ')) {
 
200
            crtPos++;
 
201
        }
 
202
    }
 
203
 
 
204
    if (crtPos<endPtr) {
 
205
        range.position = (crtPos - bytes);
 
206
        range.count = (endPtr - crtPos);
 
207
        if (range.count > MAXCMD_SIZE) {
 
208
            /* Flooooooding!!!! */
 
209
            sendMessage(cPtr, "Message too long\n\r");
 
210
            WMFreeArray(messages);
 
211
            WMReleaseData(aData);
 
212
            WMCloseConnection(cPtr);
 
213
            enqueueConnectionForRemoval(cPtr);
 
214
            return NULL;
 
215
        }
 
216
        holdData = WMGetSubdataWithRange(aData, range);
 
217
        WMSetConnectionClientData(cPtr, holdData);
 
218
    }
 
219
    WMReleaseData(aData);
 
220
 
 
221
    if (WMGetArrayItemCount(messages)==0) {
 
222
        WMFreeArray(messages);
 
223
        messages = NULL;
 
224
    }
 
225
    return messages;
 
226
}
 
227
 
 
228
 
 
229
 
 
230
static void
 
231
complainAboutBadArgs(WMConnection *cPtr, char *cmdName, char *badArgs)
 
232
{
 
233
    char *buf = wmalloc(strlen(cmdName) + strlen(badArgs) + 100);
 
234
 
 
235
    sprintf(buf, _("Invalid parameters '%s' for command %s. Use HELP for"
 
236
                   " a list of commands.\n"), badArgs, cmdName);
 
237
    sendMessage(cPtr, buf);
 
238
    wfree(buf);
 
239
}
 
240
 
 
241
 
 
242
static void
 
243
sendUpdateMessage(WMConnection *cPtr, char *id, int time)
 
244
{
 
245
    char *buf = wmalloc(strlen(id) + 100);
 
246
 
 
247
    sprintf(buf, "%s has %i minutes left\n", id, time);
 
248
    sendMessage(cPtr, buf);
 
249
    wfree(buf);
 
250
}
 
251
 
 
252
 
 
253
static void
 
254
showId(WMConnection *cPtr)
 
255
{
 
256
    sendMessage(cPtr, "Server example based on WMConnection\n");
 
257
}
 
258
 
 
259
 
 
260
static void
 
261
showHelp(WMConnection *cPtr)
 
262
{
 
263
    char *buf = wmalloc(strlen(WMGetApplicationName()) + 16);
 
264
 
 
265
    sprintf(buf, _("%s commands:\n\n"), WMGetApplicationName());
 
266
 
 
267
    enqueueMessage(cPtr, _("\n"));
 
268
    enqueueMessage(cPtr, buf);
 
269
    enqueueMessage(cPtr, _("GET <id>\t- return time left (in minutes) "
 
270
                           "for user with id <id>\n"));
 
271
    enqueueMessage(cPtr, _("SET <id> <time>\t- set time limit to <time> "
 
272
                           "minutes for user with id <id>\n"));
 
273
    enqueueMessage(cPtr, _("ADD <id> <time>\t- add <time> minutes "
 
274
                           "for user with id <id>\n"));
 
275
    enqueueMessage(cPtr, _("SUB <id> <time>\t- subtract <time> minutes "
 
276
                           "for user with id <id>\n"));
 
277
    enqueueMessage(cPtr, _("REMOVE <id>\t- remove time limitations for "
 
278
                           "user with id <id>\n"));
 
279
    enqueueMessage(cPtr, _("LIST\t\t- list all users and their "
 
280
                           "corresponding time limit\n"));
 
281
    enqueueMessage(cPtr, _("ID\t\t- returns the Time Manager "
 
282
                           "identification string\n"));
 
283
    enqueueMessage(cPtr, _("EXIT\t\t- exits session\n"));
 
284
    enqueueMessage(cPtr, _("QUIT\t\t- exits session\n"));
 
285
    enqueueMessage(cPtr, _("HELP\t\t- show this message\n\n"));
 
286
    /* Just flush the queue we made before */
 
287
    WMFlushConnection(cPtr);
 
288
    wfree(buf);
 
289
}
 
290
 
 
291
 
 
292
static void
 
293
listUsers(WMConnection *cPtr)
 
294
{
 
295
    WMPropList *userList;
 
296
    char *id;
 
297
    int i, time;
 
298
 
 
299
    userList = WMGetUDKeys(timeDB);
 
300
 
 
301
    for (i=0; i<WMGetPropListItemCount(userList); i++) {
 
302
        id = WMGetFromPLString(WMGetFromPLArray(userList, i));
 
303
        time = WMGetUDIntegerForKey(timeDB, id);
 
304
        sendUpdateMessage(cPtr, id, time);
 
305
    }
 
306
 
 
307
    WMReleasePropList(userList);
 
308
}
 
309
 
 
310
 
 
311
static void
 
312
setTimeForUser(WMConnection *cPtr, char *cmdArgs)
 
313
{
 
314
    char *id;
 
315
    int i, time;
 
316
 
 
317
    id = wmalloc(strlen(cmdArgs));
 
318
    if (sscanf(cmdArgs, "%s %d", id, &time)!=2) {
 
319
        complainAboutBadArgs(cPtr, "SET", cmdArgs);
 
320
        wfree(id);
 
321
        return;
 
322
    }
 
323
    if (time<0)
 
324
        time = 0;
 
325
 
 
326
    WMSetUDIntegerForKey(timeDB, time, id);
 
327
 
 
328
    for (i=0; i<WMGetArrayItemCount(clientConnections); i++) {
 
329
        cPtr = WMGetFromArray(clientConnections, i);
 
330
        sendUpdateMessage(cPtr, id, time);
 
331
    }
 
332
    wfree(id);
 
333
}
 
334
 
 
335
 
 
336
static void
 
337
addTimeToUser(WMConnection *cPtr, char *cmdArgs)
 
338
{
 
339
    char *id;
 
340
    int i, time, newTime;
 
341
 
 
342
    id = wmalloc(strlen(cmdArgs));
 
343
    if (sscanf(cmdArgs, "%s %d", id, &time)!=2) {
 
344
        complainAboutBadArgs(cPtr, "ADD", cmdArgs);
 
345
        wfree(id);
 
346
        return;
 
347
    }
 
348
 
 
349
    newTime = WMGetUDIntegerForKey(timeDB, id) + time;
 
350
    if (newTime<0)
 
351
        newTime = 0;
 
352
 
 
353
    WMSetUDIntegerForKey(timeDB, newTime, id);
 
354
 
 
355
    for (i=0; i<WMGetArrayItemCount(clientConnections); i++) {
 
356
        cPtr = WMGetFromArray(clientConnections, i);
 
357
        sendUpdateMessage(cPtr, id, newTime);
 
358
    }
 
359
    wfree(id);
 
360
}
 
361
 
 
362
 
 
363
static void
 
364
subTimeFromUser(WMConnection *cPtr, char *cmdArgs)
 
365
{
 
366
    char *id;
 
367
    int i, time, newTime;
 
368
 
 
369
    id = wmalloc(strlen(cmdArgs));
 
370
    if (sscanf(cmdArgs, "%s %d", id, &time)!=2) {
 
371
        complainAboutBadArgs(cPtr, "SUB", cmdArgs);
 
372
        wfree(id);
 
373
        return;
 
374
    }
 
375
 
 
376
    newTime = WMGetUDIntegerForKey(timeDB, id) - time;
 
377
    if (newTime<0)
 
378
        newTime = 0;
 
379
 
 
380
    WMSetUDIntegerForKey(timeDB, newTime, id);
 
381
 
 
382
    for (i=0; i<WMGetArrayItemCount(clientConnections); i++) {
 
383
        cPtr = WMGetFromArray(clientConnections, i);
 
384
        sendUpdateMessage(cPtr, id, newTime);
 
385
    }
 
386
    wfree(id);
 
387
}
 
388
 
 
389
 
 
390
static void
 
391
removeTimeForUser(WMConnection *cPtr, char *cmdArgs)
 
392
{
 
393
    char *ptr;
 
394
    int i;
 
395
 
 
396
    if (cmdArgs[0]=='\0') {
 
397
        sendMessage(cPtr, _("Missing parameter for command REMOVE."
 
398
                            " Use HELP for a list of commands.\n"));
 
399
        return;
 
400
    }
 
401
 
 
402
    ptr = cmdArgs;
 
403
    while (*ptr && *ptr!=' ' && *ptr!='\t')
 
404
        ptr++;
 
405
    *ptr = '\0';
 
406
 
 
407
    WMRemoveUDObjectForKey(timeDB, cmdArgs);
 
408
 
 
409
    for (i=0; i<WMGetArrayItemCount(clientConnections); i++) {
 
410
        cPtr = WMGetFromArray(clientConnections, i);
 
411
        sendUpdateMessage(cPtr, cmdArgs, -1);
 
412
    }
 
413
}
 
414
 
 
415
 
 
416
static void
 
417
getTimeForUser(WMConnection *cPtr, char *cmdArgs)
 
418
{
 
419
    char *ptr;
 
420
    int time;
 
421
 
 
422
    if (cmdArgs[0]=='\0') {
 
423
        sendMessage(cPtr, _("Missing parameter for command GET."
 
424
                            " Use HELP for a list of commands.\n"));
 
425
        return;
 
426
    }
 
427
 
 
428
    ptr = cmdArgs;
 
429
    while (*ptr && *ptr!=' ' && *ptr!='\t')
 
430
        ptr++;
 
431
    *ptr = '\0';
 
432
 
 
433
    if (WMGetUDObjectForKey(timeDB, cmdArgs)!=NULL)
 
434
        time = WMGetUDIntegerForKey(timeDB, cmdArgs);
 
435
    else
 
436
        time = -1;
 
437
 
 
438
    sendUpdateMessage(cPtr, cmdArgs, time);
 
439
}
 
440
 
 
441
 
 
442
static void
 
443
handleConnection(WMConnection *cPtr)
 
444
{
 
445
    char *command, *ptr, *cmdArgs, *buffer;
 
446
    WMArray *commands;
 
447
    int i;
 
448
 
 
449
    commands = getAvailableMessages(cPtr);
 
450
    if (!commands)
 
451
        return;
 
452
 
 
453
    for (i=0; i<WMGetArrayItemCount(commands); i++) {
 
454
        command = WMGetFromArray(commands, i);
 
455
        while (*command && (*command==' ' || *command=='\t'))
 
456
            command++;
 
457
        ptr = command;
 
458
        while(*ptr && *ptr!=' ' && *ptr!='\t')
 
459
            ptr++;
 
460
        if (*ptr) {
 
461
            *ptr = '\0';
 
462
            ptr++;
 
463
        }
 
464
        while (*ptr && (*ptr==' ' || *ptr=='\t'))
 
465
            ptr++;
 
466
 
 
467
        cmdArgs = ptr;
 
468
 
 
469
        fprintf(stderr, "Command: '%s', args: '%s'\n", command, cmdArgs);
 
470
 
 
471
        if (strcasecmp(command, "quit")==0 || strcasecmp(command, "exit")==0) {
 
472
            sendMessage(cPtr, "Bye\n");
 
473
            WMCloseConnection(cPtr);
 
474
            enqueueConnectionForRemoval(cPtr);
 
475
            WMFreeArray(commands);
 
476
            return;
 
477
        } else if (strcasecmp(command, "id")==0) {
 
478
            showId(cPtr);
 
479
        } else if (strcasecmp(command, "help")==0) {
 
480
            showHelp(cPtr);
 
481
        } else if (strcasecmp(command, "list")==0) {
 
482
            listUsers(cPtr);
 
483
        } else if (strcasecmp(command, "set")==0) {
 
484
            setTimeForUser(cPtr, cmdArgs);
 
485
        } else if (strcasecmp(command, "add")==0) {
 
486
            addTimeToUser(cPtr, cmdArgs);
 
487
        } else if (strcasecmp(command, "sub")==0) {
 
488
            subTimeFromUser(cPtr, cmdArgs);
 
489
        } else if (strcasecmp(command, "remove")==0) {
 
490
            removeTimeForUser(cPtr, cmdArgs);
 
491
        } else if (strcasecmp(command, "get")==0) {
 
492
            getTimeForUser(cPtr, cmdArgs);
 
493
        } else {
 
494
            buffer = wmalloc(strlen(command) + 100);
 
495
            sprintf(buffer, _("Unknown command '%s'. Try HELP for"
 
496
                              " a list of commands.\n"), command);
 
497
            sendMessage(cPtr, buffer);
 
498
            wfree(buffer);
 
499
        }
 
500
    }
 
501
 
 
502
    WMFreeArray(commands);
 
503
}
 
504
 
 
505
 
 
506
static Bool
 
507
isAllowedToConnect(WMConnection *cPtr)
 
508
{
 
509
    WMHost *hPtr;
 
510
    int i;
 
511
 
 
512
    if (allowedHostList == NULL)
 
513
        return True; /* No list. Allow all by default */
 
514
 
 
515
    hPtr = WMGetHostWithAddress(WMGetConnectionAddress(cPtr));
 
516
    for (i=0; i<WMGetArrayItemCount(allowedHostList); i++) {
 
517
        if (WMIsHostEqualToHost(hPtr, WMGetFromArray(allowedHostList, i))) {
 
518
            WMReleaseHost(hPtr);
 
519
            return True;
 
520
        }
 
521
    }
 
522
 
 
523
    WMReleaseHost(hPtr);
 
524
 
 
525
    return False;
 
526
}
 
527
 
 
528
 
 
529
static void
 
530
didReceiveInput(ConnectionDelegate *self, WMConnection *cPtr)
 
531
{
 
532
    if (cPtr == serverPtr) {
 
533
        WMConnection *newPtr = WMAcceptConnection(cPtr);
 
534
 
 
535
        if (newPtr) {
 
536
            if (isAllowedToConnect(newPtr)) {
 
537
                WMSetConnectionDelegate(newPtr, &socketDelegate);
 
538
                WMSetConnectionSendTimeout(newPtr, 120);
 
539
                WMAddToArray(clientConnections, newPtr);
 
540
            } else {
 
541
                sendMessage(newPtr, "Sorry, you are not allowed to connect.\n");
 
542
                WMDestroyConnection(newPtr);
 
543
            }
 
544
        }
 
545
    } else {
 
546
        /* Data arriving on an already-connected socket */
 
547
        handleConnection(cPtr);
 
548
    }
 
549
}
 
550
 
 
551
 
 
552
static void
 
553
connectionDidTimeout(ConnectionDelegate *self, WMConnection *cPtr)
 
554
{
 
555
    WMHost *hPtr;
 
556
 
 
557
    if (cPtr == serverPtr) {
 
558
        wfatal(_("The server listening socket did timeout. Exiting."));
 
559
        exit(1);
 
560
    }
 
561
 
 
562
    hPtr = WMGetHostWithAddress(WMGetConnectionAddress(cPtr));
 
563
    wwarning(_("Connection with %s did timeout. Closing connection."),
 
564
             WMGetHostName(hPtr));
 
565
    WMReleaseHost(hPtr);
 
566
 
 
567
    enqueueConnectionForRemoval(cPtr);
 
568
}
 
569
 
 
570
 
 
571
static void
 
572
connectionDidDie(ConnectionDelegate *self, WMConnection *cPtr)
 
573
{
 
574
    if (cPtr == serverPtr) {
 
575
        /* trouble. server listening port itself died!!! */
 
576
        wfatal(_("The server listening socket died. Exiting."));
 
577
        exit(1);
 
578
    }
 
579
 
 
580
    enqueueConnectionForRemoval(cPtr);
 
581
}
 
582
 
 
583
 
 
584
static void
 
585
removeConnection(void *observer, WMNotification *notification)
 
586
{
 
587
    WMConnection *cPtr = (WMConnection*)WMGetNotificationObject(notification);
 
588
    WMData *data;
 
589
 
 
590
    WMRemoveFromArray(clientConnections, cPtr);
 
591
    if ((data = (WMData*)WMGetConnectionClientData(cPtr))!=NULL)
 
592
        WMReleaseData(data);
 
593
    WMDestroyConnection(cPtr);
 
594
}
 
595
 
 
596
static void
 
597
updatedDomain(void *observer, WMNotification *notification)
 
598
{
 
599
    wmessage("defaults domain file changed on disk. synchronizing.");
 
600
}
 
601
 
 
602
 
 
603
#if 0
 
604
static Bool
 
605
isDifferent(char *str1, char *str2)
 
606
{
 
607
    if ((!str1 && !str2) || (str1 && str2 && strcmp(str1, str2)==0))
 
608
        return False;
 
609
 
 
610
    return True;
 
611
}
 
612
#endif
 
613
 
 
614
 
 
615
int
 
616
main(int argc, char **argv)
 
617
{
 
618
    int i;
 
619
 
 
620
    wsetabort(wAbort);
 
621
 
 
622
    WMInitializeApplication("server", &argc, argv);
 
623
 
 
624
    if (argc>1) {
 
625
        for (i=1; i<argc; i++) {
 
626
            if (strcmp(argv[i], "--help")==0) {
 
627
                printHelp(argv[0]);
 
628
                exit(0);
 
629
            } else if (strcmp(argv[i], "--listen")==0) {
 
630
                char *p;
 
631
 
 
632
                if ((p = strchr(argv[++i], ':')) != NULL) {
 
633
                    *p = 0;
 
634
                    ServerAddress = wstrdup(argv[i]);
 
635
                    ServerPort = wstrdup(p+1);
 
636
                    *p = ':';
 
637
                    if (ServerAddress[0] == 0) {
 
638
                        wfree(ServerAddress);
 
639
                        ServerAddress = NULL;
 
640
                    }
 
641
                    if (ServerPort[0] == 0) {
 
642
                        wfree(ServerPort);
 
643
                        ServerPort = "34567";
 
644
                    }
 
645
                } else if (argv[i][0]!=0) {
 
646
                    ServerPort = argv[i];
 
647
                }
 
648
            } else if (strcmp(argv[i], "--allow")==0) {
 
649
                char *p, *ptr;
 
650
                int done;
 
651
                WMHost *hPtr;
 
652
 
 
653
                ptr = argv[++i];
 
654
                done = 0;
 
655
                while (!done) {
 
656
                    if ((p = strchr(ptr, ',')) != NULL) {
 
657
                        *p = 0;
 
658
                    }
 
659
                    if (*ptr != 0) {
 
660
                        hPtr = WMGetHostWithName(ptr);
 
661
                        if (hPtr) {
 
662
                            if (!allowedHostList)
 
663
                                allowedHostList = WMCreateArray(4);
 
664
                            WMAddToArray(allowedHostList, hPtr);
 
665
                        } else {
 
666
                            wwarning(_("Unknown host '%s'. Ignored."), ptr);
 
667
                        }
 
668
                    }
 
669
 
 
670
                    if (p!=NULL) {
 
671
                        *p = ',';
 
672
                        ptr = p+1;
 
673
                    } else {
 
674
                        done = 1;
 
675
                    }
 
676
                }
 
677
            } else {
 
678
                printf(_("%s: invalid argument '%s'\n"), argv[0], argv[i]);
 
679
                printf(_("Try '%s --help' for more information\n"), argv[0]);
 
680
                exit(1);
 
681
            }
 
682
        }
 
683
    }
 
684
 
 
685
    timeDB = WMGetDefaultsFromPath("./UserTime.plist");
 
686
    WMAddNotificationObserver(updatedDomain, NULL,
 
687
                              WMUserDefaultsDidChangeNotification, NULL);
 
688
 
 
689
    clientConnections = WMCreateArray(4);
 
690
 
 
691
    /* A NULL ServerAddress means to listen on any address the host has.
 
692
     * Else if ServerAddress points to a specific address (like "localhost",
 
693
     * "host.domain.com" or "192.168.1.1"), then it will only listen on that
 
694
     * interface and ignore incoming connections on the others. */
 
695
    if (ServerAddress && strcasecmp(ServerAddress, "Any")==0)
 
696
        ServerAddress = NULL;
 
697
    if (ServerPort==NULL)
 
698
        ServerPort = "34567";
 
699
 
 
700
    printf("Server will listen on '%s:%s'\n", ServerAddress?ServerAddress:"Any",
 
701
           ServerPort);
 
702
    printf("This server will allow connections from:");
 
703
    if (allowedHostList) {
 
704
        int i;
 
705
        char *hName;
 
706
 
 
707
        for (i=0; i<WMGetArrayItemCount(allowedHostList); i++) {
 
708
            hName = WMGetHostName(WMGetFromArray(allowedHostList, i));
 
709
            printf("%s'%s'", i==0?" ":", ", hName);
 
710
        }
 
711
        printf(".\n");
 
712
    } else {
 
713
        printf(" any host.\n");
 
714
    }
 
715
 
 
716
    serverPtr = WMCreateConnectionAsServerAtAddress(ServerAddress, ServerPort,
 
717
                                                    NULL);
 
718
 
 
719
    if (!serverPtr) {
 
720
        wfatal("could not create server on `%s:%s`. Exiting.",
 
721
               ServerAddress ? ServerAddress : "localhost", ServerPort);
 
722
        exit(1);
 
723
    }
 
724
 
 
725
    WMSetConnectionDelegate(serverPtr, &socketDelegate);
 
726
 
 
727
    WMAddNotificationObserver(removeConnection, NULL,
 
728
                              SEConnectionShouldBeRemovedNotification, NULL);
 
729
 
 
730
    while (1) {
 
731
        /* The ASAP notification queue is called at the end of WHandleEvents()
 
732
         * There's where died connections we get while running through
 
733
         * WHandleEvents() get removed. */
 
734
        WHandleEvents();
 
735
    }
 
736
 
 
737
    return 0;
 
738
}
 
739
 
 
740