示例#1
0
int erl_rpc_struct_printf(erl_rpc_ctx_t* ctx, char* name, char* fmt, ...)
{
	int n, buff_size;
	char *buff;
	va_list ap;
	erl_rpc_param_t *param;

	LM_ERR("parsing name:%s fmt: %s\n",name, fmt);

	buff = (char*)pkg_malloc(RPC_BUF_SIZE);
	if (!buff) {
			ERR("No memory left\n");
			return -1;
	}

	buff_size = RPC_BUF_SIZE;

	while(1)
	{
		/* Try to print in the allocated space. */
		va_start(ap, fmt);
		n = vsnprintf(buff, buff_size, fmt, ap);
		va_end(ap);
			 /* If that worked, return the string. */
		if (n > -1 && n < buff_size)
		{

			if(add_to_recycle_bin(JUNK_PKGCHAR,(void*)buff,ctx))
			{
				goto error;
			}
			else if ((param = erl_new_param(ctx)))
			{
				param->type = ERL_STRING_EXT;
				param->value.S.s = buff;
				param->value.S.len = n;
				param->member_name = name;
				erl_rpc_append_param(ctx,param);
			}
			else
			{
				goto error;
			}

			return 0;
		}

		/* Else try again with more space. */
		if (n > -1)
		{	/* glibc 2.1 */
			buff_size = n + 1; /* precisely what is needed */
		}
		else
		{	/* glibc 2.0 */
			buff_size *= 2;  /* twice the old size */
		}
		if ((buff = pkg_realloc(buff, buff_size)) == 0)
		{
			ERR("No memory left\n");
			goto error;
		}
	}

	return 0;

error:
	if(buff) pkg_free(buff);
	return -1;
}
示例#2
0
int redis_raw_query_handle_reply(redisReply *reply,cdb_raw_entry ***ret,
		int expected_kv_no,int *reply_no)
{
	int current_size=0,len,i;

	/* start with a single returned document */
	*ret = pkg_malloc(1 * sizeof(cdb_raw_entry *));
	if (*ret == NULL) {
		LM_ERR("No more PKG mem\n");
		goto error;
	}

	**ret = pkg_malloc(expected_kv_no * sizeof(cdb_raw_entry));
	if (**ret == NULL) {
		LM_ERR("No more pkg mem\n");
		goto error;
	}

	switch (reply->type) {
		case REDIS_REPLY_STRING:
			(*ret)[current_size][0].val.s.s = pkg_malloc(reply->len);
			if (! (*ret)[current_size][0].val.s.s ) {
				LM_ERR("No more pkg \n");
				goto error;
			}

			memcpy((*ret)[current_size][0].val.s.s,reply->str,reply->len);
			(*ret)[current_size][0].val.s.len = reply->len;
			(*ret)[current_size][0].type = CDB_STR;

			current_size++;
			break;
		case REDIS_REPLY_INTEGER:
			(*ret)[current_size][0].val.n = reply->integer;
			(*ret)[current_size][0].type = CDB_INT;
			current_size++;
			break;
		case REDIS_REPLY_NIL:
			(*ret)[current_size][0].type = CDB_NULL;
			(*ret)[current_size][0].val.s.s = NULL;
			(*ret)[current_size][0].val.s.len = 0;
			current_size++;
			break;
		case REDIS_REPLY_ARRAY:
			for (i=0;i<reply->elements;i++) {
				switch (reply->element[i]->type) {
					case REDIS_REPLY_STRING:
					case REDIS_REPLY_INTEGER:
					case REDIS_REPLY_NIL:
						if (current_size > 0) {
							*ret = pkg_realloc(*ret,(current_size + 1) * sizeof(cdb_raw_entry *));
							if (*ret == NULL) {
								LM_ERR("No more pkg\n");
								goto error;
							}
							(*ret)[current_size] = pkg_malloc(expected_kv_no * sizeof(cdb_raw_entry));
							if ((*ret)[current_size] == NULL) {
								LM_ERR("No more pkg\n");
								goto error;
							}
						}


						if (reply->element[i]->type == REDIS_REPLY_INTEGER) {
							(*ret)[current_size][0].val.n = reply->element[i]->integer;
							(*ret)[current_size][0].type = CDB_INT;
                                                } else if (reply->element[i]->type == REDIS_REPLY_NIL) {
							(*ret)[current_size][0].val.s.s = NULL;
							(*ret)[current_size][0].val.s.len = 0;
							(*ret)[current_size][0].type = CDB_NULL;
							
						} else {
							(*ret)[current_size][0].val.s.s = pkg_malloc(reply->element[i]->len);
							if (! (*ret)[current_size][0].val.s.s ) {
								LM_ERR("No more pkg \n");
								goto error;
							}

							memcpy((*ret)[current_size][0].val.s.s,reply->element[i]->str,reply->element[i]->len);
							(*ret)[current_size][0].val.s.len = reply->element[i]->len;
							(*ret)[current_size][0].type = CDB_STR;
						}

						current_size++;
						break;
					default:
						LM_DBG("Unexpected data type %d found in array - skipping \n",reply->element[i]->type);
				}
			}
			break;
	}

	*reply_no = current_size;
	freeReplyObject(reply);
	return 1;

error:
	if (*ret) {
		pkg_free(*ret);
		for (len = 0;len<current_size;len++) {
			if ( (*ret)[len][0].type == CDB_STR)
				pkg_free((*ret)[len][0].val.s.s);
			pkg_free((*ret)[len]);
		}
	}

	*ret = NULL;
	*reply_no=0;

	freeReplyObject(reply);
	return -1;
}
示例#3
0
/*
 * Load ODBC cell data into a single cell
 */
int db_unixodbc_load_cell(const db1_con_t* _h, int colindex, strn * cell, const db_type_t _t)
{
	SQLRETURN ret = 0;
	unsigned int truesize = 0;
	unsigned char hasnull = (_t != DB1_BLOB) ? 1 : 0;

	do {
		SQLLEN indicator;
		int chunklen;
		char * s;	/* Pointer to available area for next chunk */
		char * ns;

		if (cell->buflen > 0) {
			ns = (char *)pkg_realloc(cell->s, cell->buflen + STRN_LEN);
			if (ns == NULL) {
				LM_ERR("no memory left\n");
				return 0;
			}
			cell->s = ns;

			/* Overwrite the previous null terminator */
			s = cell->s + cell->buflen - hasnull;
			chunklen = STRN_LEN + hasnull;
		} else {
			ns = (char *)pkg_malloc(STRN_LEN);
			if (ns == NULL) {
				LM_ERR("no memory left\n");
				return 0;
			}
			cell->s = ns;
			s = cell->s;
			chunklen = STRN_LEN;
		}
		cell->buflen += STRN_LEN;

		ret = SQLGetData(CON_RESULT(_h), colindex, hasnull ? SQL_C_CHAR : SQL_C_BINARY,
					s, chunklen, &indicator);
		LM_DBG("SQLGetData returned ret=%d indicator=%d\n", (int)ret, (int)indicator);
		if (ret == SQL_SUCCESS) {
			if (indicator == SQL_NULL_DATA) {
			    /* TODO: set buffer pointer to NULL instead of string "NULL" */
			    strcpy(cell->s, "NULL");
			    truesize = 4 + (1 - hasnull);
			} else {
			    /* Get length of data that was available before last SQLGetData call */
			    if (truesize == 0) truesize = indicator;
			}
		} else if (ret == SQL_SUCCESS_WITH_INFO) {
			SQLINTEGER   i = 0;
			SQLINTEGER   native;
			SQLCHAR  state[ 7 ];
			SQLCHAR  text[256];
			SQLSMALLINT  len;
			SQLRETURN	ret2;

			/* Check whether field data was truncated */
			do
			{
				ret2 = SQLGetDiagRec(SQL_HANDLE_STMT, CON_RESULT(_h), ++i, state, &native, text,
					sizeof(text), &len );
				if (SQL_SUCCEEDED(ret2)) {
					if (!strcmp("00000", (const char*)state)) break;
					if (strcmp("01004", (const char*)state) != 0) {
						/* Not a string truncation */
						LM_ERR("SQLGetData failed unixodbc:  =%s:%ld:%ld:%s\n", state, (long)i,
							(long)native, text);
						return 0;
					}

					/* Get length of data that was available before last SQLGetData call */
					if (truesize == 0) truesize = indicator;
				} else if (ret2 == SQL_NO_DATA) {
				    /* Reached end of diagnostic records */
					break;
				} else {
					/* Failed to get diagnostics */
					LM_ERR("SQLGetData failed, failed to get diagnostics (ret2=%d i=%d)\n",
						ret2, i);
					return 0;
				}
			}
			while( ret2 == SQL_SUCCESS );
		} else {
			LM_ERR("SQLGetData failed\n");
		}
	} while (ret == SQL_SUCCESS_WITH_INFO);

	LM_DBG("Total allocated for this cell (before resize): %d bytes\n", cell->buflen);

	if (cell->buflen > truesize) {
		cell->s[truesize] = '\0'; /* guarantee strlen() will terminate */
	}
	cell->buflen = truesize + hasnull;

	LM_DBG("Total allocated for this cell (after resize): %d bytes\n", cell->buflen);
	LM_DBG("strlen() reports for this cell: %d bytes\n", (int)strlen(cell->s));

	return 1;
}
示例#4
0
static char* serialize_dns_rdata(struct rdata *head,int buf_len,int *len,int do_encoding)
{
	unsigned char *p;
	struct rdata *it;
	int needed_len;
	int entry_len,base64_len=0;
	struct cname_rdata *cname_rd;
	struct srv_rdata *srv_rd;
	struct naptr_rdata *naptr_rd;
	struct ebl_rdata *ebl_rd;
	struct txt_rdata *txt_rd;

	if (do_encoding) {
		base64_len = calc_base64_encode_len(buf_len);
		needed_len = buf_len + base64_len; 
	} else {
		needed_len = buf_len;
	}	

	if (rdata_buf == NULL || needed_len > rdata_buf_len) {
		rdata_buf = pkg_realloc(rdata_buf,needed_len);	
		if (rdata_buf == NULL) {
			LM_ERR("No more pkg\n");
			return NULL;				
		}
		rdata_buf_len = needed_len;
	}

	p = rdata_buf;
	
	for (it=head;it;it=it->next) {
		/* copy non-pointer fields of the struct */
		memcpy(p,it,rdata_struct_len);
		p+=rdata_struct_len;
		
		switch (it->type) {
			case T_A:
				/* copy all 4 bytes */
				memcpy(p,it->rdata,sizeof(struct a_rdata));
				p+=sizeof(struct a_rdata);
				break;				
			case T_AAAA:
				/* copy all 16 bytes */
				memcpy(p,it->rdata,sizeof(struct aaaa_rdata));
				p+=sizeof(struct aaaa_rdata);
				break;				
			case T_CNAME:
				cname_rd=(struct cname_rdata *)it->rdata;
				entry_len=strlen(cname_rd->name);
				/* copy len of alias */
				memcpy(p,&entry_len,sizeof(int));
				p+=sizeof(int);
				/* copy alias */
				memcpy(p,cname_rd->name,entry_len+1);
				p+=entry_len+1;
				break;				
			case T_NAPTR:
				/* copy priority, etc */
				memcpy(p,it->rdata,2*sizeof(unsigned short) + 
						sizeof(unsigned int)); 
				p+=2*sizeof(unsigned short) + sizeof(unsigned int);
				naptr_rd=it->rdata;
				/* copy flags, flags_len was copied above */
				memcpy(p,naptr_rd->flags,naptr_rd->flags_len+1);
				p+=naptr_rd->flags_len+1;
				/* copy services & len */
				memcpy(p,&naptr_rd->services_len,sizeof(unsigned int));
				p+=sizeof(unsigned int);
				memcpy(p,naptr_rd->services,naptr_rd->services_len+1);
				p+=naptr_rd->services_len+1;
				/* copy regexp & len */
				memcpy(p,&naptr_rd->regexp_len,sizeof(unsigned int));
				p+=sizeof(unsigned int);
				memcpy(p,naptr_rd->regexp,naptr_rd->regexp_len+1);
				p+=naptr_rd->regexp_len+1;
				/* copy repl & len */
				memcpy(p,&naptr_rd->repl_len,sizeof(unsigned int));
				p+=sizeof(unsigned int);
				memcpy(p,naptr_rd->repl,naptr_rd->repl_len+1);
				p+=naptr_rd->repl_len+1;
				break;				
			case T_SRV:
				srv_rd=it->rdata;
				memcpy(p,srv_rd,4*sizeof(unsigned short) +
					sizeof(unsigned int));
				p+=4*sizeof(unsigned short) + sizeof(unsigned int);
				memcpy(p,srv_rd->name,srv_rd->name_len+1);
				p+=srv_rd->name_len+1;
				break;				
			case T_TXT:
				txt_rd=it->rdata;
				entry_len=strlen(txt_rd->txt);
				memcpy(p,&entry_len,sizeof(int));
				p+=sizeof(int);
				memcpy(p,txt_rd->txt,entry_len+1);
				p+=entry_len+1;		
				break;				
			case T_EBL:
				ebl_rd=it->rdata;
				memcpy(p,ebl_rd,sizeof(unsigned char) + 
					sizeof(unsigned int));
				p+=sizeof(unsigned char) + sizeof(unsigned int);
				memcpy(p,ebl_rd->separator,ebl_rd->separator_len+1);
				p+=ebl_rd->separator_len+1;
				memcpy(p,&ebl_rd->apex_len,sizeof(unsigned int));
				p+=sizeof(unsigned int);
				memcpy(p,ebl_rd->apex,ebl_rd->apex_len+1);
				p+=ebl_rd->apex_len+1;
				break;				
			default:
				LM_ERR("Unexpected DNS record type\n");
				return NULL;
		}
	}
	
	if (do_encoding) {
		if (*len)
			*len = base64_len;

		/* encode and return beggining of encoding */
		base64encode(p,rdata_buf,buf_len);
		return (char *)p;	
	} else { 
		if (*len)
			*len = needed_len;
		return (char *)rdata_buf;
	}
}
示例#5
0
static struct rdata* deserialize_dns_rdata(char *buff,int buf_len,int do_decoding)
{
	unsigned char *p;
	int max_len=0,actual_len=0,entry_len=0;
	struct rdata *head,*it,**last;
	struct naptr_rdata *naptr_rd;
	struct srv_rdata *srv_rd;
	struct txt_rdata *txt_rd;
	struct ebl_rdata *ebl_rd;

	head=it=NULL;
	last=&head;	

	if (do_decoding) {
		max_len = calc_max_base64_decode_len(buf_len);
	} else {
		max_len = buf_len;
	}

	if (dec_rdata_buf == NULL || max_len > dec_rdata_buf_len) {
		/* realloc buff if not enough space */
		dec_rdata_buf = pkg_realloc(dec_rdata_buf,max_len);	
		if (dec_rdata_buf == NULL) {
			LM_ERR("No more pkg\n");
			return NULL;				
		}
		dec_rdata_buf_len = max_len;
	}

	if (do_decoding) {
		/* decode base64 buf */
		actual_len = base64decode(dec_rdata_buf,(unsigned char *)buff,buf_len);	
		p = dec_rdata_buf;
	} else {
		memcpy(dec_rdata_buf,buff,buf_len);
		actual_len = buf_len;
		p = dec_rdata_buf;
	}

	while ( p < dec_rdata_buf+actual_len) {
		it = pkg_malloc(sizeof(struct rdata));		
		if (it == 0) {
			LM_ERR("no more pkg mem\n");
			goto it_alloc_error;
		}

		/* copy type, class & ttl */
		memcpy(it,p,rdata_struct_len);
		p+=rdata_struct_len;			
		it->next=0;
		it->rdata=0;

		switch (it->type) {
			case T_A:
				it->rdata = pkg_malloc(sizeof(struct a_rdata)); 
				if (it->rdata == 0) {
					LM_ERR("no more pkg\n");
					goto rdata_alloc_error;
				}
				memcpy(p,it->rdata,sizeof(struct a_rdata));
				p+=sizeof(struct a_rdata);	
				*last=it;
				last=&(it->next);
				break;	
			case T_AAAA:
				it->rdata = pkg_malloc(sizeof(struct aaaa_rdata)); 
				if (it->rdata == 0) {
					LM_ERR("no more pkg\n");
					goto rdata_alloc_error;
				}
				memcpy(p,it->rdata,sizeof(struct aaaa_rdata));
				p+=sizeof(struct aaaa_rdata);	
				*last=it;
				last=&(it->next);
				break;	
			case T_CNAME:
				it->rdata = pkg_malloc(sizeof(struct cname_rdata));	
				if (it->rdata == 0) {
					LM_ERR("no more pkg\n");
					goto rdata_alloc_error;
				}	
				memcpy(&entry_len,p,sizeof(int));
				p+=sizeof(int);	
				memcpy(((struct cname_rdata*)it->rdata)->name,
					p,entry_len+1);
				p+=entry_len+1;		
				*last=it;
				last=&(it->next);
				break;
			case T_NAPTR:
				it->rdata = pkg_malloc(sizeof(struct naptr_rdata));
				if (it->rdata == 0) {
					LM_ERR("no more pkg\n");
					goto rdata_alloc_error;
				}
				naptr_rd = (struct naptr_rdata*)it->rdata;
				memcpy(naptr_rd,p,2*sizeof(unsigned short) + 
					sizeof(unsigned int));
				p+=2*sizeof(unsigned short) + sizeof(unsigned int);
				memcpy(naptr_rd->flags,p,naptr_rd->flags_len+1);
				p+=naptr_rd->flags_len+1;
				memcpy(&naptr_rd->services_len,p,sizeof(unsigned int));
				p+=sizeof(unsigned int);
				memcpy(naptr_rd->services,p,naptr_rd->services_len+1);
				p+=naptr_rd->services_len+1;
				memcpy(&naptr_rd->regexp_len,p,sizeof(unsigned int));
				p+=sizeof(unsigned int);
				memcpy(naptr_rd->regexp,p,naptr_rd->regexp_len+1);
				p+=naptr_rd->regexp_len+1;
				memcpy(&naptr_rd->repl_len,p,sizeof(unsigned int));
				p+=sizeof(unsigned int);
				memcpy(naptr_rd->repl,p,naptr_rd->repl_len+1);
				p+=naptr_rd->repl_len+1;
				*last=it;
				last=&(it->next);
				break;
			case T_SRV:
				it->rdata = pkg_malloc(sizeof(struct srv_rdata));
				if (it->rdata == 0) {
					LM_ERR("no more pkg\n");
					goto rdata_alloc_error;
				}
				srv_rd = (struct srv_rdata*)it->rdata;
				memcpy(srv_rd,p,4*sizeof(unsigned short) + 
					sizeof(unsigned int));
				p+=4*sizeof(unsigned short) + sizeof(unsigned int);
				memcpy(srv_rd->name,p,srv_rd->name_len+1);
				p+=srv_rd->name_len+1;
				*last=it;
				last=&(it->next);
				break;
			case T_TXT:
				it->rdata = pkg_malloc(sizeof(struct txt_rdata));
				if (it->rdata == 0) {
					LM_ERR("no more pkg\n");
					goto rdata_alloc_error;
				}
				txt_rd = (struct txt_rdata*)it->rdata;
				memcpy(&entry_len,p,sizeof(int));
				p+=sizeof(int);	
				memcpy(txt_rd->txt,p,entry_len+1);
				p+=entry_len+1;		
				*last=it;
				last=&(it->next);
				break;
			case T_EBL:
				it->rdata = pkg_malloc(sizeof(struct ebl_rdata));
				if (it->rdata == 0) {
					LM_ERR("no more pkg\n");
					goto rdata_alloc_error;
				}
				ebl_rd = (struct ebl_rdata*)it->rdata;
				memcpy(ebl_rd,p,sizeof(unsigned char) + 
					sizeof(unsigned int));	
				p+=sizeof(unsigned char)+sizeof(unsigned int);	
				memcpy(ebl_rd->separator,p,ebl_rd->separator_len+1);
				p+=ebl_rd->separator_len+1;
				memcpy(&ebl_rd->apex_len,p,sizeof(unsigned int));
				p+=sizeof(unsigned int);
				memcpy(ebl_rd->apex,p,ebl_rd->apex_len+1);
				p+=ebl_rd->apex_len+1;
				*last=it;
				last=&(it->next);
				break;
		}
	}

	return head;

rdata_alloc_error:
	if (it) 
		pkg_free(it);
it_alloc_error:
	if (head)
		free_rdata_list(head);
	return NULL;
}
示例#6
0
void python_handle_exception(const char *fmt, ...)
{
    PyObject *pResult;
    const char *msg;
    char *buf;
    size_t buflen, msglen;
    PyObject *exception, *v, *tb, *args;
    PyObject *line;
    int i;
    char *srcbuf;

    // We don't want to generate traceback when no errors occured
    if (!PyErr_Occurred())
        return;

    if (fmt == NULL)
        srcbuf = NULL;
    else
        srcbuf = make_message(fmt);

    PyErr_Fetch(&exception, &v, &tb);
    PyErr_Clear();
    if (exception == NULL) {
        LM_ERR("python_handle_exception(): Can't get traceback, PyErr_Fetch() has failed.\n");
        return;
    }

    PyErr_NormalizeException(&exception, &v, &tb);
    if (exception == NULL) {
        LM_ERR("python_handle_exception(): Can't get traceback, PyErr_NormalizeException() has failed.\n");
        return;
    }

    args = PyTuple_Pack(3, exception, v, tb ? tb : Py_None);
    Py_XDECREF(exception);
    Py_XDECREF(v);
    Py_XDECREF(tb);
    if (args == NULL) {
        LM_ERR("python_handle_exception(): Can't get traceback, PyTuple_Pack() has failed.\n");
        return;
    }

    pResult = PyObject_CallObject(format_exc_obj, args);
    Py_DECREF(args);
    if (pResult == NULL) {
        LM_ERR("python_handle_exception(): Can't get traceback, traceback.format_exception() has failed.\n");
        return;
    }

    buflen = 1;
    buf = (char *)pkg_realloc(NULL, buflen * sizeof(char *));
    if (!buf)
    {
        LM_ERR("python_handle_exception(): Can't allocate memory (%lu bytes), pkg_realloc() has failed. Not enough memory.\n", (unsigned long)(buflen * sizeof(char *)));
        return;
    }
    memset(buf, 0, sizeof(char *));

    for (i = 0; i < PySequence_Size(pResult); i++) {
        line = PySequence_GetItem(pResult, i);
        if (line == NULL) {
            LM_ERR("python_handle_exception(): Can't get traceback, PySequence_GetItem() has failed.\n");
            Py_DECREF(pResult);
            if (buf)
                pkg_free(buf);
            return;
        }

        msg = PyString_AsString(line);

        if (msg == NULL) {
            LM_ERR("python_handle_exception(): Can't get traceback, PyString_AsString() has failed.\n");
            Py_DECREF(line);
            Py_DECREF(pResult);
            if (buf)
                pkg_free(buf);
            return;
        }

        msglen = strlen(msg);
        buflen += ++msglen;

        buf = (char *)pkg_realloc(buf, buflen * sizeof(char *));
        if (!buf)
        {
            LM_ERR("python_handle_exception(): Can't allocate memory (%lu bytes), pkg_realloc() has failed. Not enough memory.\n", (unsigned long)(buflen * sizeof(char *)));
            Py_DECREF(line);
            Py_DECREF(pResult);
            return;
        }

        strncat(buf, msg, msglen >= buflen ? buflen-1 : msglen);

        Py_DECREF(line);
    }

    if (srcbuf == NULL)
        LM_ERR("Unhandled exception in the Python code:\n%s", buf);
    else
        LM_ERR("%s: Unhandled exception in the Python code:\n%s", srcbuf, buf);

    if (buf)
        pkg_free(buf);

    if (srcbuf)
        pkg_free(srcbuf);

    Py_DECREF(pResult);
}
示例#7
0
static inline int internal_mi_print_dlg(struct mi_node *rpl,
									struct dlg_cell *dlg, int with_context)
{
	struct mi_node* node= NULL;
	struct mi_node* node1 = NULL;
	struct mi_node* node2 = NULL;
	struct mi_node* node3 = NULL;
	struct mi_attr* attr= NULL;
	struct dlg_profile_link *dl;
	struct dlg_val* dv;
	int len;
	char* p;
	int i, j;
	time_t _ts;
	struct tm* t;
	char date_buf[MI_DATE_BUF_LEN];
	int date_buf_len;

	node = add_mi_node_child(rpl, 0, "dialog",6 , 0, 0 );
	if (node==0)
		goto error;

	attr = addf_mi_attr( node, 0, "hash", 4, "%u:%u",
			dlg->h_entry, dlg->h_id );
	if (attr==0)
		goto error;

	p= int2str((unsigned long)dlg->state, &len);
	node1 = add_mi_node_child( node, MI_DUP_VALUE, "state", 5, p, len);
	if (node1==0)
		goto error;

	p= int2str((unsigned long)dlg->user_flags, &len);
	node1 = add_mi_node_child( node, MI_DUP_VALUE, "user_flags", 10, p, len);
	if (node1==0)
		goto error;

	_ts = (time_t)dlg->start_ts;
	p= int2str((unsigned long)_ts, &len);
	node1 = add_mi_node_child(node,MI_DUP_VALUE,"timestart",9, p, len);
	if (node1==0)
		goto error;
	if (_ts) {
		t = localtime(&_ts);
		date_buf_len = strftime(date_buf, MI_DATE_BUF_LEN - 1,
						"%Y-%m-%d %H:%M:%S", t);
		if (date_buf_len != 0) {
			node1 = add_mi_node_child(node,MI_DUP_VALUE, "datestart", 9,
						date_buf, date_buf_len);
			if (node1==0)
				goto error;
		}
	}

	_ts = (time_t)(dlg->tl.timeout?((unsigned int)time(0) +
                dlg->tl.timeout - get_ticks()):0);
	p= int2str((unsigned long)_ts, &len);
	node1 = add_mi_node_child(node,MI_DUP_VALUE, "timeout", 7, p, len);
	if (node1==0)
		goto error;
	if (_ts) {
		t = localtime(&_ts);
		date_buf_len = strftime(date_buf, MI_DATE_BUF_LEN - 1,
						"%Y-%m-%d %H:%M:%S", t);
		if (date_buf_len != 0) {
			node1 = add_mi_node_child(node,MI_DUP_VALUE, "dateout", 7,
						date_buf, date_buf_len);
			if (node1==0)
				goto error;
		}
	}

	node1 = add_mi_node_child(node, MI_DUP_VALUE, "callid", 6,
			dlg->callid.s, dlg->callid.len);
	if(node1 == 0)
		goto error;

	node1 = add_mi_node_child(node, MI_DUP_VALUE, "from_uri", 8,
			dlg->from_uri.s, dlg->from_uri.len);
	if(node1 == 0)
		goto error;

	node1 = add_mi_node_child(node, MI_DUP_VALUE, "to_uri", 6,
			dlg->to_uri.s, dlg->to_uri.len);
	if(node1 == 0)
		goto error;

	if (dlg->legs_no[DLG_LEGS_USED]>0) {
		node1 = add_mi_node_child(node, MI_DUP_VALUE, "caller_tag", 10,
				dlg->legs[DLG_CALLER_LEG].tag.s,
				dlg->legs[DLG_CALLER_LEG].tag.len);
		if(node1 == 0)
			goto error;

		node1 = add_mi_node_child(node, MI_DUP_VALUE, "caller_contact", 14,
				dlg->legs[DLG_CALLER_LEG].contact.s,
				dlg->legs[DLG_CALLER_LEG].contact.len);
		if(node1 == 0)
			goto error;

		node1 = add_mi_node_child(node, MI_DUP_VALUE, "callee_cseq", 11,
				dlg->legs[DLG_CALLER_LEG].r_cseq.s,
				dlg->legs[DLG_CALLER_LEG].r_cseq.len);
		if(node1 == 0)
			goto error;

		node1 = add_mi_node_child(node, MI_DUP_VALUE,"caller_route_set",16,
				dlg->legs[DLG_CALLER_LEG].route_set.s,
				dlg->legs[DLG_CALLER_LEG].route_set.len);
		if(node1 == 0)
			goto error;

		node1 = add_mi_node_child(node, 0,"caller_bind_addr",16,
				dlg->legs[DLG_CALLER_LEG].bind_addr->sock_str.s,
				dlg->legs[DLG_CALLER_LEG].bind_addr->sock_str.len);
		if(node1 == 0)
			goto error;

		node1 = add_mi_node_child(node, MI_DUP_VALUE,"caller_sdp",10,
				dlg->legs[DLG_CALLER_LEG].sdp.s,
				dlg->legs[DLG_CALLER_LEG].sdp.len);
		if(node1 == 0)
			goto error;
	}

	node1 = add_mi_node_child(node, MI_IS_ARRAY, "CALLEES", 7, NULL, 0);
	if(node1 == 0)
		goto error;

	for( i=1 ; i < dlg->legs_no[DLG_LEGS_USED] ; i++  ) {

		node2 = add_mi_node_child(node1, 0, "callee", 6, NULL, 0);
		if(node2 == 0)
			goto error;

		node3 = add_mi_node_child(node2, MI_DUP_VALUE, "callee_tag", 10,
				dlg->legs[i].tag.s, dlg->legs[i].tag.len);
		if(node3 == 0)
			goto error;

		node3 = add_mi_node_child(node2, MI_DUP_VALUE, "callee_contact", 14,
				dlg->legs[i].contact.s, dlg->legs[i].contact.len);
		if(node3 == 0)
			goto error;

		node3 = add_mi_node_child(node2, MI_DUP_VALUE, "caller_cseq", 11,
				dlg->legs[i].r_cseq.s, dlg->legs[i].r_cseq.len);
		if(node3 == 0)
			goto error;

		node3 = add_mi_node_child(node2, MI_DUP_VALUE,"callee_route_set",16,
				dlg->legs[i].route_set.s, dlg->legs[i].route_set.len);
		if(node3 == 0)
			goto error;

		if (dlg->legs[i].bind_addr) {
			node3 = add_mi_node_child(node2, 0,
				"callee_bind_addr",16,
				dlg->legs[i].bind_addr->sock_str.s,
				dlg->legs[i].bind_addr->sock_str.len);
		} else {
			node3 = add_mi_node_child(node2, 0,
				"callee_bind_addr",16,0,0);
		}
		if(node3 == 0)
			goto error;
		
		node3 = add_mi_node_child(node2, MI_DUP_VALUE,"callee_sdp",10,
				dlg->legs[i].sdp.s,
				dlg->legs[i].sdp.len);
		if(node3 == 0)
			goto error;
	}

	if (with_context) {
		node1 = add_mi_node_child(node, 0, "context", 7, 0, 0);
		if(node1 == 0)
			goto error;
		if (dlg->vals) {
			node2 = add_mi_node_child(node1, 0, "values", 6, 0, 0);
			if(node2 == 0)
				goto error;
			/* print dlg values -> iterate the list */
			for( dv=dlg->vals ; dv ; dv=dv->next) {
				/* escape non-printable chars */
				p = pkg_realloc(dlg_val_buf, 4 * dv->val.len + 1);
				if (!p) {
					LM_ERR("not enough mem to allocate: %d\n", dv->val.len);
					continue;
				}
				for (i = 0, j = 0; i < dv->val.len; i++) {
					if (dv->val.s[i] < 0x20 || dv->val.s[i] >= 0x7F) {
						p[j++] = '\\';
						switch ((unsigned char)dv->val.s[i]) {
						case 0x8: p[j++] = 'b'; break;
						case 0x9: p[j++] = 't'; break;
						case 0xA: p[j++] = 'n'; break;
						case 0xC: p[j++] = 'f'; break;
						case 0xD: p[j++] = 'r'; break;
						default:
							p[j++] = 'x';
							j += snprintf(&p[j], 3, "%02x",
									(unsigned char)dv->val.s[i]);
							break;
						}
					} else {
						p[j++] = dv->val.s[i];
					}
				}
				add_mi_node_child(node2, MI_DUP_NAME|MI_DUP_VALUE,dv->name.s,dv->name.len,
					p,j);
				dlg_val_buf = p;
			}
		}
		/* print dlg profiles */
		if (dlg->profile_links) {
			node3 = add_mi_node_child(node1, MI_IS_ARRAY, "profiles", 8, 0, 0);
			if(node3 == 0)
				goto error;
			for( dl=dlg->profile_links ; dl ; dl=dl->next) {
				add_mi_node_child(node3, MI_DUP_NAME|MI_DUP_VALUE,
					dl->profile->name.s,dl->profile->name.len,
					ZSW(dl->value.s),dl->value.len);
			}
		}
		/* print external context info */
		run_dlg_callbacks( DLGCB_MI_CONTEXT, dlg, NULL,
			DLG_DIR_NONE, (void *)node1);
	}

	return 0;

error:
	LM_ERR("failed to add node\n");
	return -1;
}
示例#8
0
void* my_pkg_realloc(void * p, size_t size){

	return pkg_realloc(p, size);
}
// Check if the requested asymmetrics file has changed and reload it if needed
static void
checkAsymmetricFile(AsymmetricClients *aptr)
{
    char buf[512], errbuf[256], *which;
    regex_t *re, **regs;
    int i, size, code;
    Bool firstTime = False;
    struct stat statbuf;
    FILE *file;
    str line;

    if (stat(aptr->file, &statbuf) < 0)
        return; // ignore missing file

    if (statbuf.st_mtime <= aptr->timestamp)
        return; // not changed

    // now we have work to do

    which = (aptr == &sipAsymmetrics ? "SIP" : "RTP");

    if (!aptr->clients) {
        // if we are here the first time allocate memory to hold the regexps

        // initial size of array
        // (hopefully not reached so we won't need to realloc)
        size = 32;
        aptr->clients = (regex_t**)pkg_malloc(size*sizeof(regex_t**));
        if (!aptr->clients) {
            LOG(L_WARN, "warning: mediaproxy/checkAsymmetricFile() cannot "
                "allocate memory for the %s asymmetric client list. "
                "%s asymmetric clients will not be handled properly.\n",
                which, which);
            return; // ignore as it is not fatal
        }
        aptr->size  = size;
        aptr->count = 0;
        firstTime = True;
    } else {
        // else clean old stuff
        for (i=0; i<aptr->count; i++) {
            regfree(aptr->clients[i]);
            pkg_free(aptr->clients[i]);
            aptr->clients[i] = NULL;
        }
        aptr->count = 0;
    }

    // read new
    file = fopen(aptr->file, "r");
    i = 0; // this will count on which line are we in the file
    while (!feof(file)) {
        if (!fgets(buf, 512, file))
            break;
        i++;

        line.s = buf;
        line.len = strlen(buf);
        trim(&line);
        if (line.len == 0 || line.s[0] == '#')
            continue; // comment or empty line. ignore
        line.s[line.len] = 0;

        re = (regex_t*)pkg_malloc(sizeof(regex_t));
        if (!re) {
            LOG(L_WARN, "warning: mediaproxy/checkAsymmetricFile(): "
                "cannot allocate memory for all the %s asymmetric "
                "clients listed in file. Some of them will not be "
                "handled properly.\n", which);
            break;
        }
        code = regcomp(re, line.s, REG_EXTENDED|REG_ICASE|REG_NOSUB);
        if (code == 0) {
            if (aptr->count+1 > aptr->size) {
                size = aptr->size * 2;
                regs = aptr->clients;
                regs = (regex_t**)pkg_realloc(regs, size*sizeof(regex_t**));
                if (!regs) {
                    LOG(L_WARN, "warning: mediaproxy/checkAsymmetricFile(): "
                        "cannot allocate memory for all the %s asymmetric "
                        "clients listed in file. Some of them will not be "
                        "handled properly.\n", which);
                    break;
                }
                aptr->clients = regs;
                aptr->size = size;
            }
            aptr->clients[aptr->count] = re;
            aptr->count++;
        } else {
            regerror(code, re, errbuf, 256);
            LOG(L_WARN, "warning: mediaproxy/checkAsymmetricFile(): cannot "
                "compile line %d of the %s asymmetric clients file into a "
                "regular expression (will be ignored): %s", i, which, errbuf);
            pkg_free(re);
        }
    }

    aptr->timestamp = statbuf.st_mtime;

    LOG(L_INFO, "info: mediaproxy: %sloaded %s asymmetric clients file "
        "containing %d entr%s.\n", firstTime ? "" : "re",
        which, aptr->count, aptr->count==1 ? "y" : "ies");

}
示例#10
0
/*!
 * \brief Wrapper functions around our internal memory management for libmemcached (version < 0.38) callback
 * \param mem pointer to allocated memory
 * \param size new size of memory area
 * \return allocated memory, or NULL on failure
 * \see pkg_realloc
 */
static inline void* mcd_realloc_compat(memcached_st *ptr, void *mem, const size_t size) {
        return pkg_realloc(mem, size);
}
示例#11
0
static void *osips_realloc(void *ptr, size_t size)
{
	void *p = pkg_realloc(ptr, size);

	return p;
}
示例#12
0
/*!
 * \brief Wrapper functions around our internal memory management for libmemcached (version >= 0.38) callback
 * \param mem pointer to allocated memory
 * \param size new size of memory area
 * \return allocated memory, or NULL on failure
 * \see pkg_realloc
 */
static inline void* mcd_realloc(memcached_st *ptr, void *mem, const size_t size, void *context) {
 	return pkg_realloc(mem, size);
}
示例#13
0
文件: lb_data.c 项目: ryzhov/ATS0
int do_load_balance(struct sip_msg *req, int grp, struct lb_res_str_list *rl,
										unsigned int alg, struct lb_data *data)
{
	static struct lb_resource **call_res = NULL;
	static unsigned int call_res_no = 0;
	static unsigned int *dst_bitmap = NULL;
	static unsigned int bitmap_size = 0;
	unsigned int * used_dst_bitmap;
	struct lb_resource *res;
	int size;
	int i,j;
	unsigned int load, ld;
	struct lb_dst *dst;
	struct lb_dst *it;
	struct lb_dst *last_dst;
	struct usr_avp *grp_avp;
	struct usr_avp *mask_avp;
	struct usr_avp *id_avp;
	int_str grp_val;
	int_str mask_val;
	int_str id_val;

	/* get references to the resources */
	if (rl->n>call_res_no) {
		call_res = (struct lb_resource**)pkg_realloc
			(call_res, rl->n*sizeof(struct lb_resorce*));
		if (call_res==NULL) {
			LM_ERR("no more pkg mem - res ptr realloc\n");
			return -1;
		}
		call_res_no = rl->n;
	}
	for( i=0,res=data->resources ; (i<rl->n)&&res ; res=res->next) {
		if (search_resource_str( rl, &res->name)) {
			call_res[i++] = res;
			LM_DBG("found requested (%d) resource %.*s\n",
				i-1, res->name.len,res->name.s);
		}
	}
	if (i!=rl->n) {
		LM_ERR("unknown resource in input string\n");
		return -1;
	}

	/* any previous iteration due failover ? */
	grp_avp = search_first_avp( 0, grp_avp_name, &grp_val, 0);
	mask_avp = search_first_avp( 0, mask_avp_name, &mask_val, 0);
	id_avp = search_first_avp( 0, id_avp_name, &id_val, 0);

	if ( grp_avp && mask_avp && id_avp && ((grp_avp->flags&AVP_VAL_STR)==0) &&
	(mask_avp->flags&AVP_VAL_STR) && ((id_avp->flags&AVP_VAL_STR)==0) ) {
		/* not the first iteration -> use data from AVPs */
		grp = grp_val.n ;
		used_dst_bitmap = (unsigned int*)mask_val.s.s;
		/* set the previous dst as used (not selected) */
		for(last_dst=data->dsts,i=0,j=0 ; last_dst ; last_dst=last_dst->next) {
			if (last_dst->id==id_val.n) {used_dst_bitmap[i] &= ~(1<<j);break;}
			j++;
			if (j==sizeof(unsigned int)) {i++;j=0;}
		}
	} else {
		/* first iteration for this call */
		grp_avp = mask_avp = id_avp = NULL;
		last_dst = NULL;

		/* search destinations that fulfill the resources */
		for( size=(unsigned int)(-1),i=0 ; i<rl->n ; i++) {
			if (call_res[i]->bitmap_size<size)
				size = call_res[i]->bitmap_size;
		}
		if (size>bitmap_size) {
			dst_bitmap = (unsigned int*)pkg_realloc
				( dst_bitmap, size*sizeof(unsigned int) );
			if (dst_bitmap==NULL) {
				LM_ERR("no more pkg mem - bitmap realloc\n");
				return -1;
			}
			bitmap_size = size;
		}
		memset( dst_bitmap, 0xff , size*sizeof(unsigned int) );
		for( i=0 ; i<rl->n ; i++) {
			for( j=0 ; j<size ; j++)
				dst_bitmap[j] &= call_res[i]->dst_bitmap[j];
		}
		used_dst_bitmap = dst_bitmap;

		/* create dialog */
		if (lb_dlg_binds.create_dlg( req )!=1 ) {
			LM_ERR("failed to create dialog\n");
			return -1;
		}
	} /* end - first LB run */


	/* lock the resources */
	for( i=0 ; i<rl->n ; i++)
		get_lock( call_res[i]->lock );

	/* do the load-balancing */
	load = 0;
	dst = NULL;
	for( it=data->dsts,i=0,j=0 ; it ; it=it->next) {
		if ( (used_dst_bitmap[i] & (1<<j)) && it->group==grp &&
		(it->flags&LB_DST_STAT_DSBL_FLAG)==0 ) {
			/* valid destination (resources & group & status) */
			if ( (ld = get_dst_load(call_res, call_res_no, it, alg)) > load) {
				/* computing a max */
				load = ld;
				dst = it;
			}
			LM_DBG("destination <%.*s> selected for LB set with free=%d "
				"(max=%d)\n",it->uri.len, it->uri.s,ld, load);
		}
		j++;
		if (j==8*sizeof(unsigned int)) {i++;j=0;}
	}

	/* if re-trying, remove the dialog from previous profiles */
	if (last_dst) {
		for( i=0 ; i<rl->n ; i++) {
			if (lb_dlg_binds.unset_profile( req, &last_dst->profile_id,
			call_res[i]->profile)!=1)
				LM_ERR("failed to remove from profile\n");
		}
	}

	if (dst==NULL) {
		LM_DBG("no destination found\n");
	} else {
		/* add to the profiles */
		for( i=0 ; i<rl->n ; i++) {
			if (lb_dlg_binds.set_profile( req, &dst->profile_id,
			call_res[i]->profile)!=0)
				LM_ERR("failed to add to profile\n");
		}
	}

	/* unlock the resources*/
	for( i=0 ; i<rl->n ; i++)
		release_lock( call_res[i]->lock );

	if (dst) {
		/* change (add/edit) the AVPs for the next iteration */
		if (grp_avp==NULL && mask_avp==NULL) {
			grp_val.n = grp;
			if (add_avp( 0, grp_avp_name, grp_val)!=0) {
				LM_ERR("failed to add GRP AVP");
			}
			mask_val.s.s = (char*)used_dst_bitmap;
			mask_val.s.len = bitmap_size*sizeof(unsigned int);
			if (add_avp( AVP_VAL_STR, mask_avp_name, mask_val)!=0) {
				LM_ERR("failed to add MASK AVP");
			}
		}
		if (id_avp) {
			id_avp->data = (void*)(long)dst->id;
		} else {
			id_val.n = dst->id;
			if (add_avp( 0, id_avp_name, id_val)!=0) {
				LM_ERR("failed to add ID AVP");
			}
		}

		/* set dst uri */
		if (set_dst_uri( req, &dst->uri )!=0) {
			LM_ERR("failed to set duri\n");
			return -2;
		}
	}

	return dst?0:-2;
}
示例#14
0
void timeout_listener_process(int rank)
{
	struct sockaddr_un saddr_un;
	struct sockaddr_un *s_un;
	struct sockaddr_in saddr_in;
	struct sockaddr_in *s_in;
	struct sockaddr_in6 *s_in6;
	int connect_fd;
	char buffer[BUF_LEN];
	char *p, *sp, *end, *start;
	unsigned int h_entry, h_id;
	str id;
	unsigned short port;
	struct sockaddr* saddr;
	int len, i,n, left;
	int optval = 1;
	struct sockaddr rtpp_info;
	struct rtpp_notify_node *rtpp_lst;
	str terminate_reason = str_init("RTPProxy Timeout");
	int offset = 0;

	if (init_child(PROC_MODULE) != 0) {
		LM_ERR("cannot init child process");
		return;
	}

	if (!rtpp_notify_socket_un) {
		p = strrchr(rtpp_notify_socket.s, ':');
		if (!p) {
			LM_ERR("invalid udp address <%.*s>\n", rtpp_notify_socket.len, rtpp_notify_socket.s);
			return;
		}
		n = p- rtpp_notify_socket.s;
		rtpp_notify_socket.s[n] = 0;

		id.s = p+1;
		id.len = rtpp_notify_socket.len - n -1;
		port= str2s(id.s, id.len, &n);
		if(n) {
			LM_ERR("Bad format for socket name. Expected ip:port\n");
			return;
		}
		memset(&saddr_in, 0, sizeof(saddr_in));
		saddr_in.sin_addr.s_addr = inet_addr(rtpp_notify_socket.s);
		saddr_in.sin_family = AF_INET;
		saddr_in.sin_port = htons(port);

		socket_fd = socket(AF_INET, SOCK_STREAM, 0);
		if (socket_fd == -1) {
			LM_ERR("can't create timeout socket\n");
			return;
		}
		saddr = (struct sockaddr*)&saddr_in;
		len = sizeof(saddr_in);
		LM_DBG("binding socket %d to %s:%d\n", socket_fd, rtpp_notify_socket.s, port);
	} else {
		/* create socket */
		socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
		if (socket_fd == -1) {
			LM_ERR("Failed to create unix socket\n");
			return;
		}

		memset(&saddr_un, 0, sizeof(struct sockaddr_un));
		saddr_un.sun_family = AF_LOCAL;
		strncpy(saddr_un.sun_path, rtpp_notify_socket.s,
				sizeof(saddr_un.sun_path) - 1);
		saddr = (struct sockaddr*)&saddr_un;
		len = sizeof(saddr_un);
		LM_DBG("binding unix socket %s\n", rtpp_notify_socket.s);
	}

	if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, (void*)&optval,
				sizeof(optval)) == -1) {
		LM_ERR("setsockopt failed %s\n", strerror(errno));
		return;
	}

	if (bind(socket_fd, saddr, len) == -1) {
		LM_ERR("failed to bind to socket: %s\n", strerror(errno));
		return;
	}

	/* open socket for listening */
	if(listen(socket_fd, 10) == -1) {
		LM_ERR("socket listen failed: %s(%d)\n", strerror(errno), errno);
		close(socket_fd);
		return;
	}

	pfds = (struct pollfd *)pkg_malloc(pfds_size*sizeof(struct pollfd));
	if (!pfds) {
		LM_ERR("no more pkg memory\n");
		return;
	}
	pfds[0].fd = socket_fd;
	pfds[nfds++].events = POLLIN;

	for(;;) {
		nr_events = poll(pfds, nfds, -1);
		if (nr_events < 0)
			continue;

		/* check if the rtpproxy list needs updates */
		lock_get(rtpp_notify_h->lock);
		if (rtpp_notify_h->changed) {
			/* update list */
			update_rtpproxy_list();
			rtpp_notify_h->changed = 0;
		}
		lock_release(rtpp_notify_h->lock);

		rtpp_lst = NULL;
		/* there is a new connection */
		if (pfds[0].revents & POLLIN) {
			i = sizeof(rtpp_info);
			memset(&rtpp_info, 0, i);
			connect_fd = accept(socket_fd, &rtpp_info, (socklen_t *)&i);
			if(connect_fd < 0) {
				LM_ERR("socket accept failed: %s(%d)\n", strerror(errno), errno);
				continue;
			}

			/* if it is a unix socket, try to authenticate it */
			if (rtpp_info.sa_family == AF_UNIX) {
				s_un = (struct sockaddr_un*)&rtpp_info;
				/* check if the socket is already opened */
				lock_get(rtpp_notify_h->lock);
				for (rtpp_lst = rtpp_notify_h->rtpp_list; rtpp_lst; rtpp_lst = rtpp_lst->next)
					if ( rtpp_lst->mode == 0 && !strcmp(rtpp_lst->addr, s_un->sun_path))
						break;

				/* if not found add a new one */
				if (!rtpp_lst) {
					/* leave the lock for a moment */
					lock_release(rtpp_notify_h->lock);
					rtpp_lst = (struct rtpp_notify_node*)
						shm_malloc(sizeof(struct rtpp_notify_node));
					if (!rtpp_lst) {
						LM_ERR("no shm more memory\n");
						return;
					}
					rtpp_lst->index = 0;
					rtpp_lst->mode = 0;
					rtpp_lst->addr = 0;

					/* copy the socket name */
					len = strlen(s_un->sun_path);
					rtpp_lst->addr = (char *)shm_malloc(len + 1);
					if (!rtpp_lst->addr) {
						LM_ERR("no more shm memory\n");
						return;
					}
					memcpy(rtpp_lst->addr, s_un->sun_path, len + 1);

					lock_get(rtpp_notify_h->lock);
					rtpp_lst->next = rtpp_notify_h->rtpp_list;
					rtpp_notify_h->rtpp_list = rtpp_lst;
				}
			} else {
				/* search if I can find this connection */
				if (rtpp_info.sa_family == AF_INET) {
					s_in = (struct sockaddr_in*)&rtpp_info;
					lock_get(rtpp_notify_h->lock);
					for (rtpp_lst = rtpp_notify_h->rtpp_list; rtpp_lst; rtpp_lst = rtpp_lst->next)
						if (rtpp_lst->mode == 1 &&
							memcmp(rtpp_lst->addr, &s_in->sin_addr.s_addr, 4) == 0)
							break;
				} else if (rtpp_info.sa_family == AF_INET6) {
					s_in6 = (struct sockaddr_in6*)&rtpp_info;
					lock_get(rtpp_notify_h->lock);
					for (rtpp_lst = rtpp_notify_h->rtpp_list; rtpp_lst; rtpp_lst = rtpp_lst->next)
						if (rtpp_lst->mode == 6 &&
							memcmp(rtpp_lst->addr, s_in6->sin6_addr.s6_addr, 16) == 0)
							break;
				} else {
					LM_ERR("cannot accept this type of connection\n");
				}
			}

			if (!rtpp_lst) {
				lock_release(rtpp_notify_h->lock);
				LM_DBG("unknown rtpproxy -- ignoring\n");
				shutdown(connect_fd, SHUT_RDWR);
				close(connect_fd);
			} else {
				/* valid connection - checking if already connected */
				if (rtpp_lst->index) {
					LM_DBG("rtpproxy restarted - update connection status\n");
					shutdown(rtpp_lst->fd, SHUT_RDWR);
					close(rtpp_lst->fd);
				} else {
					rtpp_lst->index = nfds++;
					if (nfds > pfds_size) {
						pfds_size *= 2;
						pfds = (struct pollfd*)pkg_realloc(pfds,
								pfds_size*sizeof(struct pollfd));
					}
				}

				LM_DBG("rtpproxy accepted\n");
				pfds[rtpp_lst->index].fd = connect_fd;
				pfds[rtpp_lst->index].events = POLLIN;
				rtpp_lst->fd = connect_fd;
				lock_release(rtpp_notify_h->lock);
			}
			nr_events--;
		}

		for (i=1; (nr_events && i<nfds); i++)
		{
			if (!(pfds[i].revents & POLLIN))
				continue;
			nr_events--;

			do
				len = read(pfds[i].fd, buffer + offset, BUF_LEN - offset);
			while (len == -1 && errno == EINTR);

			if (len < 0) {
				LM_ERR("reading from socket failed: %s\n",strerror(errno));
				continue;
			}

			if (!len) {
				LM_DBG("closing rtpproxy\n");
				lock_get(rtpp_notify_h->lock);
				for (rtpp_lst=rtpp_notify_h->rtpp_list;
						rtpp_lst;rtpp_lst=rtpp_lst->next)
					if (rtpp_lst->index == i)
						break;
				if (!rtpp_lst) {
					LM_ERR("BUG - rtpproxy not found\n");
					lock_release(rtpp_notify_h->lock);
					continue;
				}
				rtpp_lst->index = 0;
				lock_release(rtpp_notify_h->lock);
				nfds--;
				shutdown(pfds[i].fd, SHUT_RDWR);
				close(pfds[i].fd);

				if (nfds == i)
					continue;

				pfds[i].fd = pfds[nfds].fd;
				lock_get(rtpp_notify_h->lock);
				for (rtpp_lst=rtpp_notify_h->rtpp_list; rtpp_lst; rtpp_lst=rtpp_lst->next)
					if (rtpp_lst->index == nfds)
						break;
				if (!rtpp_lst) {
					LM_ERR("BUG - rtpproxy index mismatch\n");
					lock_release(rtpp_notify_h->lock);
					continue;
				}
				rtpp_lst->index = i;
				lock_release(rtpp_notify_h->lock);
				continue;
			}
			LM_INFO("Timeout detected on the following calls [%.*s]\n", len, buffer);
			p = buffer;
			left = len + offset;
			offset = 0;
			end = buffer + left;

			do {
				start = p;
				/* the message is: h_entry.h_id\n */
				sp = memchr(p, '.', left);
				if (sp == NULL)
					break;

				id.s = p;
				id.len = sp - p;

				if (sp >= end)
					break;

				p = sp + 1;
				left -= id.len + 1;

				if(str2int(&id, &h_entry)< 0) {
					LM_ERR("Wrong formated message received from rtpproxy - invalid"
							" dialog entry [%.*s]\n", id.len, id.s);
					break;
				}

				sp = memchr(p, '\n', left);
				if (sp == NULL)
					break;

				id.s = p;
				id.len = sp - p;

				if (sp >= end)
					break;

				p = sp + 1;
				left -= id.len + 1;

				if(str2int(&id, &h_id)< 0) {
					LM_ERR("Wrong formated message received from rtpproxy - invalid"
							" dialog id [%.*s]\n", id.len, id.s);
					break;
				}
				LM_DBG("hentry = %u, h_id = %u\n", h_entry, h_id);

				if(dlg_api.terminate_dlg(h_entry, h_id,&terminate_reason)< 0)
					LM_ERR("Failed to terminate dialog h_entry=[%u], h_id=[%u]\n", h_entry, h_id);

				LM_DBG("Left to process: %d\n[%.*s]\n", left, left, p);

			} while (p < end);

			offset = end - start;
			memmove(buffer, start, end - start);
		}
	}
}
示例#15
0
/**
 * Returns the content of the Service-Route header.
 * data vector is pkg_alloced and should be later freed
 * inside values are not duplicated
 * @param msg - the SIP message
 * @param size - size of the returned vector, filled with the result
 * @param is_shm - msg from shared memory
 * @returns - the str vector of uris
 */
str* cscf_get_service_route(struct sip_msg *msg, int *size, int is_shm) {
	struct hdr_field *h;
	rr_t *r, *r2;
	str *x = 0;
	int k;
	if (!size)
		return 0;

	*size = 0;

	if (!msg)
		return 0;
	if (parse_headers(msg, HDR_EOH_F, 0) < 0) {
		LM_ERR("error parsing headers\n");
		return 0;
	}
	h = msg->headers;
	while (h) {
		if (h->name.len == 13
				&& strncasecmp(h->name.s, "Service-Route", 13) == 0) {
			if (parse_rr(h) < 0) {
				LM_ERR("Error parsing as Route header\n");
				continue;
			}
			r = (rr_t*) h->parsed;
			h->type = HDR_ROUTE_T;
			r2 = r;
			k = 0;
			while (r2) {
				k++;
				r2 = r2->next;
			}
			if (!k) {
				LM_DBG("No items in this Service-Route\n");
				continue;
			}
			x = pkg_realloc(x,(*size+k)*sizeof(str));
			if (!x) {
				LM_ERR("Error our of pkg memory");
				return 0;
			}
			r2 = r;
			while (r2) {
				x[*size] = r2->nameaddr.uri;
				(*size) = (*size) + 1;
				r2 = r2->next;
			}
		}
		h = h->next;
	}
	if (is_shm) {
		h = msg->headers;
		while (h) {
			if (h->name.len == 13
					&& strncasecmp(h->name.s, "Service-Route", 13) == 0) {
				r = (rr_t*) h->parsed;
				h->parsed = 0;
				free_rr(&r);
			}
			h = h->next;
		}
	}

	return x;
}
示例#16
0
static char* serialize_he_rdata(struct hostent *he,int *buf_len,int do_encoding)
{
	unsigned char *p;
	int i,len=0,needed_len=0,base64_len=0,alias_no=0,addr_no=0;

	/* addr_type, name_len, alias_no, addr_no */ 
	len+=sizeof(int)*4;

	/* compute needed buffer length */
	if (he->h_name)
		len+=strlen(he->h_name)+1;

	if (he->h_aliases)
       		for (i=0;he->h_aliases[i];i++) {
			/* integer with len + len bytes of alias */
			len+=strlen(he->h_aliases[i])+1+sizeof(int);
			alias_no++;
		}


	i=0;
	if (he->h_addr_list)
       		for (i=0;he->h_addr_list[i];i++) {
			len+=he->h_length;
			addr_no++;
		}

	if (do_encoding) {
		/* backend does not support binary values - allocate continous buffer
		for encoding */
		base64_len = calc_base64_encode_len(len);
		needed_len=len+base64_len;
	} else
		needed_len = len;	

	if (he_buf == NULL || needed_len > he_buf_len) {
		/* realloc if not enough space */
		he_buf = pkg_realloc(he_buf,needed_len);	
		if (he_buf == NULL) {
			LM_ERR("No more pkg\n");
			return NULL;				
		}
		he_buf_len = needed_len;
	}

	p = he_buf;

	/* copy address type */
	memcpy(p,&he->h_addrtype,sizeof(int));
	p+=sizeof(int);

	/* copy h_name len */
	len=strlen(he->h_name)+1;			
	memcpy(p,&len,sizeof(int));
	p+=sizeof(int);
	/* copy h_name */
	memcpy(p,he->h_name,len);
	p+=len;
	
	/* copy number of aliases */
	memcpy(p,&alias_no,sizeof(int));
	p+=sizeof(int);

	/* copy aliases, if any */
	if (he->h_aliases)
       		for (i=0;he->h_aliases[i];i++) {
			len=strlen(he->h_aliases[i])+1;
			/* copy alias length */
			memcpy(p,&len,sizeof(int));
			p+=sizeof(int);
			/* copy alias */
			memcpy(p,he->h_aliases[i],len);
			p+=len;
		}

	/* copy address no */
	memcpy(p,&addr_no,sizeof(int));
	p+=sizeof(int);

	/* copy addresses */
	if (he->h_addr_list)
       		for (i=0;he->h_addr_list[i];i++) {
			/* copy addreses. length will be known from the addrtype field */
			len=he->h_length;
			memcpy(p,he->h_addr_list[i],len);
			p+=len;
		}

	if (do_encoding) {
		len = needed_len - base64_len;

		if (buf_len)
			*buf_len=base64_len;

		/* do encoding, and return pointer after unencoded data */
		base64encode(p,he_buf,len);
		return (char *)p;	
	} else {
		if (buf_len)
			*buf_len = needed_len;
		return (char *)he_buf;	
	}
}
示例#17
0
/* creates an url string without password field*/
static void db_get_url(const str* url){
	struct db_id* id = new_db_id(url);
	static str scheme_delimiter={"://",3};
	static str port_delimiter={":",1};
	static str host_delimiter={"@",1};
	static str database_delimiter={"/",1};
	str port;

	/* allocate memory for the database url if necessary*/
	database_url.len = 0;

	/* sanity checks */
	if (id == NULL)
		return;

	database_url.s = pkg_realloc(database_url.s, url->len * sizeof(char));

	if (database_url.s == NULL) {
		free_db_id(id);
		return;
	}

	/* shortest database_url is s://a/b so we always need the scheme delimiter*/
	if (id->scheme != NULL) {
		memcpy(database_url.s + database_url.len, id->scheme, strlen(id->scheme));
		database_url.len += strlen(id->scheme);
		memcpy(database_url.s + database_url.len, scheme_delimiter.s, scheme_delimiter.len);
		database_url.len += scheme_delimiter.len;
	}

	if (id->username != NULL) {
		memcpy(database_url.s + database_url.len, id->username, strlen(id->username));
		database_url.len += strlen(id->username);
	}

	if (id->host != NULL) {
		memcpy(database_url.s + database_url.len, host_delimiter.s, host_delimiter.len);
		database_url.len += host_delimiter.len;
		memcpy(database_url.s + database_url.len, id->host, strlen(id->host));
		database_url.len += strlen(id->host);
	}

	if (id->port > 0) {
		port.s = int2str(id->port,&port.len);
		memcpy(database_url.s + database_url.len, port_delimiter.s, port_delimiter.len);
		database_url.len += port_delimiter.len;
		memcpy(database_url.s + database_url.len, port.s, port.len);
		database_url.len += port.len;
	}

	if (id->database != NULL){
		memcpy(database_url.s + database_url.len,
			database_delimiter.s, database_delimiter.len);
		database_url.len += database_delimiter.len;
		memcpy(database_url.s + database_url.len, id->database, strlen(id->database));
		database_url.len += strlen(id->database);
	}

	/* free alocated memory */
	free_db_id(id);
}
示例#18
0
static struct hostent* deserialize_he_rdata(char *buff,int buf_len,int do_decoding)
{
	char **ap,**hap;
	unsigned char *p;
	int max_len=0,actual_len=0;
	int i,alias_no=0,addr_no=0,len=0;
	
	/* max estimation of needed buffer */
	if (do_decoding) {
		max_len=calc_max_base64_decode_len(buf_len);
	} else {
		max_len = buf_len;
	}

	if (dec_he_buf == NULL || max_len > dec_he_buf_len) {
		/* realloc buff if not enough space */
		dec_he_buf = pkg_realloc(dec_he_buf,max_len);	
		if (dec_he_buf == NULL) {
			LM_ERR("No more pkg\n");
			return NULL;				
		}
		dec_he_buf_len = max_len;
	}

	/* set pointer in dec_global_he */
	ap = host_aliases;
	*ap = NULL;
	dec_global_he.h_aliases = host_aliases;
	hap = h_addr_ptrs;
	*hap = NULL;
	dec_global_he.h_addr_list = h_addr_ptrs;
	
	if (do_decoding) {
		/* decode base64 buf */
		actual_len = base64decode(dec_he_buf,(unsigned char *)buff,buf_len);	
		p = dec_he_buf;
	} else {
		memcpy(dec_he_buf,buff,buf_len);
		p = dec_he_buf;
	}

	/* set address type & length */
	memcpy(&dec_global_he.h_addrtype,p,sizeof(int));
	p+=sizeof(int);
	if (dec_global_he.h_addrtype == AF_INET)
		dec_global_he.h_length=4;
	else
		dec_global_he.h_length=16;

	/* set name */
	memcpy(&len,p,sizeof(int));
	p+=sizeof(int);
	dec_global_he.h_name = (char *)p;
	p+=len;

	/* get number of aliases */
	memcpy(&alias_no,p,sizeof(int));
	p+=sizeof(int);

	for (i=0;i<alias_no;i++) {
		/* get alias length, set pointer and skip over length */
		memcpy(&len,p,sizeof(int));
		p+=sizeof(int);
		*ap++ = (char *)p;
		p+=len;		
	}

	/* get number of addresses */
	memcpy(&addr_no,p,sizeof(int));	
	p+=sizeof(int);

	for (i=0;i<addr_no;i++) {
		/* set pointer and skip over length */
		*hap++ = (char *)p;	
		p+=dec_global_he.h_length;
	}			
		
	return &dec_global_he;
}
示例#19
0
/* method that processes a stream and keeps the original order
 * of codecs with the same name */
static int stream_process(struct sip_msg * msg, struct sdp_stream_cell *cell,
			str * s, str* ss, regex_t* re, int op,int description)
{
	static sdp_payload_attr_t static_payloads[] = {
	/* as per http://www.iana.org/assignments/rtp-parameters/rtp-parameters.xml */
	{ NULL,0,{ "0",1},{"PCMU",4},{ "8000",4},{NULL,0},{NULL,0} },   /* 0 - PCMU/8000  */
	{ NULL,0,{ "3",1},{ "GSM",3},{ "8000",4},{NULL,0},{NULL,0} },   /* 3 -  GSM/8000  */
	{ NULL,0,{ "4",1},{"G723",4},{ "8000",4},{NULL,0},{NULL,0} },   /* 4 - G723/8000  */
	{ NULL,0,{ "5",1},{"DVI4",4},{ "8000",4},{NULL,0},{NULL,0} },   /* 5 - DVI4/8000  */
	{ NULL,0,{ "6",1},{"DVI4",4},{"16000",5},{NULL,0},{NULL,0} },   /* 6 - DVI4/16000 */
	{ NULL,0,{ "7",1},{ "LPC",3},{ "8000",4},{NULL,0},{NULL,0} },   /* 7 -  LPC/8000  */
	{ NULL,0,{ "8",1},{"PCMA",4},{ "8000",4},{NULL,0},{NULL,0} },   /* 8 - PCMA/8000  */
	{ NULL,0,{ "9",1},{"G722",4},{ "8000",4},{NULL,0},{NULL,0} },   /* 9 - G722/8000  */
	{ NULL,0,{"10",2},{ "L16",3},{"44100",5},{NULL,0},{NULL,0} },   /*10 -  L16/44100 */
	{ NULL,0,{"11",2},{ "L16",3},{"44100",5},{NULL,0},{NULL,0} },   /*11 -  L16/44100 */
	{ NULL,0,{"12",2},{"QCELP",5},{"8000",4},{NULL,0},{NULL,0} },   /*12 -QCELP/8000  */
	{ NULL,0,{"13",2},{  "CN",2},{ "8000",4},{NULL,0},{NULL,0} },   /*13 -   CN/8000  */
	{ NULL,0,{"14",2},{ "MPA",3},{"90000",5},{NULL,0},{NULL,0} },   /*14 -  MPA/90000 */
	{ NULL,0,{"15",2},{"G728",4},{ "8000",4},{NULL,0},{NULL,0} },   /*15 - G728/8000  */
	{ NULL,0,{"16",2},{"DVI4",4},{"11025",5},{NULL,0},{NULL,0} },   /*16 - DVI4/11025 */
	{ NULL,0,{"17",2},{"DVI4",4},{"22050",5},{NULL,0},{NULL,0} },   /*17 - DVI4/22050 */
	{ NULL,0,{"18",2},{"G729",4},{ "8000",4},{NULL,0},{NULL,0} },   /*18 - G729/8000  */
	{ NULL,0,{"25",2},{"CelB",4},{ "8000",4},{NULL,0},{NULL,0} },   /*25 - CelB/8000  */
	{ NULL,0,{"26",2},{"JPEG",4},{"90000",5},{NULL,0},{NULL,0} },   /*26 - JPEG/90000 */
	{ NULL,0,{"28",2},{  "nv",2},{"90000",5},{NULL,0},{NULL,0} },   /*28 -   nv/90000 */
	{ NULL,0,{"31",2},{"H261",4},{"90000",5},{NULL,0},{NULL,0} },   /*31 - H261/90000 */
	{ NULL,0,{"32",2},{ "MPV",3},{"90000",5},{NULL,0},{NULL,0} },   /*32 -  MPV/90000 */
	{ NULL,0,{"33",2},{"MP2T",4},{"90000",5},{NULL,0},{NULL,0} },   /*33 - MP2T/90000 */
	{ NULL,0,{"34",2},{"H263",4},{"90000",5},{NULL,0},{NULL,0} },   /*34 - H263/90000 */
	{ NULL,0,{"t38",3},{"t38",3},{     "",0},{NULL,0},{NULL,0} },   /*T38- fax        */
	{ NULL,0,{NULL,0},{  NULL,0},{   NULL,0},{NULL,0},{NULL,0} }
	};
	sdp_payload_attr_t *payload;
	char *cur, *tmp, *buff, temp;
	struct lump * lmp;
	str found;
	int ret, i, depl, single, match, buff_len, is_static;
	regmatch_t pmatch;


	lmp = get_associated_lump(msg, cell);
	if( lmp == NULL)
	{
		LM_ERR("There is no lump for this sdp cell\n");
		return -1;
	}

	/* is stream deleted ?? */
	if (lmp->len == 0)
		return -1;


	buff_len = 0;
	ret = 0;

	buff = pkg_malloc(lmp->len+1);
	if( buff == NULL)
	{
		LM_ERR("Out of memory\n");
		return -1;
	}

	/* search through each payload */
	is_static = 0;
	payload = cell->payload_attr;

	while(payload)
	{
		if( payload->rtp_enc.s == NULL
		 || (payload->rtp_clock.s == NULL && ss != NULL)
		 || payload->rtp_payload.s == NULL)
		{
			goto next_payload;
		}

		match = 0;

		if( description == DESC_REGEXP ||description == DESC_REGEXP_COMPLEMENT )
		{
			/* try to match a regexp */
			if (is_static) {
				match = regexec( re, payload->rtp_enc.s, 1, &pmatch, 0) == 0;
			} else {
				temp = payload->rtp_enc.s[payload->rtp_enc.len];
				payload->rtp_enc.s[payload->rtp_enc.len] = 0;
				match = regexec( re, payload->rtp_enc.s, 1, &pmatch, 0) == 0;
				payload->rtp_enc.s[payload->rtp_enc.len] = temp;
			}
		}

		if( description == DESC_REGEXP_COMPLEMENT)
			match = !match;

		if( description == DESC_NAME  )
		{
			match = s->len == payload->rtp_enc.len &&
			strncasecmp( s->s, payload->rtp_enc.s ,	payload->rtp_enc.len) == 0;
		}

		if( description == DESC_NAME_AND_CLOCK)
		{
			/* try to match name and clock if there is one */
			match = s->len == payload->rtp_enc.len &&
			strncasecmp( s->s, payload->rtp_enc.s ,
				payload->rtp_enc.len) == 0
			&&
			(ss == NULL || ( ss->len == payload->rtp_clock.len &&
			strncasecmp( ss->s, payload->rtp_clock.s ,
				payload->rtp_clock.len) == 0
			) );
		}

		/* if found, search its index in the m= line */
		if (match) {

			match = 0;

			cur = lmp->u.value;
			while( !match && cur < lmp->u.value + lmp->len)
			{
				/* find the end of the number */
				found.s = cur;

				while(  cur < lmp->u.value + lmp->len &&  *cur != ' ' )
					cur++;

				found.len = cur - found.s;

				/* does it matches payload number */
				if ( found.len == payload->rtp_payload.len &&
				strncmp( found.s,payload->rtp_payload.s,found.len) == 0) {
					match = 1;
				} else {
					/* continue on searching => skip spaces
					   if there still are any */
					while( cur < lmp->u.value + lmp->len && * cur == ' '  )
						cur++;
				}
			}

			/* have we found both payload and index */
			if (match) {

				if(op == FIND)
				{
					ret = 1;
					goto end;
				}

				if( op == DELETE && !is_static )
				{
					/* find the full 'a=...' entry */

					if( delete_sdp_line( msg, payload->rtp_enc.s) < 0 )
					{
						LM_ERR("Unable to add delete lump for a=\n");
						ret = -1;
						goto end;
					}

					if( delete_sdp_line( msg, payload->fmtp_string.s) < 0 )
					{
						LM_ERR("Unable to add delete lump for a=\n");
						ret = -1;
						goto end;
					}
				}

				{
					/* take the following whitespaces as well */
					while( cur < lmp->u.value + lmp->len &&  *cur == ' '  )
					{
						cur++;
						found.len++;
					}

					/* when trimming the very last payload, avoid trailing ws */
					if (cur == lmp->u.value + lmp->len) {
						tmp = found.s;
						while (*(--tmp) == ' ') {
							found.s--;
							found.len++;
						}
					}

					/* delete the string and update iterators */
					for(tmp=found.s ; tmp< lmp->u.value + lmp->len ; tmp++ )
						*tmp  = *(tmp+found.len);

					cur -= found.len;
					lmp->len -= found.len;
				}

				/* add the deleted number into a buffer to be addded later */
				if( op == ADD_TO_FRONT  || op == ADD_TO_BACK)
				{
					if( buff_len > 0)
					{
						memcpy(&buff[buff_len]," ",1);
						buff_len++;
					}

					memcpy(&buff[buff_len],payload->rtp_payload.s,
						payload->rtp_payload.len);

					buff_len += payload->rtp_payload.len;
				}

				ret = 1;
			}

		}

		/* next payload */
	next_payload:
		if (!is_static) {
			payload = payload->next;
			if (payload==NULL) {
				payload = static_payloads;
				is_static = 1;
			}
		} else {
			payload ++;
			if (payload->rtp_payload.s==NULL)
				payload=NULL;
		}
	}


	if( op == ADD_TO_FRONT && buff_len >0 )
	{
		depl = buff_len;
		single = 1;

		if( lmp->len > 0)
		{
			depl++;
			single = 0;
		}

		lmp->u.value = (char*)pkg_realloc(lmp->u.value, lmp->len+depl);
		if(!lmp->u.value) {
			LM_ERR("No more pkg memory\n");
			ret = -1;
			goto end;
		}

		for( i = lmp->len -1 ; i>=0;i--)
			lmp->u.value[i+depl] = lmp->u.value[i];

		memcpy(lmp->u.value,buff,buff_len);

		if(!single)
			lmp->u.value[buff_len] = ' ';

		lmp->len += depl;

	}

	if( op == ADD_TO_BACK && buff_len >0 )
	{

		lmp->u.value = (char*)pkg_realloc(lmp->u.value, lmp->len+buff_len+1);
		if(!lmp->u.value) {
			LM_ERR("No more pkg memory\n");
			ret = -1;
			goto end;
		}


		if( lmp->len > 0)
		{

			memcpy(&lmp->u.value[lmp->len]," ",1);
			lmp->len++;
		}


		memcpy(&lmp->u.value[lmp->len],buff,buff_len);

		lmp->len += buff_len;

	}

end:
	pkg_free(buff);
	return ret;
}
/**
 * Query a table for specified rows.
 * \param _h structure representing database connection
 * \param _k key names
 * \param _op operators
 *\param  _v values of the keys that must match
 * \param _c column names to return
 * \param _n number of key=values pairs to compare
 * \param _nc number of columns to return
 * \param _o order by the specified column
 * \param _r pointer to a structure representing the result
 * \return zero on success, negative value on failure
 */
int erlang_srdb1_query(const db1_con_t* _h, const db_key_t* _k, const db_op_t* _op,
	     const db_val_t* _v, const db_key_t* _c, const int _n, const int _nc,
	     const db_key_t _o, db1_res_t** _r) {
	ei_x_buff argbuf,retbuf;
	int retcode,i,j,x;
	int n_cols,n_rows,len;
	db1_res_t *res;
	db_row_t *rows = NULL, *row;
	db_val_t *val;
	char atom[MAXATOMLEN], *p;
	ei_term term;
	int ei_type,size;
	str *sname;

	if (!_h || !_r) {
		LM_ERR("invalid parameter value\n");
		return -1;
	}
	*_r=NULL;
	LM_DBG("erlang_srdb1_query table %.*s\n",CON_TABLE(_h)->len, CON_TABLE(_h)->s);
	ei_x_new(&argbuf);
	//encode tuple {db_op, table, [cols], [params]}
	ei_x_encode_tuple_header(&argbuf, 5);
	ei_x_encode_atom(&argbuf,"select");
	ei_x_encode_atom_len(&argbuf,CON_TABLE(_h)->s,CON_TABLE(_h)->len);

	srdb1_encode_c(_c, _nc, &argbuf);
	srdb1_encode_k(_k, _op, _v, _n, &argbuf);
//	ei_x_encode_atom_len(&argbuf,_o->s,_o->len);
	ei_x_encode_list_header(&argbuf, 0);

	retcode=erl_bind.do_erlang_call(&(CON_ERLANG(_h)->con),&(CON_ERLANG(_h)->regname), &argbuf, &retbuf);
	ei_x_free(&argbuf);
	if (retcode<0) {
		if(retbuf.buff) shm_free(retbuf.buff);
		return retcode;
	}
	// we have a tuple there:
	ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &i);
	x=retbuf.index;
	ei_skip_term(retbuf.buff, &x);
	LM_DBG("erlang_srdb1_query: position of end of field list should be %d\n",x);
	//first is list of 5-element tuples containing name and type of field
	ei_decode_list_header(retbuf.buff, &(retbuf.index), &n_cols);
	LM_DBG("erlang_srdb1_query: length -f field_list is %d\n",n_cols);
	res=db_new_result();
	if (db_allocate_columns(res, n_cols) != 0) {
		LM_ERR("erlang_srdb1_query: db_allocate_columns failed\n");
		goto error;
	}
	RES_COL_N(res) = n_cols;
	for(i=0; i < n_cols; i++) {
		x=retbuf.index;
		ei_skip_term(retbuf.buff, &x);
		LM_DBG("erlang_srdb1_query: position of end of this field should be %d\n",x);
		ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &j);
		if( j!=5) LM_ERR("erlang_srdb1_query name&type list element tuple is not 5\n");
		ei_decode_atom(retbuf.buff, &(retbuf.index), atom);  //1  name
		len=strlen(atom);
		sname = (str*)pkg_malloc(sizeof(str)+len+1);
		if (!sname) {
			LM_ERR("no private memory left\n");
			goto error;
		}
		sname->len = len;
		sname->s = (char*)sname + sizeof(str);
		memcpy(sname->s, atom, len);
		sname->s[len] = '\0';
		RES_NAMES(res)[i] = sname;
		LM_DBG("decoded header %d, fieled 1: %s\n",i,atom);
		ei_decode_atom(retbuf.buff, &(retbuf.index), atom); //2 type atom
		if(strcmp("int",atom)==0) { RES_TYPES(res)[i]=DB1_INT; }
		if(strcmp("string",atom)==0) { RES_TYPES(res)[i]=DB1_STRING; }
		if(strcmp("float",atom)==0) { RES_TYPES(res)[i]=DB1_DOUBLE; }
		if(strcmp("datetime",atom)==0) { RES_TYPES(res)[i]=DB1_DATETIME; }
//		if(strcmp("string",atom)==0) { RES_TYPES(res)[i]=DB1_BLOB; }
		ei_skip_term(retbuf.buff, &(retbuf.index));  //3 size (ignored)
		ei_skip_term(retbuf.buff, &(retbuf.index));  //4 default value (ignored)
		ei_skip_term(retbuf.buff, &(retbuf.index));  //3 null status (ignored)
		LM_DBG("end of %d record: %d\n",i,retbuf.index);
	}
	ei_decode_ei_term(retbuf.buff, &(retbuf.index), &term); // List tail,
	LM_DBG("erlang_srdb1_query: position after scanning is %d\n",retbuf.index);
	//now rows, list of tuples
	ei_decode_list_header(retbuf.buff, &(retbuf.index), &n_rows);
	LM_DBG("erlang_srdb1_query values list size is %d\n",n_rows);
	if (n_rows<=0) {
		LM_DBG("erlang_srdb1_query no rows returned\n");
		RES_ROWS(res) = NULL;
		RES_NUM_ROWS(res)=0;
		*_r=res;
		return 0;
	}
	RES_NUM_ROWS(res)=n_rows;
	rows = pkg_realloc(rows, sizeof(db_row_t) * n_rows);
	if (rows == NULL) {
		LM_ERR("erlang_srdb1_query: pkg_realloc rows failed\n");
		goto error;
	}
	RES_ROWS(res) = rows;
	for(i=0; i < n_rows; i++) {
		RES_ROW_N(res)=i+1;
		row = &RES_ROWS(res)[i];
		if (db_allocate_row(res, row) != 0) {
			LM_ERR("erlang_srdb1_query: db_allocate_row failed for row %d\n",i);
			goto error;
		}
		ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &j);
		if(j!=n_cols) {
			LM_ERR("erlang_srdb1_query: mismatch:values list element tuple size is %d n_cols from header was %d\n",j, n_cols);
		}
		for (j = 0, val = ROW_VALUES(row); j < RES_COL_N(res); j++, val++) {
			VAL_TYPE(val) = RES_TYPES(res)[j];
			VAL_NULL(val) = 0;
			VAL_FREE(val) = 0;
			retcode=ei_get_type_internal(retbuf.buff, &(retbuf.index), &ei_type, &size);
			if (retcode < 0) {
				LM_ERR("erlang_srdb1_query: error getting type for element %d %d\n",i,j);
				goto error;
			}
			LM_DBG("erlang_srdb1_query: element %d %d ei_type=%d size=%d\n",i,j,ei_type, size);
			switch(ei_type) {
				case ERL_SMALL_INTEGER_EXT:
				case ERL_INTEGER_EXT:
					retcode=ei_decode_long(retbuf.buff, &(retbuf.index), &VAL_INT(val));
					if(retcode < 0) goto error;
					LM_DBG("decoded interger %d\n",VAL_INT(val));
					break;
				case ERL_FLOAT_EXT:
				case NEW_FLOAT_EXT:
					retcode=ei_decode_double(retbuf.buff, &(retbuf.index), &VAL_DOUBLE(val));
					if(retcode < 0) goto error;
					LM_DBG("decoded float %f\n",VAL_DOUBLE(val));
					break;
				case ERL_ATOM_EXT:
				case ERL_SMALL_ATOM_EXT:
				case ERL_ATOM_UTF8_EXT:
				case ERL_SMALL_ATOM_UTF8_EXT:
					p=pkg_malloc(size+1);
					if(!p) { LM_ERR("erlang_srdb1_query: no memory\n"); goto error; }
					retcode=ei_decode_atom(retbuf.buff, &(retbuf.index), p);
					if(retcode < 0) {
						pkg_free(p);
						goto error;
					}
					LM_DBG("decoded small_atom_utf %s\n",p);
					VAL_STRING(val)=p;
					VAL_FREE(val)=1;
					break;
				case ERL_STRING_EXT:
					p=pkg_malloc(size+1);
					if(!p) { LM_ERR("erlang_srdb1_query: no memory\n"); goto error; }
					retcode=ei_decode_string(retbuf.buff, &(retbuf.index), p);
					if(retcode < 0) {
						pkg_free(p);
						goto error;
					}
					LM_DBG("decoded string %s\n",p);
					VAL_STRING(val)=p;
					VAL_FREE(val)=1;
					break;
				case ERL_SMALL_TUPLE_EXT:
				case ERL_LARGE_TUPLE_EXT:
					LM_DBG("got tuple)\n");
					if (VAL_TYPE(val)==DB1_DATETIME) {
					    struct tm tm;
					    LM_DBG("and col type is datetime\n");
					    retcode=ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &x);
					    if(retcode < 0) goto error;
					    retcode=ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &x);
					    if(retcode < 0) goto error;
					    retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_year);tm.tm_year -=1900;
					    if(retcode < 0) goto error;
					    retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_mon); tm.tm_mon -=1;
					    if(retcode < 0) goto error;
					    retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_mday);
					    if(retcode < 0) goto error;
					    retcode=ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &x);
					    if(retcode < 0) goto error;
					    retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_hour);
					    if(retcode < 0) goto error;
					    retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_min);
					    if(retcode < 0) goto error;
					    retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_sec);
					    if(retcode < 0) goto error;
					    VAL_TIME(val)=mktime(&tm);
					    break;
					}
					LM_ERR("erlang_srdb1_query: got tuple but valtype is not datetime element %d in row %d in response\n",j,i);
					break;
				case ERL_REFERENCE_EXT:
				case ERL_NEW_REFERENCE_EXT:
				case ERL_PORT_EXT:
				case ERL_PID_EXT:
				case ERL_NIL_EXT:
				case ERL_LIST_EXT:
				case ERL_BINARY_EXT:
				case ERL_SMALL_BIG_EXT:
				case ERL_LARGE_BIG_EXT:
				case ERL_NEW_FUN_EXT:
				case ERL_FUN_EXT:
				default:
				    LM_ERR("erlang_srdb1_query: don't know how to handle element %d in row %d in response\n",j,i);
			}
		}
	}
	ei_decode_ei_term(retbuf.buff, &(retbuf.index), &term); // List tail,
	*_r=res;
	return 0;
error:
	if (res)
		db_free_result(res);
	LM_ERR("erlang_srdb1_query: Failed\n");
	return -1;
}