Browse code

Aligned to the new qvalue type

Jan Janak authored on 27/04/2004 14:53:22
Showing 17 changed files
... ...
@@ -41,6 +41,7 @@
41 41
 #include "../../error.h"
42 42
 #include "save.h"
43 43
 #include "lookup.h"
44
+#include "reply.h"
44 45
 #include "reg_mod.h"
45 46
 
46 47
 
... ...
@@ -49,19 +50,18 @@ MODULE_VERSION
49 49
 
50 50
 static int mod_init(void);                           /* Module init function */
51 51
 static int domain_fixup(void** param, int param_no); /* Fixup that converts domain name */
52
+static void mod_destroy(void);
52 53
 
53 54
 usrloc_api_t ul;            /* Structure containing pointers to usrloc functions */
54 55
 
55
-int default_expires = 3600; /* Default expires value in seconds */
56
-int default_q       = 0;    /* Default q value multiplied by 1000 */
57
-int append_branches = 1;    /* If set to 1, lookup will put all contacts found in msg structure */
58
-int case_sensitive  = 0;    /* If set to 1, username in aor will be case sensitive */
59
-int desc_time_order = 0;    /* By default do not order according to the descending modification time */
60
-int nat_flag        = 4;    /* SER flag marking contacts behind NAT */
61
-int min_expires     = 60;   /* Minimum expires the phones are allowed to use in seconds,
62
-			     * use 0 to switch expires checking off */
63
-
64
-float def_q;                /* default_q converted to float in mod_init */
56
+int default_expires = 3600;           /* Default expires value in seconds */
57
+qvalue_t default_q  = Q_UNSPECIFIED;  /* Default q value multiplied by 1000 */
58
+int append_branches = 1;              /* If set to 1, lookup will put all contacts found in msg structure */
59
+int case_sensitive  = 0;              /* If set to 1, username in aor will be case sensitive */
60
+int desc_time_order = 0;              /* By default do not order according to the descending modification time */
61
+int nat_flag        = 4;              /* SER flag marking contacts behind NAT */
62
+int min_expires     = 60;             /* Minimum expires the phones are allowed to use in seconds,
63
+			               * use 0 to switch expires checking off */
65 64
 
66 65
 
67 66
 /*
... ...
@@ -102,13 +102,13 @@ static param_export_t params[] = {
102 102
  */
103 103
 struct module_exports exports = {
104 104
 	"registrar", 
105
-	cmds,       /* Exported functions */
106
-	params,     /* Exported parameters */
107
-	mod_init,   /* module initialization function */
105
+	cmds,        /* Exported functions */
106
+	params,      /* Exported parameters */
107
+	mod_init,    /* module initialization function */
108 108
 	0,
109
-	0,          /* destroy function */
110
-	0,          /* oncancel function */
111
-	0           /* Per-child init function */
109
+	mod_destroy, /* destroy function */
110
+	0,           /* oncancel function */
111
+	0            /* Per-child init function */
112 112
 };
113 113
 
114 114
 
... ...
@@ -137,12 +137,22 @@ static int mod_init(void)
137 137
 		return -1;
138 138
 	}
139 139
 
140
+	     /* Normalize default_q parameter */
141
+	if (default_q != Q_UNSPECIFIED) {
142
+		if (default_q > MAX_Q) {
143
+			DBG("registrar: default_q = %d, lowering to MAX_Q: %d\n", default_q, MAX_Q);
144
+			default_q = MAX_Q;
145
+		} else if (default_q < MIN_Q) {
146
+			DBG("registrar: default_q = %d, raising to MIN_Q: %d\n", default_q, MIN_Q);
147
+			default_q = MIN_Q;
148
+		}
149
+	}
150
+	
151
+
140 152
 	if (bind_usrloc(&ul) < 0) {
141 153
 		return -1;
142 154
 	}
143 155
 
144
-	def_q = (float)default_q / (float)1000;
145
-
146 156
 	return 0;
147 157
 }
148 158
 
... ...
@@ -164,3 +174,9 @@ static int domain_fixup(void** param, int param_no)
164 164
 	}
165 165
 	return 0;
166 166
 }
167
+
168
+
169
+static void mod_destroy(void)
170
+{
171
+	free_contact_buf();
172
+}
... ...
@@ -32,18 +32,17 @@
32 32
 #define REG_MOD_H
33 33
 
34 34
 #include "../../parser/msg_parser.h"
35
+#include "../../qvalue.h"
35 36
 #include "../usrloc/usrloc.h"
36 37
 
37 38
 extern int default_expires;
38
-extern int default_q;
39
+extern qvalue_t default_q;
39 40
 extern int append_branches;
40 41
 extern int case_sensitive;
41 42
 extern int desc_time_order;
42 43
 extern int nat_flag;
43 44
 extern int min_expires;
44 45
 
45
-extern float def_q;
46
-
47 46
 usrloc_api_t ul;  /* Structure containing pointers to usrloc functions */
48 47
 
49 48
 extern int (*sl_reply)(struct sip_msg* _m, char* _s1, char* _s2);
... ...
@@ -50,74 +50,125 @@
50 50
 #define E_INFO "P-Registrar-Error: "
51 51
 #define E_INFO_LEN (sizeof(E_INFO) - 1)
52 52
 
53
+#define CONTACT_BEGIN "Contact: "
54
+#define CONTACT_BEGIN_LEN (sizeof(CONTACT_BEGIN) - 1)
53 55
 
54
-static char b[MAX_CONTACT_BUFFER];
55
-static int l;
56
+#define Q_PARAM ">;q="
57
+#define Q_PARAM_LEN (sizeof(Q_PARAM) - 1)
58
+
59
+#define EXPIRES_PARAM ";expires="
60
+#define EXPIRES_PARAM_LEN (sizeof(EXPIRES_PARAM) - 1)
61
+
62
+#define CONTACT_SEP ", "
63
+#define CONTACT_SEP_LEN (sizeof(CONTACT_SEP) - 1)
64
+
65
+
66
+/*
67
+ * Buffer for Contact header field
68
+ */
69
+static struct {
70
+	char* buf;
71
+	int buf_len;
72
+	int data_len;
73
+} contact = {0, 0, 0};
56 74
 
57 75
 
58 76
 /*
59
- * Build Contact HF for reply
77
+ * Calculate the length of buffer needed to
78
+ * print contacts
60 79
  */
61
-void build_contact(ucontact_t* _c)
80
+static inline unsigned int calc_buf_len(ucontact_t* c)
62 81
 {
63
-	char *lastgoodend;
64
-	int nummissed;
65
-	
66
-	l = 0;
67
-	lastgoodend = b;
68
-	while(_c) {
69
-		if (VALID_CONTACT(_c, act_time)) {
70
-			if (l + 10 >= MAX_CONTACT_BUFFER)
71
-				break;
72
-			memcpy(b + l, "Contact: <", 10);
73
-			l += 10;
74
-			
75
-			if (l + _c->c.len >= MAX_CONTACT_BUFFER)
76
-				break;
77
-			memcpy(b + l, _c->c.s, _c->c.len);
78
-			l += _c->c.len;
79
-			
80
-			if (l + 4 >= MAX_CONTACT_BUFFER)
81
-				break;
82
-			memcpy(b + l, ">;q=", 4);
83
-			l += 4;
84
-			
85
-			l += snprintf(b + l, MAX_CONTACT_BUFFER - l, "%-3.2f", _c->q);
86
-			if (l >= MAX_CONTACT_BUFFER)
87
-				break;
88
-			
89
-			if (l + 9 >= MAX_CONTACT_BUFFER)
90
-				break;
91
-			memcpy(b + l, ";expires=", 9);
92
-			l += 9;
93
-			
94
-			l += snprintf(b + l, MAX_CONTACT_BUFFER - l, "%d", (int)(_c->expires - act_time));
95
-			if (l >= MAX_CONTACT_BUFFER)
96
-				break;
97
-
98
-			if (l + 2 >= MAX_CONTACT_BUFFER)
99
-				break;
100
-			*(b + l++) = '\r';
101
-			*(b + l++) = '\n';
102
-			lastgoodend = b + l;
103
-		}
82
+	unsigned int len;
83
+	int qlen;
104 84
 
105
-		_c = _c->next;
85
+	len = 0;
86
+	while(c) {
87
+		if (VALID_CONTACT(c, act_time)) {
88
+			if (len) len += CONTACT_SEP_LEN;
89
+			len += 2 /* < > */ + c->c.len;
90
+			qlen = len_q(c->q);
91
+			if (qlen) len += Q_PARAM_LEN + qlen;
92
+			len += EXPIRES_PARAM_LEN + INT2STR_MAX_LEN;
93
+		}
94
+		c = c->next;
106 95
 	}
107
-	if (lastgoodend - b != l) {
108
-		l = lastgoodend - b;
109
-		for(nummissed = 0; _c; _c = _c->next)
110
-			nummissed++;
111
-		LOG(L_ERR, "build_contact(): Contact list buffer exhaused, %d contact(s) ignored\n", nummissed);
96
+
97
+	if (len) len += CONTACT_BEGIN_LEN + CRLF_LEN;
98
+	return len;
99
+}
100
+
101
+
102
+/*
103
+ * Allocate a memory buffer and print Contact
104
+ * header fields into it
105
+ */
106
+int build_contact(ucontact_t* c)
107
+{
108
+	char* p;
109
+	int fl, len;
110
+
111
+	contact.data_len = calc_buf_len(c);
112
+	if (!contact.data_len) return 0;
113
+
114
+	if (!contact.buf || (contact.buf_len < contact.data_len)) {
115
+		if (contact.buf) pkg_free(contact.buf);
116
+		contact.buf = (char*)pkg_malloc(contact.data_len);
117
+		if (!contact.buf) {
118
+			contact.data_len = 0;
119
+			contact.buf_len = 0;
120
+			LOG(L_ERR, "build_contact(): No memory left\n");
121
+			return -1;
122
+		} else {
123
+			contact.buf_len = contact.data_len;
124
+		}
112 125
 	}
113 126
 
114
-	if (_c) {
115
-		DBG("build_contact(): Created Contact HF: %.*s\n", l, /*ZSW*/(b));
116
-		/*b can never be 0; ZSW commented out to get rid of an icc warning
117
-		 * --andrei */
127
+	p = contact.buf;
128
+	
129
+	memcpy(p, CONTACT_BEGIN, CONTACT_BEGIN_LEN);
130
+	p += CONTACT_BEGIN_LEN;
131
+
132
+	fl = 0;
133
+	while(c) {
134
+		if (VALID_CONTACT(c, act_time)) {
135
+			if (fl) {
136
+				memcpy(p, CONTACT_SEP, CONTACT_SEP_LEN);
137
+				p += CONTACT_SEP_LEN;
138
+			} else {
139
+				fl = 1;
140
+			}
141
+
142
+			*p++ = '<';
143
+			memcpy(p, c->c.s, c->c.len);
144
+			p += c->c.len;
145
+			*p++ = '<';
146
+
147
+			len = len_q(c->q);
148
+			if (len) {
149
+				memcpy(p, Q_PARAM, Q_PARAM_LEN);
150
+				p += Q_PARAM_LEN;
151
+				memcpy(p, q2str(c->q, 0), len);
152
+				p += len;
153
+			}
154
+
155
+			memcpy(p, EXPIRES_PARAM, EXPIRES_PARAM_LEN);
156
+			p += EXPIRES_PARAM_LEN;
157
+			memcpy(p, int2str((int)(c->expires - act_time), &len), len);
158
+			p += len;
159
+		}
160
+
161
+		c = c->next;
118 162
 	}
119
-}
120 163
 
164
+	memcpy(p, CRLF, CRLF_LEN);
165
+	p += CRLF_LEN;
166
+
167
+	contact.data_len = p - contact.buf;
168
+
169
+	DBG("build_contact(): Created Contact HF: %.*s\n", contact.data_len, contact.buf);
170
+	return 0;
171
+}
121 172
 
122 173
 
123 174
 #define MSG_200 "OK"
... ...
@@ -217,9 +268,9 @@ int send_reply(struct sip_msg* _m)
217 217
 	char* msg = MSG_200; /* makes gcc shut up */
218 218
 	char* buf;
219 219
 
220
-	if (l > 0) {
221
-		add_lump_rpl( _m, b, l, LUMP_RPL_HDR|LUMP_RPL_NODUP|LUMP_RPL_NOFREE);
222
-		l = 0;
220
+	if (contact.data_len > 0) {
221
+		add_lump_rpl( _m, contact.buf, contact.data_len, LUMP_RPL_HDR|LUMP_RPL_NODUP|LUMP_RPL_NOFREE);
222
+		contact.data_len = 0;
223 223
 	}
224 224
 
225 225
 	code = codes[rerrno];
... ...
@@ -247,3 +298,17 @@ int send_reply(struct sip_msg* _m)
247 247
 		return -1;
248 248
 	} else return 0;	
249 249
 }
250
+
251
+
252
+/*
253
+ * Release contact buffer if any
254
+ */
255
+void free_contact_buf(void)
256
+{
257
+	if (contact.buf) {
258
+		pkg_free(contact.buf);
259
+		contact.buf = 0;
260
+		contact.buf_len = 0;
261
+		contact.data_len = 0;
262
+	}
263
+}
... ...
@@ -32,7 +32,7 @@
32 32
 #define REPLY_H
33 33
 
34 34
 #include "../../parser/msg_parser.h"
35
-
35
+#include "ucontact.h"
36 36
 
37 37
 /*
38 38
  * Send a reply
... ...
@@ -43,7 +43,13 @@ int send_reply(struct sip_msg* _m);
43 43
 /*
44 44
  * Build Contact HF for reply
45 45
  */
46
-void build_contact(ucontact_t* _c);
46
+int build_contact(ucontact_t* c);
47
+
48
+
49
+/*
50
+ * Release contact buffer if any
51
+ */
52
+void free_contact_buf(void);
47 53
 
48 54
 
49 55
 #endif /* REPLY_H */
... ...
@@ -41,6 +41,7 @@
41 41
 #include "../../trim.h"
42 42
 #include "../../ut.h"
43 43
 #include "../usrloc/usrloc.h"
44
+#include "../../qvalue.h"
44 45
 #include "common.h"
45 46
 #include "sip_msg.h"
46 47
 #include "rerrno.h"
... ...
@@ -153,7 +154,7 @@ static inline int insert(struct sip_msg* _m, contact_t* _c, udomain_t* _d, str*
153 153
 	urecord_t* r = 0;
154 154
 	ucontact_t* c;
155 155
 	int e, cseq;
156
-	float q;
156
+	qvalue_t q;
157 157
 	str callid;
158 158
 	unsigned int flags;
159 159
 
... ...
@@ -234,7 +235,7 @@ static inline int update(struct sip_msg* _m, urecord_t* _r, contact_t* _c)
234 234
 	ucontact_t* c, *c2;
235 235
 	str callid;
236 236
 	int cseq, e;
237
-	float q;
237
+	qvalue_t q;
238 238
 	unsigned int fl;
239 239
 
240 240
 	fl = (isflagset(_m, nat_flag) == 1);
... ...
@@ -33,6 +33,7 @@
33 33
 #include <dprint.h>
34 34
 #include "../../parser/parse_expires.h"  
35 35
 #include "../../ut.h"
36
+#include "../../qvalue.h"
36 37
 #include "reg_mod.h"                     /* Module parameters */
37 38
 #include "regtime.h"                     /* act_time */
38 39
 #include "rerrno.h"
... ...
@@ -242,14 +243,14 @@ int calc_contact_expires(struct sip_msg* _m, param_t* _ep, int* _e)
242 242
 /*
243 243
  * Calculate contact q value as follows:
244 244
  * 1) If q parameter exists, use it
245
- * 2) If the parameter doesn't exist, use default value
245
+ * 2) If the parameter doesn't exist, use the default value
246 246
  */
247
-int calc_contact_q(param_t* _q, float* _r)
247
+int calc_contact_q(param_t* _q, qvalue_t* _r)
248 248
 {
249 249
 	if (!_q || (_q->body.len == 0)) {
250
-		*_r = def_q;
250
+		*_r = default_q;
251 251
 	} else {
252
-		if (str2float(&_q->body, _r) < 0) {
252
+		if (str2q(_r, _q->body.s, _q->body.len) < 0) {
253 253
 			rerrno = R_INV_Q; /* Invalid q parameter */
254 254
 			LOG(L_ERR, "calc_contact_q(): Invalid q parameter\n");
255 255
 			return -1;
... ...
@@ -31,7 +31,7 @@
31 31
 #ifndef SIP_MSG_H
32 32
 #define SIP_MSG_H
33 33
 
34
-
34
+#include "../../qvalue.h"
35 35
 #include "../../parser/msg_parser.h"
36 36
 #include "../../parser/contact/parse_contact.h"
37 37
 
... ...
@@ -80,7 +80,7 @@ int calc_contact_expires(struct sip_msg* _m, param_t* _ep, int* _e);
80 80
  * 1) If q parameter exist, use it
81 81
  * 2) If the parameter doesn't exist, use default value
82 82
  */
83
-int calc_contact_q(param_t* _q, float* _r);
83
+int calc_contact_q(param_t* _q, qvalue_t* _r);
84 84
 
85 85
 
86 86
 #endif /* SIP_MSG_H */
... ...
@@ -371,7 +371,7 @@ cont)
371 371
 
372 372
      * time_t expires - Expires of the contact in absolute value.
373 373
 
374
-     * float q - q value of the contact.
374
+     * qvalue_t q - q value of the contact.
375 375
 
376 376
      * str* callid - Call-ID of the REGISTER message that
377 377
        contained the contact.
... ...
@@ -434,7 +434,7 @@ cont)
434 434
 
435 435
      * time_t expires - Expires of the contact in absolute value.
436 436
 
437
-     * float q - q value of the contact.
437
+     * qvalue_t q - q value of the contact.
438 438
 
439 439
      * str* callid - Call-ID of the REGISTER message that
440 440
        contained the contact.
... ...
@@ -123,7 +123,7 @@ int process_ins_list(str* _d)
123 123
 		VAL_STR(vals + 1).s = p->cont->s;
124 124
 
125 125
 		VAL_TIME(vals + 2) = p->expires;
126
-		VAL_DOUBLE(vals + 3) = p->q;
126
+		VAL_DOUBLE(vals + 3) = q2double(p->q);
127 127
 		
128 128
 		VAL_STR(vals + 4).len = p->cid_len;
129 129
 		VAL_STR(vals + 4).s = p->callid;
... ...
@@ -36,13 +36,14 @@
36 36
 #define INS_LIST_H
37 37
 
38 38
 #include "ucontact.h"
39
+#include "../../qvalue.h"
39 40
 #include "../../str.h"
40 41
 
41 42
 
42 43
 struct ins_itm {
43 44
 	struct ins_itm* next;
44 45
 	time_t expires;
45
-	float q;
46
+	qvalue_t q;
46 47
 	int cseq;
47 48
 	int replicate;
48 49
 	cstate_t state;
... ...
@@ -47,7 +47,7 @@
47 47
 /*
48 48
  * Create a new contact structure
49 49
  */
50
-int new_ucontact(str* _dom, str* _aor, str* _contact, time_t _e, float _q,
50
+int new_ucontact(str* _dom, str* _aor, str* _contact, time_t _e, qvalue_t _q,
51 51
 		 str* _callid, int _cseq, unsigned int _flags, int _rep, ucontact_t** _c)
52 52
 {
53 53
 	*_c = (ucontact_t*)shm_malloc(sizeof(ucontact_t));
... ...
@@ -130,7 +130,7 @@ void print_ucontact(FILE* _f, ucontact_t* _c)
130 130
 		fprintf(_f, "Expires: -%u\n", (unsigned int)(t - _c->expires));
131 131
 	else
132 132
 		fprintf(_f, "Expires: %u\n", (unsigned int)(_c->expires - t));
133
-	fprintf(_f, "q      : %10.2f\n", _c->q);
133
+	fprintf(_f, "q      : %s\n", q2str(_c->q, 0));
134 134
 	fprintf(_f, "Call-ID: '%.*s'\n", _c->callid.len, ZSW(_c->callid.s));
135 135
 	fprintf(_f, "CSeq   : %d\n", _c->cseq);
136 136
 	fprintf(_f, "replic : %u\n", _c->replicate);
... ...
@@ -145,7 +145,7 @@ void print_ucontact(FILE* _f, ucontact_t* _c)
145 145
 /*
146 146
  * Update ucontact structure in memory
147 147
  */
148
-int mem_update_ucontact(ucontact_t* _c, time_t _e, float _q, str* _cid, int _cs,
148
+int mem_update_ucontact(ucontact_t* _c, time_t _e, qvalue_t _q, str* _cid, int _cs,
149 149
 			unsigned int _set, unsigned int _res)
150 150
 {
151 151
 	char* ptr;
... ...
@@ -460,7 +460,7 @@ int db_insert_ucontact(ucontact_t* _c)
460 460
 
461 461
 	vals[3].type = DB_DOUBLE;
462 462
 	vals[3].nul = 0;
463
-	vals[3].val.double_val = _c->q;
463
+	vals[3].val.double_val = q2double(_c->q);
464 464
 
465 465
 	vals[4].type = DB_STR;
466 466
 	vals[4].nul = 0;
... ...
@@ -549,7 +549,7 @@ int db_update_ucontact(ucontact_t* _c)
549 549
 
550 550
 	vals2[1].type = DB_DOUBLE;
551 551
 	vals2[1].nul = 0;
552
-	vals2[1].val.double_val = _c->q;
552
+	vals2[1].val.double_val = q2double(_c->q);
553 553
 
554 554
 	vals2[2].type = DB_STR;
555 555
 	vals2[2].nul = 0;
... ...
@@ -649,7 +649,7 @@ int db_delete_ucontact(ucontact_t* _c)
649 649
  * the replication mark.
650 650
  * FIXME: i'm not sure if we need this...
651 651
  */
652
-int update_ucontact_rep(ucontact_t* _c, time_t _e, float _q, str* _cid, int _cs, int _rep,
652
+int update_ucontact_rep(ucontact_t* _c, time_t _e, qvalue_t _q, str* _cid, int _cs, int _rep,
653 653
 			unsigned int _set, unsigned int _res)
654 654
 {
655 655
 	_c->replicate = _rep;
... ...
@@ -659,7 +659,7 @@ int update_ucontact_rep(ucontact_t* _c, time_t _e, float _q, str* _cid, int _cs,
659 659
 /*
660 660
  * Update ucontact with new values
661 661
  */
662
-int update_ucontact(ucontact_t* _c, time_t _e, float _q, str* _cid, int _cs,
662
+int update_ucontact(ucontact_t* _c, time_t _e, qvalue_t _q, str* _cid, int _cs,
663 663
 		    unsigned int _set, unsigned int _res)
664 664
 {
665 665
 	/* run callbacks for UPDATE event */
... ...
@@ -38,6 +38,7 @@
38 38
 
39 39
 #include <stdio.h>
40 40
 #include <time.h>
41
+#include "../../qvalue.h"
41 42
 #include "../../str.h"
42 43
 
43 44
 typedef enum cstate {
... ...
@@ -74,7 +75,7 @@ typedef struct ucontact {
74 74
 	str* aor;               /* Pointer to the address of record string in record structure*/
75 75
 	str c;                  /* Contact address */
76 76
 	time_t expires;         /* expires parameter */
77
-	float q;                /* q parameter */
77
+	qvalue_t q;             /* q parameter */
78 78
 	str callid;             /* Call-ID header field */
79 79
         int cseq;               /* CSeq value */
80 80
 	unsigned int replicate; /* replication marker */
... ...
@@ -95,7 +96,7 @@ typedef struct ucontact {
95 95
 /*
96 96
  * Create a new contact structure
97 97
  */
98
-int new_ucontact(str* _dom, str* _aor, str* _contact, time_t _e, float _q, 
98
+int new_ucontact(str* _dom, str* _aor, str* _contact, time_t _e, qvalue_t _q, 
99 99
 		 str* _callid, int _cseq, unsigned int _flags, int _rep, ucontact_t** _c);
100 100
 
101 101
 
... ...
@@ -114,7 +115,7 @@ void print_ucontact(FILE* _f, ucontact_t* _c);
114 114
 /*
115 115
  * Update existing contact in memory with new values
116 116
  */
117
-int mem_update_ucontact(ucontact_t* _c, time_t _e, float _q, str* _cid, int _cs,
117
+int mem_update_ucontact(ucontact_t* _c, time_t _e, qvalue_t _q, str* _cid, int _cs,
118 118
 			unsigned int _set, unsigned int _res);
119 119
 
120 120
 
... ...
@@ -182,15 +183,15 @@ int db_delete_ucontact(ucontact_t* _c);
182 182
 /*
183 183
  * Update ucontact with new values without replication
184 184
  */
185
-typedef int (*update_ucontact_t)(ucontact_t* _c, time_t _e, float _q, str* _cid, int _cs, 
185
+typedef int (*update_ucontact_t)(ucontact_t* _c, time_t _e, qvalue_t _q, str* _cid, int _cs, 
186 186
 				 unsigned int _set, unsigned int _res);
187
-int update_ucontact(ucontact_t* _c, time_t _e, float _q, str* _cid, int _cs,
187
+int update_ucontact(ucontact_t* _c, time_t _e, qvalue_t _q, str* _cid, int _cs,
188 188
 		    unsigned int _set, unsigned int _res);
189 189
 
190 190
 /*
191 191
  * Update ucontact with new values with addtional replication argument
192 192
  */
193
-int update_ucontact_rep(ucontact_t* _c, time_t _e, float _q, str* _cid, int _cs, int _rep,
193
+int update_ucontact_rep(ucontact_t* _c, time_t _e, qvalue_t _q, str* _cid, int _cs, int _rep,
194 194
 			unsigned int _set, unsigned int _res);
195 195
 
196 196
 
... ...
@@ -213,7 +213,7 @@ int preload_udomain(db_con_t* _c, udomain_t* _d)
213 213
 	str user, contact, callid;
214 214
 	char* domain;
215 215
 	time_t expires;
216
-	float q;
216
+	qvalue_t q;
217 217
 
218 218
 	urecord_t* r;
219 219
 	ucontact_t* c;
... ...
@@ -253,7 +253,7 @@ int preload_udomain(db_con_t* _c, udomain_t* _d)
253 253
 		contact.s   = (char*)VAL_STRING(ROW_VALUES(row) + 1);
254 254
 		contact.len = strlen(contact.s);
255 255
 		expires     = VAL_TIME  (ROW_VALUES(row) + 2);
256
-		q           = VAL_DOUBLE(ROW_VALUES(row) + 3);
256
+		q           = double2q(VAL_DOUBLE(ROW_VALUES(row) + 3));
257 257
 		cseq        = VAL_INT   (ROW_VALUES(row) + 5);
258 258
 		rep         = VAL_INT   (ROW_VALUES(row) + 6);
259 259
 		state       = VAL_INT   (ROW_VALUES(row) + 7);
... ...
@@ -35,17 +35,18 @@
35 35
 #include "../../fifo_server.h"
36 36
 #include "../../dprint.h"
37 37
 #include "../../ut.h"
38
+#include "../../qvalue.h"
38 39
 #include "ul_fifo.h"
39 40
 #include "dlist.h"
40 41
 #include "udomain.h"
41 42
 #include "utime.h"
42 43
 #include "ul_mod.h"
43 44
 
44
-#define MAX_CONTACT 128
45
-#define MAX_EXPIRES 20
46
-#define MAX_Q 20
47
-#define MAX_REPLICATE 12
48
-#define MAX_FLAGS 12
45
+#define MAX_CONTACT_LEN 128
46
+#define MAX_EXPIRES_LEN 20
47
+#define MAX_Q_LEN 20
48
+#define MAX_REPLICATE_LEN 12
49
+#define MAX_FLAGS_LEN 12
49 50
 
50 51
 
51 52
 /*
... ...
@@ -137,7 +138,7 @@ static inline void fifo_find_domain(str* _name, udomain_t** _d)
137 137
 }
138 138
 
139 139
 
140
-static inline int add_contact(udomain_t* _d, str* _u, str* _c, time_t _e, float _q, int _r, int _f)
140
+static inline int add_contact(udomain_t* _d, str* _u, str* _c, time_t _e, qvalue_t _q, int _r, int _f)
141 141
 {
142 142
 	urecord_t* r;
143 143
 	ucontact_t* c = 0;
... ...
@@ -195,15 +196,15 @@ static int ul_add(FILE* pipe, char* response_file)
195 195
 {
196 196
 	char table_s[MAX_TABLE];
197 197
 	char user_s[MAX_USER];
198
-	char contact_s[MAX_CONTACT];
199
-	char expires_s[MAX_EXPIRES];
200
-	char q_s[MAX_Q];
201
-	char rep_s[MAX_REPLICATE];
202
-	char flags_s[MAX_FLAGS];
198
+	char contact_s[MAX_CONTACT_LEN];
199
+	char expires_s[MAX_EXPIRES_LEN];
200
+	char q_s[MAX_Q_LEN];
201
+	char rep_s[MAX_REPLICATE_LEN];
202
+	char flags_s[MAX_FLAGS_LEN];
203 203
 	udomain_t* d;
204
-	float q_f;
205 204
 	int exp_i, rep_i, flags_i;
206 205
 	char* at;
206
+	qvalue_t qval;
207 207
 
208 208
 	str table, user, contact, expires, q, rep, flags;
209 209
 
... ...
@@ -236,14 +237,14 @@ static int ul_add(FILE* pipe, char* response_file)
236 236
 		}
237 237
 	}
238 238
 
239
-	if (!read_line(contact_s, MAX_CONTACT, pipe, &contact.len) || contact.len == 0) {
239
+	if (!read_line(contact_s, MAX_CONTACT_LEN, pipe, &contact.len) || contact.len == 0) {
240 240
 		fifo_reply(response_file,
241 241
 			   "400 ul_add: contact expected\n");
242 242
 		LOG(L_ERR, "ERROR: ul_add: contact expected\n");
243 243
 		return 1;
244 244
 	}
245 245
 	
246
-	if (!read_line(expires_s, MAX_EXPIRES, pipe, &expires.len) || expires.len == 0) {
246
+	if (!read_line(expires_s, MAX_EXPIRES_LEN, pipe, &expires.len) || expires.len == 0) {
247 247
 		fifo_reply(response_file,
248 248
 			   "400 ul_add: expires expected\n");
249 249
 		LOG(L_ERR, "ERROR: ul_add: expires expected\n");
... ...
@@ -257,14 +258,14 @@ static int ul_add(FILE* pipe, char* response_file)
257 257
 		return 1;
258 258
 	}
259 259
 	
260
-	if (!read_line(rep_s, MAX_REPLICATE, pipe, &rep.len) || rep.len == 0) {
260
+	if (!read_line(rep_s, MAX_REPLICATE_LEN, pipe, &rep.len) || rep.len == 0) {
261 261
 		fifo_reply(response_file,
262 262
 			   "400 ul_add: replicate expected\n");
263 263
 		LOG(L_ERR, "ERROR: ul_add: replicate expected\n");
264 264
 		return 1;
265 265
 	}
266 266
 
267
-	if (!read_line(flags_s, MAX_FLAGS, pipe, &flags.len) || flags.len == 0) {
267
+	if (!read_line(flags_s, MAX_FLAGS_LEN, pipe, &flags.len) || flags.len == 0) {
268 268
 		fifo_reply(response_file,
269 269
 			   "400 ul_add: flags expected\n");
270 270
 		LOG(L_ERR, "ERROR: ul_add: flags expected\n");
... ...
@@ -288,9 +289,9 @@ static int ul_add(FILE* pipe, char* response_file)
288 288
 			fifo_reply(response_file, "400 Invalid expires format\n");
289 289
 			return 1;
290 290
 		}
291
-		
292
-		if (str2float(&q, &q_f) < 0) {
293
-			fifo_reply(response_file, "400 Invalid q format\n");
291
+
292
+		if (str2q(&qval, q.s, q.len) < 0) {
293
+			fifo_reply(response_file, "400 Invalid q value\n");
294 294
 			return 1;
295 295
 		}
296 296
 
... ...
@@ -306,7 +307,7 @@ static int ul_add(FILE* pipe, char* response_file)
306 306
 		
307 307
 		lock_udomain(d);
308 308
 		
309
-		if (add_contact(d, &user, &contact, exp_i, q_f, rep_i, flags_i) < 0) {
309
+		if (add_contact(d, &user, &contact, exp_i, qval, rep_i, flags_i) < 0) {
310 310
 			unlock_udomain(d);
311 311
 			LOG(L_ERR, "ul_add(): Error while adding contact ('%.*s','%.*s') in table '%.*s'\n",
312 312
 			    user.len, ZSW(user.s), contact.len, ZSW(contact.s), table.len, ZSW(table.s));
... ...
@@ -398,7 +399,7 @@ static int ul_rm_contact(FILE* pipe, char* response_file)
398 398
 {
399 399
 	char table[MAX_TABLE];
400 400
 	char user[MAX_USER];
401
-	char contact[MAX_CONTACT];
401
+	char contact[MAX_CONTACT_LEN];
402 402
 	udomain_t* d;
403 403
 	urecord_t* r;
404 404
 	ucontact_t* con;
... ...
@@ -435,7 +436,7 @@ static int ul_rm_contact(FILE* pipe, char* response_file)
435 435
 	}
436 436
 
437 437
 
438
-	if (!read_line(contact, MAX_CONTACT, pipe, &c.len) || c.len == 0) {
438
+	if (!read_line(contact, MAX_CONTACT_LEN, pipe, &c.len) || c.len == 0) {
439 439
 		fifo_reply(response_file,
440 440
 			   "400 ul_rm_contact: contact expected\n");
441 441
 		LOG(L_ERR, "ERROR: ul_rm_contact: contact expected\n");
... ...
@@ -517,9 +518,9 @@ static inline int print_contacts(FILE* _o, ucontact_t* _c)
517 517
 			if (cnt==1) {
518 518
 				fputs( "200 OK\n", _o);
519 519
 			}
520
-			fprintf(_o, "<%.*s>;q=%-3.2f;expires=%d\n",
520
+			fprintf(_o, "<%.*s>;q=%s;expires=%d\n",
521 521
 				_c->c.len, ZSW(_c->c.s),
522
-				_c->q, (int)(_c->expires - act_time));
522
+				q2str(_c->q, 0), (int)(_c->expires - act_time));
523 523
 		}
524 524
 
525 525
 		_c = _c->next;
... ...
@@ -29,6 +29,7 @@
29 29
 #include "../../unixsock_server.h"
30 30
 #include "../../ut.h"
31 31
 #include "../../str.h"
32
+#include "../../qvalue.h"
32 33
 #include "dlist.h"
33 34
 #include "ul_mod.h"
34 35
 #include "ul_fifo.h"
... ...
@@ -43,7 +44,7 @@
43 43
 #define UNIXSOCK_CSEQ 42
44 44
 
45 45
 
46
-static inline int add_contact(udomain_t* _d, str* _u, str* _c, time_t _e, float _q, int _r, int _f)
46
+static inline int add_contact(udomain_t* _d, str* _u, str* _c, time_t _e, qvalue_t _q, int _r, int _f)
47 47
 {
48 48
 	urecord_t* r;
49 49
 	ucontact_t* c = 0;
... ...
@@ -328,7 +329,7 @@ static int ul_dump(str* msg)
328 328
 static int ul_add(str* msg)
329 329
 {
330 330
 	udomain_t* d;
331
-	float q_f;
331
+	qvalue_t qval;
332 332
 	int exp_i, rep_i, flags_i;
333 333
 	char* at;
334 334
 	str table, user, contact, expires, q, rep, flags;
... ...
@@ -390,11 +391,11 @@ static int ul_add(str* msg)
390 390
 			goto err;
391 391
 		}
392 392
 		
393
-		if (str2float(&q, &q_f) < 0) {
394
-			unixsock_reply_asciiz("400 Invalid q format\n");
393
+		if (str2q(&qval, q.s, q.len) < 0) {
394
+			unixsock_reply_asciiz("400 invalid q value\n");
395 395
 			goto err;
396 396
 		}
397
-
397
+		
398 398
 		if (str2int(&rep, (unsigned int*)&rep_i) < 0) {
399 399
 			unixsock_reply_asciiz("400 Invalid replicate format\n");
400 400
 			goto err;
... ...
@@ -407,7 +408,7 @@ static int ul_add(str* msg)
407 407
 		
408 408
 		lock_udomain(d);
409 409
 		
410
-		if (add_contact(d, &user, &contact, exp_i, q_f, rep_i, flags_i) < 0) {
410
+		if (add_contact(d, &user, &contact, exp_i, qval, rep_i, flags_i) < 0) {
411 411
 			unlock_udomain(d);
412 412
 			LOG(L_ERR, "ul_add(): Error while adding contact ('%.*s','%.*s') in table '%.*s'\n",
413 413
 			    user.len, ZSW(user.s), contact.len, ZSW(contact.s), table.len, ZSW(table.s));
... ...
@@ -448,9 +449,9 @@ static inline int print_contacts(ucontact_t* _c)
448 448
 			if (cnt == 1) {
449 449
 				unixsock_reply_asciiz("200 OK\n");
450 450
 			}
451
-			if (unixsock_reply_printf("<%.*s>;q=%-3.2f;expires=%d\n",
451
+			if (unixsock_reply_printf("<%.*s>;q=%s;expires=%d\n",
452 452
 						  _c->c.len, ZSW(_c->c.s),
453
-						  _c->q, (int)(_c->expires - act_time)) < 0) {
453
+						  q2str(_c->q, 0), (int)(_c->expires - act_time)) < 0) {
454 454
 				return -1;
455 455
 			}
456 456
 		}
... ...
@@ -120,7 +120,7 @@ void print_urecord(FILE* _f, urecord_t* _r)
120 120
  * Contacts are ordered by: 1) q 
121 121
  *                          2) descending modification time
122 122
  */
123
-int mem_insert_ucontact(urecord_t* _r, str* _c, time_t _e, float _q, str* _cid, int _cs, 
123
+int mem_insert_ucontact(urecord_t* _r, str* _c, time_t _e, qvalue_t _q, str* _cid, int _cs, 
124 124
 			unsigned int _flags, int _rep, struct ucontact** _con)
125 125
 {
126 126
 	ucontact_t* ptr, *prev = 0;
... ...
@@ -490,7 +490,7 @@ void release_urecord(urecord_t* _r)
490 490
  * Create and insert new contact
491 491
  * into urecord
492 492
  */
493
-int insert_ucontact_rep(urecord_t* _r, str* _c, time_t _e, float _q, str* _cid, 
493
+int insert_ucontact_rep(urecord_t* _r, str* _c, time_t _e, qvalue_t _q, str* _cid, 
494 494
 			int _cs, unsigned int _flags, int _rep, struct ucontact** _con)
495 495
 {
496 496
 	if (mem_insert_ucontact(_r, _c, _e, _q, _cid, _cs, _flags, _rep, _con) < 0) {
... ...
@@ -519,7 +519,7 @@ int insert_ucontact_rep(urecord_t* _r, str* _c, time_t _e, float _q, str* _cid,
519 519
  * Wrapper around insert_ucontact_rep for compatibility
520 520
  * inserts a contact without replication
521 521
  */
522
-int insert_ucontact(urecord_t* _r, str* _c, time_t _e, float _q, str* _cid, 
522
+int insert_ucontact(urecord_t* _r, str* _c, time_t _e, qvalue_t _q, str* _cid, 
523 523
 		    int _cs, unsigned int _flags, struct ucontact** _con)
524 524
 {
525 525
 	return insert_ucontact_rep(_r, _c, _e, _q, _cid, _cs, _flags, 0, _con);
... ...
@@ -40,6 +40,7 @@
40 40
 #include <time.h>
41 41
 #include "hslot.h"
42 42
 #include "../../str.h"
43
+#include "../../qvalue.h"
43 44
 #include "ucontact.h"
44 45
 #include "notify.h"
45 46
 
... ...
@@ -86,7 +87,7 @@ void print_urecord(FILE* _f, urecord_t* _r);
86 86
 /*
87 87
  * Add a new contact
88 88
  */
89
-int mem_insert_ucontact(urecord_t* _r, str* _c, time_t _e, float _q, str* _cid, int _cs, 
89
+int mem_insert_ucontact(urecord_t* _r, str* _c, time_t _e, qvalue_t _q, str* _cid, int _cs, 
90 90
 			unsigned int _flags, int _rep, struct ucontact** _con);
91 91
 
92 92
 
... ...
@@ -132,7 +133,7 @@ void release_urecord(urecord_t* _r);
132 132
  */
133 133
 typedef int (*insert_ucontact_t)(urecord_t* _r, str* _c, time_t _e, float _q, str* _cid, int _cs, 
134 134
 				 unsigned int _flags, struct ucontact** _con);
135
-int insert_ucontact_rep(urecord_t* _r, str* _c, time_t _e, float _q, str* _cid, int _cs, 
135
+int insert_ucontact_rep(urecord_t* _r, str* _c, time_t _e, qvalue_t _q, str* _cid, int _cs, 
136 136
 			unsigned int _flags, int _rep, struct ucontact** _con);
137 137
 
138 138
 /*
... ...
@@ -140,7 +141,7 @@ int insert_ucontact_rep(urecord_t* _r, str* _c, time_t _e, float _q, str* _cid,
140 140
  * into urecord without replication
141 141
  */
142 142
 
143
-int insert_ucontact(urecord_t* _r, str* _c, time_t _e, float _q, str* _cid, int _cs, 
143
+int insert_ucontact(urecord_t* _r, str* _c, time_t _e, qvalue_t _q, str* _cid, int _cs, 
144 144
 		    unsigned int _flags, struct ucontact** _con);
145 145
 
146 146