int _eXosip_notify_set_refresh_interval (eXosip_notify_t * jn, osip_message_t * inc_subscribe) { osip_header_t *exp; time_t now; now = time (NULL); if (jn == NULL || inc_subscribe == NULL) return -1; osip_message_get_expires (inc_subscribe, 0, &exp); if (exp == NULL || exp->hvalue == NULL) jn->n_ss_expires = now + 600; else { jn->n_ss_expires = osip_atoi (exp->hvalue); if (jn->n_ss_expires != -1) jn->n_ss_expires = now + jn->n_ss_expires; else /* on error, set it to default */ jn->n_ss_expires = now + 600; } return 0; }
int osip_dialog_update_osip_cseq_as_uas (osip_dialog_t * dialog, osip_message_t * invite) { if (dialog == NULL) return OSIP_BADPARAMETER; if (invite == NULL || invite->cseq == NULL || invite->cseq->number == NULL) return OSIP_BADPARAMETER; dialog->remote_cseq = osip_atoi (invite->cseq->number); return OSIP_SUCCESS; }
int osip_dialog_update_osip_cseq_as_uas (osip_dialog_t * dialog, osip_message_t * invite) { if (dialog == NULL) return -1; if (invite == NULL || invite->cseq == NULL || invite->cseq->number == NULL) return -1; dialog->remote_cseq = osip_atoi (invite->cseq->number); return 0; }
int _eXosip_subscribe_set_refresh_interval (eXosip_subscribe_t * js, osip_message_t * out_subscribe) { osip_header_t *exp; if (js == NULL || out_subscribe == NULL) return OSIP_BADPARAMETER; osip_message_get_expires (out_subscribe, 0, &exp); if (exp != NULL && exp->hvalue != NULL) { js->s_reg_period = osip_atoi (exp->hvalue); if (js->s_reg_period < 0) js->s_reg_period = 3600; } return OSIP_SUCCESS; }
int osip_dialog_init_as_uas (osip_dialog_t ** dialog, osip_message_t * invite, osip_message_t * response) { int i; *dialog = NULL; if (response->cseq == NULL) return OSIP_SYNTAXERROR; i = __osip_dialog_init (dialog, invite, response, response->to, response->from, invite); if (i != 0) { *dialog = NULL; return i; } (*dialog)->type = CALLEE; (*dialog)->remote_cseq = osip_atoi (response->cseq->number); return OSIP_SUCCESS; }
int _eXosip_subscribe_set_refresh_interval(eXosip_subscribe_t *js, osip_message_t *out_subscribe) { osip_header_t *exp; time_t now = time(NULL); if (js==NULL || out_subscribe==NULL) return -1; osip_message_get_expires(out_subscribe, 0, &exp); if (exp==NULL || exp->hvalue==NULL) js->s_ss_expires = now + atoi(eXosip.subscribe_timeout); else { js->s_ss_expires = osip_atoi(exp->hvalue); if (js->s_ss_expires!=-1) js->s_ss_expires = now + js->s_ss_expires; else /* on error, set it to default */ js->s_ss_expires = now + atoi(eXosip.subscribe_timeout); } return 0; }
/* SIPIT13 */ int osip_dialog_init_as_uac_with_remote_request (osip_dialog_t ** dialog, osip_message_t * next_request, int local_cseq) { int i; *dialog = NULL; if (next_request->cseq == NULL) return OSIP_BADPARAMETER; i = __osip_dialog_init (dialog, next_request, next_request, next_request->to, next_request->from, next_request); if (i != 0) { *dialog = NULL; return i; } (*dialog)->type = CALLER; (*dialog)->state = DIALOG_CONFIRMED; (*dialog)->local_cseq = local_cseq; /* -1 osip_atoi (xxx->cseq->number); */ (*dialog)->remote_cseq = osip_atoi (next_request->cseq->number); return OSIP_SUCCESS; }
int osip_dialog_update_osip_cseq_as_uas (osip_dialog_t * dialog, osip_message_t * invite) { dialog->remote_cseq = osip_atoi (invite->cseq->number); return 0; }
int __osip_nict_init (osip_nict_t ** nict, osip_t * osip, osip_message_t * request) { osip_route_t *route; int i; time_t now; OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "allocating NICT context\n")); *nict = (osip_nict_t *) osip_malloc (sizeof (osip_nict_t)); if (*nict == NULL) return -1; now = time (NULL); #ifndef DISABLE_MEMSET memset (*nict, 0, sizeof (osip_nict_t)); #else (*ict)->destination = NULL; #endif /* for REQUEST retransmissions */ { osip_via_t *via; char *proto; i = osip_message_get_via (request, 0, &via); /* get top via */ if (i != 0) goto ii_error_1; proto = via_get_protocol (via); if (proto == NULL) goto ii_error_1; i = osip_strncasecmp (proto, "TCP", 3); if (i != 0) { /* for other reliable protocol than TCP, the timer must be desactived by the external application */ (*nict)->timer_e_length = DEFAULT_T1; (*nict)->timer_e_start = now; /* started */ (*nict)->timer_k_length = DEFAULT_T4; (*nict)->timer_k_start = -1; /* not started */ } else { /* TCP is used: */ (*nict)->timer_e_length = -1; /* E is not ACTIVE */ (*nict)->timer_e_start = -1; (*nict)->timer_k_length = 0; /* MUST do the transition immediatly */ (*nict)->timer_k_start = -1; /* not started */ } } /* for PROXY, the destination MUST be set by the application layer, this one may not be correct. */ osip_message_get_route (request, 0, &route); if (route != NULL) { int port = 5060; if (route->url->port != NULL) port = osip_atoi (route->url->port); osip_nict_set_destination ((*nict), osip_strdup (route->url->host), port); } else (*nict)->port = 5060; (*nict)->timer_f_length = 64 * DEFAULT_T1; (*nict)->timer_f_start = now; /* started */ /* Oups! a Bug! */ /* (*nict)->port = 5060; */ return 0; ii_error_1: osip_free (*nict); return -1; }
int eXosip_publish (struct eXosip_t *excontext, osip_message_t * message, const char *to) { osip_transaction_t *transaction; osip_event_t *sipevent; int i; eXosip_pub_t *pub = NULL; if (message == NULL) return OSIP_BADPARAMETER; if (message->cseq == NULL || message->cseq->number == NULL) { osip_message_free (message); return OSIP_SYNTAXERROR; } if (to == NULL) { osip_message_free (message); return OSIP_BADPARAMETER; } i = _eXosip_pub_find_by_aor (excontext, &pub, to); if (i != 0 || pub == NULL) { osip_header_t *expires; osip_message_get_expires (message, 0, &expires); if (expires == NULL || expires->hvalue == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: missing expires header in PUBLISH!")); osip_message_free (message); return OSIP_SYNTAXERROR; } else { /* start a new publication context */ i = _eXosip_pub_init (&pub, to, expires->hvalue); if (i != 0) { osip_message_free (message); return i; } ADD_ELEMENT (excontext->j_pub, pub); } } else { if (pub->p_sip_etag[0] != '\0') { /* increase cseq */ osip_message_set_header (message, "SIP-If-Match", pub->p_sip_etag); } { osip_header_t *expires; osip_message_get_expires (message, 0, &expires); if (expires == NULL || expires->hvalue == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: missing expires header in PUBLISH!")); osip_message_free (message); return OSIP_SYNTAXERROR; } pub->p_period = atoi (expires->hvalue); } if (pub->p_last_tr != NULL && pub->p_last_tr->cseq != NULL && pub->p_last_tr->cseq->number != NULL) { int osip_cseq_num = osip_atoi (pub->p_last_tr->cseq->number); int length = (int) strlen (pub->p_last_tr->cseq->number); osip_cseq_num++; osip_free (message->cseq->number); message->cseq->number = (char *) osip_malloc (length + 2); /* +2 like for 9 to 10 */ if (message->cseq->number == NULL) { osip_message_free (message); return OSIP_NOMEM; } snprintf (message->cseq->number, length + 2, "%i", osip_cseq_num); } } i = _eXosip_transaction_init (excontext, &transaction, NICT, excontext->j_osip, message); if (i != 0) { osip_message_free (message); return i; } if (pub->p_last_tr != NULL) osip_list_add (&excontext->j_transactions, pub->p_last_tr, 0); pub->p_last_tr = transaction; sipevent = osip_new_outgoing_sipmessage (message); sipevent->transactionid = transaction->transactionid; osip_transaction_add_event (transaction, sipevent); _eXosip_wakeup (excontext); return transaction->transactionid; }
static int _eXosip_register_build_register (eXosip_reg_t * jr, osip_message_t ** _reg) { osip_message_t *reg = NULL; int i; reg = NULL; *_reg = NULL; if (jr->r_last_tr != NULL) { if (jr->r_last_tr->state != NICT_TERMINATED && jr->r_last_tr->state != NICT_COMPLETED) return -1; else { osip_message_t *last_response = NULL; osip_transaction_t *tr; osip_message_clone (jr->r_last_tr->orig_request, ®); if (reg == NULL) return -1; /* reg = jr->r_last_tr->orig_request; */ if (jr->r_last_tr->last_response != NULL) { osip_message_clone (jr->r_last_tr->last_response, &last_response); if (last_response == NULL) { osip_message_free (reg); return -1; } } __eXosip_delete_jinfo (jr->r_last_tr); tr = jr->r_last_tr; jr->r_last_tr = NULL; osip_list_add (eXosip.j_transactions, tr, 0); /* modify the REGISTER request */ { int osip_cseq_num = osip_atoi (reg->cseq->number); int length = strlen (reg->cseq->number); osip_list_special_free(®->authorizations, (void *(*)(void *)) &osip_authorization_free); osip_list_special_free(®->proxy_authorizations, (void *(*)(void *)) &osip_proxy_authorization_free); if (-1 == eXosip_update_top_via (reg)) { osip_message_free (reg); if (last_response != NULL) osip_message_free (last_response); return -1; } osip_cseq_num++; osip_free (reg->cseq->number); reg->cseq->number = (char *) osip_malloc (length + 2); /* +2 like for 9 to 10 */ sprintf (reg->cseq->number, "%i", osip_cseq_num); { osip_header_t *exp; osip_message_header_get_byname (reg, "expires", 0, &exp); if (exp!=NULL) { if (exp->hvalue!=NULL) osip_free (exp->hvalue); exp->hvalue = (char *) osip_malloc (10); snprintf (exp->hvalue, 9, "%i", jr->r_reg_period); } } osip_message_force_update (reg); } if (last_response != NULL) { if (last_response->status_code==401 || last_response->status_code==407) { eXosip_add_authentication_information (reg, last_response); } else eXosip_add_authentication_information (reg, NULL); osip_message_free (last_response); } } } if (reg == NULL) { i = generating_register (jr, ®, eXosip.transport, jr->r_aor, jr->r_registrar, jr->r_contact, jr->r_reg_period); if (i != 0) { return -2; } } *_reg = reg; return 0; }
char * sdp_context_get_answer ( sdp_context_t *ctx,sdp_message_t *remote) { sdp_message_t *answer=NULL; char *mtype=NULL, *tmp=NULL; char *proto=NULL, *port=NULL, *pt=NULL; int i, j, ncodec, m_lines_accepted = 0; int err; sdp_payload_t payload; sdp_handler_t *sdph=ctx->handler; sdp_bandwidth_t *sbw=NULL; char *relay; tmp = sdp_message_c_addr_get (remote, 0, 0); if (tmp == NULL) tmp = sdp_message_c_addr_get (remote, -1, 0); if (ctx->localip==NULL) { /* NULL means guess, otherwise we use the address given as localip */ ctx->localip=osip_malloc(128); eXosip_guess_localip(strchr(tmp,':') ? AF_INET6 : AF_INET,ctx->localip,128); } else eXosip_trace(OSIP_INFO1,("Using firewall address in sdp.")); answer = sdp_context_generate_template (ctx); /* for each m= line */ for (i = 0; !sdp_message_endof_media (remote, i); i++) { sdp_payload_init(&payload); mtype = sdp_message_m_media_get (remote, i); proto = sdp_message_m_proto_get (remote, i); port = sdp_message_m_port_get (remote, i); payload.remoteport = osip_atoi (port); payload.proto = proto; payload.line = i; payload.c_addr = sdp_message_c_addr_get (remote, i, 0); if (payload.c_addr == NULL) payload.c_addr = sdp_message_c_addr_get (remote, -1, 0); /*parse relay address if given*/ relay=sdp_message_a_attr_value_get(remote,i,"relay-addr"); if (relay){ payload.relay_host=parse_relay_addr(relay,&payload.relay_port); } payload.relay_session_id=sdp_message_a_attr_value_get(remote,i,"relay-session-id"); /* get application specific bandwidth, if any */ for(j=0;(sbw=sdp_message_bandwidth_get(remote,i,j))!=NULL;j++){ if (strcasecmp(sbw->b_bwtype,"AS")==0) payload.b_as_bandwidth=atoi(sbw->b_bandwidth); } payload.a_ptime=_sdp_message_get_a_ptime(remote,i); if (keywordcmp ("audio", mtype) == 0) { if (sdph->accept_audio_codecs != NULL) { ncodec = 0; /* for each payload type */ for (j = 0; ((pt = sdp_message_m_payload_get (remote, i, j)) != NULL); j++) { payload.pt = osip_atoi (pt); /* get the rtpmap associated to this codec, if any */ payload.a_rtpmap = sdp_message_a_attr_value_get_with_pt (remote, i, payload.pt, "rtpmap"); /* get the fmtp, if any */ payload.a_fmtp = sdp_message_a_attr_value_get_with_pt (remote, i, payload.pt, "fmtp"); /* ask the application if this codec is supported */ err = sdph->accept_audio_codecs (ctx, &payload); if (err == 0 && payload.localport > 0) { ncodec++; /* codec accepted */ if (ncodec == 1) { /* first codec accepted, setup the line */ sdp_message_m_media_add (answer, osip_strdup (mtype), int_2char (payload. localport), NULL, osip_strdup (proto)); /* and accept the remote relay addr if we planned to use our own */ if (ctx->relay!=NULL && relay){ add_relay_info(answer,i,relay,payload.relay_session_id); } } /* add the payload, rtpmap, fmtp */ sdp_message_m_payload_add (answer, i, int_2char (payload. pt)); if (payload.a_rtpmap != NULL) { sdp_message_a_attribute_add (answer, i, osip_strdup ("rtpmap"), sstrdup_sprintf ("%i %s", payload.pt, payload. a_rtpmap)); } if (payload.a_fmtp != NULL) { sdp_message_a_attribute_add (answer, i, osip_strdup ("fmtp"), sstrdup_sprintf ("%i %s", payload.pt, payload. a_fmtp)); } if (payload.b_as_bandwidth != 0) { if (sdp_message_bandwidth_get(answer,i,0)==NULL) sdp_message_b_bandwidth_add (answer, i, osip_strdup ("AS"), sstrdup_sprintf ("%i", payload. b_as_bandwidth)); } } } if (ncodec == 0) { /* refuse the line */ refuse_mline(answer,mtype,proto,i); } else m_lines_accepted++; } else { /* refuse this line (leave port to 0) */ refuse_mline(answer,mtype,proto,i); } } else if (keywordcmp ("video", mtype) == 0) { if (sdph->accept_video_codecs != NULL) { ncodec = 0; /* for each payload type */ for (j = 0; ((pt = sdp_message_m_payload_get (remote, i, j)) != NULL); j++) { payload.pt = osip_atoi (pt); /* get the rtpmap associated to this codec, if any */ payload.a_rtpmap = sdp_message_a_attr_value_get_with_pt (remote, i, payload.pt, "rtpmap"); /* get the fmtp, if any */ payload.a_fmtp = sdp_message_a_attr_value_get_with_pt (remote, i, payload.pt, "fmtp"); /* ask the application if this codec is supported */ err = sdph->accept_video_codecs (ctx, &payload); if (err == 0 && payload.localport > 0) { ncodec++; /* codec accepted */ if (ncodec == 1) { /* first codec accepted, setup the line */ sdp_message_m_media_add (answer, osip_strdup (mtype), int_2char (payload.localport), NULL, osip_strdup (proto)); /* and accept the remote relay addr if we planned to use our own */ if (ctx->relay!=NULL && relay){ add_relay_info(answer,i,relay,payload.relay_session_id); } } /* add the payload, rtpmap, fmtp */ sdp_message_m_payload_add (answer, i, int_2char (payload. pt)); if (payload.a_rtpmap != NULL) { sdp_message_a_attribute_add (answer, i, osip_strdup ("rtpmap"), sstrdup_sprintf ("%i %s", payload.pt, payload. a_rtpmap)); } if (payload.a_fmtp != NULL) { sdp_message_a_attribute_add (answer, i, osip_strdup ("fmtp"), sstrdup_sprintf ("%i %s", payload.pt, payload. a_fmtp)); } if (payload.b_as_bandwidth !=0) { if (sdp_message_bandwidth_get(answer,i,0)==NULL) sdp_message_b_bandwidth_add (answer, i, osip_strdup ("AS"), sstrdup_sprintf ("%i", payload. b_as_bandwidth)); } } } if (ncodec == 0) { /* refuse the line */ refuse_mline(answer,mtype,proto,i); } else m_lines_accepted++; } else { /* refuse the line */ refuse_mline(answer,mtype,proto,i); } } } if (ctx->answer!=NULL) sdp_message_free(ctx->answer); ctx->answer = answer; if (m_lines_accepted > 0){ ctx->negoc_status = 200; sdp_message_to_str(answer,&tmp); if (ctx->answerstr!=NULL) osip_free(ctx->answerstr); ctx->answerstr=tmp; return tmp; }else{ ctx->negoc_status = 415; return NULL; } }
static int udp_tl_send_message (osip_transaction_t * tr, osip_message_t * sip, char *host, int port, int out_socket) { int len = 0; size_t length = 0; struct addrinfo *addrinfo; struct __eXosip_sockaddr addr; char *message; char *crypt_date; char ipbuf[INET6_ADDRSTRLEN]; int i; if (udp_socket <= 0) return -1; if (host == NULL) { host = sip->req_uri->host; if (sip->req_uri->port != NULL) port = osip_atoi (sip->req_uri->port); else port = 5060; } eXtl_update_local_target (sip); i = -1; #ifndef MINISIZE if (tr != NULL && tr->record.name[0] != '\0' && tr->record.srventry[0].srv[0] != '\0') { /* always choose the first here. if a network error occur, remove first entry and replace with next entries. */ osip_srv_entry_t *srv; int n = 0; for (srv = &tr->record.srventry[0]; n < 10 && tr->record.srventry[0].srv[0]; srv = &tr->record.srventry[0]) { i = eXosip_get_addrinfo (&addrinfo, srv->srv, srv->port, IPPROTO_UDP); if (i == 0) { host = srv->srv; port = srv->port; break; } memmove (&tr->record.srventry[0], &tr->record.srventry[1], 9 * sizeof (osip_srv_entry_t)); memset (&tr->record.srventry[9], 0, sizeof (osip_srv_entry_t)); i = -1; /* copy next element */ n++; } } #endif /* if SRV was used, distination may be already found */ if (i != 0) { i = eXosip_get_addrinfo (&addrinfo, host, port, IPPROTO_UDP); } if (i != 0) { return -1; } memcpy (&addr, addrinfo->ai_addr, addrinfo->ai_addrlen); len = addrinfo->ai_addrlen; eXosip_freeaddrinfo (addrinfo); /* remove preloaded route if there is no tag in the To header */ { osip_route_t *route = NULL; osip_generic_param_t *tag = NULL; osip_message_get_route (sip, 0, &route); osip_to_get_tag (sip->to, &tag); if (tag == NULL && route != NULL && route->url != NULL) { osip_list_remove (&sip->routes, 0); } i = osip_message_to_str (sip, &message, &length); if (tag == NULL && route != NULL && route->url != NULL) { osip_list_add (&sip->routes, route, 0); } } if (i != 0 || length <= 0) { return -1; } switch (((struct sockaddr *) &addr)->sa_family) { case AF_INET: inet_ntop (((struct sockaddr *) &addr)->sa_family, &(((struct sockaddr_in *) &addr)->sin_addr), ipbuf, sizeof (ipbuf)); break; case AF_INET6: inet_ntop (((struct sockaddr *) &addr)->sa_family, &(((struct sockaddr_in6 *) &addr)->sin6_addr), ipbuf, sizeof (ipbuf)); break; default: strncpy (ipbuf, "(unknown)", sizeof (ipbuf)); break; } OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "Message sent: (to dest=%s:%i)\n%s\n", ipbuf, port, message)); if (tr != NULL) { if (tr->ict_context != NULL) osip_ict_set_destination (tr->ict_context, osip_strdup (ipbuf), port); if (tr->nict_context != NULL) osip_nict_set_destination (tr->nict_context, osip_strdup (ipbuf), port); } //SIP加密点 crypt_date = (char *)malloc(length); memcpy(crypt_date,(const char *)message, length); #ifdef ENABLE_MYCRYPT CRYPT_DATA_SIP((unsigned char *)crypt_date,length); #endif // ENABLE_MYCRYPT if (0 > sendto (udp_socket, (const void *) crypt_date, length, 0, (struct sockaddr *) &addr, len)) { #ifdef WIN32 if (WSAECONNREFUSED == WSAGetLastError ()) #else if (ECONNREFUSED == errno) #endif { /* This can be considered as an error, but for the moment, I prefer that the application continue to try sending message again and again... so we are not in a error case. Nevertheless, this error should be announced! ALSO, UAS may not have any other options than retry always on the same port. */ osip_free (message); return 1; } else { #ifndef MINISIZE /* delete first SRV entry that is not reachable */ if (tr != NULL && tr->record.name[0] != '\0' && tr->record.srventry[0].srv[0] != '\0') { memmove (&tr->record.srventry[0], &tr->record.srventry[1], 9 * sizeof (osip_srv_entry_t)); memset (&tr->record.srventry[9], 0, sizeof (osip_srv_entry_t)); osip_free (message); return OSIP_SUCCESS; /* retry for next retransmission! */ } #endif /* SIP_NETWORK_ERROR; */ osip_free (message); return -1; } } if (eXosip.keep_alive > 0) { if (MSG_IS_REGISTER (sip)) { eXosip_reg_t *reg = NULL; if (_eXosip_reg_find (®, tr) == 0) { memcpy (&(reg->addr), &addr, len); reg->len = len; } } } osip_free (message); return OSIP_SUCCESS; }
void sdp_context_read_answer (sdp_context_t *ctx, sdp_message_t *remote) { char *mtype; char *proto, *port, *pt; int i, j,err; char *relay; sdp_payload_t payload,arg_payload; sdp_handler_t *sdph=ctx->handler; sdp_bandwidth_t *sbw=NULL; /* for each m= line */ for (i = 0; !sdp_message_endof_media (remote, i); i++) { sdp_payload_init(&payload); mtype = sdp_message_m_media_get (remote, i); proto = sdp_message_m_proto_get (remote, i); port = sdp_message_m_port_get (remote, i); payload.remoteport = osip_atoi (port); payload.localport = osip_atoi (sdp_message_m_port_get (ctx->offer, i)); payload.proto = proto; payload.line = i; payload.c_addr = sdp_message_c_addr_get (remote, i, 0); if (payload.c_addr == NULL) payload.c_addr = sdp_message_c_addr_get (remote, -1, 0); /*parse relay address if given*/ relay=sdp_message_a_attr_value_get(remote,i,"relay-addr"); if (relay){ payload.relay_host=parse_relay_addr(relay,&payload.relay_port); } payload.relay_session_id=sdp_message_a_attr_value_get(remote,i,"relay-session-id"); for(j=0;(sbw=sdp_message_bandwidth_get(remote,i,j))!=NULL;++j){ if (strcasecmp(sbw->b_bwtype,"AS")==0) payload.b_as_bandwidth=atoi(sbw->b_bandwidth); } payload.a_ptime=_sdp_message_get_a_ptime(remote,i); if (keywordcmp ("audio", mtype) == 0) { if (sdph->get_audio_codecs != NULL) { /* for each payload type */ for (j = 0; ((pt = sdp_message_m_payload_get (remote, i, j)) != NULL); j++) { payload.pt = osip_atoi (pt); /* get the rtpmap associated to this codec, if any */ payload.a_rtpmap = sdp_message_a_attr_value_get_with_pt (remote, i, payload.pt, "rtpmap"); /* get the fmtp, if any */ payload.a_fmtp = sdp_message_a_attr_value_get_with_pt (remote, i, payload.pt, "fmtp"); /* ask the application if this codec is supported */ memcpy(&arg_payload,&payload,sizeof(payload)); err = sdph->get_audio_codecs (ctx, &arg_payload); } } } else if (keywordcmp ("video", mtype) == 0) { if (sdph->get_video_codecs != NULL) { /* for each payload type */ for (j = 0; ((pt = sdp_message_m_payload_get (remote, i, j)) != NULL); j++) { payload.pt = osip_atoi (pt); /* get the rtpmap associated to this codec, if any */ payload.a_rtpmap = sdp_message_a_attr_value_get_with_pt (remote, i, payload.pt, "rtpmap"); /* get the fmtp, if any */ payload.a_fmtp = sdp_message_a_attr_value_get_with_pt (remote, i, payload.pt, "fmtp"); /* ask the application if this codec is supported */ memcpy(&arg_payload,&payload,sizeof(payload)); err = sdph->get_video_codecs (ctx, &arg_payload); } } } } }
int eXosip_call_send_ack (int did, osip_message_t * ack) { eXosip_dialog_t *jd = NULL; eXosip_call_t *jc = NULL; int i; osip_route_t *route; char *host; int port; if (did <= 0) return OSIP_BADPARAMETER; if (did > 0) { eXosip_call_dialog_find (did, &jc, &jd); } if (jc == NULL || jd == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: No call here?\n")); if (ack != NULL) osip_message_free (ack); return OSIP_NOTFOUND; } if (ack == NULL) { i = eXosip_call_build_ack (did, &ack); if (i != 0) { return i; } } osip_message_get_route (ack, 0, &route); if (route != NULL) { osip_uri_param_t *lr_param = NULL; osip_uri_uparam_get_byname (route->url, "lr", &lr_param); if (lr_param == NULL) route = NULL; } if (route != NULL) { port = 5060; if (route->url->port != NULL) port = osip_atoi (route->url->port); host = route->url->host; } else { /* search for maddr parameter */ osip_uri_param_t *maddr_param = NULL; osip_uri_uparam_get_byname (ack->req_uri, "maddr", &maddr_param); host = NULL; if (maddr_param != NULL && maddr_param->gvalue != NULL) host = maddr_param->gvalue; port = 5060; if (ack->req_uri->port != NULL) port = osip_atoi (ack->req_uri->port); if (host == NULL) host = ack->req_uri->host; } i = cb_snd_message (NULL, ack, host, port, -1); if (jd->d_ack != NULL) osip_message_free (jd->d_ack); jd->d_ack = ack; if (i < 0) return i; /* TODO: could be 1 for icmp... */ return OSIP_SUCCESS; }
void nist_rcv_request (osip_transaction_t * nist, osip_event_t * evt) { int i; osip_t *osip = (osip_t *) nist->config; if (nist->state == NIST_PRE_TRYING) /* announce new REQUEST */ { /* Here we have ist->orig_request == NULL */ nist->orig_request = evt->sip; if (MSG_IS_REGISTER (evt->sip)) __osip_message_callback (OSIP_NIST_REGISTER_RECEIVED, nist, nist->orig_request); else if (MSG_IS_BYE (evt->sip)) __osip_message_callback (OSIP_NIST_BYE_RECEIVED, nist, nist->orig_request); else if (MSG_IS_OPTIONS (evt->sip)) __osip_message_callback (OSIP_NIST_OPTIONS_RECEIVED, nist, nist->orig_request); else if (MSG_IS_INFO (evt->sip)) __osip_message_callback (OSIP_NIST_INFO_RECEIVED, nist, nist->orig_request); else if (MSG_IS_CANCEL (evt->sip)) __osip_message_callback (OSIP_NIST_CANCEL_RECEIVED, nist, nist->orig_request); else if (MSG_IS_NOTIFY (evt->sip)) __osip_message_callback (OSIP_NIST_NOTIFY_RECEIVED, nist, nist->orig_request); else if (MSG_IS_SUBSCRIBE (evt->sip)) __osip_message_callback (OSIP_NIST_SUBSCRIBE_RECEIVED, nist, nist->orig_request); else __osip_message_callback (OSIP_NIST_UNKNOWN_REQUEST_RECEIVED, nist, nist->orig_request); } else /* NIST_PROCEEDING or NIST_COMPLETED */ { /* delete retransmission */ osip_message_free (evt->sip); __osip_message_callback (OSIP_NIST_REQUEST_RECEIVED_AGAIN, nist, nist->orig_request); if (nist->last_response != NULL) /* retransmit last response */ { osip_via_t *via; via = (osip_via_t *) osip_list_get (nist->last_response->vias, 0); if (via) { char *host; int port; osip_generic_param_t *maddr; osip_generic_param_t *received; osip_generic_param_t *rport; osip_via_param_get_byname (via, "maddr", &maddr); osip_via_param_get_byname (via, "received", &received); osip_via_param_get_byname (via, "rport", &rport); /* 1: user should not use the provided information (host and port) if they are using a reliable transport. Instead, they should use the already open socket attached to this transaction. */ /* 2: check maddr and multicast usage */ if (maddr != NULL) host = maddr->gvalue; /* we should check if this is a multicast address and use set the "ttl" in this case. (this must be done in the UDP message (not at the SIP layer) */ else if (received != NULL) host = received->gvalue; else host = via->host; if (rport == NULL || rport->gvalue == NULL) { if (via->port != NULL) port = osip_atoi (via->port); else port = 5060; } else port = osip_atoi (rport->gvalue); i = osip->cb_send_message (nist, nist->last_response, host, port, nist->out_socket); } else i = -1; if (i != 0) { nist_handle_transport_error (nist, i); return; } else { if (MSG_IS_STATUS_1XX (nist->last_response)) __osip_message_callback (OSIP_NIST_STATUS_1XX_SENT, nist, nist->last_response); else if (MSG_IS_STATUS_2XX (nist->last_response)) __osip_message_callback (OSIP_NIST_STATUS_2XX_SENT_AGAIN, nist, nist->last_response); else __osip_message_callback (OSIP_NIST_STATUS_3456XX_SENT_AGAIN, nist, nist->last_response); return; } } /* we are already in the proper state */ return; } /* we come here only if it was the first REQUEST received */ __osip_transaction_set_state (nist, NIST_TRYING); }
int osip_dialog_init_as_uas (osip_dialog_t ** dialog, osip_message_t * invite, osip_message_t * response) { int i; int pos; osip_generic_param_t *tag; (*dialog) = (osip_dialog_t *) osip_malloc (sizeof (osip_dialog_t)); if (*dialog == NULL) return -1; (*dialog)->type = CALLEE; if (MSG_IS_STATUS_2XX (response)) (*dialog)->state = DIALOG_CONFIRMED; else /* 1XX */ (*dialog)->state = DIALOG_EARLY; i = osip_call_id_to_str (response->call_id, &((*dialog)->call_id)); if (i != 0) goto diau_error_0; i = osip_to_get_tag (response->to, &tag); if (i != 0) goto diau_error_1; (*dialog)->local_tag = osip_strdup (tag->gvalue); i = osip_from_get_tag (response->from, &tag); if (i != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "Remote UA is not compliant: missing a tag in response!\n")); (*dialog)->remote_tag = NULL; } else (*dialog)->remote_tag = osip_strdup (tag->gvalue); (*dialog)->route_set = (osip_list_t *) osip_malloc (sizeof (osip_list_t)); osip_list_init ((*dialog)->route_set); pos = 0; while (!osip_list_eol (response->record_routes, pos)) { osip_record_route_t *rr; osip_record_route_t *rr2; rr = (osip_record_route_t *) osip_list_get (response->record_routes, pos); i = osip_record_route_clone (rr, &rr2); if (i != 0) goto diau_error_2; osip_list_add ((*dialog)->route_set, rr2, -1); pos++; } /* local_cseq is set to response->cseq->number for better handling of bad UA */ (*dialog)->local_cseq = osip_atoi (response->cseq->number); (*dialog)->remote_cseq = osip_atoi (response->cseq->number); i = osip_from_clone (response->from, &((*dialog)->remote_uri)); if (i != 0) goto diau_error_3; i = osip_to_clone (response->to, &((*dialog)->local_uri)); if (i != 0) goto diau_error_4; { osip_contact_t *contact; if (!osip_list_eol (invite->contacts, 0)) { contact = osip_list_get (invite->contacts, 0); i = osip_contact_clone (contact, &((*dialog)->remote_contact_uri)); if (i != 0) goto diau_error_5; } else { (*dialog)->remote_contact_uri = NULL; OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "Remote UA is not compliant: missing a contact in response!\n")); } } (*dialog)->secure = -1; /* non secure */ return 0; diau_error_5: osip_from_free ((*dialog)->local_uri); diau_error_4: osip_from_free ((*dialog)->remote_uri); diau_error_3: diau_error_2: osip_list_special_free ((*dialog)->route_set, (void *(*)(void *)) &osip_record_route_free); osip_free ((*dialog)->remote_tag); osip_free ((*dialog)->local_tag); diau_error_1: osip_free ((*dialog)->call_id); diau_error_0: OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Could not establish dialog!\n")); osip_free (*dialog); *dialog = NULL; return -1; }
/* we don't have to compare remote_uri with from && local_uri with to. ----> we have both tag recognized, it's enough.. */ if (0 == strcmp (tag_param_remote->gvalue, dlg->remote_tag)) return 0; return -1; } int osip_dialog_init_as_uac (osip_dialog_t ** dialog, osip_message_t * response) { int i; int pos; osip_generic_param_t *tag; *dialog = NULL; i = osip_to_get_tag (response->to, &tag); if (i != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "Remote UA is not compliant: missing a tag in response!\n")); return -1; } (*dialog) = (osip_dialog_t *) osip_malloc (sizeof (osip_dialog_t)); if (*dialog == NULL) return -1; (*dialog)->type = CALLER; if (MSG_IS_STATUS_2XX (response)) (*dialog)->state = DIALOG_CONFIRMED; else /* 1XX */ (*dialog)->state = DIALOG_EARLY; i = osip_call_id_to_str (response->call_id, &((*dialog)->call_id)); if (i != 0) goto diau_error_0; i = osip_from_get_tag (response->from, &tag); if (i != 0) goto diau_error_1; (*dialog)->local_tag = osip_strdup (tag->gvalue); i = osip_to_get_tag (response->to, &tag); if (i != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "Remote UA is not compliant: missing a tag in response!\n")); (*dialog)->remote_tag = NULL; } else (*dialog)->remote_tag = osip_strdup (tag->gvalue); (*dialog)->route_set = (osip_list_t *) osip_malloc (sizeof (osip_list_t)); osip_list_init ((*dialog)->route_set); pos = 0; while (!osip_list_eol (response->record_routes, pos)) { osip_record_route_t *rr; osip_record_route_t *rr2; rr = (osip_record_route_t *) osip_list_get (response->record_routes, pos); i = osip_record_route_clone (rr, &rr2); if (i != 0) goto diau_error_2; osip_list_add ((*dialog)->route_set, rr2, -1); pos++; } (*dialog)->local_cseq = osip_atoi (response->cseq->number); (*dialog)->remote_cseq = -1; i = osip_to_clone (response->to, &((*dialog)->remote_uri)); if (i != 0) goto diau_error_3; i = osip_from_clone (response->from, &((*dialog)->local_uri)); if (i != 0) goto diau_error_4; { osip_contact_t *contact; if (!osip_list_eol (response->contacts, 0)) { contact = osip_list_get (response->contacts, 0); i = osip_contact_clone (contact, &((*dialog)->remote_contact_uri)); if (i != 0) goto diau_error_5; } else { (*dialog)->remote_contact_uri = NULL; OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "Remote UA is not compliant: missing a contact in response!\n")); } } (*dialog)->secure = -1; /* non secure */ return 0; diau_error_5: osip_from_free ((*dialog)->local_uri); diau_error_4: osip_from_free ((*dialog)->remote_uri); diau_error_3: diau_error_2: osip_list_special_free ((*dialog)->route_set, (void *(*)(void *)) &osip_record_route_free); osip_free ((*dialog)->remote_tag); osip_free ((*dialog)->local_tag); diau_error_1: osip_free ((*dialog)->call_id); diau_error_0: OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Could not establish dialog!\n")); osip_free (*dialog); *dialog = NULL; return -1; } #if 1 /* SIPIT13 */ int osip_dialog_init_as_uac_with_remote_request (osip_dialog_t ** dialog, osip_message_t *next_request, int local_cseq) { int i; osip_generic_param_t *tag; *dialog = NULL; i = osip_to_get_tag (next_request->from, &tag); if (i != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "Remote UA is not compliant: missing a tag in next request!\n")); return -1; } (*dialog) = (osip_dialog_t *) osip_malloc (sizeof (osip_dialog_t)); if (*dialog == NULL) return -1; (*dialog)->type = CALLER; #if 0 (*dialog)->state = DIALOG_CONFIRMED; #endif (*dialog)->state = DIALOG_EARLY; i = osip_call_id_to_str (next_request->call_id, &((*dialog)->call_id)); if (i != 0) goto diau_error_0; i = osip_from_get_tag (next_request->to, &tag); if (i != 0) goto diau_error_1; (*dialog)->local_tag = osip_strdup (tag->gvalue); i = osip_to_get_tag (next_request->from, &tag); if (i != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "Remote UA is not compliant: missing a tag in next request!\n")); (*dialog)->remote_tag = NULL; } else (*dialog)->remote_tag = osip_strdup (tag->gvalue); (*dialog)->route_set = (osip_list_t *) osip_malloc (sizeof (osip_list_t)); osip_list_init ((*dialog)->route_set); (*dialog)->local_cseq = local_cseq; /* -1 osip_atoi (xxx->cseq->number); */ (*dialog)->remote_cseq = osip_atoi (next_request->cseq->number); i = osip_to_clone (next_request->from, &((*dialog)->remote_uri)); if (i != 0) goto diau_error_3; i = osip_from_clone (next_request->to, &((*dialog)->local_uri)); if (i != 0) goto diau_error_4; (*dialog)->secure = -1; /* non secure */ return 0; diau_error_4: osip_from_free ((*dialog)->remote_uri); diau_error_3: osip_free ((*dialog)->remote_tag); osip_free ((*dialog)->local_tag); diau_error_1: osip_free ((*dialog)->call_id); diau_error_0: OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Could not establish dialog!\n")); osip_free (*dialog); *dialog = NULL; return -1; }
int eXosip_reinvite_with_authentication (struct eXosip_call_t *jc) { struct eXosip_call_t *jcc; #ifdef SM char *locip; #else char locip[50]; #endif osip_message_t * cloneinvite; osip_event_t *sipevent; osip_transaction_t *transaction; int osip_cseq_num,length; osip_via_t *via; char *tmp; int i; osip_message_clone (jc->c_out_tr->orig_request, &cloneinvite); osip_cseq_num = osip_atoi(jc->c_out_tr->orig_request->cseq->number); length = strlen(jc->c_out_tr->orig_request->cseq->number); tmp = (char *)osip_malloc(90*sizeof(char)); via = (osip_via_t *) osip_list_get (cloneinvite->vias, 0); osip_list_remove(cloneinvite->vias, 0); osip_via_free(via); #ifdef SM eXosip_get_localip_for(cloneinvite->req_uri->host,&locip); #else eXosip_guess_ip_for_via(eXosip.ip_family, locip, 49); #endif if (eXosip.ip_family==AF_INET6) { sprintf(tmp, "SIP/2.0/UDP [%s]:%s;branch=z9hG4bK%u", locip, eXosip.localport, via_branch_new_random()); } else { sprintf(tmp, "SIP/2.0/UDP %s:%s;branch=z9hG4bK%u", locip, eXosip.localport, via_branch_new_random()); } #ifdef SM osip_free(locip); #endif osip_via_init(&via); osip_via_parse(via, tmp); osip_list_add(cloneinvite->vias, via, 0); osip_free(tmp); osip_cseq_num++; osip_free(cloneinvite->cseq->number); cloneinvite->cseq->number = (char*)osip_malloc(length + 2); sprintf(cloneinvite->cseq->number, "%i", osip_cseq_num); eXosip_add_authentication_information(cloneinvite, jc->c_out_tr->last_response); cloneinvite->message_property = 0; eXosip_call_init(&jcc); i = osip_transaction_init(&transaction, ICT, eXosip.j_osip, cloneinvite); if (i!=0) { eXosip_call_free(jc); osip_message_free(cloneinvite); return -1; } jcc->c_out_tr = transaction; sipevent = osip_new_outgoing_sipmessage(cloneinvite); sipevent->transactionid = transaction->transactionid; osip_transaction_set_your_instance(transaction, __eXosip_new_jinfo(jcc, NULL, NULL, NULL)); osip_transaction_add_event(transaction, sipevent); jcc->external_reference = 0; ADD_ELEMENT(eXosip.j_calls, jcc); eXosip_update(); /* fixed? */ __eXosip_wakeup(); return 0; }
void nist_snd_23456xx (osip_transaction_t * nist, osip_event_t * evt) { int i; osip_via_t *via; osip_t *osip = (osip_t *) nist->config; if (nist->last_response != NULL) { osip_message_free (nist->last_response); } nist->last_response = evt->sip; via = (osip_via_t *) osip_list_get (nist->last_response->vias, 0); if (via) { char *host; int port; osip_generic_param_t *maddr; osip_generic_param_t *received; osip_generic_param_t *rport; osip_via_param_get_byname (via, "maddr", &maddr); osip_via_param_get_byname (via, "received", &received); osip_via_param_get_byname (via, "rport", &rport); /* 1: user should not use the provided information (host and port) if they are using a reliable transport. Instead, they should use the already open socket attached to this transaction. */ /* 2: check maddr and multicast usage */ if (maddr != NULL) host = maddr->gvalue; /* we should check if this is a multicast address and use set the "ttl" in this case. (this must be done in the UDP message (not at the SIP layer) */ else if (received != NULL) host = received->gvalue; else host = via->host; if (rport == NULL || rport->gvalue == NULL) { if (via->port != NULL) port = osip_atoi (via->port); else port = 5060; } else port = osip_atoi (rport->gvalue); i = osip->cb_send_message (nist, nist->last_response, host, port, nist->out_socket); } else i = -1; if (i != 0) { nist_handle_transport_error (nist, i); return; } else { if (EVT_IS_SND_STATUS_2XX (evt)) __osip_message_callback (OSIP_NIST_STATUS_2XX_SENT, nist, nist->last_response); else if (MSG_IS_STATUS_3XX (nist->last_response)) __osip_message_callback (OSIP_NIST_STATUS_3XX_SENT, nist, nist->last_response); else if (MSG_IS_STATUS_4XX (nist->last_response)) __osip_message_callback (OSIP_NIST_STATUS_4XX_SENT, nist, nist->last_response); else if (MSG_IS_STATUS_5XX (nist->last_response)) __osip_message_callback (OSIP_NIST_STATUS_5XX_SENT, nist, nist->last_response); else __osip_message_callback (OSIP_NIST_STATUS_6XX_SENT, nist, nist->last_response); } if (nist->state != NIST_COMPLETED) /* start J timer */ nist->nist_context->timer_j_start = time (NULL); __osip_transaction_set_state (nist, NIST_COMPLETED); }
static int dtls_tl_send_message(osip_transaction_t * tr, osip_message_t * sip, char *host, int port, int out_socket) { int len = 0; size_t length = 0; struct addrinfo *addrinfo; struct __eXosip_sockaddr addr; char *message; char ipbuf[INET6_ADDRSTRLEN]; int i; int pos; struct socket_tab *socket_tab_used=NULL; BIO *sbio=NULL; if (dtls_socket <= 0) return -1; if (host == NULL) { host = sip->req_uri->host; if (sip->req_uri->port != NULL) port = osip_atoi (sip->req_uri->port); else port = 5061; } if (port == 5060) port = 5061; if (MSG_IS_REQUEST(sip)) { if (MSG_IS_REGISTER(sip) ||MSG_IS_INVITE(sip) ||MSG_IS_SUBSCRIBE(sip) || MSG_IS_NOTIFY(sip)) eXtl_update_local_target(sip); } i=-1; #ifndef MINISIZE if (tr!=NULL && tr->record.name[0]!='\0' && tr->record.srventry[0].srv[0]!='\0') { /* always choose the first here. if a network error occur, remove first entry and replace with next entries. */ osip_srv_entry_t *srv; int n=0; for (srv = &tr->record.srventry[0]; n<10 && tr->record.srventry[0].srv[0]; srv = &tr->record.srventry[0]) { i = eXosip_get_addrinfo (&addrinfo, srv->srv, srv->port, IPPROTO_UDP); if (i == 0) { host = srv->srv; port = srv->port; break; } memmove(&tr->record.srventry[0], &tr->record.srventry[1], 9*sizeof(osip_srv_entry_t)); memset(&tr->record.srventry[9], 0, sizeof(osip_srv_entry_t)); i=-1; /* copy next element */ n++; } } #endif /* if SRV was used, distination may be already found */ if (i != 0) { i = eXosip_get_addrinfo (&addrinfo, host, port, IPPROTO_UDP); } if (i != 0) { return -1; } memcpy (&addr, addrinfo->ai_addr, addrinfo->ai_addrlen); len = addrinfo->ai_addrlen; eXosip_freeaddrinfo (addrinfo); /* remove preloaded route if there is no tag in the To header */ { osip_route_t *route=NULL; osip_generic_param_t *tag=NULL; osip_message_get_route (sip, 0, &route); osip_to_get_tag (sip->to, &tag); if (tag==NULL && route != NULL && route->url != NULL) { osip_list_remove(&sip->routes, 0); } i = osip_message_to_str (sip, &message, &length); if (tag==NULL && route != NULL && route->url != NULL) { osip_list_add(&sip->routes, route, 0); } } if (i != 0 || length <= 0) { return -1; } switch ( ((struct sockaddr *)&addr)->sa_family ) { case AF_INET: inet_ntop (((struct sockaddr *)&addr)->sa_family, &(((struct sockaddr_in *) &addr)->sin_addr), ipbuf, sizeof (ipbuf)); break; case AF_INET6: inet_ntop (((struct sockaddr *)&addr)->sa_family, &(((struct sockaddr_in6 *) &addr)->sin6_addr), ipbuf, sizeof (ipbuf)); break; default: strncpy (ipbuf, "(unknown)", sizeof (ipbuf)); break; } OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "Message sent: \n%s (to dest=%s:%i)\n", message, ipbuf, port)); for (pos = 0; pos < EXOSIP_MAX_SOCKETS; pos++) { if (dtls_socket_tab[pos].ssl_conn != NULL && dtls_socket_tab[pos].ssl_type == EXOSIP_AS_A_SERVER) { if (dtls_socket_tab[pos].remote_port == port && (strcmp (dtls_socket_tab[pos].remote_ip, ipbuf) == 0)) { BIO *rbio; socket_tab_used = &dtls_socket_tab[pos]; rbio = BIO_new_dgram (dtls_socket, BIO_NOCLOSE); BIO_dgram_set_peer (rbio, &addr); dtls_socket_tab[pos].ssl_conn->rbio = rbio; break; } } } if (socket_tab_used==NULL) { for (pos = 0; pos < EXOSIP_MAX_SOCKETS; pos++) { if (dtls_socket_tab[pos].ssl_conn != NULL && dtls_socket_tab[pos].ssl_type == EXOSIP_AS_A_CLIENT) { if (dtls_socket_tab[pos].remote_port == port && (strcmp (dtls_socket_tab[pos].remote_ip, ipbuf) == 0)) { BIO *rbio; socket_tab_used = &dtls_socket_tab[pos]; rbio = BIO_new_dgram (dtls_socket, BIO_NOCLOSE); BIO_dgram_set_peer (rbio, &addr); dtls_socket_tab[pos].ssl_conn->rbio = rbio; break; } } } } if (socket_tab_used==NULL) { /* delete an old one! */ pos=0; if (dtls_socket_tab[pos].ssl_conn != NULL) { shutdown_free_client_dtls (pos); shutdown_free_server_dtls (pos); } memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab)); } if (dtls_socket_tab[pos].ssl_conn == NULL) { /* create a new one */ SSL_CTX_set_read_ahead (client_ctx, 1); dtls_socket_tab[pos].ssl_conn = SSL_new (client_ctx); if (dtls_socket_tab[pos].ssl_conn == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "DTLS SSL_new error\n")); if (dtls_socket_tab[pos].ssl_conn != NULL) { shutdown_free_client_dtls (pos); shutdown_free_server_dtls (pos); } memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab)); osip_free (message); return -1; } if (connect (dtls_socket, (struct sockaddr *) &addr, sizeof (addr)) == -1) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "DTLS connect error\n")); if (dtls_socket_tab[pos].ssl_conn != NULL) { shutdown_free_client_dtls (pos); shutdown_free_server_dtls (pos); } memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab)); osip_free (message); return -1; } SSL_set_options (dtls_socket_tab[pos].ssl_conn, SSL_OP_NO_QUERY_MTU); SSL_set_mtu (dtls_socket_tab[pos].ssl_conn, 2000); SSL_set_connect_state (dtls_socket_tab[pos].ssl_conn); sbio = BIO_new_dgram (dtls_socket, BIO_NOCLOSE); BIO_ctrl_set_connected (sbio, 1, (struct sockaddr *) &addr); SSL_set_bio (dtls_socket_tab[pos].ssl_conn, sbio, sbio); dtls_socket_tab[pos].ssl_type = 2; dtls_socket_tab[pos].ssl_state = 2; osip_strncpy (dtls_socket_tab[pos].remote_ip, ipbuf, sizeof (dtls_socket_tab[pos].remote_ip)); dtls_socket_tab[pos].remote_port = port; } i = SSL_write (dtls_socket_tab[pos].ssl_conn, message, length); if (i<0) { i = SSL_get_error (dtls_socket_tab[pos].ssl_conn, i); print_ssl_error (i); if (i==SSL_ERROR_SSL || i==SSL_ERROR_SYSCALL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "DTLS SSL_write error\n")); if (dtls_socket_tab[pos].ssl_conn != NULL) { shutdown_free_client_dtls (pos); shutdown_free_server_dtls (pos); } memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab)); } #ifndef MINISIZE /* delete first SRV entry that is not reachable */ if (tr->record.name[0]!='\0' && tr->record.srventry[0].srv[0]!='\0') { memmove(&tr->record.srventry[0], &tr->record.srventry[1], 9*sizeof(osip_srv_entry_t)); memset(&tr->record.srventry[9], 0, sizeof(osip_srv_entry_t)); osip_free (message); return 0; /* retry for next retransmission! */ } #endif /* SIP_NETWORK_ERROR; */ osip_free (message); return -1; } if (eXosip.keep_alive > 0) { if (MSG_IS_REGISTER (sip)) { eXosip_reg_t *reg = NULL; if (_eXosip_reg_find (®, tr) == 0) { memcpy (&(reg->addr), &addr, len); reg->len = len; } } } osip_free (message); return 0; }
static int __osip_dialog_init (osip_dialog_t ** dialog, osip_message_t * invite, osip_message_t * response, osip_from_t * local, osip_to_t * remote, osip_message_t * remote_msg) { int i; int pos; osip_generic_param_t *tag; *dialog = NULL; if (response == NULL) return OSIP_BADPARAMETER; if (response->cseq == NULL || local == NULL || remote == NULL) return OSIP_SYNTAXERROR; (*dialog) = (osip_dialog_t *) osip_malloc (sizeof (osip_dialog_t)); if (*dialog == NULL) return OSIP_NOMEM; memset (*dialog, 0, sizeof (osip_dialog_t)); (*dialog)->your_instance = NULL; if (MSG_IS_STATUS_2XX (response)) (*dialog)->state = DIALOG_CONFIRMED; else /* 1XX */ (*dialog)->state = DIALOG_EARLY; i = osip_call_id_to_str (response->call_id, &((*dialog)->call_id)); if (i != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Could not establish dialog!\n")); osip_dialog_free (*dialog); *dialog = NULL; return i; } i = osip_to_get_tag (local, &tag); if (i != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Could not establish dialog!\n")); osip_dialog_free (*dialog); *dialog = NULL; return i; } (*dialog)->local_tag = osip_strdup (tag->gvalue); i = osip_from_get_tag (remote, &tag); if (i == 0) (*dialog)->remote_tag = osip_strdup (tag->gvalue); /* VR-2785: remember line value */ if (invite) { osip_uri_param_t *line_param; i = osip_uri_param_get_byname (&invite->req_uri->url_params, "line", &line_param); if (i == 0 && line_param != NULL && line_param->gvalue != NULL) (*dialog)->line_param = osip_strdup (line_param->gvalue); } osip_list_init (&(*dialog)->route_set); pos = 0; while (!osip_list_eol (&response->record_routes, pos)) { osip_record_route_t *rr; osip_record_route_t *rr2; rr = (osip_record_route_t *) osip_list_get (&response->record_routes, pos); i = osip_record_route_clone (rr, &rr2); if (i != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Could not establish dialog!\n")); osip_dialog_free (*dialog); *dialog = NULL; return i; } if (invite == NULL) osip_list_add (&(*dialog)->route_set, rr2, 0); else osip_list_add (&(*dialog)->route_set, rr2, -1); pos++; } /* local_cseq is set to response->cseq->number for better handling of bad UA */ (*dialog)->local_cseq = osip_atoi (response->cseq->number); i = osip_from_clone (remote, &((*dialog)->remote_uri)); if (i != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Could not establish dialog!\n")); osip_dialog_free (*dialog); *dialog = NULL; return i; } i = osip_to_clone (local, &((*dialog)->local_uri)); if (i != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Could not establish dialog!\n")); osip_dialog_free (*dialog); *dialog = NULL; return i; } { osip_contact_t *contact; if (!osip_list_eol (&remote_msg->contacts, 0)) { contact = osip_list_get (&remote_msg->contacts, 0); i = osip_contact_clone (contact, &((*dialog)->remote_contact_uri)); if (i != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Could not establish dialog!\n")); osip_dialog_free (*dialog); *dialog = NULL; return i; } } else { (*dialog)->remote_contact_uri = NULL; OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "Remote UA is not compliant: missing a contact in remote message!\n")); } } (*dialog)->secure = -1; /* non secure */ return OSIP_SUCCESS; }
static int udp_tl_send_message(osip_transaction_t * tr, osip_message_t * sip, char *host, int port, int out_socket) { int len = 0; size_t length = 0; struct addrinfo *addrinfo; struct __eXosip_sockaddr addr; char *message = NULL; char ipbuf[INET6_ADDRSTRLEN]; int i; osip_naptr_t *naptr_record=NULL; if (udp_socket <= 0) return -1; if (host == NULL) { host = sip->req_uri->host; if (sip->req_uri->port != NULL) port = osip_atoi(sip->req_uri->port); else port = 5060; } eXtl_update_local_target(sip); i = -1; #ifndef MINISIZE if (tr==NULL) { _eXosip_srv_lookup(sip, &naptr_record); if (naptr_record!=NULL) { eXosip_dnsutils_dns_process(naptr_record, 1); if (naptr_record->naptr_state==OSIP_NAPTR_STATE_NAPTRDONE ||naptr_record->naptr_state==OSIP_NAPTR_STATE_SRVINPROGRESS) eXosip_dnsutils_dns_process(naptr_record, 1); } if (naptr_record!=NULL && naptr_record->naptr_state==OSIP_NAPTR_STATE_SRVDONE) { /* 4: check if we have the one we want... */ if (naptr_record->sipudp_record.name[0] != '\0' && naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index].srv[0] != '\0') { /* always choose the first here. if a network error occur, remove first entry and replace with next entries. */ osip_srv_entry_t *srv; int n = 0; for (srv = &naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index]; n < 10 && naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index].srv[0]; srv = &naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index]) { if (srv->ipaddress[0]) i = eXosip_get_addrinfo(&addrinfo, srv->ipaddress, srv->port, IPPROTO_UDP); else i = eXosip_get_addrinfo(&addrinfo, srv->srv, srv->port, IPPROTO_UDP); if (i == 0) { host = srv->srv; port = srv->port; break; } i = eXosip_dnsutils_rotate_srv(&naptr_record->sipudp_record); if (i<=0) { return -1; } if (i>=n) { return -1; } i = -1; /* copy next element */ n++; } } } if (naptr_record!=NULL && naptr_record->keep_in_cache==0) osip_free(naptr_record); naptr_record=NULL; } else { naptr_record = tr->naptr_record; } if (naptr_record!=NULL) { /* 1: make sure there is no pending DNS */ eXosip_dnsutils_dns_process(naptr_record, 0); if (naptr_record->naptr_state==OSIP_NAPTR_STATE_NAPTRDONE ||naptr_record->naptr_state==OSIP_NAPTR_STATE_SRVINPROGRESS) eXosip_dnsutils_dns_process(naptr_record, 0); if (naptr_record->naptr_state==OSIP_NAPTR_STATE_UNKNOWN) { /* fallback to DNS A */ if (naptr_record->keep_in_cache==0) osip_free(naptr_record); naptr_record=NULL; if (tr!=NULL) tr->naptr_record=NULL; /* must never happen? */ } else if (naptr_record->naptr_state==OSIP_NAPTR_STATE_INPROGRESS) { /* 2: keep waiting (naptr answer not received) */ return OSIP_SUCCESS + 1; } else if (naptr_record->naptr_state==OSIP_NAPTR_STATE_NAPTRDONE) { /* 3: keep waiting (naptr answer received/no srv answer received) */ return OSIP_SUCCESS + 1; } else if (naptr_record->naptr_state==OSIP_NAPTR_STATE_SRVINPROGRESS) { /* 3: keep waiting (naptr answer received/no srv answer received) */ return OSIP_SUCCESS + 1; } else if (naptr_record->naptr_state==OSIP_NAPTR_STATE_SRVDONE) { /* 4: check if we have the one we want... */ if (naptr_record->sipudp_record.name[0] != '\0' && naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index].srv[0] != '\0') { /* always choose the first here. if a network error occur, remove first entry and replace with next entries. */ osip_srv_entry_t *srv; int n = 0; for (srv = &naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index]; n < 10 && naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index].srv[0]; srv = &naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index]) { if (srv->ipaddress[0]) i = eXosip_get_addrinfo(&addrinfo, srv->ipaddress, srv->port, IPPROTO_UDP); else i = eXosip_get_addrinfo(&addrinfo, srv->srv, srv->port, IPPROTO_UDP); if (i == 0) { host = srv->srv; port = srv->port; break; } i = eXosip_dnsutils_rotate_srv(&naptr_record->sipudp_record); if (i<=0) { return -1; } if (i>=n) { return -1; } i = -1; /* copy next element */ n++; } } } else if (naptr_record->naptr_state==OSIP_NAPTR_STATE_NOTSUPPORTED ||naptr_record->naptr_state==OSIP_NAPTR_STATE_RETRYLATER) { /* 5: fallback to DNS A */ if (naptr_record->keep_in_cache==0) osip_free(naptr_record); naptr_record=NULL; if (tr!=NULL) tr->naptr_record=NULL; } } #endif /* if SRV was used, destination may be already found */ if (i != 0) { i = eXosip_get_addrinfo(&addrinfo, host, port, IPPROTO_UDP); } if (i != 0) { return -1; } memcpy(&addr, addrinfo->ai_addr, addrinfo->ai_addrlen); len = addrinfo->ai_addrlen; eXosip_freeaddrinfo(addrinfo); /* remove preloaded route if there is no tag in the To header */ { osip_route_t *route = NULL; osip_generic_param_t *tag = NULL; osip_message_get_route(sip, 0, &route); osip_to_get_tag(sip->to, &tag); if (tag == NULL && route != NULL && route->url != NULL) { osip_list_remove(&sip->routes, 0); } i = osip_message_to_str(sip, &message, &length); if (tag == NULL && route != NULL && route->url != NULL) { osip_list_add(&sip->routes, route, 0); } } if (i != 0 || length <= 0) { osip_free(message); return -1; } switch (((struct sockaddr *) &addr)->sa_family) { case AF_INET: inet_ntop(((struct sockaddr *) &addr)->sa_family, &(((struct sockaddr_in *) &addr)->sin_addr), ipbuf, sizeof(ipbuf)); break; case AF_INET6: inet_ntop(((struct sockaddr *) &addr)->sa_family, &(((struct sockaddr_in6 *) &addr)->sin6_addr), ipbuf, sizeof(ipbuf)); break; default: strncpy(ipbuf, "(unknown)", sizeof(ipbuf)); break; } OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO1, NULL, "Message sent: (to dest=%s:%i)\n%s\n", ipbuf, port, message)); if (osip_strcasecmp(host, ipbuf)!=0 && MSG_IS_REQUEST(sip)) { if (MSG_IS_REGISTER(sip)) { struct eXosip_dns_cache entry; memset(&entry, 0, sizeof(struct eXosip_dns_cache)); snprintf(entry.host, sizeof(entry.host), "%s", host); snprintf(entry.ip, sizeof(entry.ip), "%s", ipbuf); eXosip_set_option(EXOSIP_OPT_ADD_DNS_CACHE, (void *) &entry); } } if (tr != NULL) { if (tr->ict_context != NULL) osip_ict_set_destination(tr->ict_context, osip_strdup(ipbuf), port); if (tr->nict_context != NULL) osip_nict_set_destination(tr->nict_context, osip_strdup(ipbuf), port); } if (0 > sendto(udp_socket, (const void *) message, length, 0, (struct sockaddr *) &addr, len)) { #ifndef MINISIZE if (naptr_record!=NULL) { /* rotate on failure! */ if (eXosip_dnsutils_rotate_srv(&naptr_record->sipudp_record)>0) { osip_free(message); return OSIP_SUCCESS + 1; /* retry for next retransmission! */ } } #endif /* SIP_NETWORK_ERROR; */ osip_free(message); return -1; } if (eXosip.keep_alive > 0) { if (MSG_IS_REGISTER(sip)) { eXosip_reg_t *reg = NULL; if (_eXosip_reg_find(®, tr) == 0) { memcpy(&(reg->addr), &addr, len); reg->len = len; } } } #ifndef MINISIZE if (naptr_record!=NULL) { if (tr!=NULL && MSG_IS_REGISTER(sip) && tr->last_response==NULL) { /* failover for outgoing transaction */ time_t now; now = time(NULL); OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "not yet answered\n")); if (tr != NULL && now - tr->birth_time > 10 && now - tr->birth_time < 13) { /* avoid doing this twice... */ if (eXosip_dnsutils_rotate_srv(&naptr_record->sipudp_record)>0) { OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO1, NULL, "Doing failover: %s:%i->%s:%i\n", host, port, naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index].srv, naptr_record->sipudp_record.srventry[naptr_record->sipudp_record.index].port)); osip_free(message); return OSIP_SUCCESS + 1; /* retry for next retransmission! */ } } } } #endif osip_free(message); return OSIP_SUCCESS; }
static int _eXosip_register_build_register(eXosip_reg_t * jr, osip_message_t ** _reg) { osip_message_t *reg = NULL; int i; *_reg = NULL; if (jr == NULL) return OSIP_BADPARAMETER; if (jr->r_last_tr != NULL) { if (jr->r_last_tr->state != NICT_TERMINATED && jr->r_last_tr->state != NICT_COMPLETED) return OSIP_WRONG_STATE; else { osip_message_t *last_response = NULL; osip_transaction_t *tr; i = osip_message_clone(jr->r_last_tr->orig_request, ®); if (i != 0) return i; if (jr->r_last_tr->last_response != NULL) { i = osip_message_clone(jr->r_last_tr->last_response, &last_response); if (i != 0) { osip_message_free(reg); return i; } } __eXosip_delete_jinfo(jr->r_last_tr); tr = jr->r_last_tr; jr->r_last_tr = NULL; osip_list_add(&eXosip.j_transactions, tr, 0); /* modify the REGISTER request */ { int osip_cseq_num = osip_atoi(reg->cseq->number); int length = strlen(reg->cseq->number); osip_list_special_free(®->authorizations, (void (*)(void *)) &osip_authorization_free); osip_list_special_free(®->proxy_authorizations, (void (*)(void *)) &osip_proxy_authorization_free); i = eXosip_update_top_via(reg); if (i != 0) { osip_message_free(reg); if (last_response != NULL) osip_message_free(last_response); return i; } osip_cseq_num++; osip_free(reg->cseq->number); reg->cseq->number = (char *) osip_malloc(length + 2); /* +2 like for 9 to 10 */ if (reg->cseq->number == NULL) { osip_message_free(reg); if (last_response != NULL) osip_message_free(last_response); return OSIP_NOMEM; } snprintf(reg->cseq->number, length + 2, "%i", osip_cseq_num); if (last_response != NULL && last_response->status_code == 423) { /* increase expires value to "min-expires" value */ osip_header_t *exp; osip_header_t *min_exp; osip_message_header_get_byname(reg, "expires", 0, &exp); osip_message_header_get_byname(last_response, "min-expires", 0, &min_exp); if (exp != NULL && exp->hvalue != NULL && min_exp != NULL && min_exp->hvalue != NULL) { osip_free(exp->hvalue); exp->hvalue = osip_strdup(min_exp->hvalue); jr->r_reg_period = atoi(min_exp->hvalue); } else { osip_message_free(reg); if (last_response != NULL) osip_message_free(last_response); OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: missing Min-Expires or Expires in REGISTER\n")); return OSIP_SYNTAXERROR; } } else { osip_header_t *exp; osip_message_header_get_byname(reg, "expires", 0, &exp); if (exp != NULL) { if (exp->hvalue != NULL) osip_free(exp->hvalue); exp->hvalue = (char *) osip_malloc(10); if (exp->hvalue == NULL) { osip_message_free(reg); if (last_response != NULL) osip_message_free(last_response); return OSIP_NOMEM; } snprintf(exp->hvalue, 9, "%i", jr->r_reg_period); } } osip_message_force_update(reg); } if (last_response != NULL) { if (last_response->status_code == 401 || last_response->status_code == 407) { eXosip_add_authentication_information(reg, last_response); } else eXosip_add_authentication_information(reg, NULL); osip_message_free(last_response); } } } if (reg == NULL) { i = generating_register(jr, ®, eXosip.transport, jr->r_aor, jr->r_registrar, jr->r_contact, jr->r_reg_period); if (i != 0) return i; } *_reg = reg; return OSIP_SUCCESS; }
void ict_rcv_3456xx(osip_transaction_t * ict, osip_event_t * evt) { osip_route_t *route; int i; osip_t *osip = (osip_t *) ict->config; /* leave this answer to the core application */ if (ict->last_response != NULL) osip_message_free(ict->last_response); ict->last_response = evt->sip; if (ict->state != ICT_COMPLETED) { /* not a retransmission */ /* automatic handling of ack! */ osip_message_t *ack = ict_create_ack(ict, evt->sip); ict->ack = ack; if (ict->ack == NULL) { __osip_transaction_set_state(ict, ICT_TERMINATED); __osip_kill_transaction_callback(OSIP_ICT_KILL_TRANSACTION, ict); return; } /* reset ict->ict_context->destination only if it is not yet set. */ if (ict->ict_context->destination == NULL) { osip_message_get_route(ack, 0, &route); if (route != NULL && route->url != NULL) { osip_uri_param_t *lr_param; osip_uri_uparam_get_byname(route->url, "lr", &lr_param); if (lr_param == NULL) { /* using uncompliant proxy: destination is the request-uri */ route = NULL; } } if (route != NULL && route->url != NULL) { int port = 5060; if (route->url->port != NULL) port = osip_atoi(route->url->port); osip_ict_set_destination(ict->ict_context, osip_strdup(route->url->host), port); } else { int port = 5060; /* search for maddr parameter */ osip_uri_param_t *maddr_param = NULL; port = 5060; if (ack->req_uri->port != NULL) port = osip_atoi(ack->req_uri->port); osip_uri_uparam_get_byname(ack->req_uri, "maddr", &maddr_param); if (maddr_param != NULL && maddr_param->gvalue != NULL) osip_ict_set_destination(ict->ict_context, osip_strdup(maddr_param->gvalue), port); else osip_ict_set_destination(ict->ict_context, osip_strdup(ack->req_uri->host), port); } } i = osip->cb_send_message(ict, ack, ict->ict_context->destination, ict->ict_context->port, ict->out_socket); if (i != 0) { ict_handle_transport_error(ict, i); return; } if (MSG_IS_STATUS_3XX(evt->sip)) __osip_message_callback(OSIP_ICT_STATUS_3XX_RECEIVED, ict, evt->sip); else if (MSG_IS_STATUS_4XX(evt->sip)) __osip_message_callback(OSIP_ICT_STATUS_4XX_RECEIVED, ict, evt->sip); else if (MSG_IS_STATUS_5XX(evt->sip)) __osip_message_callback(OSIP_ICT_STATUS_5XX_RECEIVED, ict, evt->sip); else __osip_message_callback(OSIP_ICT_STATUS_6XX_RECEIVED, ict, evt->sip); __osip_message_callback(OSIP_ICT_ACK_SENT, ict, evt->sip); } /* start timer D (length is set to MAX (64*DEFAULT_T1 or 32000) */ osip_gettimeofday(&ict->ict_context->timer_d_start, NULL); add_gettimeofday(&ict->ict_context->timer_d_start, ict->ict_context->timer_d_length); __osip_transaction_set_state(ict, ICT_COMPLETED); }
PPL_DECLARE (int) psp_core_event_add_sip_message (osip_event_t * evt) { osip_transaction_t *transaction; osip_message_t *answer1xx; int i; if (MSG_IS_REQUEST (evt->sip)) { /* delete request where cseq method does not match the method in request-line */ if (evt->sip->cseq==NULL || evt->sip==NULL || evt->sip->cseq->method==NULL || evt->sip->sip_method==NULL) { osip_event_free (evt); return -1; } if (0 != strcmp (evt->sip->cseq->method, evt->sip->sip_method)) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "core module: Discard invalid message with method!=cseq!\n")); osip_event_free (evt); return -1; } } i = psp_core_find_osip_transaction_and_add_event (evt); if (i == 0) { psp_osip_wakeup (core->psp_osip); return 0; /*evt consumed */ } if (MSG_IS_REQUEST (evt->sip)) { if (MSG_IS_ACK (evt->sip)) { /* continue as it is a new transaction... */ osip_route_t *route; /* If a route header is present, then plugins will give the correct location. */ osip_message_get_route (evt->sip, 0, &route); if (route == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "core module: This is a late ACK to discard!\n")); /* It can be a ACK for 200 ok, but those ACK SHOULD never go through this proxy! (and should be sent to the contact header of the 200ok */ #ifdef SUPPORT_FOR_BROKEN_UA /* if this ACK has a request-uri that is not us, forward the message there. How should I modify this message?? */ if (evt!=NULL && evt->sip!=NULL && evt->sip!=NULL && evt->sip->req_uri!=NULL) { if (psp_core_is_responsible_for_this_domain(evt->sip->req_uri)!=0) { int port = 5060; if (evt->sip->req_uri->port != NULL) port = osip_atoi (evt->sip->req_uri->port); psp_core_cb_snd_message(NULL, evt->sip, evt->sip->req_uri->host, port, -1); } } #endif osip_event_free (evt); return 0; } OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "core module: This is a ACK for INVITE!\n")); psp_core_event_add_sfp_inc_ack (evt->sip); osip_free (evt); return 0; } /* we can create the transaction and send a 1xx */ transaction = osip_create_transaction (core->psp_osip->osip, evt); if (transaction == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO3, NULL, "core module: Could not create a transaction for this request!\n")); osip_event_free (evt); return -1; } /* now, all retransmissions will be handled by oSIP. */ /* From rfc3261: (Section: 16.2) "Thus, a stateful proxy SHOULD NOT generate 100 (Trying) responses to non-INVITE requests." */ if (MSG_IS_INVITE (evt->sip)) { i = osip_msg_build_response (&answer1xx, 100, evt->sip); if (i != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "sfp module: could not create a 100 Trying for this transaction. (discard it and let the transaction die itself)!\n")); osip_event_free (evt); return -1; } osip_transaction_add_event (transaction, evt); evt = osip_new_outgoing_sipmessage (answer1xx); evt->transactionid = transaction->transactionid; osip_transaction_add_event (transaction, evt); } else osip_transaction_add_event (transaction, evt); psp_osip_wakeup (core->psp_osip); return 0; } else { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO3, NULL, "sfp module: No module seems to be able to forward this response!\n")); /* this is probably a late answer? */ /* let's forward it! */ i = psp_core_handle_late_answer (evt->sip); if (i != 0) { osip_event_free (evt); return -1; } osip_event_free (evt); } return 0; }
static int msg_osip_body_parse(osip_message_t * sip, const char *start_of_buf, const char **next_body, size_t length) { const char *start_of_body; const char *end_of_body; const char *end_of_buf; char *tmp; int i; char *sep_boundary; size_t len_sep_boundary; osip_generic_param_t *ct_param; if (sip->content_type == NULL || sip->content_type->type == NULL || sip->content_type->subtype == NULL) return OSIP_SUCCESS; /* no body is attached */ if (0 != osip_strcasecmp(sip->content_type->type, "multipart")) { size_t osip_body_len; if (start_of_buf[0] == '\0') return OSIP_SYNTAXERROR; /* final CRLF is missing */ /* get rid of the first CRLF */ if ('\r' == start_of_buf[0]) { if ('\n' == start_of_buf[1]) start_of_body = start_of_buf + 2; else start_of_body = start_of_buf + 1; } else if ('\n' == start_of_buf[0]) start_of_body = start_of_buf + 1; else return OSIP_SYNTAXERROR; /* message does not end with CRLFCRLF, CRCR or LFLF */ /* update length (without CRLFCRLF */ length = length - (start_of_body - start_of_buf); /* fixed 24 08 2004 */ if (length <= 0) return OSIP_SYNTAXERROR; if (sip->content_length != NULL) osip_body_len = osip_atoi(sip->content_length->value); else { /* if content_length does not exist, set it. */ char tmp[16]; /* case where content-length is missing but the body only contains non-binary data */ if (0 == osip_strcasecmp(sip->content_type->type, "application") && 0 == osip_strcasecmp(sip->content_type->subtype, "sdp")) { osip_body_len = strlen(start_of_body); sprintf(tmp, "%i", osip_body_len); i = osip_message_set_content_length(sip, tmp); if (i != 0) return i; } else return OSIP_SYNTAXERROR; /* Content-type may be non binary data */ } if (length < osip_body_len) { OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Message was not receieved enterely. length=%i osip_body_len=%i\n", length, osip_body_len)); return OSIP_SYNTAXERROR; } end_of_body = start_of_body + osip_body_len; tmp = osip_malloc(end_of_body - start_of_body + 2); if (tmp == NULL) return OSIP_NOMEM; memcpy(tmp, start_of_body, end_of_body - start_of_body); tmp[end_of_body - start_of_body] = '\0'; i = osip_message_set_body(sip, tmp, end_of_body - start_of_body); osip_free(tmp); if (i != 0) return i; return OSIP_SUCCESS; } /* find the boundary */ i = osip_generic_param_get_byname(&sip->content_type->gen_params, "boundary", &ct_param); if (i != 0) return i; if (ct_param == NULL) return OSIP_SYNTAXERROR; if (ct_param->gvalue == NULL) return OSIP_SYNTAXERROR; /* No boundary but multiple headers??? */ { const char *boundary_prefix = "\n--"; size_t len = strlen(ct_param->gvalue); sep_boundary = (char *) osip_malloc(len + 4); if (sep_boundary == NULL) return OSIP_NOMEM; strcpy(sep_boundary, boundary_prefix); if (ct_param->gvalue[0] == '"' && ct_param->gvalue[len - 1] == '"') strncat(sep_boundary, ct_param->gvalue + 1, len - 2); else strncat(sep_boundary, ct_param->gvalue, len); } len_sep_boundary = strlen(sep_boundary); *next_body = NULL; start_of_body = start_of_buf; end_of_buf = start_of_buf + length; for (;;) { size_t body_len = 0; i = __osip_find_next_occurence(sep_boundary, start_of_body, &start_of_body, end_of_buf); if (i != 0) { osip_free(sep_boundary); return i; } i = __osip_find_next_occurence(sep_boundary, start_of_body + len_sep_boundary, &end_of_body, end_of_buf); if (i != 0) { osip_free(sep_boundary); return i; } /* this is the real beginning of body */ start_of_body = start_of_body + len_sep_boundary + 1; if ('\n' == start_of_body[0] || '\r' == start_of_body[0]) start_of_body++; body_len = end_of_body - start_of_body; /* Skip CR before end boundary. */ if (*(end_of_body - 1) == '\r') body_len--; tmp = osip_malloc(body_len + 2); if (tmp == NULL) { osip_free(sep_boundary); return OSIP_NOMEM; } memcpy(tmp, start_of_body, body_len); tmp[body_len] = '\0'; i = osip_message_set_body_mime(sip, tmp, body_len); osip_free(tmp); if (i != 0) { osip_free(sep_boundary); return i; } if (strncmp(end_of_body + len_sep_boundary, "--", 2) == 0) { /* end of all bodies */ *next_body = end_of_body; osip_free(sep_boundary); return OSIP_SUCCESS; } /* continue on the next body */ start_of_body = end_of_body; } /* Unreachable code */ /* osip_free (sep_boundary); */ return OSIP_SYNTAXERROR; }
static int tcp_tl_send_message(osip_transaction_t * tr, osip_message_t * sip, char *host, int port, int out_socket) { size_t length = 0; char *message; int i; if (host == NULL) { host = sip->req_uri->host; if (sip->req_uri->port != NULL) port = osip_atoi (sip->req_uri->port); else port = 5060; } /* remove preloaded route if there is no tag in the To header */ { osip_route_t *route=NULL; osip_generic_param_t *tag=NULL; osip_message_get_route (sip, 0, &route); osip_to_get_tag (sip->to, &tag); if (tag==NULL && route != NULL && route->url != NULL) { osip_list_remove(&sip->routes, 0); } i = osip_message_to_str (sip, &message, &length); if (tag==NULL && route != NULL && route->url != NULL) { osip_list_add(&sip->routes, route, 0); } } if (i != 0 || length <= 0) { return -1; } /* Step 1: find existing socket to send message */ if (out_socket <= 0) { out_socket = _tcp_tl_find_socket (host, port); /* Step 2: create new socket with host:port */ if (out_socket <= 0) { out_socket = _tcp_tl_connect_socket (host, port); } OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "Message sent: \n%s (to dest=%s:%i)\n", message, host, port)); } else { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "Message sent: \n%s (reusing REQUEST connection)\n", message)); } if (out_socket <= 0) { return -1; } if (0 > send (out_socket, (const void *) message, length, 0)) { #ifdef WIN32 if (WSAECONNREFUSED == WSAGetLastError ()) #else if (ECONNREFUSED == errno) #endif { /* This can be considered as an error, but for the moment, I prefer that the application continue to try sending message again and again... so we are not in a error case. Nevertheless, this error should be announced! ALSO, UAS may not have any other options than retry always on the same port. */ osip_free (message); return 1; } else { /* SIP_NETWORK_ERROR; */ #if !defined(_WIN32_WCE) OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "TCP error: \n%s\n", strerror (errno))); #endif osip_free (message); return -1; } } osip_free (message); return 0; }
int _eXosip_srv_lookup(osip_transaction_t * tr, osip_message_t * sip, struct osip_srv_record *record) { int use_srv = 1; int port; char *host; osip_via_t *via; via = (osip_via_t *) osip_list_get(&sip->vias, 0); if (via == NULL || via->protocol == NULL) return OSIP_BADPARAMETER; if (MSG_IS_REQUEST(sip)) { osip_route_t *route; osip_message_get_route(sip, 0, &route); if (route != NULL) { osip_uri_param_t *lr_param = NULL; osip_uri_uparam_get_byname(route->url, "lr", &lr_param); if (lr_param == NULL) route = NULL; } if (route != NULL) { port = 5060; if (route->url->port != NULL) { port = osip_atoi(route->url->port); use_srv = 0; } host = route->url->host; } else { /* search for maddr parameter */ osip_uri_param_t *maddr_param = NULL; osip_uri_uparam_get_byname(sip->req_uri, "maddr", &maddr_param); host = NULL; if (maddr_param != NULL && maddr_param->gvalue != NULL) host = maddr_param->gvalue; port = 5060; if (sip->req_uri->port != NULL) { use_srv = 0; port = osip_atoi(sip->req_uri->port); } if (host == NULL) host = sip->req_uri->host; } } else { osip_generic_param_t *maddr; osip_generic_param_t *received; osip_generic_param_t *rport; osip_via_param_get_byname(via, "maddr", &maddr); osip_via_param_get_byname(via, "received", &received); osip_via_param_get_byname(via, "rport", &rport); if (maddr != NULL) host = maddr->gvalue; else if (received != NULL) host = received->gvalue; else host = via->host; if (via->port == NULL) use_srv = 0; if (rport == NULL || rport->gvalue == NULL) { if (via->port != NULL) port = osip_atoi(via->port); else port = 5060; } else port = osip_atoi(rport->gvalue); } if (host == NULL) { return OSIP_UNKNOWN_HOST; } /* check if we have an IPv4 or IPv6 address */ if (strchr(host, ':') || (INADDR_NONE != inet_addr(host))) { return OSIP_UNKNOWN_HOST; } if (use_srv == 1) { int i; i = eXosip_get_srv_record(record, host, via->protocol); return i; } return OSIP_SUCCESS; }