callid.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2001-2003 FhG Fokus
00003  *
00004  * This file is part of SIP-router, a free SIP server.
00005  *
00006  * SIP-router is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version
00010  *
00011  * SIP-router is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License 
00017  * along with this program; if not, write to the Free Software 
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  * History:
00021  * ----------
00022  *  2003-04-09  Created by janakj
00023  *  2003-10-24  updated to the new socket_info lists (andrei)
00024  */
00025 
00037 #include <stdio.h>
00038 #include <stdlib.h>
00039 #include "../../dprint.h"
00040 #include "../../pt.h"
00041 #include "../../socket_info.h"
00042 #include "callid.h"
00043 
00047 #define CALLID_NR_LEN 20
00048 
00052 #define CALLID_SUFFIX_LEN ( 1 /* - */                                            + \
00053                             5 /* pid */                                          + \
00054                            42 /* embedded v4inv6 address can be looong '128.' */ + \
00055                             2 /* parenthesis [] */                               + \
00056                             1 /* ZT 0 */                                         + \
00057                            16 /* one never knows ;-) */                            \
00058                           )
00059 
00060 
00061 static unsigned long callid_nr;
00062 static char callid_buf[CALLID_NR_LEN + CALLID_SUFFIX_LEN];
00063 
00064 static str callid_prefix;
00065 static str callid_suffix;
00066 
00067 
00072 int init_callid(void)
00073 {
00074         int rand_bits, i;
00075 
00076              /* calculate the initial call-id */
00077              /* how many bits and chars do we need to display the 
00078               * whole ULONG number */
00079         callid_prefix.len = sizeof(unsigned long) * 2;
00080         callid_prefix.s = callid_buf;
00081 
00082         if (callid_prefix.len > CALLID_NR_LEN) {
00083                 LOG(L_ERR, "ERROR: Too small callid buffer\n");
00084                 return -1;
00085         }
00086         
00087         for(rand_bits = 1, i = RAND_MAX; i; i >>= 1, rand_bits++);  /* how long are the rand()s ? */
00088         i = callid_prefix.len * 4 / rand_bits; /* how many rands() fit in the ULONG ? */
00089 
00090              /* now fill in the callid with as many random
00091               * numbers as you can + 1 */
00092         callid_nr = rand(); /* this is the + 1 */
00093 
00094         while(i--) {
00095                 callid_nr <<= rand_bits;
00096                 callid_nr |= rand();
00097         }
00098 
00099         i = snprintf(callid_prefix.s, callid_prefix.len + 1, "%0*lx", callid_prefix.len, callid_nr);
00100         if ((i == -1) || (i > callid_prefix.len)) {
00101                 LOG(L_CRIT, "BUG: SORRY, callid calculation failed\n");
00102                 return -2;
00103         }
00104         
00105         DBG("Call-ID initialization: '%.*s'\n", callid_prefix.len, callid_prefix.s);
00106         return 0;
00107 }
00108 
00109 
00115 int child_init_callid(int rank) 
00116 {
00117         struct socket_info *si;
00118         
00119         /* on tcp/tls bind_address is 0 so try to get the first address we listen
00120          * on no matter the protocol */
00121         si=bind_address?bind_address:get_first_socket();
00122         if (si==0){
00123                 LOG(L_CRIT, "BUG: child_init_callid: null socket list\n");
00124                 return -1;
00125         }
00126         callid_suffix.s = callid_buf + callid_prefix.len;
00127 
00128         callid_suffix.len = snprintf(callid_suffix.s, CALLID_SUFFIX_LEN,
00129                                      "%c%d@%.*s", '-', my_pid(), 
00130                                      si->address_str.len,
00131                                      si->address_str.s);
00132         if ((callid_suffix.len == -1) || (callid_suffix.len > CALLID_SUFFIX_LEN)) {
00133                 LOG(L_ERR, "ERROR: child_init_callid: buffer too small\n");
00134                 return -1;
00135         }
00136 
00137         DBG("DEBUG: callid: '%.*s'\n", callid_prefix.len + callid_suffix.len, callid_prefix.s);
00138         return 0;
00139 }
00140 
00141 
00147 static inline int inc_hexchar(char* _c)
00148 {
00149         if (*_c == '9') {
00150                 *_c = 'a';
00151                 return 0;
00152         }
00153 
00154         if (*_c == 'f') {
00155                 *_c = '0';
00156                 return 1;
00157         }
00158 
00159         (*_c)++;
00160         return 0;
00161 }
00162 
00163 
00168 void generate_callid(str* callid)
00169 {
00170         int i;
00171 
00172         for(i = callid_prefix.len; i; i--) {
00173                 if (!inc_hexchar(callid_prefix.s + i - 1)) break;
00174         }
00175         callid->s = callid_prefix.s;
00176         callid->len = callid_prefix.len + callid_suffix.len;
00177 }