Exemplo n.º 1
0
/* This function extracts meta-info from the sip_msg structure and
 * formats it so that it can be used to rapidly access the message structured
 * parts.
 *
 * RETURNS: LENGTH of structure on success, <0 if failure
 * if there was failure, you don't need to pkg_free the payload (it is done inside).
 * if there was success, you __NEED_TO_PKG_FREE_THE_PAYLOAD__ from the calling function.
 *
 * The encoded meta-info is composed by 3 sections:
 *
 * MSG_META_INFO:
 * 2: short int in network-byte-order, if <100, the msg is a REQUEST and the int
 * is the code of the METHOD. if >100, it is a RESPONSE and the int is the code
 * of the response.
 * 2: short int in NBO: payload-start based pointer (index) to where the SIP MSG starts.
 * 2: short int in NBO: the sip-message length
 * 2: METHOD or CODE string SIP-START-based pointer and length
 * 2: R-URI or REASON PHRASE string SIP-START-based pointer and length
 * 2: VERSION string SIP-START-based pointer and length
 * 2: short int in NBO: start of the content of the SIP message
 * [1+N]: in case this is a request, the length of the encoded-uri and the encoded-uri
 * 1: how many present headers have been found.
 *
 * MSG_HEADERS_INDEX:
 * N*3: groups of 3 bytes, each one describing a header struct: the first byte
 * is a letter that corresponds to a header type, the second and third bytes are a NBO
 * inidex to where this struct begins within the HEADERS_META_INFO section.
 *
 * HEADERS_META_INFO:
 * M: all the codified headers meta info structs one after another
 *
 * SIP_MSG:
 * the SIP message as it has been received.
 *
 * The length of the structure, will be ((short*)payload)[1] + ((short*)payload)[2]
 *
 * TODO: msg->parsed_uri msg->parsed_orig_uri_ok, msg->first_line->u.request.uri
 * buggy and little bit fuzzy
 */
int encode_msg(struct sip_msg *msg,char *payload,int len)
{
   int i,j,k,u,request;
   unsigned short int h;
   struct hdr_field* hf;
   struct msg_start* ms;
   struct sip_uri miuri;
   char *myerror=NULL;
   ptrdiff_t diff;
   str body = {NULL,0};

   if(len < MAX_ENCODED_MSG + MAX_MESSAGE_LEN)
      return -1;
   if(parse_headers(msg,HDR_EOH_F,0)<0){
      myerror="in parse_headers";
      goto error;
   }
   memset(payload,0,len);
   ms=&msg->first_line;
	if(ms->type == SIP_REQUEST)
		request=1;
	else if(ms->type == SIP_REPLY)
		request=0;
	else{
		myerror="message is neither request nor response";
		goto error;
	}
	if(request) {
		for(h=0,j=1;h<32;j=(0x01<<h),h++)
			if(j & ms->u.request.method_value)
				break;
	} else {
		h=(unsigned short)(ms->u.reply.statuscode);
	}
   if(h==32){/*statuscode wont be 32...*/
      myerror="unknown message type\n";
      goto error;
   }
   h=htons(h);
   /*first goes the message code type*/
   memcpy(payload,&h,2);
   h=htons((unsigned short int)msg->len);
   /*then goes the message start idx, but we'll put it later*/
   /*then goes the message length (we hope it to be less than 65535 bytes...)*/
   memcpy(&payload[MSG_LEN_IDX],&h,2);
   /*then goes the content start index (starting from SIP MSG START)*/
   if (get_body(msg,&body) < 0) {
      myerror="body parsing failed";
      goto error;
   }
   if(0>(diff=(body.s-msg->buf))){
      myerror="body starts before the message (uh ?)";
      goto error;
   }else
      h=htons((unsigned short int)diff);
   memcpy(payload+CONTENT_IDX,&h,2);
   payload[METHOD_CODE_IDX]=(unsigned char)(request?
	 (ms->u.request.method.s-msg->buf):
	 (ms->u.reply.status.s-msg->buf));
   payload[METHOD_CODE_IDX+1]=(unsigned char)(request?
	 (ms->u.request.method.len):
	 (ms->u.reply.status.len));
   payload[URI_REASON_IDX]=(unsigned char)(request?
	 (ms->u.request.uri.s-msg->buf):
	 (ms->u.reply.reason.s-msg->buf));
   payload[URI_REASON_IDX+1]=(unsigned char)(request?
	 (ms->u.request.uri.len):
	 (ms->u.reply.reason.len));
   payload[VERSION_IDX]=(unsigned char)(request?
	 (ms->u.request.version.s-msg->buf):
	 (ms->u.reply.version.s-msg->buf));
   if(request){
      if (parse_uri(ms->u.request.uri.s,ms->u.request.uri.len, &miuri)<0){
	 LM_ERR("<%.*s>\n",ms->u.request.uri.len,ms->u.request.uri.s);
	 myerror="while parsing the R-URI";
	 goto error;
      }
      if(0>(j=encode_uri2(msg->buf,
		  ms->u.request.method.s-msg->buf+ms->len,
		  ms->u.request.uri,&miuri,
		  (unsigned char*)&payload[REQUEST_URI_IDX+1])))
      {
	    myerror="ENCODE_MSG: ERROR while encoding the R-URI";
	    goto error;
      }
      payload[REQUEST_URI_IDX]=(unsigned char)j;
      k=REQUEST_URI_IDX+1+j;
   }else
      k=REQUEST_URI_IDX;
   u=k;
   k++;
   for(i=0,hf=msg->headers;hf;hf=hf->next,i++);
   i++;/*we do as if there was an extra header, that marks the end of
	 the previous header in the headers hashtable(read below)*/
   j=k+3*i;
   for(i=0,hf=msg->headers;hf;hf=hf->next,k+=3){
      payload[k]=(unsigned char)(hf->type & 0xFF);
      h=htons(j);
      /*now goes a payload-based-ptr to where the header-code starts*/
      memcpy(&payload[k+1],&h,2);
      /*TODO fix this... fixed with k-=3?*/
      if(0>(i=encode_header(msg,hf,(unsigned char*)(payload+j),MAX_ENCODED_MSG+MAX_MESSAGE_LEN-j))){
	 LM_ERR("encoding header %.*s\n",hf->name.len,hf->name.s);
	 goto error;
	 /* XXX: not sure if this should be considered or not, but the code is
	  * not executed anyway; commenting it for now.
	 k-=3;
	 continue;
	 */
      }
      j+=(unsigned short int)i;
   }
   /*now goes the number of headers that have been found, right after the meta-msg-section*/
   payload[u]=(unsigned char)((k-u-1)/3);
   j=htons(j);
   /*now copy the number of bytes that the headers-meta-section has occupied,right afther
    * headers-meta-section(the array with ['v',[2:where],'r',[2:where],'R',[2:where],...]
    * this is to know where the LAST header ends, since the length of each header-struct
    * is calculated substracting the nextHeaderStart - presentHeaderStart
    * the k+1 is because payload[k] is usually the letter*/
   memcpy(&payload[k+1],&j,2);
   k+=3;
   j=ntohs(j);
   /*now we copy the headers-meta-section after the msg-headers-meta-section*/
   /*memcpy(&payload[k],payload2,j);*/
   /*j+=k;*/
   /*pkg_free(payload2);*/
   /*now we copy the actual message after the headers-meta-section*/
   memcpy(&payload[j],msg->buf,msg->len);
   LM_DBG("msglen = %d,msg starts at %d\n",msg->len,j);
   j=htons(j);
   /*now we copy at the beginning, the index to where the actual message starts*/
   memcpy(&payload[MSG_START_IDX],&j,2);
   return GET_PAY_SIZE( payload );
error:
   LM_ERR("%s\n",myerror);
   return -1;
}
Exemplo n.º 2
0
/**
 * @brief Initialize async module children
 */
static int child_init(int rank)
{
	int pid;
	int i;

	LM_DBG("child initializing async http\n");

	if(num_workers<=0)
		return 0;

	/* initialize query counter and id */
	q_idx = 0;
	q_id[0] = '\0';

	if (rank==PROC_INIT) {
		for(i=0; i<num_workers; i++) {
			LM_DBG("initializing worker notification socket: %d\n", i);
			if(async_http_init_sockets(&workers[i])<0) {
				LM_ERR("failed to initialize tasks sockets\n");
				return -1;
			}
		}

		return 0;
	}

	if(rank>0) {
		for(i=0; i<num_workers; i++) {
			close(workers[i].notication_socket[0]);
		}
		return 0;
	}
	if (rank!=PROC_MAIN)
		return 0;

	for(i=0; i<num_workers; i++) {
		if(async_http_init_worker(i+1, &workers[i])<0) {
			LM_ERR("failed to initialize worker process: %d\n", i);
			return -1;
		}
		pid=fork_process(PROC_RPC, "Http Async Worker", 1);
		if (pid<0)
			return -1; /* error */
		if(pid==0) {
			/* child */
			/* enforce http_reply_parse=yes */
			http_reply_parse = 1;
			/* initialize the config framework */
			if (cfg_child_init())
				return -1;
			/* init msg structure for http reply parsing */
			ah_reply = pkg_malloc(sizeof(struct sip_msg));
			if(!ah_reply) {
				LM_ERR("failed to allocate pkg memory\n");
				return -1;
			}
			memset(ah_reply, 0, sizeof(struct sip_msg));
			/* main function for workers */
			async_http_run_worker(&workers[i]);
		}
	}

	return 0;
}
Exemplo n.º 3
0
static int ah_set_req(struct sip_msg* msg, pv_param_t *param,
		int op, pv_value_t *val)
{
	pv_value_t *tval;

	if(param==NULL || tmb.t_request==NULL)
		return -1;

	tval = val;
	if((tval!=NULL) && (tval->flags&PV_VAL_NULL)) {
		tval = NULL;
	}

	switch((enum http_req_name_t) param->pvn.u.isname.name.n) {
	case E_HRN_ALL:
		if (tval == NULL)
			set_query_params(&ah_params);
		break;
	case E_HRN_HDR:
		if (tval) {
			if (!(tval->flags & PV_VAL_STR)) {
				LM_ERR("invalid value type for $http_req(hdr)\n");
				return -1;
			}
			header_list_add(&ah_params.headers, &tval->rs);
		}
		break;
	case E_HRN_METHOD:
		if (tval) {
			if (!(tval->flags & PV_VAL_STR)) {
				LM_ERR("invalid value type for $http_req(method)\n");
				return -1;
			}
			query_params_set_method(&ah_params, &tval->rs);
		} else {
			ah_params.method = AH_METH_DEFAULT;
		}
		break;
	case E_HRN_TIMEOUT:
		if (tval) {
			if (!(tval->flags & PV_VAL_INT)) {
				LM_ERR("invalid value type for $http_req(timeout)\n");
				return -1;
			}
			ah_params.timeout = tval->ri;
		} else {
			ah_params.timeout = http_timeout;
		}
		break;
	case E_HRN_TLS_CA_PATH:
		if (tval) {
			if (!(tval->flags & PV_VAL_STR)) {
				LM_ERR("invalid value type for $http_req(tls_ca_path)\n");
				return -1;
			}
			set_query_cparam(&ah_params.tls_ca_path, tval->rs);
		}
		break;
	case E_HRN_TLS_CLIENT_KEY:
		if (tval) {
			if (!(tval->flags & PV_VAL_STR)) {
				LM_ERR("invalid value type for $http_req(tls_client_key)\n");
				return -1;
			}
			set_query_cparam(&ah_params.tls_client_key, tval->rs);
		}
		break;
	case E_HRN_TLS_CLIENT_CERT:
		if (tval) {
			if (!(tval->flags & PV_VAL_STR)) {
				LM_ERR("invalid value type for $http_req(tls_client_cert)\n");
				return -1;
			}
			set_query_cparam(&ah_params.tls_client_cert, tval->rs);
		}
		break;
	case E_HRN_SUSPEND:
		if (tval) {
			if (!(tval->flags & PV_VAL_INT)) {
				LM_ERR("invalid value type for $http_req(suspend)\n");
				return -1;
			}
			ah_params.suspend_transaction = tval->ri?1:0;
		} else {
			ah_params.suspend_transaction = 1;
		}
		break;
	case E_HRN_BODY:
		if (tval) {
			if (!(tval->flags & PV_VAL_STR)) {
				LM_ERR("invalid value type for $http_req(body)\n");
				return -1;
			}
			set_query_param(&ah_params.body, tval->rs);
		}
		break;
	case E_HRN_AUTHMETHOD:
		if (tval) {
			if (!(tval->flags & PV_VAL_INT)) {
				LM_ERR("invalid value type for $http_req(authmethod)\n");
				return -1;
			}
			ah_params.authmethod = tval->ri;
		} else {
			ah_params.authmethod = default_authmethod;
		}
		break;
	case E_HRN_USERNAME:
		if (tval) {
			if (!(tval->flags & PV_VAL_STR)) {
				LM_ERR("invalid value type for $http_req(username)\n");
				return -1;
			}
			set_query_cparam(&ah_params.username, tval->rs);
		}
		break;
	case E_HRN_PASSWORD:
		if (tval) {
			if (!(tval->flags & PV_VAL_STR)) {
				LM_ERR("invalid value type for $http_req(password)\n");
				return -1;
			}
			set_query_cparam(&ah_params.password, tval->rs);
		}
		break;
	}

	return 1;
}
Exemplo n.º 4
0
/* parses the first line, returns pointer to  next line  & fills fl;
   also  modifies buffer (to avoid extra copy ops) */
char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl)
{

	char *tmp;
	char* second;
	char* third;
	char* nl;
	unsigned int offset;
	/* int l; */
	char* end;
	char s1,s2,s3;
	char *prn;
	unsigned int t;

	/* grammar:
		request  =  method SP uri SP version CRLF
		response =  version SP status  SP reason  CRLF
		(version = "SIP/2.0")
	*/


	end=buffer+len;
	/* see if it's a reply (status) */

	/* jku  -- parse well-known methods */

	/* drop messages which are so short they are for sure useless;
           utilize knowledge of minimum size in parsing the first
	   token
        */
	if (len <=16 ) {
		LM_INFO("message too short: %d\n", len);
		goto error1;
	}

	tmp=buffer;
  	/* is it perhaps a reply, ie does it start with "SIP...." ? */
	if ( 	(*tmp=='S' || *tmp=='s') &&
		strncasecmp( tmp+1, SIP_VERSION+1, SIP_VERSION_LEN-1)==0 &&
		(*(tmp+SIP_VERSION_LEN)==' ')) {
			fl->type=SIP_REPLY;
			fl->u.reply.version.len=SIP_VERSION_LEN;
			tmp=buffer+SIP_VERSION_LEN;
	} else IFISMETHOD( INVITE, 'I' )
	else IFISMETHOD( CANCEL, 'C')
	else IFISMETHOD( ACK, 'A' )
	else IFISMETHOD( BYE, 'B' )
	else IFISMETHOD( INFO, 'I' )
	/* if you want to add another method XXX, include METHOD_XXX in
           H-file (this is the value which you will take later in
           processing and define XXX_LEN as length of method name;
	   then just call IFISMETHOD( XXX, 'X' ) ... 'X' is the first
	   latter; everything must be capitals
	*/
	else {
		/* neither reply, nor any of known method requests,
		   let's believe it is an unknown method request
        	*/
		tmp=eat_token_end(buffer,buffer+len);
		if ((tmp==buffer)||(tmp>=end)){
			LM_INFO("empty  or bad first line\n");
			goto error1;
		}
		if (*tmp!=' ') {
			LM_INFO("method not followed by SP\n");
			goto error1;
		}
		fl->type=SIP_REQUEST;
		/* see if it is another known method */
		/* fl->u.request.method_value=METHOD_OTHER; */
		if(parse_method(buffer, tmp,
				(unsigned int*)&fl->u.request.method_value)==0)
		{
			LM_INFO("failed to parse the method\n");
			goto error1;
		}
		fl->u.request.method.len=tmp-buffer;
	}


	/* identifying type of message over now;
	   tmp points at space after; go ahead */

	fl->u.request.method.s=buffer;  /* store ptr to first token */
	second=tmp+1;			/* jump to second token */
	offset=second-buffer;

/* EoJku */

	/* next element */
	tmp=eat_token_end(second, second+len-offset);
	if (tmp>=end){
		goto error;
	}
	offset+=tmp-second;
	third=eat_space_end(tmp, tmp+len-offset);
	offset+=third-tmp;
	if ((third==tmp)||(tmp>=end)){
		goto error;
	}
	fl->u.request.uri.s=second;
	fl->u.request.uri.len=tmp-second;

	/* jku: parse status code */
	if (fl->type==SIP_REPLY) {
		if (fl->u.request.uri.len!=3) {
			LM_INFO("len(status code)!=3: %.*s\n",
				fl->u.request.uri.len, ZSW(second) );
			goto error;
		}
		s1=*second; s2=*(second+1);s3=*(second+2);
		if (s1>='0' && s1<='9' &&
		    s2>='0' && s2<='9' &&
		    s3>='0' && s3<='9' ) {
			fl->u.reply.statuscode=(s1-'0')*100+10*(s2-'0')+(s3-'0');
		} else {
			LM_INFO("status_code non-numerical: %.*s\n",
				fl->u.request.uri.len, ZSW(second) );
			goto error;
		}
	}
	/* EoJku */

	/*  last part: for a request it must be the version, for a reply
	 *  it can contain almost anything, including spaces, so we don't care
	 *  about it*/
	if (fl->type==SIP_REQUEST){
		tmp=eat_token_end(third,third+len-offset);
		offset+=tmp-third;
		if ((tmp==third)||(tmp>=end)){
			goto error;
		}
		if (! is_empty_end(tmp, tmp+len-offset)){
			goto error;
		}
	}else{
		tmp=eat_token2_end(third,third+len-offset,'\r'); /* find end of line
												  ('\n' or '\r') */
		if (tmp>=end){ /* no crlf in packet => invalid */
			goto error;
		}
		offset+=tmp-third;
	}
	nl=eat_line(tmp,len-offset);
	if (nl>=end){ /* no crlf in packet or only 1 line > invalid */
		goto error;
	}
	fl->u.request.version.s=third;
	fl->u.request.version.len=tmp-third;
	fl->len=nl-buffer;

	return nl;

error:
	LM_ERR("bad %s first line\n",
		(fl->type==SIP_REPLY)?"reply(status)":"request");

	LM_ERR("at line 0 char %d: \n", offset );
	prn=pkg_malloc( offset );
	if (prn) {
		for (t=0; t<offset; t++)
			if (*(buffer+t)) *(prn+t)=*(buffer+t);
			else *(prn+t)='°';
		LM_ERR("parsed so far: %.*s\n", offset, ZSW(prn) );
		pkg_free( prn );
	};
error1:
	fl->type=SIP_INVALID;
	LM_INFO("bad message\n");
	/* skip  line */
	nl=eat_line(buffer,len);
	return nl;
}
Exemplo n.º 5
0
void async_cdp_callback(int is_timeout, void *param, AAAMessage *saa, long elapsed_msecs) {
    struct cell *t = 0;
    int rc = -1, experimental_rc = -1;
    int result = CSCF_RETURN_TRUE;
    saved_transaction_t* data = 0;

    str xml_data = {0, 0}, ccf1 = {0, 0}, ccf2 = {0, 0}, ecf1 = {0, 0}, ecf2 = {0, 0};
    ims_subscription* s = 0;
    rerrno = R_FINE;

    if (!param) {
        LM_DBG("No transaction data this must have been called from usrloc cb impu deleted - just log result code and then exit");
        cxdx_get_result_code(saa, &rc);
        cxdx_get_experimental_result_code(saa, &experimental_rc);

        if (saa) cdpb.AAAFreeMessage(&saa);

        if (!rc && !experimental_rc) {
            LM_ERR("bad SAA result code\n");
            return;
        }
        switch (rc) {
            case -1:
                LM_DBG("Received Diameter error\n");
                return;

            case AAA_UNABLE_TO_COMPLY:
                LM_DBG("Unable to comply\n");
                return;

            case AAA_SUCCESS:
                LM_DBG("received AAA success\n");
                return;

            default:
                LM_ERR("Unknown error\n");
                return;
        }

    } else {
        LM_DBG("There is transaction data this must have been called from save or assign server unreg");
        data = (saved_transaction_t*) param;
        if (tmb.t_lookup_ident(&t, data->tindex, data->tlabel) < 0) {
            LM_ERR("t_continue: transaction not found\n");
            rerrno = R_SAR_FAILED;
            goto error_no_send;
        }

        get_act_time();

        if (is_timeout) {
        	update_stat(stat_sar_timeouts, 1);
            LM_ERR("Transaction timeout - did not get SAA\n");
            rerrno = R_SAR_FAILED;
            goto error;
        }
        if (!saa) {
            LM_ERR("Error sending message via CDP\n");
            rerrno = R_SAR_FAILED;
            goto error;
        }

        update_stat(sar_replies_received, 1);
        update_stat(sar_replies_response_time, elapsed_msecs);

        /* check and see that all the required headers are available and can be parsed */
        if (parse_message_for_register(t->uas.request) < 0) {
            LM_ERR("Unable to parse register message correctly\n");
            rerrno = R_SAR_FAILED;
            goto error;
        }

        cxdx_get_result_code(saa, &rc);
        cxdx_get_experimental_result_code(saa, &experimental_rc);
        cxdx_get_charging_info(saa, &ccf1, &ccf2, &ecf1, &ecf2);

        if (!rc && !experimental_rc) {
            LM_ERR("bad SAA result code\n");
            rerrno = R_SAR_FAILED;
            goto error;
        }

        switch (rc) {
            case -1:
                LM_DBG("Received Diameter error\n");
                rerrno = R_SAR_FAILED;
                goto error;

            case AAA_UNABLE_TO_COMPLY:
                LM_DBG("Unable to comply\n");
                rerrno = R_SAR_FAILED;
                goto error;

            case AAA_SUCCESS:
                LM_DBG("received AAA success\n");
                break;

            default:
                LM_ERR("Unknown error\n");
                rerrno = R_SAR_FAILED;
                goto error;
        }
        //success
        //if this is from a save (not a server assign unreg) and expires is zero we don't update usrloc as this is a dereg and usrloc was updated previously
        if (data->sar_assignment_type != AVP_IMS_SAR_UNREGISTERED_USER && data->expires == 0) {
            LM_DBG("no need to update usrloc - already done for de-reg\n");
            result = CSCF_RETURN_TRUE;
            goto success;
        }

        xml_data = cxdx_get_user_data(saa);
        /*If there is XML user data we must be able to parse it*/
        if (xml_data.s && xml_data.len > 0) {
            LM_DBG("Parsing user data string from SAA\n");
            s = parse_user_data(xml_data);
            if (!s) {
                LM_ERR("Unable to parse user data XML string\n");
                rerrno = R_SAR_FAILED;
                goto error;
            }
            LM_DBG("Successfully parse user data XML\n");
        } else {
            if (data->require_user_data) {
                LM_ERR("We require User data for this assignment/register and none was supplied\n");
                rerrno = R_SAR_FAILED;
                result = CSCF_RETURN_FALSE;
                goto done;
            }
        }

        if (data->sar_assignment_type == AVP_IMS_SAR_REGISTRATION || data->sar_assignment_type == AVP_IMS_SAR_RE_REGISTRATION) {
            if (build_p_associated_uri(s) != 0) {
                LM_ERR("Unable to build p_associated_uri\n");
                rerrno = R_SAR_FAILED;
                goto error;
            }
        }

        //here we update the contacts and also build the new contact header for the 200 OK reply
        if (update_contacts_new(t->uas.request, data->domain, &data->public_identity, data->sar_assignment_type, &s, &ccf1, &ccf2, &ecf1, &ecf2, &data->contact_header) <= 0) {
            LM_ERR("Error processing REGISTER\n");
            rerrno = R_SAR_FAILED;
            goto error;
        }
        
        if (data->contact_header) {
            LM_DBG("Updated contacts: %.*s\n", data->contact_header->data_len, data->contact_header->buf);
        } else {
            LM_DBG("Updated unreg contact\n");
        }
        
    }

success:
    update_stat(accepted_registrations, 1);

done:
    if (data->sar_assignment_type != AVP_IMS_SAR_UNREGISTERED_USER)
        reg_send_reply_transactional(t->uas.request, data->contact_header, t);
    LM_DBG("DBG:SAR Async CDP callback: ... Done resuming transaction\n");
    set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &t->uri_avps_from);
    set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &t->uri_avps_to);
    set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &t->user_avps_from);
    set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &t->user_avps_to);
    set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &t->domain_avps_from);
    set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &t->domain_avps_to);

    create_return_code(result);

    //free memory
    if (saa) cdpb.AAAFreeMessage(&saa);
    if (t) {
        del_nonshm_lump_rpl(&t->uas.request->reply_lump);
        tmb.unref_cell(t);
    }
    //free path vector pkg memory
    reset_path_vector(t->uas.request);

    tmb.t_continue(data->tindex, data->tlabel, data->act);
    free_saved_transaction_data(data);
    return;

error:
    if (data->sar_assignment_type != AVP_IMS_SAR_UNREGISTERED_USER)
        reg_send_reply_transactional(t->uas.request, data->contact_header, t);

error_no_send: //if we don't have the transaction then we can't send a transaction response
    update_stat(rejected_registrations, 1);
    //free memory
    if (saa) cdpb.AAAFreeMessage(&saa);
    if (t) {
        del_nonshm_lump_rpl(&t->uas.request->reply_lump);
        tmb.unref_cell(t);
    }
    tmb.t_continue(data->tindex, data->tlabel, data->act);
    free_saved_transaction_data(data);
    return;
}
Exemplo n.º 6
0
/**
 * Receive a file descriptor from another process
 * @param pipe_fd - pipe to read from
 * @param fd - file descriptor to fill
 * @param p - optional pipe to fill
 * @returns 1 on success or 0 on failure
 */
static int receive_fd(int pipe_fd, int* fd,peer **p)
{
	struct msghdr msg;
	struct iovec iov[1];
	int new_fd;
	int ret;

#ifdef HAVE_MSGHDR_MSG_CONTROL
	struct cmsghdr* cmsg;
	union{
		struct cmsghdr cm;
		char control[CMSG_SPACE(sizeof(new_fd))];
	}control_un;

	msg.msg_control=control_un.control;
	msg.msg_controllen=sizeof(control_un.control);
#else
	msg.msg_accrights=(caddr_t) &new_fd;
	msg.msg_accrightslen=sizeof(int);
#endif

	msg.msg_name=0;
	msg.msg_namelen=0;

	iov[0].iov_base=p;
	iov[0].iov_len=sizeof(peer*);
	msg.msg_iov=iov;
	msg.msg_iovlen=1;

again:
	ret=recvmsg(pipe_fd, &msg, MSG_DONTWAIT|MSG_WAITALL);
	if (ret<0){
		if (errno==EINTR) goto again;
		if ((errno==EAGAIN)||(errno==EWOULDBLOCK)) goto error;
		LM_CRIT( "receive_fd: recvmsg on %d failed: %s\n",
				pipe_fd, strerror(errno));
		goto error;
	}
	if (ret==0){
		/* EOF */
		LM_CRIT( "receive_fd: EOF on %d\n", pipe_fd);
		goto error;
	}
	if (ret!=sizeof(peer *)){
		LM_WARN("receive_fd: different number of bytes received than expected (%d from %ld)"
				"trying to fix...\n", ret, (long int)sizeof(peer*));
		goto error;
	}

#ifdef HAVE_MSGHDR_MSG_CONTROL
	cmsg=CMSG_FIRSTHDR(&msg);
	if ((cmsg!=0) && (cmsg->cmsg_len==CMSG_LEN(sizeof(new_fd)))){
		if (cmsg->cmsg_type!= SCM_RIGHTS){
			LM_ERR("receive_fd: msg control type != SCM_RIGHTS\n");
			goto error;
		}
		if (cmsg->cmsg_level!= SOL_SOCKET){
			LM_ERR("receive_fd: msg level != SOL_SOCKET\n");
			goto error;
		}
		*fd=*((int*) CMSG_DATA(cmsg));
	}else{
		if(!cmsg)
			LM_ERR("receive_fd: no descriptor passed, empty control message");
		else
			LM_ERR("receive_fd: no descriptor passed, cmsg=%p,"
					"len=%d\n", cmsg, (unsigned)cmsg->cmsg_len);
		*fd=-1;
		*p=0;
		/* it's not really an error */
	}
#else
	if (msg.msg_accrightslen==sizeof(int)){
		*fd=new_fd;
	}else{
		LM_ERR("receive_fd: no descriptor passed,"
				" accrightslen=%d\n", msg.msg_accrightslen);
		*fd=-1;
	}
#endif

	return 1;
error:
	return 0;
}
Exemplo n.º 7
0
/**
 * Selects once on sockets for receiving and sending stuff.
 * Monitors:
 *  - the fd exchange pipe, for receiving descriptors to be handled here
 *  - the tcp sockets of all serviced peers, triggering the incoming messages do_receive()
 *  - the send pipes of all serviced peers, triggering the sending of outgoing messages
 * @returns 0 on normal exit or -1 on error
 */
int receive_loop(peer *original_peer)
{
	fd_set rfds,efds;
	struct timeval tv;
	int n,max=0,cnt=0;
	AAAMessage *msg=0;
	serviced_peer_t *sp,*sp2;
	peer *p;
	int fd=-1;
	int fd_exchange_pipe_local=0;

	if (original_peer) fd_exchange_pipe_local = original_peer->fd_exchange_pipe_local;
	else fd_exchange_pipe_local = fd_exchange_pipe_unknown_local;

	//	if (shutdownx) return -1;

	while(shutdownx&&!*shutdownx){
		n = 0;

		while(!n){
			if (shutdownx&&*shutdownx) break;
			cfg_update();

			log_serviced_peers();

			max =-1;

			FD_ZERO(&rfds);
			FD_ZERO(&efds);

			FD_SET(fd_exchange_pipe_local,&rfds);
			if (fd_exchange_pipe_local>max) max = fd_exchange_pipe_local;

			for(sp=serviced_peers;sp;sp=sp->next){
				if (sp->tcp_socket>=0){
					FD_SET(sp->tcp_socket,&rfds);
					FD_SET(sp->tcp_socket,&efds);
					if (sp->tcp_socket>max) max = sp->tcp_socket;
				}
				if (sp->send_pipe_fd>=0) {
					FD_SET(sp->send_pipe_fd,&rfds);
					if (sp->send_pipe_fd>max) max = sp->send_pipe_fd;
				}
			}

			tv.tv_sec=1;
			tv.tv_usec=0;

			n = select(max+1,&rfds,0,&efds,&tv);
			if (n==-1){
				if (shutdownx&&*shutdownx) return 0;
				LM_ERR("select_recv(): %s\n",strerror(errno));
				for(sp=serviced_peers;sp;sp=sp2){
					sp2 = sp->next;
					disconnect_serviced_peer(sp,0);
					if (sp->p && sp->p->is_dynamic)
						drop_serviced_peer(sp,0);
				}
				sleep(1);
				break;
			}else
				if (n){

					if (FD_ISSET(fd_exchange_pipe_local,&rfds)){
						/* fd exchange */
						LM_DBG("select_recv(): There is something on the fd exchange pipe\n");
						p = 0;
						fd = -1;
						if (!receive_fd(fd_exchange_pipe_local,&fd,&p)){
							LM_ERR("select_recv(): Error reading from fd exchange pipe\n");
						}else{
							LM_DBG("select_recv(): fd exchange pipe says fd [%d] for peer %p:[%.*s]\n",fd,
									p,
									p?p->fqdn.len:0,
									p?p->fqdn.s:0);
							if (p){
								sp2=0;
								for(sp=serviced_peers;sp;sp=sp->next)
									if (sp->p==p){
										sp2 = sp;
										break;
									}
								if (!sp2)
									sp2 = add_serviced_peer(p);
								else
									make_send_pipe(sp2);
								if (!sp2) {
									LM_ERR("Error on add_serviced_peer()\n");
									continue;
								}

								sp2->tcp_socket = fd;
								if (p->state == Wait_Conn_Ack){
									p->I_sock = fd;
									sm_process(p,I_Rcv_Conn_Ack,0,0,fd);
								}else{
									p->R_sock = fd;
								}
							}else{
								sp2 = add_serviced_peer(NULL);
								if (!sp2) {
									LM_ERR("Error on add_serviced_peer()\n");
									continue;
								}
								sp2->tcp_socket = fd;
							}
						}
					}

					for(sp=serviced_peers;sp;){
						if (sp->tcp_socket>=0 && FD_ISSET(sp->tcp_socket,&efds)) {
							LM_INFO("select_recv(): [%.*s] Peer socket [%d] found on the exception list... dropping\n",
									sp->p?sp->p->fqdn.len:0,
									sp->p?sp->p->fqdn.s:0,
									sp->tcp_socket);
							goto drop_peer;
						}
						if (sp->send_pipe_fd>=0 && FD_ISSET(sp->send_pipe_fd,&rfds)) {
							/* send */
							LM_DBG("select_recv(): There is something on the send pipe\n");
							cnt = read(sp->send_pipe_fd,&msg,sizeof(AAAMessage *));
							if (cnt==0){
								//This is very stupid and might not work well - droped messages... to be fixed
								LM_INFO("select_recv(): ReOpening pipe for read. This should not happen...\n");
								close(sp->send_pipe_fd);
								sp->send_pipe_fd = open(sp->send_pipe_name.s, O_RDONLY | O_NDELAY);
								goto receive;
							}
							if (cnt<sizeof(AAAMessage *)){
								if (cnt<0) LM_ERR("select_recv(): Error reading from send pipe\n");
								goto receive;
							}
							LM_DBG("select_recv(): Send pipe says [%p] %d\n",msg,cnt);
							if (sp->tcp_socket<0){
								LM_ERR("select_recv(): got a signal to send something, but the connection was not opened");
							} else {
								while( (cnt=write(sp->tcp_socket,msg->buf.s,msg->buf.len))==-1 ) {
									if (errno==EINTR)
										continue;
									LM_ERR("select_recv(): [%.*s] write on socket [%d] returned error> %s... dropping\n",
											sp->p?sp->p->fqdn.len:0,
											sp->p?sp->p->fqdn.s:0,
											sp->tcp_socket,
											strerror(errno));
									AAAFreeMessage(&msg);
									close(sp->tcp_socket);
									goto drop_peer;
								}

								if (cnt!=msg->buf.len){
									LM_ERR("select_recv(): [%.*s] write on socket [%d] only wrote %d/%d bytes... dropping\n",
											sp->p?sp->p->fqdn.len:0,
											sp->p?sp->p->fqdn.s:0,
											sp->tcp_socket,
											cnt,
											msg->buf.len);
									AAAFreeMessage(&msg);
									close(sp->tcp_socket);
									goto drop_peer;
								}
							}
							AAAFreeMessage(&msg);
							//don't return, maybe there is something to read
						}
receive:
						/* receive */
						if (sp->tcp_socket>=0 && FD_ISSET(sp->tcp_socket,&rfds)) {
							errno=0;
							cnt = do_receive(sp);
							if (cnt<=0) {
								LM_INFO("select_recv(): [%.*s] read on socket [%d] returned %d > %s... dropping\n",
										sp->p?sp->p->fqdn.len:0,
										sp->p?sp->p->fqdn.s:0,
										sp->tcp_socket,
										cnt,
										errno?strerror(errno):"");
								goto drop_peer;
							}
						}

						//next_sp:
						/* go to next serviced peer */
						sp=sp->next;
						continue;
drop_peer:
						/* drop this serviced peer on error */
						sp2 = sp->next;
						disconnect_serviced_peer(sp,0);
						if (sp->p && sp->p->is_dynamic)
							drop_serviced_peer(sp,0);
						sp = sp2;
					}
				}
		}
	}
	return 0;
}
Exemplo n.º 8
0
static struct mi_root *mi_cachefetch(struct mi_root *cmd, void *param)
{
	str mc_system;
	str attr;
	str value;
	struct mi_node* node= NULL;
	struct mi_root *rpl_tree= NULL;
	int ret;

	if(cmd == NULL)
	{
		LM_ERR("NULL command\n");
		return init_mi_tree(404, MI_SSTR("NULL command"));
	}

	node = cmd->node.kids;
	if(node == NULL)
		return init_mi_tree(404, MI_SSTR("Too few arguments"));

	mc_system = node->value;
	if(mc_system.s == NULL || mc_system.len== 0)
	{
		LM_ERR( "empty memory cache system parameter\n");
		return init_mi_tree(404, MI_SSTR("Empty memory cache id"));
	}

	node = node->next;
	if(node == NULL)
		return init_mi_tree(404, MI_SSTR("Too few arguments"));

	attr = node->value;
	if(attr.s == NULL || attr.len== 0)
	{
		LM_ERR( "empty attribute name parameter\n");
		return init_mi_tree(404,MI_SSTR( "Empty attribute name"));
	}

	node = node->next;
	if(node != NULL)
		return init_mi_tree(404, MI_SSTR("Too many arguments"));

	ret = cachedb_fetch(&mc_system, &attr, &value);
	if(ret== -1)
	{
		LM_ERR("cachedb_fetch command failed\n");
		return init_mi_tree(500, MI_SSTR("Cache fetch command failed"));
	}

	rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
	if (rpl_tree==0)
	{
		if(value.s)
			pkg_free(value.s);
		return 0;
	}

	if(ret == -2 || value.s == 0 || value.len == 0)
	{
		add_mi_node_child( &rpl_tree->node, 0, 0, 0,
			MI_SSTR("Value not found") );
		goto done;
	}

	addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "%.*s = [%.*s]", attr.len,
			attr.s, value.len, value.s);

	pkg_free(value.s);

done:
	return rpl_tree;
}
Exemplo n.º 9
0
static int xlog_log_colors_param(modparam_t type, void *val)
{
	param_t* params_list = NULL;
	param_hooks_t phooks;
	param_t *pit=NULL;
	str s;
	int level;

	if(val==NULL)
		goto error;

	s.s = (char*)val;
	s.len = strlen(s.s);

	if(s.len<=0)
		goto error;

	if(s.s[s.len-1]==';')
		s.len--;
	if (parse_params(&s, CLASS_ANY, &phooks, &params_list)<0)
		goto error;

	for (pit = params_list; pit; pit=pit->next)
	{
		if (pit->name.len==7
				&& strncasecmp(pit->name.s, "l_alert", 7)==0) {
			level = L_ALERT;
		} else if (pit->name.len==5
				&& strncasecmp(pit->name.s, "l_bug", 5)==0) {
			level = L_BUG;
		} else if (pit->name.len==7
				&& strncasecmp(pit->name.s, "l_crit2", 7)==0) {
			level = L_CRIT2;
		} else if (pit->name.len==6
				&& strncasecmp(pit->name.s, "l_crit", 6)==0) {
			level = L_CRIT;
		} else if (pit->name.len==5
				&& strncasecmp(pit->name.s, "l_err", 5)==0) {
			level = L_ERR;
		} else if (pit->name.len==6
				&& strncasecmp(pit->name.s, "l_warn", 6)==0) {
			level = L_WARN;
		} else if (pit->name.len==8
				&& strncasecmp(pit->name.s, "l_notice", 8)==0) {
			level = L_NOTICE;
		} else if (pit->name.len==6
				&& strncasecmp(pit->name.s, "l_info", 6)==0) {
			level = L_INFO;
		} else if (pit->name.len==5
				&& strncasecmp(pit->name.s, "l_dbg", 5)==0) {
			level = L_DBG;
		} else {
			LM_ERR("invalid level name %.*s\n",
					pit->name.len, pit->name.s);
			goto error;
		}
			
		if(pit->body.len!=2) {
			LM_ERR("invalid color spec for level %.*s (%.*s)\n",
					pit->name.len, pit->name.s,
					pit->body.len, pit->body.s);
			goto error;
		}
		dprint_color_update(level, pit->body.s[0], pit->body.s[1]);
	}

	if(params_list!=NULL)
		free_params(params_list);
	return 0;

error:
	if(params_list!=NULL)
		free_params(params_list);
	return -1;

}
Exemplo n.º 10
0
Arquivo: res.c Projeto: mtulio/mtulio
/**
 * Get and convert columns from a result
 */
int db_mysql_get_columns(const db_con_t* _h, db_res_t* _r)
{
	int col;
	MYSQL_FIELD* fields;

	if ((!_h) || (!_r)) {
		LM_ERR("invalid parameter\n");
		return -1;
	}

	if (CON_HAS_PS(_h)) {
		RES_COL_N(_r) = CON_MYSQL_PS(_h)->cols_out;
	} else {
		RES_COL_N(_r) = mysql_field_count(CON_CONNECTION(_h));
	}
	if (!RES_COL_N(_r)) {
		LM_ERR("no columns returned from the query\n");
		return -2;
	} else {
		LM_DBG("%d columns returned from the query\n", RES_COL_N(_r));
	}
	
	if (db_allocate_columns(_r, RES_COL_N(_r)) != 0) {
		LM_ERR("could not allocate columns\n");
		return -3;
	}

	fields = mysql_fetch_fields(CON_RESULT(_h));
	for(col = 0; col < RES_COL_N(_r); col++) {
		/* The pointer that is here returned is part of the result structure */
		RES_NAMES(_r)[col]->s = fields[col].name;
		RES_NAMES(_r)[col]->len = strlen(fields[col].name);

		LM_DBG("RES_NAMES(%p)[%d]=[%.*s]\n", RES_NAMES(_r)[col], col,
				RES_NAMES(_r)[col]->len, RES_NAMES(_r)[col]->s);

		switch(fields[col].type) {
			case MYSQL_TYPE_TINY:
			case MYSQL_TYPE_SHORT:
			case MYSQL_TYPE_LONG:
			case MYSQL_TYPE_INT24:
			case MYSQL_TYPE_LONGLONG:
			case MYSQL_TYPE_DECIMAL:
			#if MYSQL_VERSION_ID > 49999
			case MYSQL_TYPE_NEWDECIMAL:
			#endif
			case MYSQL_TYPE_TIMESTAMP:
				LM_DBG("use DB_INT result type\n");
				RES_TYPES(_r)[col] = DB_INT;
				break;

			case MYSQL_TYPE_FLOAT:
			case MYSQL_TYPE_DOUBLE:
				LM_DBG("use DB_DOUBLE result type\n");
				RES_TYPES(_r)[col] = DB_DOUBLE;
				break;

			case MYSQL_TYPE_DATETIME:
			case MYSQL_TYPE_DATE:
				LM_DBG("use DB_DATETIME result type\n");
				RES_TYPES(_r)[col] = DB_DATETIME;
				break;

			case MYSQL_TYPE_BLOB:
				LM_DBG("use DB_BLOB result type\n");
				RES_TYPES(_r)[col] = DB_BLOB;
				break;

			case FIELD_TYPE_SET:
				LM_DBG("use DB_BITMAP result type\n");
				RES_TYPES(_r)[col] = DB_BITMAP;
				break;

			case MYSQL_TYPE_STRING:
			case MYSQL_TYPE_VAR_STRING:
				LM_DBG("use DB_STRING result type\n");
				RES_TYPES(_r)[col] = DB_STRING;
				break;

			default:
				LM_WARN("unhandled data type column (%.*s) type id (%d), "
						"use DB_STRING as default\n", RES_NAMES(_r)[col]->len,
						RES_NAMES(_r)[col]->s, fields[col].type);
				RES_TYPES(_r)[col] = DB_STRING;
				break;
		}
	}
	return 0;
}
Exemplo n.º 11
0
static struct mi_root *mi_cachestore(struct mi_root *cmd, void *param)
{
	str mc_system;
	str attr;
	str value;
	unsigned int expires = 0;
	struct mi_node* node= NULL;
	str expires_str;

	if(cmd == NULL)
	{
		LM_ERR("NULL command\n");
		return init_mi_tree(404, MI_SSTR("NULL command"));
	}

	node = cmd->node.kids;
	if(node == NULL)
		return init_mi_tree(404, MI_SSTR("Too few arguments"));

	mc_system = node->value;
	if(mc_system.s == NULL || mc_system.len== 0)
	{
		LM_ERR( "empty memory cache system parameter\n");
		return init_mi_tree(404, MI_SSTR("Empty memory cache id"));
	}

	node = node->next;
	if(node == NULL)
		return init_mi_tree(404, MI_SSTR("Too few arguments"));

	attr = node->value;
	if(attr.s == NULL || attr.len== 0)
	{
		LM_ERR( "empty attribute name parameter\n");
		return init_mi_tree(404, MI_SSTR("Empty attribute name"));
	}

	node = node->next;
	if(node == NULL)
		return init_mi_tree(404, MI_SSTR("Too few arguments"));

	value = node->value;
	if(value.s == NULL || value.len== 0)
	{
		LM_ERR( "empty value parameter\n");
		return init_mi_tree(404, MI_SSTR("Empty value argument"));
	}

	/* expires parameter is not compulsory */
	node = node->next;
	if(node!= NULL)
	{
		expires_str = node->value;
		if(expires_str.s == NULL || expires_str.len == 0)
		{
			LM_ERR( "empty expires parameter\n");
			return init_mi_tree(404, MI_SSTR("Empty expires argument"));
		}
		if(str2int(&expires_str, &expires)< 0)
		{
			LM_ERR("wrong format for expires argument- needed int\n");
			return init_mi_tree(404,
				MI_SSTR("Bad format for expires argument"));
		}

		node = node->next;
		if(node!= NULL)
			return init_mi_tree(404, MI_SSTR("Too many parameters"));
	}

	if(cachedb_store(&mc_system, &attr, &value,expires)< 0)
	{
		LM_ERR("cachedb_store command failed\n");
		return init_mi_tree(500, MI_SSTR("Cache store command failed"));
	}

	return init_mi_tree(200, MI_SSTR(MI_OK));
}
Exemplo n.º 12
0
static int load_sca_info_from_db(void)
{
	db_res_t * res = NULL;
	db_val_t * values;
	db_row_t * rows;
	int i, j, nr_rows;
	unsigned int valid_record;
	unsigned int n_result_cols = 0;
	unsigned int shared_line_col, watchers_col;
	unsigned int app_shared_entity_col[MAX_APPEARANCE_INDEX];
	unsigned int app_call_state_col[MAX_APPEARANCE_INDEX];
	unsigned int app_call_info_uri_col[MAX_APPEARANCE_INDEX];
	unsigned int app_call_info_appearance_uri_col[MAX_APPEARANCE_INDEX];
	unsigned int app_b2bl_key_col[MAX_APPEARANCE_INDEX];
	db_key_t q_cols[SCA_TABLE_TOTAL_COL_NO];

	str shared_line, watchers_csv;
	//str_lst_t *watchers;
	//unsigned int size, watcher_size, watchers_no;
	//unsigned int size;
	unsigned int hash_index;
	//char *p;
	b2b_sca_record_t *record;
	b2b_sca_call_t *call;
	unsigned int shared_entity, appearance_index, call_state;
	str call_info_uri, call_info_apperance_uri, b2bl_key;
	b2bl_cb_ctx_t *cb_params;

	if(use_sca_table()) return -1;

	q_cols[shared_line_col = n_result_cols++] = &shared_line_column;
	q_cols[watchers_col = n_result_cols++] = &watchers_column;

	for (i=0; i<MAX_APPEARANCE_INDEX; i++) {
		q_cols[app_shared_entity_col[i]	= n_result_cols++] = &app_shared_entity_column[i];
		q_cols[app_call_state_col[i] = n_result_cols++] = &app_call_state_column[i];
		q_cols[app_call_info_uri_col[i] = n_result_cols++] = &app_call_info_uri_column[i];
		q_cols[app_call_info_appearance_uri_col[i] = n_result_cols++] =
						&app_call_info_appearance_uri_column[i];
		q_cols[app_b2bl_key_col[i] = n_result_cols++] = &app_b2bl_key_column[i];
	}

	/* select the whole tabel and all the columns */
	if (DB_CAPABILITY(sca_dbf, DB_CAP_FETCH)) {
		if(sca_dbf.query(sca_db_handle, 0, 0, 0, q_cols, 0,
				SCA_TABLE_TOTAL_COL_NO, 0, 0) < 0) {
			LM_ERR("Error while querying (fetch) database\n");
			return -1;
		}
		if(sca_dbf.fetch_result(sca_db_handle, &res, SCA_FETCH_SIZE)<0){
			LM_ERR("fetching rows failed\n");
			return -1;
		}
	} else {
		if(sca_dbf.query(sca_db_handle, 0, 0, 0, q_cols, 0,
				SCA_TABLE_TOTAL_COL_NO, 0, &res) < 0) {
			LM_ERR("Error while querying database\n");
			return -1;
		}
	}

	nr_rows = RES_ROW_N(res);

	do {
		LM_DBG("loading [%i] records from db\n", nr_rows);
		rows = RES_ROWS(res);
		/* for every row/record */
		for(i=0; i<nr_rows; i++){
			values = ROW_VALUES(rows + i);
			if (VAL_NULL(values+shared_line_col) || VAL_NULL(values+watchers_col)) {
				LM_ERR("columns [%.*s] or/and [%.*s] cannot be null -> skipping\n",
					shared_line_column.len, shared_line_column.s,
					watchers_column.len, watchers_column.s);
				continue;
			}
			shared_line.s = (char*)values[shared_line_col].val.string_val;
			shared_line.len = strlen(shared_line.s);

			watchers_csv.s = (char*)values[watchers_col].val.string_val;
			watchers_csv.len = strlen(watchers_csv.s);

			record = restore_record(&shared_line, &watchers_csv);
			if (record == NULL)
				goto error;
			hash_index = core_hash(&shared_line, NULL, b2b_sca_hsize);

			j = 0;
			while (j < MAX_APPEARANCE_INDEX) {
				if(	VAL_NULL(values + app_shared_entity_col[j]) ||
					VAL_NULL(values + app_call_state_col[j]) ||
					VAL_NULL(values + app_call_info_uri_col[j]) ||
					VAL_NULL(values + app_call_info_appearance_uri_col[j]) ||
					VAL_NULL(values + app_b2bl_key_col[j]) ) {
					goto cont;
				}
				appearance_index = j + 1;
				/* 1 - get shared_entity */
				shared_entity = values[app_shared_entity_col[j]].val.int_val;
				if (shared_entity!=0 && shared_entity!=1) {
					LM_ERR("Unexpected shared_entity [%d] "
						"for shared_line [%.*s]\n",
						shared_entity, shared_line.len, shared_line.s);
					goto cont;
				}
				/* 2 - get call_state */
				call_state = values[app_call_state_col[j]].val.int_val;
				if (call_state == IDLE_STATE) {
					LM_DBG("empty call[%d]\n", appearance_index);
					goto cont;
				}
				if (call_state > MAX_INDEX_STATE) {
					LM_ERR("Unexpected call_state [%d] for shared_line [%.*s]\n",
						call_state, shared_line.len, shared_line.s);
					goto cont;
				}
				/* 3 - get call_info_uri */
				call_info_uri.s =
					(char*)values[app_call_info_uri_col[j]].val.string_val;
				if (call_info_uri.s)
					call_info_uri.len = strlen(call_info_uri.s);
				else {
					LM_ERR("Missing call_info_uri for shared_line [%.*s][%d]\n",
						shared_line.len, shared_line.s, appearance_index);
					goto cont;
				}
				LM_DBG("call_info_uri=[%.*s]\n",
					call_info_uri.len, call_info_uri.s);
				/* 4 - get call_info_apperance_uri */
				call_info_apperance_uri.s =
					(char*)
					values[app_call_info_appearance_uri_col[j]].val.string_val;
				if (call_info_apperance_uri.s)
					call_info_apperance_uri.len =
						strlen(call_info_apperance_uri.s);
				else {
					LM_ERR("Missing call_info_apperance_uri for "
						"shared_line [%.*s][%d]\n",
						shared_line.len, shared_line.s, appearance_index);
					goto cont;
				}
				LM_DBG("call_info_apperance_uri=[%.*s]\n",
					call_info_apperance_uri.len, call_info_apperance_uri.s);
				/* 5 - get b2bl_key */
				b2bl_key.s = (char*)values[app_b2bl_key_col[j]].val.string_val;
				if (b2bl_key.s) {
					b2bl_key.len = strlen(b2bl_key.s);
					if (b2bl_key.len > B2BL_MAX_KEY_LEN) {
						LM_ERR("buffer overflow on b2bl_key [%.*s]"
							" for shared_line [%.*s][%d]\n",
							b2bl_key.len, b2bl_key.s,
							shared_line.len, shared_line.s,
							appearance_index);
						goto cont;
					}
					LM_DBG("b2bl_key=[%.*s]\n", b2bl_key.len, b2bl_key.s);
				} else {
					LM_ERR("Missing b2bl_key for shared_line [%.*s][1]\n",
						shared_line.len, shared_line.s);
					goto cont;
				}
				/* restore the call */
				call = restore_call(record, appearance_index,
					shared_entity, call_state,
					&call_info_uri, &call_info_apperance_uri);
				if (call == NULL) {
					goto error;
				}
				/* update record */
				if (0!=b2b_sca_update_call_record_key(call, &b2bl_key)) {
					LM_ERR("Unable to update b2bl_key [%.*s]\n",
						b2bl_key.len, b2bl_key.s);
					shm_free(call);
					call = NULL;
					record->call[appearance_index-1] = NULL;
					goto cont;
				}
				/* Prepare b2b_logic callback params. */
				cb_params = build_cb_params(hash_index,
							&shared_line, appearance_index);
				if (cb_params == NULL) {
					LM_ERR("Unable to build cb_params\n");
					goto error;
				}
				/* re-register callbacks */
				if(b2bl_api.register_cb(&b2bl_key, &sca_logic_notify, cb_params,
					B2B_RE_INVITE_CB|B2B_CONFIRMED_CB|B2B_DESTROY_CB) != 0){
					LM_ERR("Unable register b2b cb\n");
					shm_free(call);
					call = NULL;
					record->call[appearance_index-1] = NULL;
					goto cont;
				}
cont:
				j++;
			}

			valid_record = j = 0;
			while (j < MAX_APPEARANCE_INDEX) {
				if (record->call[j]) {
					valid_record = 1;
					goto check_valid_record;
				}
				j++;
			}
check_valid_record:
			if (valid_record) {
				b2b_sca_print_record(record);
				insert_record(hash_index, record);
			} else {
				LM_DBG("removing the record from db!\n");
				delete_sca_info_from_db(record);
			}
			LM_DBG("Done\n");
		}

		/* any more data to be fetched ?*/
		if (DB_CAPABILITY(sca_dbf, DB_CAP_FETCH)) {
			if (sca_dbf.fetch_result(sca_db_handle, &res, SCA_FETCH_SIZE)<0) {
				LM_ERR("fetching more rows failed\n");
				goto error;
			}
			nr_rows = RES_ROW_N(res);
		} else {
			nr_rows = 0;
		}
	}while (nr_rows>0);

	sca_dbf.free_result(sca_db_handle, res);
	return 0;
error:
	sca_dbf.free_result(sca_db_handle, res);
	return -1;
}
Exemplo n.º 13
0
int insert_sca_info_into_db(b2b_sca_record_t *record)
{
	b2b_sca_call_t *call = NULL;
	unsigned int n_q_cols = 0;
	unsigned int i;
	unsigned int appearance_index = MAX_APPEARANCE_INDEX;
	unsigned int shared_line_col, watchers_col;
	unsigned int app_shared_entity_col[MAX_APPEARANCE_INDEX];
	unsigned int app_call_state_col[MAX_APPEARANCE_INDEX];
	unsigned int app_call_info_uri_col[MAX_APPEARANCE_INDEX];
	unsigned int app_call_info_appearance_uri_col[MAX_APPEARANCE_INDEX];
	unsigned int app_b2bl_key_col[MAX_APPEARANCE_INDEX];
	db_key_t q_cols[SCA_TABLE_TOTAL_COL_NO];
	db_val_t q_vals[SCA_TABLE_TOTAL_COL_NO];

	LM_DBG("\n");
	if(use_sca_table()) return -1;

	memset(q_vals, 0, SCA_TABLE_TOTAL_COL_NO * sizeof(db_val_t));

	q_cols[shared_line_col		= n_q_cols++] = &shared_line_column;
	q_vals[shared_line_col].type	= DB_STR;
	q_cols[watchers_col		= n_q_cols++] = &watchers_column;
	q_vals[watchers_col].type	= DB_STR;

	for (i=0; i<MAX_APPEARANCE_INDEX; i++) {
		q_cols[app_shared_entity_col[i]	= n_q_cols++] = &app_shared_entity_column[i];
		q_vals[app_shared_entity_col[i]].type = DB_INT;
		q_cols[app_call_state_col[i] = n_q_cols++] = &app_call_state_column[i];
		q_vals[app_call_state_col[i]].type = DB_INT;
		q_cols[app_call_info_uri_col[i] = n_q_cols++] = &app_call_info_uri_column[i];
		q_vals[app_call_info_uri_col[i]].type = DB_STR;
		q_cols[app_call_info_appearance_uri_col[i] = n_q_cols++] =
						&app_call_info_appearance_uri_column[i];
		q_vals[app_call_info_appearance_uri_col[i]].type = DB_STR;
		q_cols[app_b2bl_key_col[i] = n_q_cols++] = &app_b2bl_key_column[i];
		q_vals[app_b2bl_key_col[i]].type = DB_STR;
	}

	q_vals[shared_line_col].val.str_val = record->shared_line;
	/* FIXME: get all the watchers */
	if (record->watchers) {
		q_vals[watchers_col].val.str_val = record->watchers->watcher;
	}

	for (i=0; i<MAX_APPEARANCE_INDEX; i++) {
		if (record->call[i]) {
			if (call) {
				LM_ERR("This should be an UPDATE not an INSERT\n");
				return -1;
			}
			call = record->call[i];
			appearance_index = i;
		}
	}

	if (call) {
		q_vals[app_shared_entity_col[appearance_index]].val.int_val = call->shared_entity;
		q_vals[app_call_state_col[appearance_index]].val.int_val = call->call_state;
		q_vals[app_call_info_uri_col[appearance_index]].val.str_val = call->call_info_uri;
		q_vals[app_call_info_appearance_uri_col[appearance_index]].val.str_val =
							call->call_info_apperance_uri;
		q_vals[app_b2bl_key_col[appearance_index]].val.str_val = call->b2bl_key;

		if((sca_dbf.insert(sca_db_handle, q_cols, q_vals, SCA_TABLE_TOTAL_COL_NO)) != 0) {
			LM_ERR("could not add record\n");
			return -1;
		}
	} else {
		LM_ERR("Empty record?\n");
		return -1;
	}

	return 0;
}
Exemplo n.º 14
0
int update_sca_info_to_db(b2b_sca_record_t *record, unsigned int appearance_index)
{
	b2b_sca_call_t *call;
	unsigned int i;
	unsigned int n_q_cols = 0, n_q_vals = 0;
	unsigned int shared_line_col, watchers_col;
	unsigned int app_shared_entity_col[MAX_APPEARANCE_INDEX];
	unsigned int app_call_state_col[MAX_APPEARANCE_INDEX];
	unsigned int app_call_info_uri_col[MAX_APPEARANCE_INDEX];
	unsigned int app_call_info_appearance_uri_col[MAX_APPEARANCE_INDEX];
	unsigned int app_b2bl_key_col[MAX_APPEARANCE_INDEX];
	db_key_t q_cols[SCA_TABLE_TOTAL_COL_NO];
	db_val_t q_vals[SCA_TABLE_TOTAL_COL_NO];


	LM_DBG("\n");
	if(use_sca_table()) return -1;

	memset(q_vals, 0, SCA_TABLE_TOTAL_COL_NO * sizeof(db_val_t));

	q_cols[shared_line_col		= n_q_cols++] = &shared_line_column;
	q_vals[shared_line_col].type	= DB_STR;
	q_cols[watchers_col		= n_q_cols++] = &watchers_column;
	q_vals[watchers_col].type	= DB_STR;

	for (i=0; i<MAX_APPEARANCE_INDEX; i++) {
		q_cols[app_shared_entity_col[i]	= n_q_cols++] = &app_shared_entity_column[i];
		q_vals[app_shared_entity_col[i]].type = DB_INT;
		q_cols[app_call_state_col[i] = n_q_cols++] = &app_call_state_column[i];
		q_vals[app_call_state_col[i]].type = DB_INT;
		q_cols[app_call_info_uri_col[i] = n_q_cols++] = &app_call_info_uri_column[i];
		q_vals[app_call_info_uri_col[i]].type = DB_STR;
		q_cols[app_call_info_appearance_uri_col[i] = n_q_cols++] =
						&app_call_info_appearance_uri_column[i];
		q_vals[app_call_info_appearance_uri_col[i]].type = DB_STR;
		q_cols[app_b2bl_key_col[i] = n_q_cols++] = &app_b2bl_key_column[i];
		q_vals[app_b2bl_key_col[i]].type = DB_STR;
	}

	q_vals[shared_line_col].val.str_val = record->shared_line;

	i = appearance_index - 1;
	if (i >= MAX_APPEARANCE_INDEX) {
		LM_ERR("Non matching call\n");
		return -1;
	}

	call = record->call[i];
	if (call) {
		LM_DBG("update shared_entity [%d] and call_state [%d] for call[%d][%.*s]\n",
			call->shared_entity, call->call_state, i,
			call->b2bl_key.len, call->b2bl_key.s);
		switch(call->call_state) {
		case ALERTING_STATE:
			q_vals[app_call_info_uri_col[i]].val.str_val = call->call_info_uri;
			q_vals[app_call_info_appearance_uri_col[i]].val.str_val =
							call->call_info_apperance_uri;
			q_vals[app_b2bl_key_col[i]].val.str_val = call->b2bl_key;
			LM_DBG("update [%.*s][%.*s][%.*s]\n",
				call->call_info_uri.len, call->call_info_uri.s,
				call->call_info_apperance_uri.len, call->call_info_apperance_uri.s,
				call->b2bl_key.len, call->b2bl_key.s);
			n_q_vals += 3;
		default:
			q_vals[app_shared_entity_col[i]].val.int_val = call->shared_entity;
			q_vals[app_call_state_col[i]].val.int_val = call->call_state;
			n_q_vals += 2;
		}
	} else {
		n_q_vals = 5;
	}
	if(sca_dbf.update(sca_db_handle, q_cols, 0, q_vals,
			q_cols + app_shared_entity_col[i],
			q_vals + app_shared_entity_col[i], 1, n_q_vals) != 0) {
		LM_ERR("failed to update record\n");
		return -1;
	}

	return 0;
}
Exemplo n.º 15
0
void lua_sr_kemi_register_libs(lua_State *L)
{
	luaL_Reg *_sr_crt_KSRMethods = NULL;
	sr_kemi_module_t *emods = NULL;
	int emods_size = 0;
	int i;
	int k;
	int n;
	char mname[128];

#if 0
	/* dynamic lookup on function name */
	lua_sr_kemi_register_core(L);
	lua_sr_kemi_register_modules(L);
#endif

	_sr_KSRMethods = malloc(SR_LUA_KSR_METHODS_SIZE * sizeof(luaL_Reg));
	if(_sr_KSRMethods==NULL) {
		LM_ERR("no more pkg memory\n");
		return;
	}
	memset(_sr_KSRMethods, 0, SR_LUA_KSR_METHODS_SIZE * sizeof(luaL_Reg));

	emods_size = sr_kemi_modules_size_get();
	emods = sr_kemi_modules_get();

	n = 0;
	_sr_crt_KSRMethods = _sr_KSRMethods;
	if(emods_size==0 || emods[0].kexp==NULL) {
		LM_ERR("no kemi exports registered\n");
		return;
	}

	for(i=0; emods[0].kexp[i].func!=NULL; i++) {
		LM_DBG("exporting KSR.%s(...)\n", emods[0].kexp[i].fname.s);
		_sr_crt_KSRMethods[i].name = emods[0].kexp[i].fname.s;
		_sr_crt_KSRMethods[i].func =
			sr_kemi_lua_export_associate(&emods[0].kexp[i]);
		if(_sr_crt_KSRMethods[i].func == NULL) {
			LM_ERR("failed to associate kemi function with lua export\n");
			free(_sr_KSRMethods);
			_sr_KSRMethods = NULL;
			return;
		}
		n++;
	}

	luaL_openlib(L, "KSR", _sr_crt_KSRMethods, 0);

	/* special modules - pv.get(...) can return int or str */
	luaL_openlib(L, "KSR.pv", _sr_pv_Map,     0);
	luaL_openlib(L, "KSR.x",  _sr_kemi_x_Map, 0);

	/* registered kemi modules */
	if(emods_size>1) {
		for(k=1; k<emods_size; k++) {
			n++;
			_sr_crt_KSRMethods = _sr_KSRMethods + n;
			snprintf(mname, 128, "KSR.%s", emods[k].kexp[0].mname.s);
			for(i=0; emods[k].kexp[i].func!=NULL; i++) {
				LM_DBG("exporting %s.%s(...)\n", mname,
						emods[k].kexp[i].fname.s);
				_sr_crt_KSRMethods[i].name = emods[k].kexp[i].fname.s;
				_sr_crt_KSRMethods[i].func =
					sr_kemi_lua_export_associate(&emods[k].kexp[i]);
				if(_sr_crt_KSRMethods[i].func == NULL) {
					LM_ERR("failed to associate kemi function with func export\n");
					free(_sr_KSRMethods);
					_sr_KSRMethods = NULL;
					return;
				}
				n++;
			}
			luaL_openlib(L, mname, _sr_crt_KSRMethods, 0);
			LM_DBG("initializing kemi sub-module: %s (%s)\n", mname,
					emods[k].kexp[0].mname.s);
		}
	}
	LM_DBG("module 'KSR' has been initialized\n");
}
Exemplo n.º 16
0
/*!
 * \brief Function that is registered as RR callback for dialog tracking
 * 
 * Function that is registered as RR callback for dialog tracking. It
 * sets the appropriate events after the SIP method and run the state
 * machine to update the dialog state. It updates then the saved
 * dialogs and also the statistics.
 * \param req SIP request
 * \param route_params record-route parameter
 * \param param unused
 */
void dlg_onroute(struct sip_msg* req, str *route_params, void *param)
{
	dlg_cell_t *dlg;
	dlg_iuid_t *iuid;
	str val, callid, ftag, ttag;
	int h_entry, h_id, new_state, old_state, unref, event, timeout, reset;
	unsigned int dir;
	int ret = 0;

	dlg = dlg_get_ctx_dialog();
	if (dlg!=NULL) {
		dlg_release(dlg);
		return;
	}

	/* skip initial requests - they may end up here because of the
	 * preloaded route */
	if ( (!req->to && parse_headers(req, HDR_TO_F,0)<0) || !req->to ) {
		LM_ERR("bad request or missing TO hdr :-/\n");
		return;
	}
	if ( get_to(req)->tag_value.len==0 )
		return;

	dlg = 0;
	dir = DLG_DIR_NONE;

	if ( seq_match_mode!=SEQ_MATCH_NO_ID ) {
		if( d_rrb.get_route_param( req, &rr_param, &val)!=0) {
			LM_DBG("Route param '%.*s' not found\n", rr_param.len,rr_param.s);
			if (seq_match_mode==SEQ_MATCH_STRICT_ID )
				return;
		} else {
			LM_DBG("route param is '%.*s' (len=%d)\n",val.len,val.s,val.len);

			if ( parse_dlg_rr_param( val.s, val.s+val.len, &h_entry, &h_id)<0 )
				return;

			dlg = dlg_lookup(h_entry, h_id);
			if (dlg==0) {
				LM_WARN("unable to find dialog for %.*s "
					"with route param '%.*s' [%u:%u]\n",
					req->first_line.u.request.method.len,
					req->first_line.u.request.method.s,
					val.len,val.s, h_entry, h_id);
				if (seq_match_mode==SEQ_MATCH_STRICT_ID )
					return;
			} else {
				if (pre_match_parse( req, &callid, &ftag, &ttag, 1)<0) {
					// lookup_dlg has incremented the ref count by 1
					dlg_release(dlg);
					return;
				}
				if (match_dialog( dlg, &callid, &ftag, &ttag, &dir )==0) {
					LM_WARN("tight matching failed for %.*s with callid='%.*s'/%d, "
							"ftag='%.*s'/%d, ttag='%.*s'/%d and direction=%d\n",
							req->first_line.u.request.method.len,
							req->first_line.u.request.method.s,
							callid.len, callid.s, callid.len,
							ftag.len, ftag.s, ftag.len,
							ttag.len, ttag.s, ttag.len, dir);
					LM_WARN("dialog identification elements are callid='%.*s'/%d, "
							"caller tag='%.*s'/%d, callee tag='%.*s'/%d\n",
							dlg->callid.len, dlg->callid.s, dlg->callid.len,
							dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
							dlg->tag[DLG_CALLER_LEG].len,
							dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s,
							dlg->tag[DLG_CALLEE_LEG].len);
					// lookup_dlg has incremented the ref count by 1
					dlg_release(dlg);

					// Reset variables in order to do a lookup based on SIP-Elements.
					dlg = 0;
					dir = DLG_DIR_NONE;

					if (seq_match_mode==SEQ_MATCH_STRICT_ID )
						return;
				}
			}
		}
	}

	if (dlg==0) {
		if (pre_match_parse( req, &callid, &ftag, &ttag, 1)<0)
			return;
		/* TODO - try to use the RR dir detection to speed up here the
		 * search -bogdan */
		dlg = get_dlg(&callid, &ftag, &ttag, &dir);
		if (dlg==0){
			LM_DBG("Callid '%.*s' not found\n",
				req->callid->body.len, req->callid->body.s);
			return;
		}
	}

    /* set current dialog - re-use ref increment from dlg_get() above */
    set_current_dialog( req, dlg);
    _dlg_ctx.iuid.h_entry = dlg->h_entry;
    _dlg_ctx.iuid.h_id = dlg->h_id;

	if (req->first_line.u.request.method_value != METHOD_ACK) {
		iuid = dlg_get_iuid_shm_clone(dlg);
		if(iuid!=NULL)
		{
			/* register callback for the replies of this request */
			if ( d_tmb.register_tmcb( req, 0, TMCB_RESPONSE_IN|TMCB_ON_FAILURE,
					dlg_onreply, (void*)iuid, dlg_iuid_sfree)<0 ) {
				LM_ERR("failed to register TMCB (3)\n");
				shm_free(iuid);
			}
			iuid = NULL;
		}
	}
	
	/* run state machine */
	switch ( req->first_line.u.request.method_value ) {
		case METHOD_PRACK:
			event = DLG_EVENT_REQPRACK; break;
		case METHOD_ACK:
			event = DLG_EVENT_REQACK; break;
		case METHOD_BYE:
			event = DLG_EVENT_REQBYE; break;
		default:
			event = DLG_EVENT_REQ;
	}

	next_state_dlg( dlg, event, &old_state, &new_state, &unref);

	CURR_DLG_ID = req->id;
	CURR_DLG_LIFETIME = (unsigned int)(time(0))-dlg->start_ts;
	CURR_DLG_STATUS = new_state;

	dlg_run_event_route(dlg, req, old_state, new_state);

	/* delay deletion of dialog until transaction has died off in order
	 * to absorb in-air messages */
	if (new_state==DLG_STATE_DELETED && old_state!=DLG_STATE_DELETED) {
		iuid = dlg_get_iuid_shm_clone(dlg);
		if(iuid!=NULL) {
			if ( d_tmb.register_tmcb(req, NULL, TMCB_DESTROY,
					unref_dlg_from_cb, (void*)iuid, dlg_iuid_sfree)<0 ) {
				LM_ERR("failed to register deletion delay function\n");
				shm_free(iuid);
			} else {
				dlg_ref(dlg, 1);
			}
		}
	}

	if (new_state==DLG_STATE_CONFIRMED && old_state!=DLG_STATE_CONFIRMED)
		dlg_ka_add(dlg);

	/* run actions for the transition */
	if (event==DLG_EVENT_REQBYE && new_state==DLG_STATE_DELETED &&
	old_state!=DLG_STATE_DELETED) {
		LM_DBG("BYE successfully processed\n");
		/* remove from timer */
		ret = remove_dialog_timer(&dlg->tl);
		if (ret < 0) {
			LM_CRIT("unable to unlink the timer on dlg %p [%u:%u] "
				"with clid '%.*s' and tags '%.*s' '%.*s'\n",
				dlg, dlg->h_entry, dlg->h_id,
				dlg->callid.len, dlg->callid.s,
				dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
				dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
		} else if (ret > 0) {
			LM_WARN("inconsitent dlg timer data on dlg %p [%u:%u] "
				"with clid '%.*s' and tags '%.*s' '%.*s'\n",
				dlg, dlg->h_entry, dlg->h_id,
				dlg->callid.len, dlg->callid.s,
				dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
				dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
		} else {
			/* one extra unref due to removal from timer list */
			unref++;
		}
		/* dialog terminated (BYE) */
        dlg_terminated( req, dlg, dir);

		dlg_unref(dlg, unref);

		_dlg_ctx.cpid = my_pid();
		_dlg_ctx.expect_t = 1;
		dlg_set_ctx_iuid(dlg);

		if_update_stat( dlg_enable_stats, active_dlgs, -1);
		goto done;
	}

	if ( (event==DLG_EVENT_REQ || event==DLG_EVENT_REQACK)
	&& (new_state==DLG_STATE_CONFIRMED || new_state==DLG_STATE_EARLY)) {

		timeout = get_dlg_timeout(req);
		if (timeout!=default_timeout) {
			dlg->lifetime = timeout;
		}
		reset = !((dlg->iflags & DLG_IFLAG_TIMER_NORESET) || dlg_timeout_noreset);

		if ((new_state!=DLG_STATE_EARLY) && (old_state!=DLG_STATE_CONFIRMED || reset)) {
			if (update_dlg_timer( &dlg->tl, dlg->lifetime )==-1) {
				LM_ERR("failed to update dialog lifetime\n");
			} else {
				dlg->dflags |= DLG_FLAG_CHANGED;
			}
		}
		if(event != DLG_EVENT_REQACK) {
			if(update_cseqs(dlg, req, dir)!=0) {
				LM_ERR("cseqs update failed\n");
			} else {
				dlg->dflags |= DLG_FLAG_CHANGED;
			}
		}
		if(dlg_db_mode==DB_MODE_REALTIME && (dlg->dflags&DLG_FLAG_CHANGED)) {
			update_dialog_dbinfo(dlg);
		}

		if (old_state==DLG_STATE_CONFIRMED_NA) {
			LM_DBG("confirming ACK successfully processed\n");

			/* confirming ACK request */
			run_dlg_callbacks( DLGCB_CONFIRMED, dlg, req, NULL, dir, 0);
		} else {
			LM_DBG("sequential request successfully processed\n");

			/* within dialog request */
			run_dlg_callbacks( DLGCB_REQ_WITHIN, dlg, req, NULL, dir, 0);

			if ( (event!=DLG_EVENT_REQACK) &&
					(dlg->cbs.types)&DLGCB_RESPONSE_WITHIN ) {
				iuid = dlg_get_iuid_shm_clone(dlg);
				if(iuid!=NULL)
				{
					/* register callback for the replies of this request */
					if ( d_tmb.register_tmcb( req, 0, TMCB_RESPONSE_FWDED,
							(dir==DLG_DIR_UPSTREAM)?dlg_seq_down_onreply:
														dlg_seq_up_onreply,
							(void*)iuid, dlg_iuid_sfree)<0 ) {
						LM_ERR("failed to register TMCB (2)\n");
						shm_free(iuid);
					}
				}
			}
		}
	}

	if(new_state==DLG_STATE_CONFIRMED && old_state==DLG_STATE_CONFIRMED_NA){
		dlg->dflags |= DLG_FLAG_CHANGED;
		if(dlg_db_mode == DB_MODE_REALTIME)
			update_dialog_dbinfo(dlg);
	}

done:
	dlg_release(dlg);
	return;
}
Exemplo n.º 17
0
/**
 * Receives a message and does basic processing or call the sm_process().
 * This gets called from the do_receive() for every message that is received.
 * Basic processing, before the state machine, is done here.
 * @param msg - the message received
 * @param sp - the serviced peer that it was receiver on
 */
void receive_message(AAAMessage *msg,serviced_peer_t *sp)
{
	AAA_AVP *avp1,*avp2;
	LM_DBG("receive_message(): [%.*s] Recv msg %d\n",
			sp->p?sp->p->fqdn.len:0,
			sp->p?sp->p->fqdn.s:0,
			msg->commandCode);

	if (!sp->p){
		switch (msg->commandCode){
			case Code_CE:
				if (is_req(msg)){
					avp1 = AAAFindMatchingAVP(msg,msg->avpList.head,AVP_Origin_Host,0,0);
					avp2 = AAAFindMatchingAVP(msg,msg->avpList.head,AVP_Origin_Realm,0,0);
					if (avp1&&avp2){
						sp->p = get_peer_from_fqdn(avp1->data,avp2->data);
					}
					if (!sp->p) {
						LM_ERR("receive_msg(): Received CER from unknown peer (accept unknown=%d) -ignored\n",
								config->accept_unknown_peers);
						AAAFreeMessage(&msg);
					}else{
						LM_DBG("receive_message(): [%.*s] This receiver has no peer associated\n",
								sp->p?sp->p->fqdn.len:0,
								sp->p?sp->p->fqdn.s:0	);
						//set_peer_pipe();
						make_send_pipe(sp);
						sm_process(sp->p,R_Conn_CER,msg,0,sp->tcp_socket);
					}
				}
				else{
					LM_ERR("receive_msg(): Received CEA from an unknown peer -ignored\n");
					AAAFreeMessage(&msg);
				}
				break;
			default:
				LM_ERR("receive_msg(): Received non-CE from an unknown peer -ignored\n");
				AAAFreeMessage(&msg);
		}
	}else{
		touch_peer(sp->p);
		switch (sp->p->state){
			case Wait_I_CEA:
				if (msg->commandCode!=Code_CE||is_req(msg)){
					sm_process(sp->p,I_Rcv_Non_CEA,msg,0,sp->tcp_socket);
				}else
					sm_process(sp->p,I_Rcv_CEA,msg,0,sp->tcp_socket);
				break;
			case I_Open:
				switch (msg->commandCode){
					case Code_CE:
						if (is_req(msg)) sm_process(sp->p,I_Rcv_CER,msg,0,sp->tcp_socket);
						else sm_process(sp->p,I_Rcv_CEA,msg,0,sp->tcp_socket);
						break;
					case Code_DW:
						if (is_req(msg)) sm_process(sp->p,I_Rcv_DWR,msg,0,sp->tcp_socket);
						else sm_process(sp->p,I_Rcv_DWA,msg,0,sp->tcp_socket);
						break;
					case Code_DP:
						if (is_req(msg)) sm_process(sp->p,I_Rcv_DPR,msg,0,sp->tcp_socket);
						else sm_process(sp->p,I_Rcv_DPA,msg,0,sp->tcp_socket);
						break;
					default:
						sm_process(sp->p,I_Rcv_Message,msg,0,sp->tcp_socket);
				}
				break;
			case R_Open:
				switch (msg->commandCode){
					case Code_CE:
						if (is_req(msg)) sm_process(sp->p,R_Rcv_CER,msg,0,sp->tcp_socket);
						else sm_process(sp->p,R_Rcv_CEA,msg,0,sp->tcp_socket);
						break;
					case Code_DW:
						if (is_req(msg)) sm_process(sp->p,R_Rcv_DWR,msg,0,sp->tcp_socket);
						else sm_process(sp->p,R_Rcv_DWA,msg,0,sp->tcp_socket);
						break;
					case Code_DP:
						if (is_req(msg)) sm_process(sp->p,R_Rcv_DPR,msg,0,sp->tcp_socket);
						else sm_process(sp->p,R_Rcv_DPA,msg,0,sp->tcp_socket);
						break;
					default:
						sm_process(sp->p,R_Rcv_Message,msg,0,sp->tcp_socket);
				}
				break;
			default:
				LM_ERR("receive_msg(): [%.*s] Received msg while peer in state %d -ignored\n",
						sp->p->fqdn.len,
						sp->p->fqdn.s,
						sp->p->state);
				AAAFreeMessage(&msg);
		}
	}
}
Exemplo n.º 18
0
/*!
 * \brief Parse SIP message and populate leg informations
 *
 * Parse SIP message and populate leg informations. 
 * \param dlg the dialog to add cseq, contact & record_route
 * \param msg sip message
 * \param t transaction
 * \param leg type of the call leg
 * \param tag SIP To tag
 * \return 0 on success, -1 on failure
 * \note for a request: get record route in normal order, for a reply get
 * in reverse order, skipping the ones from the request and the proxies' own
 */
int populate_leg_info( struct dlg_cell *dlg, struct sip_msg *msg,
	struct cell* t, unsigned int leg, str *tag)
{
	unsigned int skip_recs;
	str cseq;
	str contact;
	str rr_set;

	dlg->bind_addr[leg] = msg->rcv.bind_address;

	/* extract the cseq number as string */
	if (leg==DLG_CALLER_LEG) {
		if((!msg->cseq && (parse_headers(msg,HDR_CSEQ_F,0)<0 || !msg->cseq))
			|| !msg->cseq->parsed){
			LM_ERR("bad sip message or missing CSeq hdr :-/\n");
			goto error0;
		}
		cseq = (get_cseq(msg))->number;
	} else {
		/* use the same as in request */
		cseq = dlg->cseq[DLG_CALLEE_LEG];
	}

	/* extract the contact address */
	if (!msg->contact&&(parse_headers(msg,HDR_CONTACT_F,0)<0||!msg->contact)){
		LM_ERR("bad sip message or missing Contact hdr\n");
		goto error0;
	}
	if ( parse_contact(msg->contact)<0 ||
	((contact_body_t *)msg->contact->parsed)->contacts==NULL ||
	((contact_body_t *)msg->contact->parsed)->contacts->next!=NULL ) {
		LM_ERR("bad Contact HDR\n");
		goto error0;
	}
	contact = ((contact_body_t *)msg->contact->parsed)->contacts->uri;

	/* extract the RR parts */
	if(!msg->record_route && (parse_headers(msg,HDR_EOH_F,0)<0)  ){
		LM_ERR("failed to parse record route header\n");
		goto error0;
	}

	if (leg==DLG_CALLER_LEG) {
		skip_recs = 0;
	} else {
		/* was the 200 OK received or local generated */
		skip_recs = dlg->from_rr_nb +
			((t->relayed_reply_branch>=0)?
				((t->uac[t->relayed_reply_branch].flags&TM_UAC_FLAG_R2)?2:
				 ((t->uac[t->relayed_reply_branch].flags&TM_UAC_FLAG_RR)?1:0))
				:0);
	}

	if(msg->record_route){
		if( print_rr_body(msg->record_route, &rr_set, leg,
							&skip_recs) != 0 ){
			LM_ERR("failed to print route records \n");
			goto error0;
		}
	} else {
		rr_set.s = 0;
		rr_set.len = 0;
	}

	if(leg==DLG_CALLER_LEG)
		dlg->from_rr_nb = skip_recs;

	LM_DBG("route_set %.*s, contact %.*s, cseq %.*s and bind_addr %.*s\n",
		rr_set.len, rr_set.s, contact.len, contact.s,
		cseq.len, cseq.s,
		msg->rcv.bind_address->sock_str.len,
		msg->rcv.bind_address->sock_str.s);

	if (dlg_set_leg_info( dlg, tag, &rr_set, &contact, &cseq, leg)!=0) {
		LM_ERR("dlg_set_leg_info failed\n");
		if (rr_set.s) pkg_free(rr_set.s);
		goto error0;
	}

	if (rr_set.s) pkg_free(rr_set.s);

	return 0;
error0:
	return -1;
}
Exemplo n.º 19
0
/**
 * Does the actual receive operations on the Diameter TCP socket, for retrieving incoming messages.
 * The functions is to be called iteratively, each time there is something to be read from the TCP socket. It uses
 * a simple state machine to read first the version, then the header and then the rest of the message. When an
 * entire message is received, it is decoded and passed to the processing functions.
 * @param sp - the serviced peer to operate on
 * @return 1 on success, 0 on failure
 */
static inline int do_receive(serviced_peer_t *sp)
{
	int cnt,n,version;
	char *dst;
	AAAMessage *dmsg;

	switch (sp->state){
		case Receiver_Waiting:
			n = 1; /* wait for version */
			dst = sp->buf;
			break;

		case Receiver_Header:
			n = DIAMETER_HEADER_LEN - sp->buf_len; /* waiting for rest of header */
			dst = sp->buf+sp->buf_len;
			break;

		case Receiver_Rest_of_Message:
			n = sp->length - sp->msg_len;	/* waiting for the rest of the message */
			dst = sp->msg+sp->msg_len;
			break;

		default:
			LM_ERR("do_receive(): [%.*s] Unknown state %d\n",
					sp->p?sp->p->fqdn.len:0,
					sp->p?sp->p->fqdn.s:0,
					sp->state);
			goto error_and_reset;
	}

	cnt = recv(sp->tcp_socket,dst,n,0);

	if (cnt<=0)
		goto error_and_reset;

	switch (sp->state){
		case Receiver_Waiting:
			version = (unsigned char)(sp->buf[0]);
			if (version!=1) {
				LM_ERR("do_receive(): [%.*s] Received Unknown version [%d]\n",
						sp->p->fqdn.len,
						sp->p->fqdn.s,
						(unsigned char)sp->buf[0]);
				goto error_and_reset;
			}else{
				sp->state = Receiver_Header;
				sp->buf_len = 1;
			}
			break;

		case Receiver_Header:
			sp->buf_len+=cnt;
			if (sp->buf_len==DIAMETER_HEADER_LEN){
				sp->length = get_3bytes(sp->buf+1);
				if (sp->length>DP_MAX_MSG_LENGTH){
					LM_ERR("do_receive(): [%.*s] Msg too big [%d] bytes\n",
							sp->p?sp->p->fqdn.len:0,
							sp->p?sp->p->fqdn.s:0,
							sp->length);
					goto error_and_reset;
				}
				LM_DBG("receive_loop(): [%.*s] Recv Version %d Length %d\n",
						sp->p?sp->p->fqdn.len:0,
						sp->p?sp->p->fqdn.s:0,
						(unsigned char)(sp->buf[0]),
						sp->length);
				sp->msg = shm_malloc(sp->length);
				if (!sp->msg) {
					LOG_NO_MEM("shm",sp->length);
					goto error_and_reset;
				}

				memcpy(sp->msg,sp->buf,sp->buf_len);
				sp->msg_len=sp->buf_len;
				sp->state = Receiver_Rest_of_Message;
			}
			break;

		case Receiver_Rest_of_Message:
			sp->msg_len+=cnt;
			if (sp->msg_len==sp->length){
				dmsg = AAATranslateMessage((unsigned char*)sp->msg,(unsigned int)sp->msg_len,1);
				if (dmsg) {
					sp->msg = 0;
					receive_message(dmsg,sp);
				}
				else {
					shm_free(sp->msg);
					sp->msg = 0;
				}
				sp->msg_len = 0;
				sp->buf_len = 0;
				sp->state = Receiver_Waiting;
			}
			break;

		default:
			LM_ERR("do_receive(): [%.*s] Unknown state %d\n",
					sp->p?sp->p->fqdn.len:0,
					sp->p?sp->p->fqdn.s:0,
					sp->state);
			goto error_and_reset;
	}
	return 1;
error_and_reset:
	if (sp->msg){
		shm_free(sp->msg);
		sp->msg = 0;
		sp->msg_len = 0;
		sp->buf_len = 0;
		sp->state = Receiver_Waiting;
	}
	return 0;
}
Exemplo n.º 20
0
/*!
 * \brief Function that is registered as TM callback and called on replies
 *
 * Function that is registered as TM callback and called on replies. It
 * parses the reply and set the appropriate event. This is then used to
 * update the dialog state, run eventual dialog callbacks and save or
 * update the necessary informations about the dialog.
 * \see next_state_dlg
 * \param t transaction, unused
 * \param type type of the entered callback
 * \param param saved dialog structure in the callback
 */
static void dlg_onreply(struct cell* t, int type, struct tmcb_params *param)
{
    dlg_cell_t *dlg = NULL;
	dlg_iuid_t *iuid = NULL;
    int new_state, old_state, unref, event;
    str tag;
    sip_msg_t *req = param->req;
	sip_msg_t *rpl = param->rpl;

	if (shutdown_done)
		return;
	iuid = (dlg_iuid_t*)(*param->param);
	dlg = dlg_get_by_iuid(iuid);
	if(dlg==0)
		return;

	unref = 0;
	if (type & (TMCB_RESPONSE_IN|TMCB_ON_FAILURE)) {
		/* Set the dialog context so it is available in onreply_route and failure_route*/
		set_current_dialog(req, dlg);
		dlg_set_ctx_iuid(dlg);
		goto done;
	}

	if (type==TMCB_RESPONSE_FWDED) {
		/* The state does not change, but the msg is mutable in this callback*/
		run_dlg_callbacks(DLGCB_RESPONSE_FWDED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
		goto done;
	}

	if (type==TMCB_DESTROY)
		event = DLG_EVENT_TDEL;
	else if (param->code<200)
		event = DLG_EVENT_RPL1xx;
	else if (param->code<300)
		event = DLG_EVENT_RPL2xx;
	else
		event = DLG_EVENT_RPL3xx;

	next_state_dlg( dlg, event, &old_state, &new_state, &unref);
	dlg_run_event_route(dlg, (rpl==FAKED_REPLY)?NULL:rpl, old_state, new_state);

	if (new_state==DLG_STATE_EARLY) {
		run_dlg_callbacks(DLGCB_EARLY, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
		if (old_state!=DLG_STATE_EARLY)
			if_update_stat(dlg_enable_stats, early_dlgs, 1);
		goto done;
	}

	if (new_state==DLG_STATE_CONFIRMED_NA &&
	old_state!=DLG_STATE_CONFIRMED_NA && old_state!=DLG_STATE_CONFIRMED ) {
		LM_DBG("dialog %p confirmed (ACK pending)\n",dlg);

		 if (rpl != FAKED_REPLY) {
			/* get to tag*/
			if ( !rpl->to && ((parse_headers(rpl, HDR_TO_F,0)<0)
						|| !rpl->to) ) {
				LM_ERR("bad reply or missing TO hdr :-/\n");
				tag.s = 0;
				tag.len = 0;
			} else {
				tag = get_to(rpl)->tag_value;
				if (tag.s==0 || tag.len==0) {
					LM_ERR("missing TAG param in TO hdr :-/\n");
					tag.s = 0;
					tag.len = 0;
				}
			}

			/* save callee's tag, cseq, contact and record route*/
			if (populate_leg_info( dlg, rpl, t, DLG_CALLEE_LEG, &tag) !=0) {
				LM_ERR("could not add further info to the dialog\n");
			}
		 } else {
			 LM_ERR("Faked reply!\n");
		 }

		/* set start time */
		dlg->start_ts = (unsigned int)(time(0));

		/* save the settings to the database,
		 * if realtime saving mode configured- save dialog now
		 * else: the next time the timer will fire the update*/
		dlg->dflags |= DLG_FLAG_NEW;
		if ( dlg_db_mode==DB_MODE_REALTIME )
			update_dialog_dbinfo(dlg);

		if (0 != insert_dlg_timer( &dlg->tl, dlg->lifetime )) {
			LM_CRIT("Unable to insert dlg %p [%u:%u] on event %d [%d->%d] "
				"with clid '%.*s' and tags '%.*s' '%.*s'\n",
				dlg, dlg->h_entry, dlg->h_id, event, old_state, new_state,
				dlg->callid.len, dlg->callid.s,
				dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
				dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
		} else {
			/* dialog pointer inserted in timer list */
			dlg_ref(dlg, 1);
		}

		/* dialog confirmed (ACK pending) */
		run_dlg_callbacks( DLGCB_CONFIRMED_NA, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);

		if (old_state==DLG_STATE_EARLY)
			if_update_stat(dlg_enable_stats, early_dlgs, -1);

		if (unref) dlg_unref(dlg, unref);
		if_update_stat(dlg_enable_stats, active_dlgs, 1);
		goto done;
	}

	if ( new_state==DLG_STATE_DELETED
				&& (old_state==DLG_STATE_UNCONFIRMED
					|| old_state==DLG_STATE_EARLY) ) {
		LM_DBG("dialog %p failed (negative reply)\n", dlg);
		/* dialog setup not completed (3456XX) */
		run_dlg_callbacks( DLGCB_FAILED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
		if(dlg_wait_ack==1)
			dlg_set_tm_waitack(t, dlg);
		/* do unref */
		if (unref)
			dlg_unref(dlg, unref);
		if (old_state==DLG_STATE_EARLY)
			if_update_stat(dlg_enable_stats, early_dlgs, -1);

		if_update_stat(dlg_enable_stats, failed_dlgs, 1);

		goto done;
	}

	if (unref) dlg_unref(dlg, unref);

done:
	/* unref due to dlg_get_by_iuid() */
	dlg_release(dlg);
	return;
}
Exemplo n.º 21
0
/**
 * Initiate a connection to a peer.
 * The obtained socket is then sent to the respective receiver.
 * This is typically called from the timer, but otherwise it can be called from any other process.
 * @param p - peer to connect to
 * @returns socket if OK, -1 on error
 */
int peer_connect(peer *p)
{
	int sock;
	unsigned int option = 1;

	struct addrinfo *ainfo=0,*res=0,*sainfo=0,hints;
	char buf[256],host[256],serv[256];
	int error;

	memset (&hints, 0, sizeof(hints));
	//hints.ai_protocol = IPPROTO_SCTP;
	//hints.ai_protocol = IPPROTO_TCP;
	hints.ai_flags = AI_ADDRCONFIG;
	hints.ai_socktype = SOCK_STREAM;

	sprintf(buf,"%d",p->port);

	error = getaddrinfo(p->fqdn.s, buf, &hints, &res);

	if (error!=0){
		LM_WARN("peer_connect(): Error opening connection to %.*s:%d >%s\n",
				p->fqdn.len,p->fqdn.s,p->port,gai_strerror(error));
		goto error;
	}

	for(ainfo = res;ainfo;ainfo = ainfo->ai_next)
	{
		if (getnameinfo(ainfo->ai_addr,ainfo->ai_addrlen,
					host,256,serv,256,NI_NUMERICHOST|NI_NUMERICSERV)==0){
			LM_WARN("peer_connect(): Trying to connect to %s port %s\n",
					host,serv);
		}

		if ((sock = socket(ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol)) == -1) {
			LM_ERR("peer_connect(): error creating client socket to %s port %s >"
					" %s\n",host,serv,strerror(errno));
			continue;
		}

		/* try to set the local socket used to connect to the peer */
		if (p->src_addr.s && p->src_addr.len > 0) {
			LM_DBG("peer_connect(): connetting to peer via src addr=%.*s",p->src_addr.len, p->src_addr.s);
			memset (&hints, 0, sizeof(hints));
			hints.ai_flags = AI_NUMERICHOST;
			hints.ai_socktype = SOCK_STREAM;
			error = getaddrinfo(p->src_addr.s, NULL, &hints, &sainfo);

			if (error!=0){
				LM_WARN("peer_connect(): error getting client socket on %.*s:%s\n",
						p->src_addr.len,p->src_addr.s,gai_strerror(error));
			} else {
				if (bind(sock, sainfo->ai_addr, sainfo->ai_addrlen )) {
					LM_WARN("peer_connect(): error opening client socket on %.*s:%s\n",
							p->src_addr.len,p->src_addr.s,strerror(errno));
				}
			}
		}

		{// Connect with timeout
			int x;
			x=fcntl(sock,F_GETFL,0);
			fcntl(sock,F_SETFL,x | O_NONBLOCK);
			int res = connect(sock,ainfo->ai_addr,ainfo->ai_addrlen);
			if (res<0){
				if (errno==EINPROGRESS){
					struct timeval tv={
						.tv_sec = config->connect_timeout,
						.tv_usec = 0,
					};
					fd_set myset;
					FD_ZERO(&myset);
					FD_SET(sock, &myset);
					if (select(sock+1, NULL, &myset, NULL, &tv) > 0) {
						socklen_t lon = sizeof(int);
						int  valopt;
						getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon);
						if (valopt) {
							LM_WARN("peer_connect(): Error opening connection to to %s port %s >%s\n",host,serv,strerror(valopt));
							close(sock);
							continue;
						}
					}else{
						LM_WARN("peer_connect(): Timeout or error opening connection to to %s port %s >%s\n",host,serv,strerror(errno));
						close(sock);
						continue;
					}
				}
			}else{
				LM_WARN("peer_connect(): Error opening connection to to %s port %s >%s\n",host,serv,strerror(errno));
				close(sock);
				continue;
			}

			x=fcntl(sock,F_GETFL,0);
			fcntl(sock,F_SETFL,x & (~O_NONBLOCK));
		}
		setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&option,sizeof(option));

		LM_INFO("peer_connect(): Peer %.*s:%d connected\n",p->fqdn.len,p->fqdn.s,p->port);

		if (!send_fd(p->fd_exchange_pipe,sock,p)){
			LM_ERR("peer_connect(): [%.*s] Error sending fd to respective receiver\n",p->fqdn.len,p->fqdn.s);
			close(sock);
			goto error;
		}

		if (res) freeaddrinfo(res);
		return sock;
	}
error:
	if (res) freeaddrinfo(res);
	return -1;
}
Exemplo n.º 22
0
/*!
 * \brief Create a new dialog from a sip message
 *
 * Create a new dialog from a SIP message, register a callback
 * to keep track of the dialog with help of the tm module.
 * This function is either called from the request callback, or
 * from the dlg_manage function in the configuration script.
 * \see dlg_onreq
 * \see w_dlg_manage
 * \param req SIP message
 * \param t transaction
 * \param run_initial_cbs if set zero, initial callbacks are not executed
 * \return 0 on success, -1 on failure
 */ 
int dlg_new_dialog(sip_msg_t *req, struct cell *t, const int run_initial_cbs)
{
	dlg_cell_t *dlg;
	str s;
	str callid;
    str ftag;
    str ttag;
    str req_uri;
    unsigned int dir;
    int mlock;

	dlg = dlg_get_ctx_dialog();
    if(dlg != NULL) {
		dlg_release(dlg);
        return -1;
	}

	if(req->first_line.u.request.method_value != METHOD_INVITE)
		return -1;

    if(pre_match_parse( req, &callid, &ftag, &ttag, 0)<0) {
        LM_WARN("pre-matching failed\n");
        return -1;
    }

    if(ttag.s!=0 && ttag.len!=0)
        return -1;

    if(pv_printf_s(req, ruri_param_model, &req_uri)<0) {
        LM_ERR("error - cannot print the r-uri format\n");
        return -1;
    }
    trim(&req_uri);

	dir = DLG_DIR_NONE;
	mlock = 1;
	/* search dialog by SIP attributes
	 * - if not found, hash table slot is left locked, to avoid races
	 *   to add 'same' dialog on parallel forking or not-handled-yet
	 *   retransmissions. Release slot after linking new dialog */
	dlg = search_dlg(&callid, &ftag, &ttag, &dir);
	if(dlg) {
		mlock = 0;
		if (detect_spirals) {
			if (spiral_detected == 1)
				return 0;

			if ( dlg->state != DLG_STATE_DELETED ) {
				LM_DBG("Callid '%.*s' found, must be a spiraled request\n",
					callid.len, callid.s);
				spiral_detected = 1;

				if (run_initial_cbs)
					run_dlg_callbacks( DLGCB_SPIRALED, dlg, req, NULL,
							DLG_DIR_DOWNSTREAM, 0);
				/* set ctx dlg id shortcuts */
				_dlg_ctx.iuid.h_entry = dlg->h_entry;
				_dlg_ctx.iuid.h_id = dlg->h_id;
				/* search_dlg() has incremented the ref count by 1 */
				dlg_release(dlg);
				return 0;
			}
			dlg_release(dlg);
        }
    }
    spiral_detected = 0;

    dlg = build_new_dlg (&callid /*callid*/,
                         &(get_from(req)->uri) /*from uri*/,
                         &(get_to(req)->uri) /*to uri*/,
                         &ftag/*from_tag*/,
                         &req_uri /*r-uri*/ );

	if (dlg==0) {
		if(likely(mlock==1)) dlg_hash_release(&callid);
		LM_ERR("failed to create new dialog\n");
		return -1;
	}

	/* save caller's tag, cseq, contact and record route*/
	if (populate_leg_info(dlg, req, t, DLG_CALLER_LEG,
			&(get_from(req)->tag_value)) !=0) {
		if(likely(mlock==1)) dlg_hash_release(&callid);
		LM_ERR("could not add further info to the dialog\n");
		shm_free(dlg);
		return -1;
	}

	/* Populate initial varlist: */
	dlg->vars = get_local_varlist_pointer(req, 1);

	/* if search_dlg() returned NULL, slot was kept locked */
	link_dlg(dlg, 0, mlock);
	if(likely(mlock==1)) dlg_hash_release(&callid);

	dlg->lifetime = get_dlg_timeout(req);
	s.s   = _dlg_ctx.to_route_name;
	s.len = strlen(s.s);
	dlg_set_toroute(dlg, &s);
	dlg->sflags |= _dlg_ctx.flags;
	dlg->iflags |= _dlg_ctx.iflags;

	if (dlg_send_bye!=0 || _dlg_ctx.to_bye!=0)
		dlg->iflags |= DLG_IFLAG_TIMEOUTBYE;

    if (run_initial_cbs)  run_create_callbacks( dlg, req);

	/* first INVITE seen (dialog created, unconfirmed) */
	if ( seq_match_mode!=SEQ_MATCH_NO_ID &&
			add_dlg_rr_param( req, dlg->h_entry, dlg->h_id)<0 ) {
		LM_ERR("failed to add RR param\n");
		goto error;
	}

    if_update_stat( dlg_enable_stats, processed_dlgs, 1);

	_dlg_ctx.cpid = my_pid();
    _dlg_ctx.iuid.h_entry = dlg->h_entry;
    _dlg_ctx.iuid.h_id = dlg->h_id;
    set_current_dialog(req, dlg);

	return 0;

error:
	if (!spiral_detected)
		dlg_unref(dlg, 1);               // undo ref regarding linking
	return -1;
}
Exemplo n.º 23
0
char* parse_fline(char* buffer, char* end, struct msg_start* fl)
{
	char* tmp;
	register int state;
	unsigned short stat;

	stat=0;
	fl->type=SIP_REQUEST;
	state=START;
	for(tmp=buffer;tmp<end;tmp++){
		switch(*tmp){
			case ' ':
			case '\t':
				switch(state){
					case START: /*allow space at the beginning, although not
								  legal*/
						break;
					case L_URI:
					case L_VER:
					case L_STATUS:
					case L_REASON:
					case L_LF:
						 /*eat  space*/
						break;
					case FIN_INVITE:
						*tmp=0;
						fl->u.request.method.len=tmp-fl->u.request.method.s;
						fl->u.request.method_value=METHOD_INVITE;
						state=L_URI;
						break;
					case FIN_ACK:
						*tmp=0;
						fl->u.request.method.len=tmp-fl->u.request.method.s;
						fl->u.request.method_value=METHOD_ACK;
						state=L_URI;
						break;
					case FIN_CANCEL:
						*tmp=0;
						fl->u.request.method.len=tmp-fl->u.request.method.s;
						fl->u.request.method_value=METHOD_CANCEL;
						state=L_URI;
						break;
					case FIN_BYE:
						*tmp=0;
						fl->u.request.method.len=tmp-fl->u.request.method.s;
						fl->u.request.method_value=METHOD_BYE;
						state=L_URI;
						break;
					case FIN_SIP:
						*tmp=0;
						fl->u.reply.version.len=tmp-fl->u.reply.version.s;
						state=L_STATUS;
						fl->type=SIP_REPLY;
						break;
					case P_URI:
						*tmp=0;
						fl->u.request.uri.len=tmp-fl->u.request.uri.s;
						state=L_VER;
						break;
					case FIN_VER:
						*tmp=0;
						fl->u.request.version.len=tmp-fl->u.request.version.s;
						state=L_LF;
						break;
					case P_STATUS:
						*tmp=0;
						fl->u.reply.status.len=tmp-fl->u.reply.status.s;
						state=L_REASON;
						break;
					case P_REASON:
					 /*	*tmp=0;
						fl->u.reply.reason.len=tmp-fl->u.reply.reason.s;
						*/
						break;
					case VER1:
					case VER2:
					case VER3:
					case VER4:
					case VER5:
					case VER6:
						LM_ERR("invalid version in request\n");
						goto error;
					case P_METHOD:
					default:
						*tmp=0;
						fl->u.request.method.len=tmp-fl->u.request.method.s;
						fl->u.request.method_value=METHOD_OTHER;
						state=L_URI;
				}
				break;
			case 's':
			case 'S':
				switch(state){
					case START:
						state=SIP1;
						fl->u.reply.version.s=tmp;
						break;
					case P_URI:
					case P_REASON:
					case P_METHOD:
						break;
					case L_REASON:
						fl->u.reply.reason.s=tmp;
						state=P_REASON;
						break;
					case P_STATUS:
					case L_STATUS:
						LM_ERR("non-number character <%c> in request"
								"status\n", *tmp);
						goto error;
					case L_LF:
						LM_ERR("invalid character <%c> in request\n", *tmp);
						goto error;
					case L_URI:
						fl->u.request.uri.s=tmp;
						state=P_URI;
						break;
					case L_VER:
						fl->u.request.version.s=tmp;
						state=VER1;
						break;
					case VER1:
					case VER2:
					case VER3:
					case VER4:
					case VER5:
					case VER6:
					case FIN_VER:
						LM_ERR("invalid version in request\n");
						goto error;
					default:
						state=P_METHOD;
				}
				break;

			case 'i':
			case 'I':
				switch(state){
					case START:
						state=INVITE1;
						fl->u.request.method.s=tmp;
						break;
					case INVITE3:
						state=INVITE4;
						break;
					case SIP1:
						state=SIP2;
						break;
					case P_URI:
					case P_REASON:
					case P_METHOD:
						break;
					case L_REASON:
						fl->u.reply.reason.s=tmp;
						state=P_REASON;
						break;
					case P_STATUS:
					case L_STATUS:
						LM_ERR("non-number "
								"character <%c> in request status\n", *tmp);
						goto error;
					case L_LF:
						LM_ERR("invalid "
								"character <%c> in request\n", *tmp);
						goto error;
					case L_URI:
						fl->u.request.uri.s=tmp;
						state=P_URI;
						break;
					case VER1:
						state=VER2;
						break;
					case L_VER:
					case VER2:
					case VER3:
					case VER4:
					case VER5:
					case VER6:
					case FIN_VER:
						LM_ERR("invalid version in request\n");
						goto error;
					default:
						state=P_METHOD;
				}
				break;

			case 'p':
			case 'P':
				switch(state){
					case START:
						state=P_METHOD;
						fl->u.request.method.s=tmp;
						break;
					case SIP2:
						state=SIP3;
						break;
					case P_URI:
					case P_REASON:
					case P_METHOD:
						break;
					case L_REASON:
						fl->u.reply.reason.s=tmp;
						state=P_REASON;
						break;
					case P_STATUS:
					case L_STATUS:
						LM_ERR("non-number "
								"character <%c> in request status\n", *tmp);
						goto error;
					case L_LF:
						LM_ERR("invalid "
								"character <%c> in request\n", *tmp);
						goto error;
					case L_URI:
						fl->u.request.uri.s=tmp;
						state=P_URI;
						break;
					case VER2:
						state=VER3;
						break;
					case L_VER:
					case VER1:
					case VER3:
					case VER4:
					case VER5:
					case VER6:
					case FIN_VER:
						LM_ERR("invalid version in request\n");
						goto error;
					default:
						state=P_METHOD;
				}
				break;


			case '/':
				switch(state){
					case START:
						state=P_METHOD;
						fl->u.request.method.s=tmp;
						break;
					case SIP3:
						state=SIP4;
						break;
					case P_URI:
					case P_REASON:
					case P_METHOD:
						break;
					case L_REASON:
						fl->u.reply.reason.s=tmp;
						state=P_REASON;
						break;
					case P_STATUS:
					case L_STATUS:
						LM_ERR("non-number "
								"character <%c> in request status\n", *tmp);
						goto error;
					case L_LF:
						LM_ERR("invalid "
								"character <%c> in request\n", *tmp);
						goto error;
					case L_URI:
						fl->u.request.uri.s=tmp;
						state=P_URI;
						break;
					case VER3:
						state=VER4;
						break;
					case L_VER:
					case VER1:
					case VER2:
					case VER4:
					case VER5:
					case VER6:
					case FIN_VER:
						LM_ERR("invalid version in request\n");
						goto error;
					default:
						state=P_METHOD;
				}
				break;

			case '2':
				switch(state){
					case START:
						state=P_METHOD;
						fl->u.request.method.s=tmp;
						break;
					case SIP4:
						state=SIP5;
						break;
					case P_URI:
					case P_REASON:
					case P_METHOD:
						break;
					case L_REASON:
						fl->u.reply.reason.s=tmp;
						state=P_REASON;
						break;
					case P_STATUS:
						stat=stat*10+*tmp-'0';
						break;
					case L_STATUS:
						stat=*tmp-'0';
						fl->u.reply.status.s=tmp;
						break;
					case L_LF:
						LM_ERR("invalid "
								"character <%c> in request\n", *tmp);
						goto error;
					case L_URI:
						fl->u.request.uri.s=tmp;
						state=P_URI;
						break;
					case VER4:
						state=VER5;
						break;
					case L_VER:
					case VER1:
					case VER2:
					case VER3:
					case VER5:
					case VER6:
					case FIN_VER:
						LM_ERR("invalid version in request\n");
						goto error;
					default:
						state=P_METHOD;
				}
				break;

			case '.':
				switch(state){
					case START:
						state=P_METHOD;
						fl->u.request.method.s=tmp;
						break;
					case SIP5:
						state=SIP6;
						break;
					case P_URI:
					case P_REASON:
					case P_METHOD:
						break;
					case L_REASON:
						fl->u.reply.reason.s=tmp;
						state=P_REASON;
						break;
					case P_STATUS:
					case L_STATUS:
						LM_ERR("non-number "
								"character <%c> in request status\n", *tmp);
						goto error;
					case L_LF:
						LM_ERR("invalid "
								"character <%c> in request\n", *tmp);
						goto error;
					case L_URI:
						fl->u.request.uri.s=tmp;
						state=P_URI;
						break;
					case VER5:
						state=VER6;
						break;
					case L_VER:
					case VER1:
					case VER2:
					case VER3:
					case VER4:
					case VER6:
					case FIN_VER:
						LM_ERR("invalid version in request\n");
						goto error;
					default:
						state=P_METHOD;
				}
				break;

			case '0':
				switch(state){
					case START:
						state=P_METHOD;
						fl->u.request.method.s=tmp;
						break;
					case SIP6:
						state=FIN_SIP;
						break;
					case P_URI:
					case P_REASON:
					case P_METHOD:
						break;
					case L_REASON:
						fl->u.reply.reason.s=tmp;
						state=P_REASON;
						break;
					case P_STATUS:
						stat=stat*10;
						break;
					case L_STATUS:
						stat=0;
						fl->u.reply.status.s=tmp;
						break;
					case L_LF:
						LM_ERR("invalid "
								"character <%c> in request\n", *tmp);
						goto error;
					case L_URI:
						fl->u.request.uri.s=tmp;
						state=P_URI;
						break;
					case VER6:
						state=FIN_VER;
						break;
					case L_VER:
					case VER1:
					case VER2:
					case VER3:
					case VER4:
					case VER5:
					case FIN_VER:
						LM_ERR("invalid version "
								" in request\n");
						goto error;
					default:
						state=P_METHOD;
				}
				break;

			case 'n':
			case 'N':
				switch(state){
					case START:
						state=P_METHOD;
						fl->u.request.method.s=tmp;
						break;
					case INVITE1:
						state=INVITE2;
						break;
					case CANCEL2:
						state=CANCEL3;
						break;
					case P_URI:
					case P_REASON:
					case P_METHOD:
						break;
					case L_REASON:
						fl->u.reply.reason.s=tmp;
						state=P_REASON;
						break;
					case P_STATUS:
					case L_STATUS:
						LM_ERR("non-number "
								"character <%c> in request status\n", *tmp);
						goto error;
					case L_LF:
						LM_ERR("invalid "
								"character <%c> in request\n", *tmp);
						goto error;
					case L_URI:
						fl->u.request.uri.s=tmp;
						state=P_URI;
						break;
					case L_VER:
					case VER1:
					case VER2:
					case VER3:
					case VER4:
					case VER5:
					case VER6:
					case FIN_VER:
						LM_ERR("invalid version in request\n");
						goto error;
					default:
						state=P_METHOD;
				}
				break;

			case 'v':
			case 'V':
				switch(state){
					case START:
						state=P_METHOD;
						fl->u.request.method.s=tmp;
						break;
					case INVITE2:
						state=INVITE3;
						break;
					case P_URI:
					case P_REASON:
					case P_METHOD:
						break;
					case L_REASON:
						fl->u.reply.reason.s=tmp;
						state=P_REASON;
						break;
					case P_STATUS:
					case L_STATUS:
						LM_ERR("non-number "
								"character <%c> in request status\n", *tmp);
						goto error;
					case L_LF:
						LM_ERR("invalid "
								"character <%c> in request\n", *tmp);
						goto error;
					case L_URI:
						fl->u.request.uri.s=tmp;
						state=P_URI;
						break;
					case L_VER:
					case VER1:
					case VER2:
					case VER3:
					case VER4:
					case VER5:
					case VER6:
					case FIN_VER:
						LM_ERR("invalid version in request\n");
						goto error;
					default:
						state=P_METHOD;
				}
				break;

			case 't':
			case 'T':
				switch(state){
					case START:
						state=P_METHOD;
						fl->u.request.method.s=tmp;
						break;
					case INVITE4:
						state=INVITE5;
						break;
					case P_URI:
					case P_REASON:
					case P_METHOD:
						break;
					case L_REASON:
						fl->u.reply.reason.s=tmp;
						state=P_REASON;
						break;
					case P_STATUS:
					case L_STATUS:
						LM_ERR("non-number "
								"character <%c> in request status\n", *tmp);
						goto error;
					case L_LF:
						LM_ERR("invalid "
								"character <%c> in request\n", *tmp);
						goto error;
					case L_URI:
						fl->u.request.uri.s=tmp;
						state=P_URI;
						break;
					case L_VER:
					case VER1:
					case VER2:
					case VER3:
					case VER4:
					case VER5:
					case VER6:
					case FIN_VER:
						LM_ERR("invalid version in request\n");
						goto error;
					default:
						state=P_METHOD;
				}
				break;

			case 'e':
			case 'E':
				switch(state){
					case START:
						state=P_METHOD;
						fl->u.request.method.s=tmp;
						break;
					case INVITE5:
						state=FIN_INVITE;
						break;
					case CANCEL4:
						state=CANCEL5;
						break;
					case BYE2:
						state=FIN_BYE;
						break;
					case P_URI:
					case P_REASON:
					case P_METHOD:
						break;
					case L_REASON:
						fl->u.reply.reason.s=tmp;
						state=P_REASON;
						break;
					case P_STATUS:
					case L_STATUS:
						LM_ERR("non-number "
								"character <%c> in request status\n", *tmp);
						goto error;
					case L_LF:
						LM_ERR("invalid "
								"character <%c> in request\n", *tmp);
						goto error;
					case L_URI:
						fl->u.request.uri.s=tmp;
						state=P_URI;
						break;
					case L_VER:
					case VER1:
					case VER2:
					case VER3:
					case VER4:
					case VER5:
					case VER6:
					case FIN_VER:
						LM_ERR("invalid version in request\n");
						goto error;
					default:
						state=P_METHOD;
				}
				break;

			case 'a':
			case 'A':
				switch(state){
					case START:
						state=ACK1;
						fl->u.request.method.s=tmp;
						break;
					case CANCEL1:
						state=CANCEL2;
						break;
					case BYE2:
						state=FIN_BYE;
						break;
					case P_URI:
					case P_REASON:
					case P_METHOD:
						break;
					case L_REASON:
						fl->u.reply.reason.s=tmp;
						state=P_REASON;
						break;
					case P_STATUS:
					case L_STATUS:
						LM_ERR("non-number "
								"character <%c> in request status\n", *tmp);
						goto error;
					case L_LF:
						LM_ERR("invalid "
								"character <%c> in request\n", *tmp);
						goto error;
					case L_URI:
						fl->u.request.uri.s=tmp;
						state=P_URI;
						break;
					case L_VER:
					case VER1:
					case VER2:
					case VER3:
					case VER4:
					case VER5:
					case VER6:
					case FIN_VER:
						LM_ERR("invalid version in request\n");
						goto error;
					default:
						state=P_METHOD;
				}
				break;

			case 'c':
			case 'C':
				switch(state){
					case START:
						state=CANCEL1;
						fl->u.request.method.s=tmp;
						break;
					case CANCEL3:
						state=CANCEL4;
						break;
					case ACK1:
						state=ACK2;
						break;
					case P_URI:
					case P_REASON:
					case P_METHOD:
						break;
					case L_REASON:
						fl->u.reply.reason.s=tmp;
						state=P_REASON;
						break;
					case P_STATUS:
					case L_STATUS:
						LM_ERR("non-number "
								"character <%c> in request status\n", *tmp);
						goto error;
					case L_LF:
						LM_ERR("invalid "
								"character <%c> in request\n", *tmp);
						goto error;
					case L_URI:
						fl->u.request.uri.s=tmp;
						state=P_URI;
						break;
					case L_VER:
					case VER1:
					case VER2:
					case VER3:
					case VER4:
					case VER5:
					case VER6:
					case FIN_VER:
						LM_ERR("invalid version in request\n");
						goto error;
					default:
						state=P_METHOD;
				}
				break;

			case 'k':
			case 'K':
				switch(state){
					case START:
						state=P_METHOD;
						fl->u.request.method.s=tmp;
						break;
					case ACK2:
						state=FIN_ACK;
						break;
					case P_URI:
					case P_REASON:
					case P_METHOD:
						break;
					case L_REASON:
						fl->u.reply.reason.s=tmp;
						state=P_REASON;
						break;
					case P_STATUS:
					case L_STATUS:
						LM_ERR("non-number "
								"character <%c> in request status\n", *tmp);
						goto error;
					case L_LF:
						LM_ERR("invalid "
								"character <%c> in request\n", *tmp);
						goto error;
					case L_URI:
						fl->u.request.uri.s=tmp;
						state=P_URI;
						break;
					case L_VER:
					case VER1:
					case VER2:
					case VER3:
					case VER4:
					case VER5:
					case VER6:
					case FIN_VER:
						LM_ERR("invalid version in request\n");
						goto error;
					default:
						state=P_METHOD;
				}
				break;

			case 'l':
			case 'L':
				switch(state){
					case START:
						state=P_METHOD;
						fl->u.request.method.s=tmp;
						break;
					case CANCEL5:
						state=FIN_CANCEL;
						break;
					case P_URI:
					case P_REASON:
					case P_METHOD:
						break;
					case L_REASON:
						fl->u.reply.reason.s=tmp;
						state=P_REASON;
						break;
					case P_STATUS:
					case L_STATUS:
						LM_ERR("non-number "
								"character <%c> in request status\n", *tmp);
						goto error;
					case L_LF:
						LM_ERR("invalid "
								"character <%c> in request\n", *tmp);
						goto error;
					case L_URI:
						fl->u.request.uri.s=tmp;
						state=P_URI;
						break;
					case L_VER:
					case VER1:
					case VER2:
					case VER3:
					case VER4:
					case VER5:
					case VER6:
					case FIN_VER:
						LM_ERR("invalid version in request\n");
						goto error;
					default:
						state=P_METHOD;
				}
				break;

			case 'b':
			case 'B':
				switch(state){
					case START:
						state=BYE1;
						fl->u.request.method.s=tmp;
						break;
					case P_URI:
					case P_REASON:
					case P_METHOD:
						break;
					case L_REASON:
						fl->u.reply.reason.s=tmp;
						state=P_REASON;
						break;
					case P_STATUS:
					case L_STATUS:
						LM_ERR("non-number "
								"character <%c> in request status\n", *tmp);
						goto error;
					case L_LF:
						LM_ERR("invalid "
								"character <%c> in request\n", *tmp);
						goto error;
					case L_URI:
						fl->u.request.uri.s=tmp;
						state=P_URI;
						break;
					case L_VER:
					case VER1:
					case VER2:
					case VER3:
					case VER4:
					case VER5:
					case VER6:
					case FIN_VER:
						LM_ERR("invalid version in request\n");
						goto error;
					default:
						state=P_METHOD;
				}
				break;

			case 'y':
			case 'Y':
				switch(state){
					case START:
						state=P_METHOD;
						fl->u.request.method.s=tmp;
						break;
					case BYE1:
						state=BYE2;
						break;
					case P_URI:
					case P_REASON:
					case P_METHOD:
						break;
					case L_REASON:
						fl->u.reply.reason.s=tmp;
						state=P_REASON;
						break;
					case P_STATUS:
					case L_STATUS:
						LM_ERR("non-number "
								"character <%c> in request status\n", *tmp);
						goto error;
					case L_LF:
						LM_ERR("invalid "
								"character <%c> in request\n", *tmp);
						goto error;
					case L_URI:
						fl->u.request.uri.s=tmp;
						state=P_URI;
						break;
					case L_VER:
					case VER1:
					case VER2:
					case VER3:
					case VER4:
					case VER5:
					case VER6:
					case FIN_VER:
						LM_ERR("invalid version in request\n");
						goto error;
					default:
						state=P_METHOD;
				}
				break;

			case '\r':
				switch(state){
					case P_REASON:
						*tmp=0;
						fl->u.reply.reason.len=tmp-fl->u.reply.reason.s;
						state=F_CR;
						break;
					case L_LF:
						state=F_CR;
						break;
					case FIN_VER:
						*tmp=0;
						fl->u.request.version.len=tmp-fl->u.request.version.s;
						state=F_CR;
						break;
					case L_REASON:
						state=F_CR;
						break;
					default:
						LM_ERR("invalid message\n");
						goto error;
				}
				break;

			case '\n':
				switch(state){
					case P_REASON:
						*tmp=0;
						fl->u.reply.reason.len=tmp-fl->u.reply.reason.s;
						state=F_LF;
						goto skip;
					case FIN_VER:
						*tmp=0;
						fl->u.request.version.len=tmp-fl->u.request.version.s;
						state=F_LF;
						goto skip;
					case L_REASON:
					case L_LF:
					case F_CR:
						state=F_LF;
						goto skip;
					default:
						LM_ERR("invalid message\n");
						goto error;
				}
				break;

			case '1':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
				switch(state){
					case START:
						state=P_METHOD;
						fl->u.request.method.s=tmp;
						break;
					case P_URI:
					case P_REASON:
					case P_METHOD:
						break;
					case L_REASON:
						fl->u.reply.reason.s=tmp;
						state=P_REASON;
						break;
					case P_STATUS:
						stat=stat*10+*tmp-'0';
						break;
					case L_STATUS:
						stat=*tmp-'0';
						state=P_STATUS;
						fl->u.reply.status.s=tmp;
						break;
					case L_LF:
						LM_ERR("invalid character <%c> in request\n", *tmp);
						goto error;
					case L_URI:
						fl->u.request.uri.s=tmp;
						state=P_URI;
						break;
					case L_VER:
					case VER1:
					case VER2:
					case VER3:
					case VER4:
					case VER5:
					case VER6:
					case FIN_VER:
						LM_ERR("invalid version in request\n");
						goto error;
					default:
						state=P_METHOD;
				}

			default:
				switch(state){
					case START:
						state=P_METHOD;
						fl->u.request.method.s=tmp;
						break;
					case P_URI:
					case P_REASON:
					case P_METHOD:
						break;
					case L_REASON:
						fl->u.reply.reason.s=tmp;
						state=P_REASON;
						break;
					case P_STATUS:
					case L_STATUS:
						LM_ERR("non-number "
								"character <%c> in request status\n", *tmp);
						goto error;
					case L_LF:
						LM_ERR("invalid character <%c> in request\n", *tmp);
						goto error;
					case L_URI:
						fl->u.request.uri.s=tmp;
						state=P_URI;
						break;
					case L_VER:
					case VER1:
					case VER2:
					case VER3:
					case VER4:
					case VER5:
					case VER6:
					case FIN_VER:
						LM_ERR("invalid version in request\n");
						goto error;
					default:
						state=P_METHOD;
				}
		}
	}
skip:
	fl->len=tmp-buf;
	if (fl->type==SIP_REPLY){
		fl->u.reply.statuscode=stat;
		/* fl->u.reply.statusclass=stat/100; */
	}
	return tmp;

error:
	LM_ERR("while parsing first line (state=%d)\n", state);
	fl->type=SIP_INVALID;
	return tmp;
}
Exemplo n.º 24
0
static int lua_sr_modf (lua_State *L)
{
	int ret;
	char *luav[MAX_ACTIONS];
	char *argv[MAX_ACTIONS];
	int argc;
	int i;
	int mod_type;
	struct run_act_ctx ra_ctx;
	unsigned modver;
	struct action *act;
	sr31_cmd_export_t* expf;
	sr_lua_env_t *env_L;

	ret = 1;
	act = NULL;
	argc = 0;
	memset(luav, 0, MAX_ACTIONS*sizeof(char*));
	memset(argv, 0, MAX_ACTIONS*sizeof(char*));
	env_L = sr_lua_env_get();
	if(env_L->msg==NULL)
		goto error;

#if 0
	app_lua_dump_stack(L);
#endif
	argc = lua_gettop(L);
	if(argc==0)
	{
		LM_ERR("name of module function not provided\n");
		goto error;
	}
	if(argc>=MAX_ACTIONS)
	{
		LM_ERR("too many parameters\n");
		goto error;
	}
	/* first is function name, then parameters */
	for(i=1; i<=argc; i++)
	{
		if (!lua_isstring(L, i))
		{
			LM_ERR("invalid parameter type (%d)\n", i);
			goto error;
		}
		luav[i-1] = (char*)lua_tostring(L, i);
	}
	/* pkg copy only parameters */
	for(i=1; i<MAX_ACTIONS; i++)
	{
		if(luav[i]!=NULL)
		{
			argv[i] = (char*)pkg_malloc(strlen(luav[i])+1);
			if(argv[i]==NULL)
			{
				LM_ERR("no more pkg\n");
				goto error;
			}
			strcpy(argv[i], luav[i]);
		}
	}

	expf = find_export_record(luav[0], argc-1, 0, &modver);
	if (expf==NULL) {
		LM_ERR("function '%s' is not available\n", luav[0]);
		goto error;
	}
	/* check fixups */
	if (expf->fixup!=NULL && expf->free_fixup==NULL) {
		LM_ERR("function '%s' has fixup - cannot be used\n", luav[0]);
		goto error;
	}
	switch(expf->param_no) {
		case 0:
			mod_type = MODULE0_T;
			break;
		case 1:
			mod_type = MODULE1_T;
			break;
		case 2:
			mod_type = MODULE2_T;
			break;
		case 3:
			mod_type = MODULE3_T;
			break;
		case 4:
			mod_type = MODULE4_T;
			break;
		case 5:
			mod_type = MODULE5_T;
			break;
		case 6:
			mod_type = MODULE6_T;
			break;
		case VAR_PARAM_NO:
			mod_type = MODULEX_T;
			break;
		default:
			LM_ERR("unknown/bad definition for function '%s' (%d params)\n",
					luav[0], expf->param_no);
			goto error;
	}

	act = mk_action(mod_type,  argc+1   /* number of (type, value) pairs */,
					MODEXP_ST, expf,    /* function */
					NUMBER_ST, argc-1,  /* parameter number */
					STRING_ST, argv[1], /* param. 1 */
					STRING_ST, argv[2], /* param. 2 */
					STRING_ST, argv[3], /* param. 3 */
					STRING_ST, argv[4], /* param. 4 */
					STRING_ST, argv[5], /* param. 5 */
					STRING_ST, argv[6]  /* param. 6 */
			);

	if (act==NULL) {
		LM_ERR("action structure could not be created for '%s'\n", luav[0]);
		goto error;
	}

	/* handle fixups */
	if (expf->fixup) {
		if(argc==1)
		{ /* no parameters */
			if(expf->fixup(0, 0)<0)
			{
				LM_ERR("Error in fixup (0) for '%s'\n", luav[0]);
				goto error;
			}
		} else {
			for(i=1; i<argc; i++)
			{
				if(expf->fixup(&(act->val[i+1].u.data), i)<0)
				{
					LM_ERR("Error in fixup (%d) for '%s'\n", i, luav[0]);
					goto error;
				}
				act->val[i+1].type = MODFIXUP_ST;
			}
		}
	}
	init_run_actions_ctx(&ra_ctx);
	ret = do_action(&ra_ctx, act, env_L->msg);

	/* free fixups */
	if (expf->fixup) {
		for(i=1; i<argc; i++)
		{
			if ((act->val[i+1].type == MODFIXUP_ST) && (act->val[i+1].u.data))
			{
				expf->free_fixup(&(act->val[i+1].u.data), i);
			}
		}
	}
	pkg_free(act);
	for(i=0; i<MAX_ACTIONS; i++)
	{
		if(argv[i]!=NULL) pkg_free(argv[i]);
		argv[i] = 0;
	}
	lua_pushinteger(L, ret);
	return 1;

error:
	if(act!=NULL)
		pkg_free(act);
	for(i=0; i<MAX_ACTIONS; i++)
	{
		if(argv[i]!=NULL) pkg_free(argv[i]);
		argv[i] = 0;
	}
	lua_pushinteger(L, -1);
	return 1;
}
Exemplo n.º 25
0
/**
 * init module function
 */
static int mod_init(void)
{
	unsigned int n;
	LM_INFO("Initializing Http Async module\n");

#ifdef STATISTICS
	/* register statistics */
	if (register_module_stats( exports.name, mod_stats)!=0 ) {
		LM_ERR("failed to register core statistics\n");
		return -1;
	}
#endif
	/* sanitize hash_size */
	if (hash_size < 1){
		LM_WARN("hash_size is smaller "
				"than 1  -> rounding from %d to 1\n",
				hash_size);
				hash_size = 1;
	}
	/* check that the hash table size is a power of 2 */
	for( n=0 ; n<(8*sizeof(n)) ; n++) {
		if (hash_size==(1<<n))
			break;
		if (n && hash_size<(1<<n)) {
			LM_WARN("hash_size is not a power "
				"of 2 as it should be -> rounding from %d to %d (n=%d)\n",
				hash_size, 1<<(n-1), n);
			hash_size = 1<<(n-1);
			break;
		}
	}
	/* check 'workers' param */
	if (num_workers < 1) {
		LM_ERR("the 'workers' parameter must be >= 1\n");
		return -1;
	}

	tls_verify_host = tls_verify_host?1:0;
	tls_verify_peer = tls_verify_peer?1:0;

	/* init http parameters list */
	init_query_params(&ah_params);

	if (strncmp("shm", memory_manager, 3) == 0) {
		curl_memory_manager = 0;
	} else if (strncmp("sys", memory_manager, 3) == 0) {
		curl_memory_manager = 1;
	} else {
		LM_ERR("invalid memory_manager parameter: '%s'\n", memory_manager);
		return -1;
	}

	/* init faked sip msg */
	if(faked_msg_init()<0) {
		LM_ERR("failed to init faked sip msg\n");
		return -1;
	}

	if(load_tm_api( &tmb ) < 0) {
		LM_INFO("cannot load the TM-functions - async relay disabled\n");
		memset(&tmb, 0, sizeof(tm_api_t));
	}

	/* allocate workers array */
	workers = shm_malloc(num_workers * sizeof(*workers));
	if(workers == NULL) {
		LM_ERR("error in shm_malloc\n");
		return -1;
	}
	memset(workers, 0, num_workers * sizeof(*workers));

	register_procs(num_workers);

	/* add child to update local config framework structures */
	cfg_register_child(num_workers);

	return 0;
}
Exemplo n.º 26
0
/**
 * puts a table with content of a xavp
 */
static int lua_sr_xavp_get(lua_State *L)
{
	str xavp_name;
	int indx = 0;
	sr_lua_env_t *env_L;
	sr_xavp_t *avp;
	int num_param = 0;
	int param = -1;
	int all_flag = 0;
	int simple_flag = 0;
	lua_Number elem = 1;
	int xavp_size = 0;

	env_L = sr_lua_env_get();
	num_param = lua_gettop(L);
	if(num_param<2 && num_param>3)
	{
		LM_ERR("wrong number of parameters [%d]\n", num_param);
		return 0;
	}

	if(num_param==3)
	{
		if(!lua_isnumber(L, param))
		{
			LM_ERR("invalid int parameter\n");
			return 0;
		}
		simple_flag = lua_tointeger(L, param);
		param = param - 1;
	}

	if(!lua_isnumber(L, param))
	{
		if(lua_isnil(L, param))
		{
			all_flag = 1;
		}
		else
		{
			LM_ERR("invalid parameter, must be int or nil\n");
			return 0;
		}
	}
	else
	{
		indx = lua_tointeger(L, param);
	}
	param = param - 1;
	xavp_name.s = (char*)lua_tostring(L, param);
	if(xavp_name.s==NULL || env_L->msg==NULL)
	{
		LM_ERR("No xavp name in %d param\n", param);
		return 0;
	}
	xavp_name.len = strlen(xavp_name.s);
	if(all_flag>0) {
		indx = 0;
		lua_newtable(L);
	}
	xavp_size = xavp_count(&xavp_name, NULL);
	if(indx<0)
	{
		if((indx*-1)>xavp_size)
		{
			LM_ERR("can't get xavp:%.*s index:%d\n", xavp_name.len, xavp_name.s, indx);
			lua_pushnil(L);
			return 1;
		}
		indx = xavp_size + indx;
	}

	avp = xavp_get_by_index(&xavp_name, indx, NULL);
	do
	{
		if(avp==NULL){
			LM_ERR("can't get xavp:%.*s index:%d\n", xavp_name.len, xavp_name.s, indx);
			lua_pushnil(L);
			return 1;
		}
		if(all_flag!=0) {
			lua_pushnumber(L, elem);
			elem = elem + 1;
		}
		lua_sr_push_xavp_table(L, avp, simple_flag);
		if(all_flag!=0) {
			lua_rawset(L, -3);
			indx = indx + 1;
			avp = xavp_get_by_index(&xavp_name, indx, NULL);
		}
		else return 1;
	}while(avp!=NULL);

	return 1;
}
Exemplo n.º 27
0
static int ah_parse_req_name(pv_spec_p sp, str *in) {
	if(sp==NULL || in==NULL || in->len<=0)
		return -1;

	switch(in->len)
	{
		case 3:
			if(strncmp(in->s, "all", 3)==0)
				sp->pvp.pvn.u.isname.name.n = E_HRN_ALL;
			else if(strncmp(in->s, "hdr", 3)==0)
				sp->pvp.pvn.u.isname.name.n = E_HRN_HDR;
			else goto error;
			break;
		case 4:
			if(strncmp(in->s, "body", 4)==0)
				sp->pvp.pvn.u.isname.name.n = E_HRN_BODY;
			else goto error;
			break;
		case 6:
			if(strncmp(in->s, "method", 6)==0)
				sp->pvp.pvn.u.isname.name.n = E_HRN_METHOD;
			else goto error;
			break;
		case 7:
			if(strncmp(in->s, "timeout", 7)==0)
				sp->pvp.pvn.u.isname.name.n = E_HRN_TIMEOUT;
			else if(strncmp(in->s, "suspend", 7)==0)
				sp->pvp.pvn.u.isname.name.n = E_HRN_SUSPEND;
			else goto error;
			break;
		case 8:
			if(strncmp(in->s, "username", 8)==0)
				sp->pvp.pvn.u.isname.name.n = E_HRN_USERNAME;
			else if(strncmp(in->s, "password", 8)==0)
				sp->pvp.pvn.u.isname.name.n = E_HRN_PASSWORD;
			else goto error;
			break;
		case 10:
			if(strncmp(in->s, "authmethod", 10)==0)
				sp->pvp.pvn.u.isname.name.n = E_HRN_AUTHMETHOD;
			else goto error;
			break;
		case 11:
			if(strncmp(in->s, "tls_ca_path", 11)==0)
				sp->pvp.pvn.u.isname.name.n = E_HRN_TLS_CA_PATH;
			else goto error;
			break;
		case 14:
			if(strncmp(in->s, "tls_client_key", 14)==0)
				sp->pvp.pvn.u.isname.name.n = E_HRN_TLS_CLIENT_KEY;
			else goto error;
			break;
		case 15:
			if(strncmp(in->s, "tls_client_cert", 15)==0)
				sp->pvp.pvn.u.isname.name.n = E_HRN_TLS_CLIENT_CERT;
			else goto error;
			break;
		default:
			goto error;
	}
	sp->pvp.pvn.type = PV_NAME_INTSTR;
	sp->pvp.pvn.u.isname.type = 0;

	return 0;

error:
	LM_ERR("unknown http_req name %.*s\n", in->len, in->s);
	return -1;
}
Exemplo n.º 28
0
int sr_kemi_lua_exec_func_ex(lua_State* L, sr_kemi_t *ket, int pdelta)
{
	int i;
	int argc;
	int ret;
	str *fname;
	str *mname;
	sr_kemi_val_t vps[SR_KEMI_PARAMS_MAX];
	sr_lua_env_t *env_L;

	env_L = sr_lua_env_get();

	if(env_L==NULL || env_L->msg==NULL || ket==NULL) {
		LM_ERR("invalid Lua environment attributes or parameters\n");
		return app_lua_return_false(L);
	}

	fname = &ket->fname;
	mname = &ket->mname;

	argc = lua_gettop(L);
	if(argc==pdelta && ket->ptypes[0]==SR_KEMIP_NONE) {
		ret = ((sr_kemi_fm_f)(ket->func))(env_L->msg);
		return sr_kemi_lua_return_int(L, ket, ret);
	}
	if(argc==pdelta && ket->ptypes[0]!=SR_KEMIP_NONE) {
		LM_ERR("invalid number of parameters for: %.*s.%.*s\n",
				mname->len, mname->s, fname->len, fname->s);
		return app_lua_return_false(L);
	}

	if(argc>=SR_KEMI_PARAMS_MAX+pdelta) {
		LM_ERR("too many parameters for: %.*s.%.*s\n",
				mname->len, mname->s, fname->len, fname->s);
		return app_lua_return_false(L);
	}

	memset(vps, 0, SR_KEMI_PARAMS_MAX*sizeof(sr_kemi_val_t));
	for(i=0; i<SR_KEMI_PARAMS_MAX; i++) {
		if(ket->ptypes[i]==SR_KEMIP_NONE) {
			break;
		} else if(ket->ptypes[i]==SR_KEMIP_STR) {
			vps[i].s.s = (char*)lua_tostring(L, i+pdelta+1);
			vps[i].s.len = strlen(vps[i].s.s);
			LM_DBG("param[%d] for: %.*s is str: %.*s\n", i,
				fname->len, fname->s, vps[i].s.len, vps[i].s.s);
		} else if(ket->ptypes[i]==SR_KEMIP_INT) {
			vps[i].n = lua_tointeger(L, i+pdelta+1);
			LM_DBG("param[%d] for: %.*s is int: %d\n", i,
				fname->len, fname->s, vps[i].n);
		} else {
			LM_ERR("unknown parameter type %d (%d)\n", ket->ptypes[i], i);
			return app_lua_return_false(L);
		}
	}

	switch(i) {
		case 1:
			if(ket->ptypes[0]==SR_KEMIP_INT) {
				ret = ((sr_kemi_fmn_f)(ket->func))(env_L->msg, vps[0].n);
				return sr_kemi_lua_return_int(L, ket, ret);
			} else if(ket->ptypes[0]==SR_KEMIP_STR) {
				ret = ((sr_kemi_fms_f)(ket->func))(env_L->msg, &vps[0].s);
				return sr_kemi_lua_return_int(L, ket, ret);
			} else {
				LM_ERR("invalid parameters for: %.*s\n",
						fname->len, fname->s);
				return app_lua_return_false(L);
			}
		break;
		case 2:
			if(ket->ptypes[0]==SR_KEMIP_INT) {
				if(ket->ptypes[1]==SR_KEMIP_INT) {
					ret = ((sr_kemi_fmnn_f)(ket->func))(env_L->msg, vps[0].n, vps[1].n);
					return sr_kemi_lua_return_int(L, ket, ret);
				} else if(ket->ptypes[1]==SR_KEMIP_STR) {
					ret = ((sr_kemi_fmns_f)(ket->func))(env_L->msg, vps[0].n, &vps[1].s);
					return sr_kemi_lua_return_int(L, ket, ret);
				} else {
					LM_ERR("invalid parameters for: %.*s\n",
							fname->len, fname->s);
					return app_lua_return_false(L);
				}
			} else if(ket->ptypes[0]==SR_KEMIP_STR) {
				if(ket->ptypes[1]==SR_KEMIP_INT) {
					ret = ((sr_kemi_fmsn_f)(ket->func))(env_L->msg, &vps[0].s, vps[1].n);
					return sr_kemi_lua_return_int(L, ket, ret);
				} else if(ket->ptypes[1]==SR_KEMIP_STR) {
					ret = ((sr_kemi_fmss_f)(ket->func))(env_L->msg, &vps[0].s, &vps[1].s);
					return sr_kemi_lua_return_int(L, ket, ret);
				} else {
					LM_ERR("invalid parameters for: %.*s\n",
							fname->len, fname->s);
					return app_lua_return_false(L);
				}
			} else {
				LM_ERR("invalid parameters for: %.*s\n",
						fname->len, fname->s);
				return app_lua_return_false(L);
			}
		break;
		case 3:
			if(ket->ptypes[0]==SR_KEMIP_INT) {
				if(ket->ptypes[1]==SR_KEMIP_INT) {
					if(ket->ptypes[2]==SR_KEMIP_INT) {
						ret = ((sr_kemi_fmnnn_f)(ket->func))(env_L->msg,
								vps[0].n, vps[1].n, vps[2].n);
						return sr_kemi_lua_return_int(L, ket, ret);
					} else if(ket->ptypes[2]==SR_KEMIP_STR) {
						ret = ((sr_kemi_fmnns_f)(ket->func))(env_L->msg,
								vps[0].n, vps[1].n, &vps[2].s);
						return sr_kemi_lua_return_int(L, ket, ret);
					} else {
						LM_ERR("invalid parameters for: %.*s\n",
								fname->len, fname->s);
						return app_lua_return_false(L);
					}
				} else if(ket->ptypes[1]==SR_KEMIP_STR) {
					if(ket->ptypes[2]==SR_KEMIP_INT) {
						ret = ((sr_kemi_fmnsn_f)(ket->func))(env_L->msg,
								vps[0].n, &vps[1].s, vps[2].n);
						return sr_kemi_lua_return_int(L, ket, ret);
					} else if(ket->ptypes[2]==SR_KEMIP_STR) {
						ret = ((sr_kemi_fmnss_f)(ket->func))(env_L->msg,
								vps[0].n, &vps[1].s, &vps[2].s);
						return sr_kemi_lua_return_int(L, ket, ret);
					} else {
						LM_ERR("invalid parameters for: %.*s\n",
								fname->len, fname->s);
						return app_lua_return_false(L);
					}
				} else {
					LM_ERR("invalid parameters for: %.*s\n",
							fname->len, fname->s);
					return app_lua_return_false(L);
				}
			} else if(ket->ptypes[0]==SR_KEMIP_STR) {
				if(ket->ptypes[1]==SR_KEMIP_INT) {
					if(ket->ptypes[2]==SR_KEMIP_INT) {
						ret = ((sr_kemi_fmsnn_f)(ket->func))(env_L->msg,
								&vps[0].s, vps[1].n, vps[2].n);
						return sr_kemi_lua_return_int(L, ket, ret);
					} else if(ket->ptypes[2]==SR_KEMIP_STR) {
						ret = ((sr_kemi_fmsns_f)(ket->func))(env_L->msg,
								&vps[0].s, vps[1].n, &vps[2].s);
						return sr_kemi_lua_return_int(L, ket, ret);
					} else {
						LM_ERR("invalid parameters for: %.*s\n",
								fname->len, fname->s);
						return app_lua_return_false(L);
					}
				} else if(ket->ptypes[1]==SR_KEMIP_STR) {
					if(ket->ptypes[2]==SR_KEMIP_INT) {
						ret = ((sr_kemi_fmssn_f)(ket->func))(env_L->msg,
								&vps[0].s, &vps[1].s, vps[2].n);
						return sr_kemi_lua_return_int(L, ket, ret);
					} else if(ket->ptypes[2]==SR_KEMIP_STR) {
						ret = ((sr_kemi_fmsss_f)(ket->func))(env_L->msg,
								&vps[0].s, &vps[1].s, &vps[2].s);
						return sr_kemi_lua_return_int(L, ket, ret);
					} else {
						LM_ERR("invalid parameters for: %.*s\n",
								fname->len, fname->s);
						return app_lua_return_false(L);
					}
				} else {
					LM_ERR("invalid parameters for: %.*s\n",
							fname->len, fname->s);
					return app_lua_return_false(L);
				}
			} else {
				LM_ERR("invalid parameters for: %.*s\n",
						fname->len, fname->s);
				return app_lua_return_false(L);
			}
		break;
		case 4:
			if(ket->ptypes[0]==SR_KEMIP_STR
					|| ket->ptypes[1]==SR_KEMIP_STR
					|| ket->ptypes[2]==SR_KEMIP_STR
					|| ket->ptypes[3]==SR_KEMIP_STR) {
				ret = ((sr_kemi_fmssss_f)(ket->func))(env_L->msg,
						&vps[0].s, &vps[1].s, &vps[2].s, &vps[3].s);
				return sr_kemi_lua_return_int(L, ket, ret);
			} else if(ket->ptypes[0]==SR_KEMIP_STR
					|| ket->ptypes[1]==SR_KEMIP_STR
					|| ket->ptypes[2]==SR_KEMIP_INT
					|| ket->ptypes[3]==SR_KEMIP_INT) {
				ret = ((sr_kemi_fmssnn_f)(ket->func))(env_L->msg,
						&vps[0].s, &vps[1].s, vps[2].n, vps[3].n);
				return sr_kemi_lua_return_int(L, ket, ret);
			} else {
				LM_ERR("invalid parameters for: %.*s\n",
						fname->len, fname->s);
				return app_lua_return_false(L);
			}
		break;
		case 5:
			if(ket->ptypes[0]==SR_KEMIP_STR
					|| ket->ptypes[1]==SR_KEMIP_STR
					|| ket->ptypes[2]==SR_KEMIP_STR
					|| ket->ptypes[3]==SR_KEMIP_STR
					|| ket->ptypes[4]==SR_KEMIP_STR) {
				ret = ((sr_kemi_fmsssss_f)(ket->func))(env_L->msg,
						&vps[0].s, &vps[1].s, &vps[2].s, &vps[3].s,
						&vps[4].s);
				return sr_kemi_lua_return_int(L, ket, ret);
			} else {
				LM_ERR("invalid parameters for: %.*s\n",
						fname->len, fname->s);
				return app_lua_return_false(L);
			}
		break;
		case 6:
			if(ket->ptypes[0]==SR_KEMIP_STR
					|| ket->ptypes[1]==SR_KEMIP_STR
					|| ket->ptypes[2]==SR_KEMIP_STR
					|| ket->ptypes[3]==SR_KEMIP_STR
					|| ket->ptypes[4]==SR_KEMIP_STR
					|| ket->ptypes[5]==SR_KEMIP_STR) {
				ret = ((sr_kemi_fmssssss_f)(ket->func))(env_L->msg,
						&vps[0].s, &vps[1].s, &vps[2].s, &vps[3].s,
						&vps[4].s, &vps[5].s);
				return sr_kemi_lua_return_int(L, ket, ret);
			} else {
				LM_ERR("invalid parameters for: %.*s\n",
						fname->len, fname->s);
				return app_lua_return_false(L);
			}
		break;
		default:
			LM_ERR("invalid parameters for: %.*s\n",
					fname->len, fname->s);
			return app_lua_return_false(L);
	}
}
Exemplo n.º 29
0
static void pipe_handle_subscribe(struct purple_subscribe *subscribe) {
	PurpleAccount *account = NULL;
	extern_account_t *accounts = NULL;
	extern_user_t *users = NULL;
	int naccounts = 0, nusers = 0;
	int i, j;
	PurpleBuddy *buddy = NULL;

	int d = 0;

	const char *note;
	enum purple_publish_basic basic;
	enum purple_publish_activity activity;

	LM_DBG("calling find_accounts(\"%s\", &naccounts)\n", subscribe->from);
	accounts = find_accounts(subscribe->from, &naccounts);
	LM_DBG("found %d extra account(s) for <%s>", naccounts, subscribe->from);
	
	LM_DBG("calling find_users(\"%s\", &nusers)\n", subscribe->to);
	users = find_users(subscribe->to, &nusers);
	LM_DBG("found %d extra user(s) for <%s>", nusers, subscribe->to);

	for (i = 0; i < naccounts; i++) {
		LM_DBG("calling client_find_account(\"%s\")\n", accounts[i].username);
		account = client_find_account(&accounts[i]);
		//if ((account) && (purple_account_is_connected(account) || purple_account_is_connecting(account))) {
		if (account) {
			for (j = 0; j < nusers; j++) {
				if (!strcmp(accounts[i].protocol, users[j].protocol)) {
					LM_DBG("found matching protocol: %s\n", accounts[i].protocol);

					LM_DBG("subscribe expires : %d\n", subscribe->expires);
					if (subscribe->expires == 0)
						d = hashtable_dec_counter(users[j].username);
					else
						d = hashtable_inc_counter(users[j].username);
					
					LM_DBG("<%s> is now referenced %d times\n", users[j].username, d);
					if (d == 0) {
						LM_DBG("<%s> is no more referenced, removing presence...\n", users[j].username);
						if (purple_send_sip_publish(subscribe->to, users[j].username, PURPLE_BASIC_CLOSED, 0, NULL) < 0)
							LM_ERR("error sending presence for %s", subscribe->to);
						else
							LM_DBG("presence message sent successfully\n");
					}

					else {
	
						buddy = purple_find_buddy(account, users[j].username);
						if (buddy == NULL) {
							LM_DBG("<%s> not found in <%s> buddy list, adding\n", users[j].username, accounts[i].username);
							buddy = purple_buddy_new(account, users[j].username, users[j].username);
							//purple_blist_add_buddy(buddy, NULL, NULL, NULL);
							purple_account_add_buddy(account, buddy);
						}
						else {
							LM_DBG("<%s> found in <%s> buddy list, sending publish\n", users[j].username, accounts[i].username);
							PurplePresence *presence = purple_buddy_get_presence(buddy);
							PurpleStatus *status = purple_presence_get_active_status(presence);
							PurpleStatusType *type = purple_status_get_type(status);
							PurpleStatusPrimitive primitive = purple_status_type_get_primitive(type);
							note = purple_status_get_attr_string(status, "message");
							primitive_parse(primitive, &basic, &activity);

							if (purple_send_sip_publish(subscribe->to, users[j].username, basic, activity, note) < 0)
								LM_ERR("error sending presence for %s", subscribe->to);
							else
								LM_DBG("presence message sent successfully\n");
							
						}	
	
					}

					break;
				}
			}
		}
	}
	if (accounts)
		extern_account_free(accounts, naccounts);
	if (users)
		extern_user_free(users, nusers);
	
}
Exemplo n.º 30
0
/*
 * Convert db_val to pv_spec
 */
int db_val2pv_spec(struct sip_msg* msg, db_val_t *dbval, pv_spec_t *pvs)
{
	pv_value_t pv;
#define LL_LEN 21   /* sign, 19 digits and \0 */
	static char ll_buf[LL_LEN];

	if(dbval->nul)
	{
		pv.flags = PV_VAL_NULL;
	} else
	{
		switch(dbval->type)
		{
			case DB1_STRING:
				pv.flags = PV_VAL_STR;
				pv.rs.s = (char*)dbval->val.string_val;
				pv.rs.len = strlen(pv.rs.s);
			break;
			case DB1_STR:
				pv.flags = PV_VAL_STR;
				pv.rs.s = (char*)dbval->val.str_val.s;
				pv.rs.len = dbval->val.str_val.len;
			break;
			case DB1_BLOB:
				pv.flags = PV_VAL_STR;
				pv.rs.s = (char*)dbval->val.blob_val.s;
				pv.rs.len = dbval->val.blob_val.len;
			break;
			case DB1_INT:
				pv.flags = PV_VAL_INT | PV_TYPE_INT;
				pv.ri = (int)dbval->val.int_val;
			break;
			case DB1_DATETIME:
				pv.flags = PV_VAL_INT | PV_TYPE_INT;
				pv.ri = (int)dbval->val.time_val;
			break;
			case DB1_BITMAP:
				pv.flags = PV_VAL_INT | PV_TYPE_INT;
				pv.ri = (int)dbval->val.bitmap_val;
			break;
			case DB1_BIGINT:
				/* BIGINT is stored as string */
				pv.flags = PV_VAL_STR;
				pv.rs.len = LL_LEN;
				db_longlong2str(dbval->val.ll_val, ll_buf, &pv.rs.len);
				pv.rs.s = ll_buf;
				/* if it fits, also store as 32 bit integer*/
				if (! ((unsigned long long)dbval->val.ll_val & 0xffffffff00000000ULL)) {
					pv.flags |= PV_VAL_INT | PV_TYPE_INT;
					pv.ri = (int)dbval->val.ll_val;
				}
			break;
			default:
				LM_NOTICE("unknown field type: %d, setting value to null\n",
				          dbval->type);
				pv.flags = PV_VAL_NULL;
		}
	}

	/* null values are ignored for avp type PV */
	if (pv.flags == PV_VAL_NULL && pvs->type == PVT_AVP)
		return 0;

	/* add value to result pv */
	if (pv_set_spec_value(msg, pvs, 0, &pv) != 0)
	{
		LM_ERR("Failed to add value to spec\n");
		return -1;
	}

	return 0;
}