summaryrefslogtreecommitdiff
path: root/protocols/Skype/msgq.c
blob: 48790e1c295bbbe81d2c54d2df42f30868d21d2c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/*
 * Implements a simple message queue for send and receive queue.
 * We could use memlist.c, but it's not efficient 
 * enough for this purpose (would always memmove on removing first
 * element), therefore it's implemented as tail queue.
 */

#include "skype.h"
#include "msgq.h"
#include "debug.h"


void MsgQ_Init(TYP_MSGQ *q)
{
	TAILQ_INIT(&q->l);
	InitializeCriticalSection (&q->cs);
}

void MsgQ_Exit(TYP_MSGQ *q)
{
	struct MsgQueue *ptr;

	EnterCriticalSection(&q->cs);
	while (ptr=q->l.tqh_first)
		free(MsgQ_RemoveMsg(q, ptr));
	LeaveCriticalSection(&q->cs);
	DeleteCriticalSection (&q->cs);
}

BOOL MsgQ_Add(TYP_MSGQ *q, char *msg)
{
	struct MsgQueue *ptr;

	if (!(ptr=(struct MsgQueue*)malloc(sizeof(struct MsgQueue))))
		return FALSE;
	ptr->message = _strdup(msg); // Don't forget to free!
	ptr->tAdded = SkypeTime(NULL);
	SkypeTime(&ptr->tReceived);
	EnterCriticalSection(&q->cs);
	TAILQ_INSERT_TAIL(&q->l, ptr, l);
	//LOG (("MsgQ_Add (%s) @%lu/%ld", msg, ptr->tReceived, ptr->tAdded));
	LeaveCriticalSection(&q->cs);
	return TRUE;
}

char *MsgQ_RemoveMsg(TYP_MSGQ *q, struct MsgQueue *ptr)
{
	char *msg;

	if (!ptr) return NULL;
	TAILQ_REMOVE(&q->l, ptr, l);
	msg=ptr->message;
	free(ptr);
	return msg;
}

char *MsgQ_Get(TYP_MSGQ *q)
{
	char *msg;

	EnterCriticalSection(&q->cs);
	msg=MsgQ_RemoveMsg(q, q->l.tqh_first);
	LeaveCriticalSection(&q->cs);
	return msg;
}

int MsgQ_CollectGarbage(TYP_MSGQ *q, time_t age)
{
	struct MsgQueue *ptr;
	int i=0;

	EnterCriticalSection(&q->cs);
	ptr=q->l.tqh_first;
	while (ptr)
	{
		if (ptr->tAdded && SkypeTime(NULL)-ptr->tAdded>age)
		{
			struct MsgQueue *ptr_;
			LOG(("GarbageCollector throwing out message: %s", ptr->message));
			ptr_=ptr;
			ptr=ptr->l.tqe_next;
			free(MsgQ_RemoveMsg(q, ptr_));
			i++;
			continue;
		}
		ptr=ptr->l.tqe_next;
	}
	LeaveCriticalSection(&q->cs);
	return i;
}