Browse code

*** empty log message ***

Jan Janak authored on 21/08/2002 20:18:11
Showing 22 changed files
... ...
@@ -4,6 +4,6 @@
4 4
 
5 5
 auto_gen=
6 6
 NAME=mysql.so
7
-LIBS=-lmysqlclient -L/usr/lib/mysql
7
+LIBS=-lmysqlclient #-L/usr/lib/mysql
8 8
 
9 9
 include ../../Makefile.modules
10 10
new file mode 100644
... ...
@@ -0,0 +1,12 @@
0
+# $Id$
1
+#
2
+# registrar module makefile
3
+#
4
+# 
5
+# WARNING: do not run this directly, it should be run by the master Makefile
6
+
7
+auto_gen=
8
+NAME=registrar.so
9
+LIBS=
10
+
11
+include ../../Makefile.modules
0 12
new file mode 100644
... ...
@@ -0,0 +1,54 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Common stuff
4
+ */
5
+
6
+#include "common.h"
7
+#include <string.h> /* memchr */
8
+
9
+
10
+/*
11
+ * Find a character occurence that is not quoted
12
+ */
13
+char* find_not_quoted(str* _s, char _c)
14
+{
15
+	int quoted = 0, i;
16
+	
17
+	for(i = 0; i < _s->len; i++) {
18
+		if (!quoted) {
19
+			if (_s->s[i] == '\"') quoted = 1;
20
+			else if (_s->s[i] == _c) return _s->s + i;
21
+		} else {
22
+			if ((_s->s[i] == '\"') && (_s->s[i - 1] != '\\')) quoted = 0;
23
+		}
24
+	}
25
+	return 0;
26
+}
27
+
28
+
29
+/*
30
+ * Extract username part from URI
31
+ */
32
+int get_user(str* _s)
33
+{
34
+	char* at, *dcolon, *dc;
35
+	dcolon = find_not_quoted(_s, ':');
36
+
37
+	if (dcolon == 0) return -1;
38
+
39
+	_s->s = dcolon + 1;
40
+	_s->len -= dcolon - _s->s + 1;
41
+	
42
+	at = memchr(_s->s, '@', _s->len);
43
+	dc = memchr(_s->s, ':', _s->len);
44
+	if (at) {
45
+		if ((dc) && (dc < at)) {
46
+			_s->len = dc - _s->s;
47
+			return 0;
48
+		}
49
+		
50
+		_s->len = at - _s->s;
51
+		return 0;
52
+	} else return -2;
53
+}
0 54
new file mode 100644
... ...
@@ -0,0 +1,36 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Common stuff
4
+ */
5
+
6
+#ifndef COMMON_H
7
+#define COMMON_H
8
+
9
+#include "../../str.h"
10
+
11
+
12
+/*
13
+ * Find a character occurence that is not quoted
14
+ */
15
+char* find_not_quoted(str* _s, char _c);
16
+
17
+
18
+/*
19
+ * Extract username part from URI
20
+ */
21
+int get_user(str* _s);
22
+
23
+
24
+/*
25
+ * Copy str structure, doesn't copy
26
+ * the whole string !
27
+ */
28
+static inline void str_copy(str* _d, str* _s)
29
+{
30
+	_d->s = _s->s;
31
+	_d->len = _s->len;
32
+}
33
+
34
+
35
+#endif /* COMMON_H */
0 36
new file mode 100644
... ...
@@ -0,0 +1,65 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Convert functions
4
+ */
5
+
6
+#ifndef CONVERT_H
7
+#define CONVERT_H
8
+
9
+#include "../../str.h"
10
+
11
+
12
+/*
13
+ * ASCII to integer
14
+ */
15
+static inline int atoi(str* _s, int* _r)
16
+{
17
+	int i;
18
+	
19
+	*_r = 0;
20
+	for(i = 0; i < _s->len; i++) {
21
+		if ((_s->s[i] >= '0') && (_s->s[i] <= '9')) {
22
+			*_r *= 10;
23
+			*_r += _s->s[i] - '0';
24
+		} else {
25
+			return -1;
26
+		}
27
+	}
28
+	
29
+	return 0;
30
+}
31
+
32
+
33
+/*
34
+ * ASCII to float
35
+ */
36
+static inline int atof(str* _s, float* _r)
37
+{
38
+	int i, dot = 0;
39
+	float order = 0.1;
40
+
41
+	*_r = 0;
42
+	for(i = 0; i < _s->len; i++) {
43
+		if (_s->s[i] == '.') {
44
+			if (dot) return -1;
45
+			dot = 1;
46
+			continue;
47
+		}
48
+		if ((_s->s[i] >= '0') && (_s->s[i] <= '9')) {
49
+			if (dot) {
50
+				*_r += (_s->s[i] - '0') * order;
51
+				order /= 10;
52
+			} else {
53
+				*_r *= 10;
54
+				*_r += _s->s[i] - '0';
55
+			}
56
+		} else {
57
+			return -2;
58
+		}
59
+	}
60
+	return 0;
61
+}
62
+
63
+
64
+#endif /* CONVERT_H */
0 65
new file mode 100644
... ...
@@ -0,0 +1,118 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Lookup contacts in usrloc
4
+ */
5
+
6
+#include "lookup.h"
7
+#include <string.h>
8
+#include "../../dset.h"
9
+#include "../../str.h"
10
+#include "../../config.h"
11
+#include "../../action.h"
12
+#include "../usrloc/usrloc.h"
13
+#include "common.h"
14
+#include "regtime.h"
15
+#include "reg_mod.h"
16
+
17
+
18
+/*
19
+ * Rewrite Request-URI
20
+ */
21
+static inline int rwrite(struct sip_msg* _m, str* _s)
22
+{
23
+	char buffer[MAX_URI_SIZE];
24
+	struct action act;
25
+	
26
+	if (_s->len > MAX_URI_SIZE - 1) {
27
+		LOG(L_ERR, "rwrite(): URI too long\n");
28
+		return -1;
29
+	}
30
+	
31
+	memcpy(buffer, _s->s, _s->len);
32
+	buffer[_s->len] = '\0';
33
+	
34
+	DBG("rwrite(): Rewriting Request-URI with \'%s\'\n", buffer);
35
+	act.type = SET_URI_T;
36
+	act.p1_type = STRING_ST;
37
+	act.p1.string = buffer;
38
+	act.next = 0;
39
+	
40
+	if (do_action(&act, _m) < 0) {
41
+		LOG(L_ERR, "rwrite(): Error in do_action\n");
42
+		return -1;
43
+	}
44
+	return 0;
45
+}
46
+
47
+
48
+/*
49
+ * Lookup contact in the database and rewrite Request-URI
50
+ */
51
+int lookup(struct sip_msg* _m, char* _t, char* _s)
52
+{
53
+	urecord_t* r;
54
+	str user;
55
+	time_t t;
56
+	ucontact_t* ptr;
57
+	int res;
58
+	
59
+	if (!_m->to && (parse_headers(_m, HDR_TO, 0) == -1)) {
60
+		LOG(L_ERR, "lookup(): Error while parsing headers\n");
61
+		return -1;
62
+	}
63
+
64
+	if (!_m->to) {
65
+	        LOG(L_ERR, "lookup(): Unable to find To HF\n");
66
+		return -2;
67
+	}
68
+	
69
+	if (_m->new_uri.s) str_copy(&user, &_m->new_uri);
70
+	else str_copy(&user, &_m->first_line.u.request.uri);
71
+	
72
+	if ((get_user(&user) < 0) || !user.len) {
73
+		LOG(L_ERR, "lookup(): Error while extracting username\n");
74
+		return -3;
75
+	}
76
+	
77
+	get_act_time();
78
+
79
+	res = ul_get_record((udomain_t*)_t, &user, &r);
80
+	if (res < 0) {
81
+		LOG(L_ERR, "lookup(): Error while querying usrloc\n");
82
+		return -4;
83
+	}
84
+	
85
+	if (res > 0) {
86
+		DBG("lookup(): \'%.*s\' Not found in usrloc\n", user.len, user.s);
87
+		return -5;
88
+	}
89
+
90
+	ptr = r->contacts;
91
+	while ((ptr) && (ptr->expires <= act_time)) ptr = ptr->next;
92
+	
93
+	if (ptr && (rwrite(_m, &ptr->c) < 0)) {
94
+		LOG(L_ERR, "lookup(): Unable to rewrite Request-URI\n");
95
+		ul_release_record(r);
96
+		return -6;
97
+	}
98
+	
99
+	     /* Append branches if enabled */
100
+	if (!append_branches) goto skip;
101
+
102
+	ptr = ptr->next;
103
+	while(ptr) {
104
+		if (ptr->expires > act_time) {
105
+			if (append_branch(_m, ptr->c.s, ptr->c.len) == -1) {
106
+				LOG(L_ERR, "lookup(): Error while appending a branch\n");
107
+				ul_release_record(r);
108
+				return -7;
109
+			}
110
+		} 
111
+		ptr = ptr->next;
112
+	}
113
+	
114
+ skip:
115
+	ul_release_record(r);
116
+	return 1;
117
+}
0 118
new file mode 100644
... ...
@@ -0,0 +1,16 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Lookup contacts in usrloc
4
+ */
5
+
6
+#ifndef LOOKUP_H
7
+#define LOOKUP_H
8
+
9
+#include "../../parser/msg_parser.h"
10
+
11
+
12
+int lookup(struct sip_msg* _m, char* _t, char* _s);
13
+
14
+
15
+#endif /* LOOKUP_H */
0 16
new file mode 100644
... ...
@@ -0,0 +1,124 @@
0
+/* 
1
+ * $Id$
2
+ *
3
+ * Registrar module interface
4
+ */
5
+
6
+#include "reg_mod.h"
7
+#include "../../sr_module.h"
8
+#include "../../timer.h"
9
+#include "../../dprint.h"
10
+#include "../../error.h"
11
+#include "../usrloc/usrloc.h"
12
+
13
+#include "save.h"
14
+#include "lookup.h"
15
+
16
+
17
+static int mod_init(void);                           /* Module init function */
18
+static int domain_fixup(void** param, int param_no); /* Fixup that converts domain name */
19
+
20
+
21
+int default_expires = 3600; /* Default expires value in seconds */
22
+int default_q       = 0;    /* Default q value multiplied by 1000 */
23
+int append_branches = 1;    /* If set to 1, lookup will put all contacts found in msg structure */
24
+
25
+float def_q;                /* default_q converted to float in mod_init */
26
+
27
+
28
+/*
29
+ * sl_send_reply function pointer
30
+ */
31
+int (*sl_reply)(struct sip_msg* _m, char* _s1, char* _s2);
32
+
33
+
34
+/*
35
+ * Module exports structure
36
+ */
37
+struct module_exports exports = {
38
+	"registrar", 
39
+	(char*[]) {
40
+		"save",
41
+		"lookup"
42
+	},
43
+	(cmd_function[]) {
44
+		save, 
45
+		lookup
46
+	},
47
+	(int[]){1, 1},
48
+	(fixup_function[]) {
49
+		domain_fixup, 
50
+		domain_fixup
51
+	},
52
+	2,
53
+	
54
+	(char*[]) { /* Module parameter names */
55
+		"default_expires",
56
+		"default_q",
57
+		"append_branches"
58
+	},
59
+	(modparam_t[]) {   /* Module parameter types */
60
+		INT_PARAM,
61
+		INT_PARAM,
62
+		INT_PARAM
63
+	},
64
+	(void*[]) {   /* Module parameter variable pointers */
65
+		&default_expires,
66
+		&default_q,
67
+		&append_branches
68
+	},
69
+	3,         /* Number of module paramers */
70
+
71
+	mod_init,   /* module initialization function */
72
+	0,
73
+	0,          /* destroy function */
74
+	0,          /* oncancel function */
75
+	0           /* Per-child init function */
76
+};
77
+
78
+
79
+/*
80
+ * Initialize parent
81
+ */
82
+static int mod_init(void)
83
+{
84
+	printf( "Initializing registrar module\n");
85
+
86
+             /*
87
+              * We will need sl_send_reply from stateless
88
+	      * module for sending replies
89
+	      */
90
+        sl_reply = find_export("sl_send_reply", 2);
91
+	if (!sl_reply) {
92
+		LOG(L_ERR, "This module requires sl module\n");
93
+		return -1;
94
+	}
95
+	
96
+	if (bind_usrloc() < 0) {
97
+		LOG(L_ERR, "Can't find usrloc module\n");
98
+		return -1;
99
+	}
100
+
101
+	def_q = (float)default_q / (float)1000;
102
+
103
+	return 0;
104
+}
105
+
106
+
107
+/*
108
+ * Convert char* parameter to udomain_t* pointer
109
+ */
110
+static int domain_fixup(void** param, int param_no)
111
+{
112
+	udomain_t* d;
113
+
114
+	if (param_no == 1) {
115
+		if (ul_register_domain((char*)*param, &d) < 0) {
116
+			LOG(L_ERR, "domain_fixup(): Error while registering domain\n");
117
+			return E_UNSPEC;
118
+		}
119
+
120
+		*param = (void*)d;
121
+	}
122
+	return 0;
123
+}
0 124
new file mode 100644
... ...
@@ -0,0 +1,20 @@
0
+/* 
1
+ * $Id$ 
2
+ *
3
+ * registrar module interface
4
+ */
5
+
6
+#ifndef REG_MOD_H
7
+#define REG_MOD_H
8
+
9
+#include "../../parser/msg_parser.h"
10
+
11
+extern int default_expires;
12
+extern int default_q;
13
+extern int append_branches;
14
+
15
+extern float def_q;
16
+
17
+extern int (*sl_reply)(struct sip_msg* _m, char* _s1, char* _s2);
18
+
19
+#endif /* REG_MOD_H */
0 20
new file mode 100644
... ...
@@ -0,0 +1,20 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Registrar time related functions
4
+ */
5
+
6
+#include "regtime.h"
7
+
8
+
9
+time_t act_time;
10
+
11
+
12
+/*
13
+ * Get actual time and store
14
+ * value in act_time
15
+ */
16
+void get_act_time(void)
17
+{
18
+	act_time = time(0);
19
+}
0 20
new file mode 100644
... ...
@@ -0,0 +1,23 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Registrar time related functions
4
+ */
5
+
6
+#ifndef REGTIME_H
7
+#define REGTIME_H
8
+
9
+#include <time.h>
10
+
11
+
12
+extern time_t act_time;
13
+
14
+
15
+/*
16
+ * Get actual time and store
17
+ * value in act_time
18
+ */
19
+void get_act_time(void);
20
+
21
+
22
+#endif /* REGTIME_H */
0 23
new file mode 100644
... ...
@@ -0,0 +1,117 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Send a reply
4
+ */
5
+
6
+#include "reply.h"
7
+#include "../../parser/msg_parser.h"
8
+#include "../../data_lump_rpl.h"
9
+#include "rerrno.h"
10
+#include "reg_mod.h"
11
+#include "regtime.h"
12
+
13
+
14
+#define MAX_CONTACT_BUFFER 1024
15
+
16
+static char b[MAX_CONTACT_BUFFER];
17
+static int l;
18
+
19
+
20
+#define MSG_200 "OK"
21
+#define MSG_400 "Bad Request"
22
+#define MSG_500 "Internal Server Error"
23
+
24
+
25
+/*
26
+ * Build Contact HF for reply
27
+ */
28
+void build_contact(ucontact_t* _c)
29
+{
30
+	struct lump_rpl* ptr;
31
+	
32
+	l = 0;
33
+	while(_c) {
34
+		if (_c->expires > act_time) {
35
+			memcpy(b + l, "Contact: <", 10);
36
+			l += 10;
37
+			
38
+			memcpy(b + l, _c->c.s, _c->c.len);
39
+			l += _c->c.len;
40
+			
41
+			memcpy(b + l, ">;q=", 4);
42
+			l += 4;
43
+			
44
+			l += sprintf(b + l, "%-3.2f", _c->q);
45
+			
46
+			memcpy(b + l, ";expires=", 9);
47
+			l += 9;
48
+			
49
+			l += sprintf(b + l, "%d", (int)(_c->expires - act_time));
50
+			
51
+			*(b + l++) = '\r';
52
+			*(b + l++) = '\n';
53
+		}
54
+
55
+		_c = _c->next;
56
+	}
57
+	
58
+	DBG("build_contact(): Created Contact HF: %.*s\n", l, b);
59
+}
60
+
61
+
62
+/*
63
+ * Convert rerrno to code and message
64
+ */
65
+static inline void rerrno2msg(int* _c, char** _m)
66
+{
67
+	switch(rerrno) {
68
+	case R_OK:         *_c = 200; *_m = MSG_200;                                       break;
69
+	case R_UL_DEL_R:   *_c = 500; *_m = MSG_500 " - Usrloc_record_delete failed";      break;
70
+	case R_UL_GET_R:   *_c = 500; *_m = MSG_500 " - Usrloc_record_get failed";         break;
71
+	case R_UL_NEW_R:   *_c = 500; *_m = MSG_500 " - Usrloc_record_new failed";         break;
72
+	case R_INV_CSEQ:   *_c = 400; *_m = MSG_400 " - Invalid CSeq number";              break;
73
+	case R_UL_INS_C:   *_c = 500; *_m = MSG_500 " - Usrloc_contact_insert failed";     break;
74
+	case R_UL_INS_R:   *_c = 500; *_m = MSG_500 " - Usrloc_record_insert failed ";     break;
75
+	case R_UL_DEL_C:   *_c = 500; *_m = MSG_500 " - Usrloc_contact_delete failed";     break;			
76
+	case R_UL_UPD_C:   *_c = 500; *_m = MSG_500 " - Usrloc_contact_update failed";     break;
77
+	case R_TO_USER:    *_c = 400; *_m = MSG_400 " - No username in To URI";            break;
78
+	case R_INV_EXP:    *_c = 400; *_m = MSG_400 " - Invalid expires param in contact"; break;
79
+	case R_INV_Q:      *_c = 400; *_m = MSG_400 " - Invalid q param in contact";       break;
80
+	case R_PARSE:      *_c = 400; *_m = MSG_400 " - Message parse error";              break;
81
+	case R_TO_MISS:    *_c = 400; *_m = MSG_400 " - To header not found";              break;
82
+	case R_CID_MISS:   *_c = 400; *_m = MSG_400 " - Call-ID header not found";         break;
83
+	case R_CS_MISS:    *_c = 400; *_m = MSG_400 " - CSeq header not found";            break;
84
+	case R_PARSE_EXP:  *_c = 400; *_m = MSG_400 " - Expires parse error";              break;
85
+	case R_PARSE_CONT: *_c = 400; *_m = MSG_400 " - Contact parse error";              break;
86
+	case R_STAR_EXP:   *_c = 400; *_m = MSG_400 " - star and expires not zero";        break;
87
+	case R_STAR_CONT:  *_c = 400; *_m = MSG_400 " - star and more contacts";           break;
88
+	case R_OOO:        *_c = 200; *_m = MSG_200 " - Out Of Order";                     break;
89
+	case R_RETRANS:    *_c = 200; *_m = MSG_200 " - Retransmission";                   break;
90
+	}
91
+}
92
+
93
+
94
+/*
95
+ * Send a reply
96
+ */
97
+int send_reply(struct sip_msg* _m)
98
+{
99
+	int code;
100
+	char* msg;
101
+
102
+	struct lump_rpl* p;
103
+
104
+	if (l > 0) {
105
+		p = build_lump_rpl(b, l);
106
+		add_lump_rpl(_m, p);
107
+		l = 0;
108
+	}
109
+
110
+	rerrno2msg(&code, &msg);
111
+	
112
+	if (sl_reply(_m, (char*)code, msg) == -1) {
113
+		LOG(L_ERR, "send_reply(): Error while sending %d %s\n", code, msg);
114
+		return -1;
115
+	} else return 0;	
116
+}
0 117
new file mode 100644
... ...
@@ -0,0 +1,26 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Send a reply
4
+ */
5
+
6
+#ifndef REPLY_H
7
+#define REPLY_H
8
+
9
+#include "../../parser/msg_parser.h"
10
+#include "../usrloc/usrloc.h"
11
+
12
+
13
+/*
14
+ * Send a reply
15
+ */
16
+int send_reply(struct sip_msg* _m);
17
+
18
+
19
+/*
20
+ * Build Contact HF for reply
21
+ */
22
+void build_contact(ucontact_t* _c);
23
+
24
+
25
+#endif /* REPLY_H */
0 26
new file mode 100644
... ...
@@ -0,0 +1,10 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Registrar errno
4
+ */
5
+
6
+#include "rerrno.h"
7
+
8
+rerr_t rerrno;
9
+
0 10
new file mode 100644
... ...
@@ -0,0 +1,40 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Registrar errno
4
+ */
5
+
6
+#ifndef RERRNO_H
7
+#define RERRNO_H
8
+
9
+
10
+typedef enum rerr {
11
+	R_OK = 0,     /* Everything went OK */
12
+	R_UL_DEL_R,   /* Usrloc record delete failed */
13
+	R_UL_GET_R,   /* Usrloc record get failed */
14
+	R_UL_NEW_R,   /* Usrloc new record failed */
15
+	R_INV_CSEQ,   /* Invalid CSeq value */
16
+	R_UL_INS_C,   /* Usrloc insert contact failed */
17
+	R_UL_INS_R,   /* Usrloc insert record failed */
18
+	R_UL_DEL_C,   /* Usrloc contact delete failed */
19
+	R_UL_UPD_C,   /* Usrloc contact update failed */
20
+	R_TO_USER,    /* No username part in To URI */
21
+	R_INV_EXP,    /* Invalid expires parameter in contact */
22
+	R_INV_Q,      /* Invalid q parameter in contact */
23
+	R_PARSE,      /* Error while parsing message */
24
+	R_TO_MISS,    /* Missing To header field */
25
+	R_CID_MISS,   /* Missing Call-ID header field */
26
+	R_CS_MISS,    /* Missing CSeq header field */
27
+	R_PARSE_EXP,  /* Error while parsing Expires */
28
+	R_PARSE_CONT, /* Error while parsing Contact */
29
+	R_STAR_EXP,   /* star and expires != 0 */
30
+	R_STAR_CONT,  /* star and more contacts */
31
+	R_OOO,        /* Out-Of-Order request */
32
+	R_RETRANS     /* Request is retransmission */
33
+} rerr_t;
34
+
35
+
36
+extern rerr_t rerrno;
37
+
38
+
39
+#endif /* RERRNO_H */
0 40
new file mode 100644
... ...
@@ -0,0 +1,335 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Process REGISTER request and send reply
4
+ */
5
+
6
+#include "save.h"
7
+#include "../../str.h"
8
+#include "../../parser/parse_to.h"
9
+#include "../../dprint.h"
10
+#include "../../trim.h"
11
+#include "../usrloc/usrloc.h"
12
+#include "common.h"
13
+#include "sip_msg.h"
14
+#include "rerrno.h"
15
+#include "reply.h"
16
+#include "convert.h"
17
+
18
+
19
+/*
20
+ * Process request that contained a star, in that case, 
21
+ * we will remove all bindings with the given username 
22
+ * from the usrloc and return 200 OK response
23
+ */
24
+static inline int star(udomain_t* _d, str* _u)
25
+{
26
+	urecord_t* r;
27
+	
28
+	if (ul_delete_record(_d, _u) < 0) {
29
+		LOG(L_ERR, "star(): Error while removing record from usrloc\n");
30
+		
31
+		     /* Delete failed, try to get corresponding
32
+		      * record structure and send back all existing
33
+		      * contacts
34
+		      */
35
+		rerrno = R_UL_DEL_R;
36
+		if (!ul_get_record(_d, _u, &r)) {
37
+			build_contact(r->contacts);
38
+			ul_release_record(r);
39
+		}
40
+		return -1;
41
+	}
42
+	return 0;
43
+}
44
+
45
+
46
+/*
47
+ * Process request that contained no contact header
48
+ * field, it means that we have to send back a response
49
+ * containing a list of all existing bindings for the
50
+ * given username (in To HF)
51
+ */
52
+static inline int no_contacts(udomain_t* _d, str* _u)
53
+{
54
+	urecord_t* r;
55
+	int res;
56
+	
57
+	res = ul_get_record(_d, _u, &r);
58
+	if (res < 0) {
59
+		rerrno = R_UL_GET_R;
60
+		LOG(L_ERR, "no_contacts(): Error while retrieving record from usrloc\n");
61
+		return -1;
62
+	}
63
+	
64
+	if (res == 0) {  /* Contacts found */
65
+		build_contact(r->contacts);
66
+		ul_release_record(r);
67
+	}
68
+	return 0;
69
+}
70
+
71
+
72
+/*
73
+ * Message contained some contacts, but record with same address
74
+ * of record was not found so we have to create a new record
75
+ * and insert all contacts from the message that have expires
76
+ * > 0
77
+ */
78
+static inline int insert(struct sip_msg* _m, contact_t* _c, udomain_t* _d, str* _u)
79
+{
80
+	urecord_t* r = 0;
81
+	int e, cseq;
82
+	float q;
83
+	str uri, callid;
84
+
85
+	while(_c) {
86
+		if (calc_contact_expires(_m, _c->expires, &e) < 0) {
87
+			LOG(L_ERR, "insert(): Error while calculating expires\n");
88
+			return -1;
89
+		}
90
+		     /* Skip contacts with zero expires */
91
+		if (e == 0) goto skip;
92
+		
93
+	        if (r == 0) {
94
+			if (ul_new_record(_u, &r) < 0) {
95
+				rerrno = R_UL_NEW_R;
96
+				LOG(L_ERR, "insert(): Can't create new record structure\n");
97
+				return -2;
98
+			}
99
+			     /* FIXME !!! */
100
+			r->domain = _d->name;
101
+		}
102
+		
103
+		     /* Calculate q value of the contact */
104
+		if (calc_contact_q(_c->q, &q) < 0) {
105
+			LOG(L_ERR, "insert(): Error while calculating q\n");
106
+			ul_free_record(r);
107
+			return -3;
108
+		}
109
+
110
+		     /* Extract raw uri from contact, ie without name part and <> */
111
+		str_copy(&uri, &_c->uri);
112
+		get_raw_uri(&uri);
113
+
114
+		     /* Get callid of the message */
115
+		str_copy(&callid, &_m->callid->body);
116
+		trim(&callid);
117
+		
118
+		     /* Get CSeq number of the message */
119
+		if (atoi(&(((struct cseq_body*)_m->cseq->parsed)->number), &cseq) < 0) {
120
+			rerrno = R_INV_CSEQ;
121
+			LOG(L_ERR, "insert(): Error while converting cseq number\n");
122
+			ul_free_record(r);
123
+			return -4;
124
+		}
125
+
126
+		if (ul_insert_contact(r, &uri, e, q, &callid, cseq) < 0) {
127
+			rerrno = R_UL_INS_C;
128
+			LOG(L_ERR, "insert(): Error while inserting contact\n");
129
+			ul_free_record(r);
130
+			return -5;
131
+		}
132
+		
133
+	skip:
134
+		_c = get_next_contact(_c);
135
+	}
136
+	
137
+	if (r) {
138
+		if (ul_insert_record(_d, r) < 0) {
139
+			rerrno = R_UL_INS_R;
140
+			LOG(L_ERR, "insert(): Error while inserting record\n");
141
+			ul_free_record(r);
142
+			return -6;
143
+		}
144
+
145
+		build_contact(r->contacts);
146
+	}
147
+
148
+	return 0;
149
+}
150
+
151
+
152
+/*
153
+ * Message contained some contacts and apropriate
154
+ * record was found, so we have to walk through
155
+ * all contacts and do the following:
156
+ * 1) If contact in usrloc doesn't exists and
157
+ *    expires > 0, insert new contact
158
+ * 2) If contact in usrloc exists and expires
159
+ *    > 0, update the contact
160
+ * 3) If contact in usrloc exists and expires
161
+ *    == 0, delete contact
162
+ */
163
+static inline int update(struct sip_msg* _m, urecord_t* _r, contact_t* _c)
164
+{
165
+	ucontact_t* c;
166
+	str uri, callid;
167
+	int cseq, e;
168
+	float q;
169
+
170
+	LOG(L_ERR, "update()\n"); /*d*/
171
+
172
+	while(_c) {
173
+		if (calc_contact_expires(_m, _c->expires, &e) < 0) {
174
+			build_contact(_r->contacts);
175
+			LOG(L_ERR, "update(): Error while calculating expires\n");
176
+			return -1;
177
+		}
178
+
179
+		str_copy(&uri, &_c->uri);
180
+		get_raw_uri(&uri);
181
+		
182
+		if (ul_get_contact(_r, &uri, &c) > 0) {
183
+			LOG(L_ERR, "contact not found\n"); /*d*/
184
+			     /* Contact not found */
185
+			if (e != 0) {
186
+				LOG(L_ERR, "expires != 0\n"); /*d*/
187
+				     /* Calculate q value of the contact */
188
+				if (calc_contact_q(_c->q, &q) < 0) {
189
+					LOG(L_ERR, "update(): Error while calculating q\n");
190
+					return -2;
191
+				}
192
+				
193
+				     /* Get callid of the message */
194
+				str_copy(&callid, &_m->callid->body);
195
+				trim(&callid);
196
+				
197
+				     /* Get CSeq number of the message */
198
+				if (atoi(&(((struct cseq_body*)_m->cseq->parsed)->number), &cseq) < 0) {
199
+					rerrno = R_INV_CSEQ;
200
+					LOG(L_ERR, "update(): Error while converting cseq number\n");
201
+					return -3;
202
+				}
203
+				
204
+				LOG(L_ERR, "inserting\n"); /*d*/
205
+				if (ul_insert_contact(_r, &uri, e, q, &callid, cseq) < 0) {
206
+					rerrno = R_UL_INS_C;
207
+					LOG(L_ERR, "update(): Error while inserting contact\n");
208
+					return -4;
209
+				}
210
+			}
211
+		} else {
212
+			LOG(L_ERR, "contact found\n"); /*d*/
213
+			if (e == 0) {
214
+				LOG(L_ERR, "deleting\n"); /*d*/
215
+				if (ul_delete_contact(_r, c) < 0) {
216
+					rerrno = R_UL_DEL_C;
217
+					LOG(L_ERR, "update(): Error while deleting contact\n");
218
+					return -5;
219
+				}
220
+			} else {
221
+				     /* Calculate q value of the contact */
222
+				if (calc_contact_q(_c->q, &q) < 0) {
223
+					LOG(L_ERR, "update(): Error while calculating q\n");
224
+					return -6;
225
+				}
226
+				
227
+				     /* Get callid of the message */
228
+				str_copy(&callid, &_m->callid->body);
229
+				trim(&callid);
230
+				
231
+				     /* Get CSeq number of the message */
232
+				if (atoi(&(((struct cseq_body*)_m->cseq->parsed)->number), &cseq) < 0) {
233
+					rerrno = R_INV_CSEQ;
234
+					LOG(L_ERR, "update(): Error while converting cseq number\n");
235
+					return -7;
236
+				}
237
+				
238
+				LOG(L_ERR, "updating\n"); /*d*/
239
+				if (ul_update_contact(c, e, q, &callid, cseq) < 0) {
240
+					rerrno = R_UL_UPD_C;
241
+					LOG(L_ERR, "update(): Error while updating contact\n");
242
+					return -8;
243
+				}
244
+			}
245
+		}
246
+		_c = _c->next;
247
+	}
248
+
249
+	return 0;
250
+}
251
+
252
+
253
+/* 
254
+ * This function will process request that
255
+ * contained some contact header fields
256
+ */
257
+static inline int contacts(struct sip_msg* _m, contact_t* _c, udomain_t* _d, str* _u)
258
+{
259
+	int res;
260
+	urecord_t* r;
261
+	LOG(L_ERR, "contacts()\n"); /*d*/
262
+
263
+	res = ul_get_record(_d, _u, &r);
264
+	if (res < 0) {
265
+		rerrno = R_UL_GET_R;
266
+		LOG(L_ERR, "contacts(): Error while retrieving record from usrloc\n");
267
+		return -2;
268
+	}
269
+
270
+	if (res == 0) { /* Contacts found */
271
+		if (update(_m, r, _c) < 0) {
272
+			LOG(L_ERR, "contacts(): Error while updating record\n");
273
+			build_contact(r->contacts);
274
+			ul_release_record(r);
275
+			return -3;
276
+		}
277
+		build_contact(r->contacts);
278
+		ul_release_record(r);
279
+	} else {
280
+		if (insert(_m, _c, _d, _u) < 0) {
281
+			LOG(L_ERR, "contacts(): Error while inserting record\n");
282
+			return -4;
283
+		}
284
+	}
285
+	return 0;
286
+}
287
+
288
+
289
+/*
290
+ * Process REGISTER request and save it's contacts
291
+ */
292
+int save(struct sip_msg* _m, char* _t, char* _s)
293
+{
294
+	contact_t* c;
295
+	int st;
296
+	str user;
297
+
298
+	rerrno = R_OK;
299
+
300
+	if (parse_message(_m) < 0) {
301
+		goto error;
302
+	}
303
+
304
+	if (check_contacts(_m, &st) > 0) {
305
+		goto error;
306
+	}
307
+	
308
+	get_act_time();
309
+	c = get_first_contact(_m);
310
+	str_copy(&user, &((struct to_body*)_m->to->parsed)->uri);
311
+
312
+	if (get_user(&user) < 0) {
313
+		rerrno = R_TO_USER;
314
+		LOG(L_ERR, "save(): Can't extract username part from To URI, sending 400\n");
315
+		goto error;
316
+	}
317
+
318
+	if (c == 0) {
319
+		if (st) {
320
+			if (star((udomain_t*)_t, &user) < 0) goto error;
321
+		} else {
322
+			if (no_contacts((udomain_t*)_t, &user) < 0) goto error;
323
+		}
324
+	} else {
325
+		if (contacts(_m, c, (udomain_t*)_t, &user) < 0) goto error;
326
+	}
327
+
328
+	if (send_reply(_m) < 0) return -1;
329
+	else return 1;
330
+	
331
+ error:
332
+	send_reply(_m);
333
+	return -1;
334
+}
0 335
new file mode 100644
... ...
@@ -0,0 +1,21 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Functions that process REGISTER message 
4
+ * and store data in usrloc
5
+ */
6
+
7
+#ifndef SAVE_H
8
+#define SAVE_H
9
+
10
+
11
+#include "../../parser/msg_parser.h"
12
+
13
+
14
+/*
15
+ * Process REGISTER request and save it's contacts
16
+ */
17
+int save(struct sip_msg* _m, char* _t, char* _s);
18
+
19
+
20
+#endif /* SAVE_H */
0 21
new file mode 100644
... ...
@@ -0,0 +1,230 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * SIP message related functions
4
+ */
5
+
6
+
7
+#include "sip_msg.h"
8
+#include "../../parser/hf.h"
9
+#include "../../dprint.h"
10
+#include "../../parser/parse_expires.h"  
11
+#include "reg_mod.h"                     /* Module parameters */
12
+#include "convert.h"                     /* atof, atoi */
13
+#include "regtime.h"                     /* act_time */
14
+#include "rerrno.h"
15
+
16
+
17
+static struct hdr_field* act_contact;
18
+
19
+
20
+/*
21
+ * Return value of Expires header field
22
+ * if the HF exists converted to absolute
23
+ * time, if the HF doesn't exist, returns
24
+ * default value;
25
+ */
26
+static inline int get_expires_hf(struct sip_msg* _m)
27
+{
28
+	exp_body_t* p;
29
+	
30
+	if (_m->expires) {
31
+		p = (exp_body_t*)_m->expires->parsed;
32
+		if (p->val != 0) {
33
+			return p->val + act_time;
34
+		} else return 0;
35
+	} else {
36
+		return act_time + default_expires;
37
+	}
38
+}
39
+
40
+
41
+/*
42
+ * Parse the whole messsage and bodies of all header fieds
43
+ * that will be needed by registrar
44
+ */
45
+int parse_message(struct sip_msg* _m)
46
+{
47
+	struct hdr_field* ptr;
48
+	
49
+	if (parse_headers(_m, HDR_EOH, 0) == -1) {
50
+		rerrno = R_PARSE;
51
+		LOG(L_ERR, "parse_message(): Error while parsing headers\n");
52
+		return -1;
53
+	}
54
+	
55
+	if (!_m->to) {
56
+		rerrno = R_TO_MISS;
57
+		LOG(L_ERR, "parse_message(): To not found\n");
58
+		return -2;
59
+	}
60
+
61
+	if (!_m->callid) {
62
+		rerrno = R_CID_MISS;
63
+		LOG(L_ERR, "parse_message(): Call-ID not found\n");
64
+		return -3;
65
+	}
66
+
67
+	if (!_m->cseq) {
68
+		rerrno = R_CS_MISS;
69
+		LOG(L_ERR, "parse_message(): CSeq not found\n");
70
+		return -4;
71
+	}
72
+
73
+	if (_m->expires && !_m->expires->parsed && (parse_expires(_m->expires) < 0)) {
74
+		rerrno = R_PARSE_EXP;
75
+		LOG(L_ERR, "parse_message(): Error while parsing expires body\n");
76
+		return -5;
77
+	}
78
+	
79
+	if (_m->contact) {
80
+		ptr = _m->contact;
81
+		while(ptr) {
82
+			if (ptr->type == HDR_CONTACT) {
83
+				if (!ptr->parsed && (parse_contact(ptr) < 0)) {
84
+					rerrno = R_PARSE_CONT;
85
+					LOG(L_ERR, "parse_message(): Error while parsing Contact body\n");
86
+					return -6;
87
+				}
88
+			}
89
+			ptr = ptr->next;
90
+		}
91
+	}
92
+	
93
+	return 0;
94
+}
95
+
96
+
97
+/*
98
+ * Check if the originating REGISTER message was formed correctly
99
+ * The whole message must be parsed before calling the function
100
+ * _s indicates whether the contact was star
101
+ */
102
+int check_contacts(struct sip_msg* _m, int* _s)
103
+{
104
+	struct hdr_field* p;
105
+	
106
+	*_s = 0;
107
+	     /* Message without contacts is OK */
108
+	if (_m->contact == 0) return 0;
109
+	
110
+	if (((contact_body_t*)_m->contact->parsed)->star == 1) { /* The first Contact HF is star */
111
+		     /* Expires must be zero */
112
+		if (get_expires_hf(_m) > 0) {
113
+			rerrno = R_STAR_EXP;
114
+			return 1;
115
+		}
116
+		
117
+		     /* Message must contain no contacts */
118
+		if (((contact_body_t*)_m->contact->parsed)->contacts) {
119
+			rerrno = R_STAR_CONT;
120
+			return 1;
121
+		}
122
+		
123
+		     /* Message must contain no other Contact HFs */
124
+		p = _m->contact->next;
125
+		while(p) {
126
+			if (p->type == HDR_CONTACT) {
127
+				rerrno = R_STAR_CONT;
128
+				return 1;
129
+			}
130
+			p = p->next;
131
+		}
132
+		
133
+		*_s = 1;
134
+	} else { /* The first Contact HF is not star */
135
+		     /* Message must contain no star Contact HF */
136
+		p = _m->contact->next;
137
+		while(p) {
138
+			if (p->type == HDR_CONTACT) {
139
+				if (((contact_body_t*)p->parsed)->star == 1) {
140
+					rerrno = R_STAR_CONT;
141
+					return 1;
142
+				}
143
+			}
144
+			p = p->next;
145
+		}
146
+	}
147
+	
148
+	return 0;
149
+}
150
+
151
+
152
+/*
153
+ * Get the first contact in message
154
+ */
155
+contact_t* get_first_contact(struct sip_msg* _m)
156
+{
157
+	if (_m->contact == 0) return 0;
158
+	
159
+	act_contact = _m->contact;
160
+	return (((contact_body_t*)_m->contact->parsed)->contacts);
161
+}
162
+
163
+
164
+/* 
165
+ * Get next contact in message
166
+ */
167
+contact_t* get_next_contact(contact_t* _c)
168
+{
169
+	struct hdr_field* p;
170
+	if (_c->next == 0) {
171
+		p = act_contact->next;
172
+		while(p) {
173
+			if (p->type == HDR_CONTACT) {
174
+				act_contact = p;
175
+				return (((contact_body_t*)p->parsed)->contacts);
176
+			}
177
+			p = p->next;
178
+		}
179
+		return 0;
180
+	} else {
181
+		return _c->next;
182
+	}
183
+}
184
+
185
+
186
+/*
187
+ * Calculate absolute expires value per contact as follows:
188
+ * 1) If the contact has expires value, use the value. If it
189
+ *    is not zero, add actual time to it
190
+ * 2) If the contact has no expires parameter, use expires
191
+ *    header field in the same way
192
+ * 3) If the message contained no expires header field, use
193
+ *    the default value
194
+ */
195
+int calc_contact_expires(struct sip_msg* _m, cparam_t* _ep, int* _e)
196
+{
197
+	if (!_ep || (_ep->body.len == 0)) {
198
+		*_e = get_expires_hf(_m);
199
+	} else {
200
+		if (atoi(&_ep->body, _e) < 0) {
201
+			rerrno = R_INV_EXP; /* Invalid expires parameter */
202
+			LOG(L_ERR, "calc_contact_expires(): Invalid expires parameter\n");
203
+			return -1;
204
+		}
205
+		     /* Convert to absolute value */
206
+		if (*_e != 0) *_e += act_time;
207
+	}		
208
+	return 0;
209
+}
210
+
211
+
212
+/*
213
+ * Calculate contact q value as follows:
214
+ * 1) If q parameter exists, use it
215
+ * 2) If the parameter doesn't exist, use default value
216
+ */
217
+int calc_contact_q(cparam_t* _q, float* _r)
218
+{
219
+	if (!_q || (_q->body.len == 0)) {
220
+		*_r = def_q;
221
+	} else {
222
+		if (atof(&_q->body, _r) < 0) {
223
+			rerrno = R_INV_Q; /* Invalid q parameter */
224
+			LOG(L_ERR, "calc_contact_q(): Invalid q parameter\n");
225
+			return -1;
226
+		}
227
+	}
228
+	return 0;
229
+}
0 230
new file mode 100644
... ...
@@ -0,0 +1,62 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * SIP message related functions
4
+ */
5
+
6
+#ifndef SIP_MSG_H
7
+#define SIP_MSG_H
8
+
9
+
10
+#include "../../parser/msg_parser.h"
11
+#include "../../parser/contact/parse_contact.h"
12
+
13
+
14
+/*
15
+ * Parse the whole messsage and bodies of all header fieds
16
+ * that will be needed by registrar
17
+ */
18
+int parse_message(struct sip_msg* _m);
19
+
20
+
21
+/*
22
+ * Check if the originating REGISTER message was formed correctly
23
+ * The whole message must be parsed before calling the function
24
+ * _s indicates whether the contact was star
25
+ */
26
+int check_contacts(struct sip_msg* _m, int* _s);
27
+
28
+
29
+/*
30
+ * Get the first contact in message
31
+ */
32
+contact_t* get_first_contact(struct sip_msg* _m);
33
+
34
+
35
+/* 
36
+ * Get next contact in message
37
+ */
38
+contact_t* get_next_contact(contact_t* _c);
39
+
40
+
41
+/*
42
+ * Calculate absolute expires value per contact as follows:
43
+ * 1) If the contact has expires value, use the value. If it
44
+ *    is not zero, add actual time to it
45
+ * 2) If the contact has no expires parameter, use expires
46
+ *    header field in the same way
47
+ * 3) If the message contained no expires header field, use
48
+ *    the default value
49
+ */
50
+int calc_contact_expires(struct sip_msg* _m, cparam_t* _ep, int* _e);
51
+
52
+
53
+/*
54
+ * Calculate contact q value as follows:
55
+ * 1) If q parameter exist, use it
56
+ * 2) If the parameter doesn't exist, use default value
57
+ */
58
+int calc_contact_q(cparam_t* _q, float* _r);
59
+
60
+
61
+#endif /* SIP_MSG_H */
0 62
new file mode 100644
... ...
@@ -0,0 +1,32 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * URI related functions
4
+ */
5
+
6
+#include "uri.h"
7
+#include "common.h"
8
+
9
+
10
+/*
11
+ * This function skips name part
12
+ * uri parsed by parse_contact must be used
13
+ * (the uri must not contain any leading or
14
+ *  trailing part and if angle bracket were
15
+ *  used, right angle bracket must be the
16
+ *  last character in the string)
17
+ *
18
+ * _s will be modified so it should be a tmp
19
+ * copy
20
+ */
21
+void get_raw_uri(str* _s)
22
+{
23
+	char* aq;
24
+	
25
+	if (_s->s[_s->len - 1] == '>') {
26
+		aq = find_not_quoted(_s, '<');
27
+		_s->len -= aq - _s->s + 2;
28
+		_s->s = aq + 1;
29
+	}
30
+}
31
+
0 32
new file mode 100644
... ...
@@ -0,0 +1,27 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * URI related functions
4
+ */
5
+
6
+#ifndef URI_H
7
+#define URI_H
8
+
9
+#include "../../str.h"
10
+
11
+
12
+/*
13
+ * This function skips name part
14