~ubuntu-branches/ubuntu/trusty/teeworlds/trusty-updates

« back to all changes in this revision

Viewing changes to src/engine/e_system.c

  • Committer: Bazaar Package Importer
  • Author(s): Jack Coulter
  • Date: 2008-04-13 18:48:12 UTC
  • Revision ID: james.westby@ubuntu.com-20080413184812-efc80waq2er6p1bs
Tags: upstream-0.4.2
ImportĀ upstreamĀ versionĀ 0.4.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
 
2
#include <stdlib.h>
 
3
#include <stdio.h>
 
4
#include <stdarg.h>
 
5
#include <string.h>
 
6
#include <ctype.h>
 
7
#include <time.h>
 
8
 
 
9
#include "e_detect.h"
 
10
#include "e_system.h"
 
11
#include "e_console.h"
 
12
 
 
13
#if defined(CONF_FAMILY_UNIX)
 
14
        #include <sys/time.h>
 
15
        #include <unistd.h>
 
16
 
 
17
        /* unix net includes */
 
18
        #include <sys/stat.h>
 
19
        #include <sys/types.h>
 
20
        #include <sys/socket.h>
 
21
        #include <sys/ioctl.h>
 
22
        #include <errno.h>
 
23
        #include <netdb.h>      
 
24
        #include <netinet/in.h>
 
25
        #include <fcntl.h>
 
26
        #include <pthread.h>
 
27
 
 
28
        #include <dirent.h>
 
29
        #include <unistd.h>
 
30
#elif defined(CONF_FAMILY_WINDOWS)
 
31
        #define WIN32_LEAN_AND_MEAN 
 
32
        #define _WIN32_WINNT 0x0400
 
33
        #include <windows.h>
 
34
        #include <winsock2.h>
 
35
        #include <ws2tcpip.h>
 
36
        #include <shlobj.h> /* for SHGetFolderPathAndSubDir */
 
37
        #include <fcntl.h>
 
38
        #include <direct.h>
 
39
        #include <errno.h>
 
40
 
 
41
        #define EWOULDBLOCK WSAEWOULDBLOCK
 
42
#else
 
43
        #error NOT IMPLEMENTED
 
44
#endif
 
45
 
 
46
#if defined(__cplusplus)
 
47
extern "C" {
 
48
#endif
 
49
 
 
50
IOHANDLE io_stdin() { return (IOHANDLE)stdin; }
 
51
IOHANDLE io_stdout() { return (IOHANDLE)stdout; }
 
52
IOHANDLE io_stderr() { return (IOHANDLE)stderr; }
 
53
 
 
54
static DBG_LOGGER loggers[16];
 
55
static int num_loggers = 0;
 
56
 
 
57
void dbg_logger(DBG_LOGGER logger)
 
58
{
 
59
        loggers[num_loggers++] = logger;
 
60
}
 
61
 
 
62
void dbg_assert_imp(const char *filename, int line, int test, const char *msg)
 
63
{
 
64
        if(!test)
 
65
        {
 
66
                dbg_msg("assert", "%s(%d): %s", filename, line, msg);
 
67
                dbg_break();
 
68
        }
 
69
}
 
70
 
 
71
void dbg_break()
 
72
{
 
73
        *((unsigned*)0) = 0x0;
 
74
}
 
75
 
 
76
void dbg_msg(const char *sys, const char *fmt, ...)
 
77
{
 
78
        va_list args;
 
79
        char str[1024*4];
 
80
        char *msg;
 
81
        int i, len;
 
82
        
 
83
        str_format(str, sizeof(str), "[%08x][%s]: ", (int)time(0), sys);
 
84
        len = strlen(str);
 
85
        msg = (char *)str + len;
 
86
        
 
87
        va_start(args, fmt);
 
88
#if defined(CONF_FAMILY_WINDOWS)
 
89
        _vsnprintf(msg, sizeof(str)-len, fmt, args);
 
90
#else
 
91
        vsnprintf(msg, sizeof(str)-len, fmt, args);
 
92
#endif
 
93
        va_end(args);
 
94
        
 
95
        for(i = 0; i < num_loggers; i++)
 
96
                loggers[i](str);
 
97
}
 
98
 
 
99
static void logger_stdout(const char *line)
 
100
{
 
101
        printf("%s\n", line);
 
102
        fflush(stdout);
 
103
}
 
104
 
 
105
static void logger_debugger(const char *line)
 
106
{
 
107
#if defined(CONF_FAMILY_WINDOWS)
 
108
        OutputDebugString(line);
 
109
        OutputDebugString("\n");
 
110
#endif
 
111
}
 
112
 
 
113
 
 
114
IOHANDLE logfile = 0;
 
115
static void logger_file(const char *line)
 
116
{
 
117
        io_write(logfile, line, strlen(line));
 
118
        io_write(logfile, "\n", 1);
 
119
        io_flush(logfile);
 
120
}
 
121
 
 
122
void dbg_logger_stdout() { dbg_logger(logger_stdout); }
 
123
void dbg_logger_debugger() { dbg_logger(logger_debugger); }
 
124
void dbg_logger_file(const char *filename)
 
125
{
 
126
        logfile = io_open(filename, IOFLAG_WRITE);
 
127
        if(logfile)
 
128
                dbg_logger(logger_file);
 
129
        else
 
130
                dbg_msg("dbg/logger", "failed to open '%s' for logging", filename);
 
131
 
 
132
}
 
133
 
 
134
/* */
 
135
 
 
136
int memory_alloced = 0;
 
137
 
 
138
struct memheader
 
139
{
 
140
        const char *filename;
 
141
        int line;
 
142
        int size;
 
143
        struct memheader *prev;
 
144
        struct memheader *next;
 
145
};
 
146
 
 
147
struct memtail
 
148
{
 
149
        int guard;
 
150
};
 
151
 
 
152
static struct memheader *first = 0;
 
153
 
 
154
int mem_allocated()
 
155
{
 
156
        return memory_alloced;
 
157
}
 
158
 
 
159
void *mem_alloc_debug(const char *filename, int line, unsigned size, unsigned alignment)
 
160
{
 
161
        /* TODO: fix alignment */
 
162
        /* TODO: add debugging */
 
163
        struct memheader *header = (struct memheader *)malloc(size+sizeof(struct memheader)+sizeof(struct memtail));
 
164
        struct memtail *tail = (struct memtail *)(((char*)(header+1))+size);
 
165
        header->size = size;
 
166
        header->filename = filename;
 
167
        header->line = line;
 
168
        memory_alloced += header->size;
 
169
        
 
170
        tail->guard = 0xbaadc0de;
 
171
 
 
172
        header->prev = (struct memheader *)0;
 
173
        header->next = first;
 
174
        if(first)
 
175
                first->prev = header;
 
176
        first = header;
 
177
        
 
178
        /*dbg_msg("mem", "++ %p", header+1); */
 
179
        return header+1;
 
180
}
 
181
 
 
182
void mem_free(void *p)
 
183
{
 
184
        if(p)
 
185
        {
 
186
                struct memheader *header = (struct memheader *)p - 1;
 
187
                struct memtail *tail = (struct memtail *)(((char*)(header+1))+header->size);
 
188
                
 
189
                if(tail->guard != 0xbaadc0de)
 
190
                        dbg_msg("mem", "!! %p", p);
 
191
                /* dbg_msg("mem", "-- %p", p); */
 
192
                memory_alloced -= header->size;
 
193
                
 
194
                if(header->prev)
 
195
                        header->prev->next = header->next;
 
196
                else
 
197
                        first = header->next;
 
198
                if(header->next)
 
199
                        header->next->prev = header->prev;
 
200
                
 
201
                free(header);
 
202
        }
 
203
}
 
204
 
 
205
void mem_debug_dump()
 
206
{
 
207
        char buf[1024];
 
208
        struct memheader *header = first;
 
209
        IOHANDLE f = io_open("memory.txt", IOFLAG_WRITE);
 
210
        
 
211
        while(header)
 
212
        {
 
213
                str_format(buf, sizeof(buf), "%s(%d): %d\n", header->filename, header->line, header->size);
 
214
                io_write(f, buf, strlen(buf));
 
215
                header = header->next;
 
216
        }
 
217
        
 
218
        io_close(f);
 
219
}
 
220
 
 
221
 
 
222
void mem_copy(void *dest, const void *source, unsigned size)
 
223
{
 
224
        memcpy(dest, source, size);
 
225
}
 
226
 
 
227
void mem_move(void *dest, const void *source, unsigned size)
 
228
{
 
229
        memmove(dest, source, size);
 
230
}
 
231
 
 
232
void mem_zero(void *block,unsigned size)
 
233
{
 
234
        memset(block, 0, size);
 
235
}
 
236
 
 
237
IOHANDLE io_open(const char *filename, int flags)
 
238
{
 
239
        if(flags == IOFLAG_READ)
 
240
                return (IOHANDLE)fopen(filename, "rb");
 
241
        if(flags == IOFLAG_WRITE)
 
242
                return (IOHANDLE)fopen(filename, "wb");
 
243
        return 0x0;
 
244
}
 
245
 
 
246
unsigned io_read(IOHANDLE io, void *buffer, unsigned size)
 
247
{
 
248
        return fread(buffer, 1, size, (FILE*)io);
 
249
}
 
250
 
 
251
unsigned io_skip(IOHANDLE io, unsigned size)
 
252
{
 
253
        fseek((FILE*)io, size, SEEK_CUR);
 
254
        return size;
 
255
}
 
256
 
 
257
int io_seek(IOHANDLE io, int offset, int origin)
 
258
{
 
259
        int real_origin;
 
260
 
 
261
        switch(origin)
 
262
        {
 
263
        case IOSEEK_START:
 
264
                real_origin = SEEK_SET;
 
265
                break;
 
266
        case IOSEEK_CUR:
 
267
                real_origin = SEEK_CUR;
 
268
                break;
 
269
        case IOSEEK_END:
 
270
                real_origin = SEEK_END;
 
271
        }
 
272
 
 
273
        return fseek((FILE*)io, offset, origin);
 
274
}
 
275
 
 
276
long int io_tell(IOHANDLE io)
 
277
{
 
278
        return ftell((FILE*)io);
 
279
}
 
280
 
 
281
long int io_length(IOHANDLE io)
 
282
{
 
283
        long int length;
 
284
        io_seek(io, 0, IOSEEK_END);
 
285
        length = io_tell(io);
 
286
        io_seek(io, 0, IOSEEK_START);
 
287
        return length;
 
288
}
 
289
 
 
290
unsigned io_write(IOHANDLE io, const void *buffer, unsigned size)
 
291
{
 
292
        return fwrite(buffer, 1, size, (FILE*)io);
 
293
}
 
294
 
 
295
int io_close(IOHANDLE io)
 
296
{
 
297
        fclose((FILE*)io);
 
298
        return 1;
 
299
}
 
300
 
 
301
int io_flush(IOHANDLE io)
 
302
{
 
303
        fflush((FILE*)io);
 
304
        return 0;
 
305
}
 
306
 
 
307
void *thread_create(void (*threadfunc)(void *), void *u)
 
308
{
 
309
#if defined(CONF_FAMILY_UNIX)
 
310
        pthread_t id;
 
311
        pthread_create(&id, NULL, (void *(*)(void*))threadfunc, u);
 
312
        return (void*)id;
 
313
#elif defined(CONF_FAMILY_WINDOWS)
 
314
        return CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadfunc, u, 0, NULL);
 
315
#else
 
316
        #error not implemented
 
317
#endif
 
318
}
 
319
 
 
320
void thread_wait(void *thread)
 
321
{
 
322
#if defined(CONF_FAMILY_UNIX)
 
323
        pthread_join((pthread_t)thread, NULL);
 
324
#elif defined(CONF_FAMILY_WINDOWS)
 
325
        WaitForSingleObject((HANDLE)thread, INFINITE);
 
326
#else
 
327
        #error not implemented
 
328
#endif
 
329
}
 
330
 
 
331
void thread_destroy(void *thread)
 
332
{
 
333
#if defined(CONF_FAMILY_UNIX)
 
334
        void *r = 0;
 
335
        pthread_join((pthread_t)thread, &r);
 
336
#else
 
337
        /*#error not implemented*/
 
338
#endif
 
339
}
 
340
 
 
341
void thread_yield()
 
342
{
 
343
#if defined(CONF_FAMILY_UNIX)
 
344
        sched_yield();
 
345
#elif defined(CONF_FAMILY_WINDOWS)
 
346
        Sleep(0);
 
347
#else
 
348
        #error not implemented
 
349
#endif
 
350
}
 
351
 
 
352
void thread_sleep(int milliseconds)
 
353
{
 
354
#if defined(CONF_FAMILY_UNIX)
 
355
        usleep(milliseconds*1000);
 
356
#elif defined(CONF_FAMILY_WINDOWS)
 
357
        Sleep(milliseconds);
 
358
#else
 
359
        #error not implemented
 
360
#endif
 
361
}
 
362
 
 
363
 
 
364
 
 
365
 
 
366
#if defined(CONF_FAMILY_UNIX)
 
367
typedef pthread_mutex_t LOCKINTERNAL;
 
368
#elif defined(CONF_FAMILY_WINDOWS)
 
369
typedef CRITICAL_SECTION LOCKINTERNAL;
 
370
#else
 
371
        #error not implemented on this platform
 
372
#endif
 
373
 
 
374
LOCK lock_create()
 
375
{
 
376
        LOCKINTERNAL *lock = (LOCKINTERNAL*)mem_alloc(sizeof(LOCKINTERNAL), 4);
 
377
 
 
378
#if defined(CONF_FAMILY_UNIX)
 
379
        pthread_mutex_init(lock, 0x0);
 
380
#elif defined(CONF_FAMILY_WINDOWS)
 
381
        InitializeCriticalSection((LPCRITICAL_SECTION)lock);
 
382
#else
 
383
        #error not implemented on this platform
 
384
#endif
 
385
        return (LOCK)lock;
 
386
}
 
387
 
 
388
void lock_destroy(LOCK lock)
 
389
{
 
390
#if defined(CONF_FAMILY_UNIX)
 
391
        pthread_mutex_destroy((LOCKINTERNAL *)lock);
 
392
#elif defined(CONF_FAMILY_WINDOWS)
 
393
        DeleteCriticalSection((LPCRITICAL_SECTION)lock);
 
394
#else
 
395
        #error not implemented on this platform
 
396
#endif
 
397
        mem_free(lock);
 
398
}
 
399
 
 
400
int lock_try(LOCK lock)
 
401
{
 
402
#if defined(CONF_FAMILY_UNIX)
 
403
        return pthread_mutex_trylock((LOCKINTERNAL *)lock);
 
404
#elif defined(CONF_FAMILY_WINDOWS)
 
405
        return TryEnterCriticalSection((LPCRITICAL_SECTION)lock);
 
406
#else
 
407
        #error not implemented on this platform
 
408
#endif
 
409
}
 
410
 
 
411
void lock_wait(LOCK lock)
 
412
{
 
413
#if defined(CONF_FAMILY_UNIX)
 
414
        pthread_mutex_lock((LOCKINTERNAL *)lock);
 
415
#elif defined(CONF_FAMILY_WINDOWS)
 
416
        EnterCriticalSection((LPCRITICAL_SECTION)lock);
 
417
#else
 
418
        #error not implemented on this platform
 
419
#endif
 
420
}
 
421
 
 
422
void lock_release(LOCK lock)
 
423
{
 
424
#if defined(CONF_FAMILY_UNIX)
 
425
        pthread_mutex_unlock((LOCKINTERNAL *)lock);
 
426
#elif defined(CONF_FAMILY_WINDOWS)
 
427
        LeaveCriticalSection((LPCRITICAL_SECTION)lock);
 
428
#else
 
429
        #error not implemented on this platform
 
430
#endif
 
431
}
 
432
 
 
433
/* -----  time ----- */
 
434
int64 time_get()
 
435
{
 
436
#if defined(CONF_FAMILY_UNIX)
 
437
        struct timeval val;
 
438
        gettimeofday(&val, NULL);
 
439
        return (int64)val.tv_sec*(int64)1000000+(int64)val.tv_usec;
 
440
#elif defined(CONF_FAMILY_WINDOWS)
 
441
        static int64 last = 0;
 
442
        int64 t;
 
443
        QueryPerformanceCounter((PLARGE_INTEGER)&t);
 
444
        if(t<last) /* for some reason, QPC can return values in the past */
 
445
                return last;
 
446
        last = t;
 
447
        return t;
 
448
#else
 
449
        #error not implemented
 
450
#endif
 
451
}
 
452
 
 
453
int64 time_freq()
 
454
{
 
455
#if defined(CONF_FAMILY_UNIX)
 
456
        return 1000000;
 
457
#elif defined(CONF_FAMILY_WINDOWS)
 
458
        int64 t;
 
459
        QueryPerformanceFrequency((PLARGE_INTEGER)&t);
 
460
        return t;
 
461
#else
 
462
        #error not implemented
 
463
#endif
 
464
}
 
465
 
 
466
/* -----  network ----- */
 
467
static void netaddr4_to_sockaddr(const NETADDR4 *src, struct sockaddr *dest)
 
468
{
 
469
        struct sockaddr_in *p = (struct sockaddr_in *)dest;
 
470
        mem_zero(p, sizeof(struct sockaddr_in));
 
471
        p->sin_family = AF_INET;
 
472
        p->sin_port = htons(src->port);
 
473
        p->sin_addr.s_addr = htonl(src->ip[0]<<24|src->ip[1]<<16|src->ip[2]<<8|src->ip[3]);
 
474
}
 
475
 
 
476
static void sockaddr_to_netaddr4(const struct sockaddr *src, NETADDR4 *dst)
 
477
{
 
478
        unsigned int ip = htonl(((struct sockaddr_in*)src)->sin_addr.s_addr);
 
479
        dst->port = htons(((struct sockaddr_in*)src)->sin_port);
 
480
        dst->ip[0] = (unsigned char)((ip>>24)&0xFF);
 
481
        dst->ip[1] = (unsigned char)((ip>>16)&0xFF);
 
482
        dst->ip[2] = (unsigned char)((ip>>8)&0xFF);
 
483
        dst->ip[3] = (unsigned char)(ip&0xFF);
 
484
}
 
485
 
 
486
int net_addr4_cmp(const NETADDR4 *a, const NETADDR4 *b)
 
487
{
 
488
        if(     a->ip[0] != b->ip[0] ||
 
489
                a->ip[1] != b->ip[1] ||
 
490
                a->ip[2] != b->ip[2] ||
 
491
                a->ip[3] != b->ip[3] ||
 
492
                a->port != b->port
 
493
        )
 
494
                return 1;
 
495
        return 0;
 
496
}
 
497
 
 
498
 
 
499
int net_host_lookup(const char *hostname, unsigned short port, NETADDR4 *addr)
 
500
{
 
501
        struct addrinfo hints;
 
502
        struct addrinfo *result;
 
503
        int e;
 
504
        
 
505
        mem_zero(&hints, sizeof(hints));
 
506
        hints.ai_family = AF_INET;
 
507
 
 
508
        e = getaddrinfo(hostname, NULL, &hints, &result);
 
509
        if(e != 0 || !result)
 
510
                return -1;
 
511
 
 
512
        sockaddr_to_netaddr4(result->ai_addr, addr);
 
513
        freeaddrinfo(result);
 
514
        addr->port = port;
 
515
        return 0;
 
516
}
 
517
 
 
518
NETSOCKET net_udp4_create(NETADDR4 bindaddr)
 
519
{
 
520
        struct sockaddr addr;
 
521
        unsigned int mode = 1;
 
522
        int broadcast = 1;
 
523
 
 
524
        /* create socket */
 
525
        int sock = socket(AF_INET, SOCK_DGRAM, 0);
 
526
        if(sock < 0)
 
527
                return NETSOCKET_INVALID;
 
528
        
 
529
        /* bind, we should check for error */
 
530
        netaddr4_to_sockaddr(&bindaddr, &addr);
 
531
        if(bind(sock, &addr, sizeof(addr)) != 0)
 
532
        {
 
533
                net_udp4_close(sock);
 
534
                return NETSOCKET_INVALID;
 
535
        }
 
536
        
 
537
        /* set non-blocking */
 
538
#if defined(CONF_FAMILY_WINDOWS)
 
539
        ioctlsocket(sock, FIONBIO, (unsigned long *)&mode);
 
540
#else
 
541
        ioctl(sock, FIONBIO, (unsigned long *)&mode);
 
542
#endif
 
543
 
 
544
        /* set boardcast */
 
545
        setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof(broadcast));
 
546
        
 
547
        /* return */
 
548
        return sock;
 
549
}
 
550
 
 
551
int net_udp4_send(NETSOCKET sock, const NETADDR4 *addr, const void *data, int size)
 
552
{
 
553
        struct sockaddr sa;
 
554
        int d;
 
555
        mem_zero(&sa, sizeof(sa));
 
556
        netaddr4_to_sockaddr(addr, &sa);
 
557
        d = sendto((int)sock, (const char*)data, size, 0, &sa, sizeof(sa));
 
558
        if(d < 0)
 
559
                dbg_msg("net", "sendto error %d %x", d, d);
 
560
        return d;
 
561
}
 
562
 
 
563
int net_udp4_recv(NETSOCKET sock, NETADDR4 *addr, void *data, int maxsize)
 
564
{
 
565
        struct sockaddr from;
 
566
        int bytes;
 
567
        socklen_t fromlen = sizeof(struct sockaddr);
 
568
        bytes = recvfrom(sock, (char*)data, maxsize, 0, &from, &fromlen);
 
569
        if(bytes > 0)
 
570
        {
 
571
                sockaddr_to_netaddr4(&from, addr);
 
572
                return bytes;
 
573
        }
 
574
        else if(bytes == 0)
 
575
                return 0;
 
576
        return -1; /* error */
 
577
}
 
578
 
 
579
int net_udp4_close(NETSOCKET sock)
 
580
{
 
581
#if defined(CONF_FAMILY_WINDOWS)
 
582
        closesocket(sock);
 
583
#else
 
584
        close((int)sock);
 
585
#endif
 
586
        return 0;
 
587
}
 
588
 
 
589
NETSOCKET net_tcp4_create(const NETADDR4 *a)
 
590
{
 
591
    struct sockaddr addr;
 
592
 
 
593
    /* create socket */
 
594
    int sock = socket(AF_INET, SOCK_STREAM, 0);
 
595
    if(sock < 0)
 
596
        return NETSOCKET_INVALID;
 
597
 
 
598
    /* bind, we should check for error */
 
599
    netaddr4_to_sockaddr(a, &addr);
 
600
    bind(sock, &addr, sizeof(addr));
 
601
 
 
602
    /* return */
 
603
    return sock;
 
604
}
 
605
 
 
606
int net_tcp4_set_non_blocking(NETSOCKET sock)
 
607
{
 
608
        unsigned int mode = 1;
 
609
#if defined(CONF_FAMILY_WINDOWS)
 
610
        return ioctlsocket(sock, FIONBIO, (unsigned long *)&mode);
 
611
#else
 
612
        return ioctl(sock, FIONBIO, (unsigned long *)&mode);
 
613
#endif
 
614
}
 
615
 
 
616
int net_tcp4_set_blocking(NETSOCKET sock)
 
617
{
 
618
        unsigned int mode = 0;
 
619
#if defined(CONF_FAMILY_WINDOWS)
 
620
        return ioctlsocket(sock, FIONBIO, (unsigned long *)&mode);
 
621
#else
 
622
        return ioctl(sock, FIONBIO, (unsigned long *)&mode);
 
623
#endif
 
624
}
 
625
 
 
626
int net_tcp4_listen(NETSOCKET sock, int backlog)
 
627
{
 
628
        return listen(sock, backlog);
 
629
}
 
630
 
 
631
int net_tcp4_accept(NETSOCKET sock, NETSOCKET *new_sock, NETADDR4 *a)
 
632
{
 
633
        int s;
 
634
        socklen_t sockaddr_len;
 
635
        struct sockaddr addr;
 
636
 
 
637
        sockaddr_len = sizeof(addr);
 
638
 
 
639
        s = accept(sock, &addr, &sockaddr_len);
 
640
 
 
641
        if (s != -1)
 
642
        {
 
643
                sockaddr_to_netaddr4(&addr, a);
 
644
                *new_sock = s;
 
645
        }
 
646
        return s;
 
647
}
 
648
 
 
649
int net_tcp4_connect(NETSOCKET sock, const NETADDR4 *a)
 
650
{
 
651
  struct sockaddr addr;
 
652
 
 
653
  netaddr4_to_sockaddr(a, &addr);
 
654
  return connect(sock, &addr, sizeof(addr)); 
 
655
}
 
656
 
 
657
int net_tcp4_connect_non_blocking(NETSOCKET sock, const NETADDR4 *a)
 
658
{
 
659
        struct sockaddr addr;
 
660
        int res;
 
661
 
 
662
        netaddr4_to_sockaddr(a, &addr);
 
663
        net_tcp4_set_non_blocking(sock);
 
664
        res = connect(sock, &addr, sizeof(addr));
 
665
        net_tcp4_set_blocking(sock);
 
666
 
 
667
        return res;
 
668
}
 
669
 
 
670
int net_tcp4_send(NETSOCKET sock, const void *data, int size)
 
671
{
 
672
  int d;
 
673
  d = send((int)sock, (const char*)data, size, 0);
 
674
  return d;
 
675
}
 
676
 
 
677
int net_tcp4_recv(NETSOCKET sock, void *data, int maxsize)
 
678
{
 
679
  int bytes;
 
680
  bytes = recv((int)sock, (char*)data, maxsize, 0);
 
681
  return bytes;
 
682
}
 
683
 
 
684
int net_tcp4_close(NETSOCKET sock)
 
685
{
 
686
#if defined(CONF_FAMILY_WINDOWS)
 
687
        closesocket(sock);
 
688
#else
 
689
        close((int)sock);
 
690
#endif
 
691
        return 0;
 
692
}
 
693
 
 
694
int net_errno()
 
695
{
 
696
        return errno;
 
697
}
 
698
 
 
699
int net_would_block()
 
700
{
 
701
        return net_errno() == EWOULDBLOCK;
 
702
}
 
703
 
 
704
int net_init()
 
705
{
 
706
#if defined(CONF_FAMILY_WINDOWS)
 
707
        WSADATA wsaData;
 
708
        int err = WSAStartup(MAKEWORD(1, 1), &wsaData);
 
709
        dbg_assert(err == 0, "network initialization failed.");
 
710
        return err==0?0:1;
 
711
#endif
 
712
 
 
713
        return 0;
 
714
}
 
715
 
 
716
int fs_listdir(const char *dir, fs_listdir_callback cb, void *user)
 
717
{
 
718
#if defined(CONF_FAMILY_WINDOWS)
 
719
        WIN32_FIND_DATA finddata;
 
720
        HANDLE handle;
 
721
        char buffer[1024*2];
 
722
        str_format(buffer, sizeof(buffer), "%s/*", dir);
 
723
 
 
724
        handle = FindFirstFileA(buffer, &finddata);
 
725
 
 
726
        if (handle == INVALID_HANDLE_VALUE)
 
727
                return 0;
 
728
 
 
729
        /* add all the entries */
 
730
        do
 
731
        {
 
732
                if(finddata.cFileName[0] != '.')
 
733
                        cb(finddata.cFileName, 0, user);
 
734
        } while (FindNextFileA(handle, &finddata));
 
735
 
 
736
        FindClose(handle);
 
737
        return 0;
 
738
#else
 
739
        struct dirent *entry;
 
740
        DIR *d = opendir(dir);
 
741
 
 
742
        if(!d)
 
743
                return 0;
 
744
                
 
745
        while((entry = readdir(d)) != NULL)
 
746
                cb(entry->d_name, 0, user);
 
747
 
 
748
        /* close the directory and return */
 
749
        closedir(d);
 
750
        return 0;
 
751
#endif
 
752
}
 
753
 
 
754
int fs_storage_path(const char *appname, char *path, int max)
 
755
{
 
756
#if defined(CONF_FAMILY_WINDOWS)
 
757
        HRESULT r;
 
758
        char home[MAX_PATH];
 
759
        r = SHGetFolderPath (NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, home);
 
760
        if(r != 0)
 
761
                        return 1;
 
762
        _snprintf(path, max, "%s/%s", home, appname);
 
763
        return 0;
 
764
#else
 
765
        char *home = getenv("HOME");
 
766
        int i;
 
767
        if(!home)
 
768
                return 0;
 
769
 
 
770
#if defined(CONF_PLATFORM_MACOSX)
 
771
        snprintf(path, max, "%s/Library/Application Support/%s", home, appname);
 
772
#else
 
773
        snprintf(path, max, "%s/.%s", home, appname);
 
774
        for(i = strlen(home)+2; path[i]; i++)
 
775
                path[i] = tolower(path[i]);
 
776
#endif
 
777
        
 
778
        return 1;
 
779
#endif
 
780
}
 
781
 
 
782
int fs_makedir(const char *path)
 
783
{
 
784
#if defined(CONF_FAMILY_WINDOWS)
 
785
        if(_mkdir(path) == 0)
 
786
                        return 0;
 
787
        if(errno == EEXIST)
 
788
                return 0;
 
789
        return 1;
 
790
#else
 
791
        if(mkdir(path, 0755) == 0)
 
792
                return 0;
 
793
        if(errno == EEXIST)
 
794
                return 0;
 
795
        return 1;
 
796
#endif
 
797
}
 
798
 
 
799
void swap_endian(void *data, unsigned elem_size, unsigned num)
 
800
{
 
801
        char *src = (char*) data;
 
802
        char *dst = src + (elem_size - 1);
 
803
 
 
804
        while(num)
 
805
        {
 
806
                unsigned n = elem_size>>1;
 
807
                char tmp;
 
808
                while(n)
 
809
                {
 
810
                        tmp = *src;
 
811
                        *src = *dst;
 
812
                        *dst = tmp;
 
813
 
 
814
                        src++;
 
815
                        dst--;
 
816
                        n--;
 
817
                }
 
818
 
 
819
                src = src + (elem_size>>1);
 
820
                dst = src + (elem_size - 1);
 
821
                num--;
 
822
        }
 
823
}
 
824
 
 
825
int net_socket_read_wait(NETSOCKET sock, int time)
 
826
{
 
827
    struct timeval tv;
 
828
    fd_set readfds;
 
829
 
 
830
    tv.tv_sec = 0;
 
831
    tv.tv_usec = 1000*time;
 
832
 
 
833
    FD_ZERO(&readfds);
 
834
    FD_SET(sock, &readfds);
 
835
 
 
836
    /* don't care about writefds and exceptfds */
 
837
    select(sock+1, &readfds, NULL, NULL, &tv);
 
838
    if(FD_ISSET(sock, &readfds))
 
839
        return 1;
 
840
    return 0;
 
841
}
 
842
 
 
843
unsigned time_timestamp()
 
844
{
 
845
        return time(0);
 
846
}
 
847
 
 
848
void str_append(char *dst, const char *src, int dst_size)
 
849
{
 
850
        int s = strlen(dst);
 
851
        int i = 0;
 
852
        while(s < dst_size)
 
853
        {
 
854
                dst[s] = src[i];
 
855
                if(!src[i]) /* check for null termination */
 
856
                        break;
 
857
                s++;
 
858
                i++;
 
859
        }
 
860
        
 
861
        dst[dst_size-1] = 0; /* assure null termination */
 
862
}
 
863
 
 
864
void str_copy(char *dst, const char *src, int dst_size)
 
865
{
 
866
        strncpy(dst, src, dst_size);
 
867
        dst[dst_size-1] = 0; /* assure null termination */
 
868
}
 
869
 
 
870
void str_format(char *buffer, int buffer_size, const char *format, ...)
 
871
{
 
872
#if defined(CONF_FAMILY_WINDOWS)
 
873
        va_list ap;
 
874
        va_start(ap, format);
 
875
        _vsnprintf(buffer, buffer_size, format, ap);
 
876
    va_end(ap);
 
877
#else
 
878
        va_list ap;
 
879
        va_start(ap, format);
 
880
        vsnprintf(buffer, buffer_size, format, ap);
 
881
    va_end(ap);
 
882
#endif
 
883
 
 
884
        buffer[buffer_size-1] = 0; /* assure null termination */
 
885
}
 
886
 
 
887
 
 
888
 
 
889
/* makes sure that the string only contains the characters between 32 and 127 */
 
890
void str_sanitize_strong(char *str_in)
 
891
{
 
892
        unsigned char *str = (unsigned char *)str_in;
 
893
        while(*str)
 
894
        {
 
895
                *str &= 0x7f;
 
896
                if(*str < 32)
 
897
                        *str = 32;
 
898
                str++;
 
899
        }
 
900
}
 
901
 
 
902
/* makes sure that the string only contains the characters between 32 and 255 + \r\n\t */
 
903
void str_sanitize(char *str_in)
 
904
{
 
905
        unsigned char *str = (unsigned char *)str_in;
 
906
        while(*str)
 
907
        {
 
908
                if(*str < 32 && !(*str == '\r') && !(*str == '\n') && !(*str == '\t'))
 
909
                        *str = ' ';
 
910
                str++;
 
911
        }
 
912
}
 
913
 
 
914
/* case */
 
915
int str_comp_nocase(const char *a, const char *b)
 
916
{
 
917
#if defined(CONF_FAMILY_WINDOWS)
 
918
        return _stricmp(a,b);
 
919
#else
 
920
        return strcasecmp(a,b);
 
921
#endif
 
922
}
 
923
 
 
924
const char *str_find_nocase(const char *haystack, const char *needle)
 
925
{
 
926
        while(*haystack) /* native implementation */
 
927
        {
 
928
                const char *a = haystack;
 
929
                const char *b = needle;
 
930
                while(*a && *b && tolower(*a) == tolower(*b))
 
931
                {
 
932
                        a++;
 
933
                        b++;
 
934
                }
 
935
                if(!(*b))
 
936
                        return haystack;
 
937
                haystack++;
 
938
        }
 
939
        
 
940
        return 0;
 
941
}
 
942
 
 
943
#if defined(__cplusplus)
 
944
}
 
945
#endif