char local_peer[128];
char remote_peer[128];
char asserted_id[128];
+ int allow_register;
int register_state;
char register_user[128];
char register_host[128];
/* bind socket */
ip = htonl(INADDR_ANY);
-// ia.s_addr = ip;
start_port = inst->next_rtp_port;
while (1) {
rc = rtp_sub_socket_bind(p_s_rtp_fd.fd, &p_s_rtp_sin_local, ip, inst->next_rtp_port);
struct in_addr ia;
ia.s_addr = htonl(p_s_rtp_ip_remote);
+ if (p_s_rtp_is_connected)
+ PDEBUG(DEBUG_SIP, "reconnecting existing RTP connection to new/same destination\n");
PDEBUG(DEBUG_SIP, "rtp_connect(ip=%s, port=%u)\n", inet_ntoa(ia), p_s_rtp_port_remote);
rc = rtp_sub_socket_connect(p_s_rtp_fd.fd, &p_s_rtp_sin_local, &p_s_rtp_sin_remote, p_s_rtp_ip_remote, p_s_rtp_port_remote);
int Psip::message_connect(unsigned int epoint_id, int message_id, union parameter *param)
{
struct sip_inst *inst = (struct sip_inst *) p_s_sip_inst;
- char sdp_str[256] = "";
- struct in_addr ia;
+ const char *sdp_str = NULL;
struct lcr_msg *message;
struct interface *interface;
int media_type;
media_type = (options.law=='a') ? MEDIA_TYPE_ALAW : MEDIA_TYPE_ULAW;
payload_type = (options.law=='a') ? PAYLOAD_TYPE_ALAW : PAYLOAD_TYPE_ULAW;
/* open local RTP peer (if not bridging) */
- if (!p_s_rtp_is_connected && rtp_connect() < 0) {
+ if (rtp_connect() < 0) {
nua_cancel(p_s_handle, TAG_END());
nua_handle_destroy(p_s_handle);
p_s_handle = NULL;
}
}
- memset(&ia, 0, sizeof(ia));
- ia.s_addr = htonl(get_local_ip(p_s_rtp_ip_local));
- SPRINT(sdp_str,
- "v=0\r\n"
- "o=LCR-Sofia-SIP 0 0 IN IP4 %s\r\n"
- "s=SIP Call\r\n"
- "c=IN IP4 %s\r\n"
- "t=0 0\r\n"
- "m=audio %d RTP/AVP %d\r\n"
- "a=rtpmap:%d %s/8000\r\n"
- , inet_ntoa(ia), inet_ntoa(ia), p_s_rtp_port_local, payload_type, payload_type, media_type2name(media_type));
+ sdp_str = generate_sdp(p_s_rtp_ip_local, p_s_rtp_port_local, 1, &payload_type, &media_type);
PDEBUG(DEBUG_SIP, "Using SDP response: %s\n", sdp_str);
/* NOTE:
sip_trace_header(this, inst->interface_name, "RESPOND", DIRECTION_OUT);
add_trace("respond", "value", "200 OK");
add_trace("reason", NULL, "call connected");
- if (sdp_str[0]) {
- add_trace("rtp", "ip", "%s", inet_ntoa(ia));
- add_trace("rtp", "port", "%d,%d", p_s_rtp_port_local, p_s_rtp_port_local + 1);
- add_trace("rtp", "payload", "%s:%d", media_type2name(media_type), payload_type);
- }
+ struct in_addr ia;
+ memset(&ia, 0, sizeof(ia));
+ ia.s_addr = htonl(get_local_ip(p_s_rtp_ip_local));
+ add_trace("rtp", "ip", "%s", inet_ntoa(ia));
+ add_trace("rtp", "port", "%d,%d", p_s_rtp_port_local, p_s_rtp_port_local + 1);
+ add_trace("rtp", "payload", "%s:%d", media_type2name(media_type), payload_type);
end_trace();
return 0;
const char *local = inst->local_peer;
char local_ip[16];
const char *remote = inst->remote_peer;
- char sdp_str[512], pt_str[32];
- struct in_addr ia;
+ const char *sdp_str = NULL;
struct epoint_list *epointlist;
sip_cseq_t *cseq = NULL;
struct lcr_msg *message;
}
}
- memset(&ia, 0, sizeof(ia));
- ia.s_addr = htonl(get_local_ip(p_s_rtp_ip_local));
p_s_handle = nua_handle(inst->nua, NULL, TAG_END());
if (!p_s_handle) {
PERROR("Failed to create handle\n");
// add_trace("handle", "new", "0x%x", p_s_handle);
// end_trace();
- SPRINT(sdp_str,
- "v=0\r\n"
- "o=LCR-Sofia-SIP 0 0 IN IP4 %s\r\n"
- "s=SIP Call\r\n"
- "c=IN IP4 %s\r\n"
- "t=0 0\r\n"
- "m=audio %d RTP/AVP"
- , inet_ntoa(ia), inet_ntoa(ia), p_s_rtp_port_local);
- for (i = 0; i < payloads; i++) {
- SPRINT(pt_str, " %d", payload_types[i]);
- SCAT(sdp_str, pt_str);
- }
- SCAT(sdp_str, "\r\n");
- for (i = 0; i < payloads; i++) {
- SPRINT(pt_str, "a=rtpmap:%d %s/8000\r\n", payload_types[i], media_type2name(media_types[i]));
- SCAT(sdp_str, pt_str);
- }
+ sdp_str = generate_sdp(p_s_rtp_ip_local, p_s_rtp_port_local, payloads, payload_types, media_types);
PDEBUG(DEBUG_SIP, "Using SDP for invite: %s\n", sdp_str);
SPRINT(from, "sip:%s@%s", p_callerinfo.id, remote);
add_trace("to", "uri", "%s", to);
if (asserted_id[0])
add_trace("assert-id", "uri", "%s", asserted_id);
+ struct in_addr ia;
+ memset(&ia, 0, sizeof(ia));
+ ia.s_addr = htonl(get_local_ip(p_s_rtp_ip_local));
add_trace("rtp", "ip", "%s", inet_ntoa(ia));
add_trace("rtp", "port", "%d,%d", p_s_rtp_port_local, p_s_rtp_port_local + 1);
for (i = 0; i < payloads; i++)
switch (param->notifyinfo.notify) {
case INFO_NOTIFY_REMOTE_HOLD:
#if 0
+ sdp_str = generate_sdp(0, 0, 0, NULL, NULL);
SPRINT(sdp_str,
"v=0\r\n"
"o=LCR-Sofia-SIP 0 0 IN IP4 0.0.0.0\r\n"
break;
case INFO_NOTIFY_REMOTE_RETRIEVAL:
#if 0
- memset(&ia, 0, sizeof(ia));
- ia.s_addr = htonl(get_local_ip(p_s_rtp_ip_local));
- SPRINT(sdp_str,
- "v=0\r\n"
- "o=LCR-Sofia-SIP 0 0 IN IP4 %s\r\n"
- "s=SIP Call\r\n"
- "c=IN IP4 %s\r\n"
- "t=0 0\r\n"
- "m=audio %d RTP/AVP %d\r\n"
- "a=rtpmap:%d %s/8000\r\n"
- , inet_ntoa(ia), inet_ntoa(ia), p_s_rtp_port_local, p_s_rtp_payload_type, p_s_rtp_payload_type, media_type2name(p_s_rtp_media_type));
+ sdp_str = generate_sdp(p_s_rtp_ip_local, p_s_rtp_port_local, 1, &payload_type, &media_type);
PDEBUG(DEBUG_SIP, "Using SDP for rertieve: %s\n", sdp_str);
nua_info(p_s_handle,
// TAG_IF(from[0], SIPTAG_FROM_STR(from)),
return 0;
}
+const char *Psip::generate_sdp(unsigned int rtp_ip_local, unsigned short rtp_port_local, int payloads, unsigned char *payload_types, int *media_types)
+{
+ struct in_addr ia;
+ static char sdp_str[256], sub_str[128];
+ int i;
+
+ memset(&ia, 0, sizeof(ia));
+ ia.s_addr = htonl(get_local_ip(p_s_rtp_ip_local));
+ SPRINT(sdp_str,
+ "v=0\r\n"
+ "o=LCR-Sofia-SIP 0 0 IN IP4 %s\r\n"
+ "s=SIP Call\r\n"
+ "c=IN IP4 %s\r\n"
+ "t=0 0\r\n", inet_ntoa(ia), inet_ntoa(ia));
+ if (payloads) {
+ SPRINT(sub_str, "m=audio %d RTP/AVP", p_s_rtp_port_local);
+ SCAT(sdp_str, sub_str);
+ for (i = 0; i < payloads; i++) {
+ SPRINT(sub_str, " %d", payload_types[i]);
+ SCAT(sdp_str, sub_str);
+ }
+ SCAT(sdp_str, "\r\n");
+ for (i = 0; i < payloads; i++) {
+ SPRINT(sub_str, "a=rtpmap:%d %s/8000\r\n", payload_types[i], media_type2name(media_types[i]));
+ SCAT(sdp_str, sub_str);
+ }
+ }
+
+ return sdp_str;
+}
+
static int challenge(struct sip_inst *inst, class Psip *psip, int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[])
{
sip_www_authenticate_t const *authenticate = NULL;
return 0;
}
+static void i_options(struct sip_inst *inst, int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[])
+{
+ #define NUTAG_WITH_THIS_MSG(msg) nutag_with, tag_ptr_v(msg)
+ nua_saved_event_t saved[1];
+ nua_save_event(nua, saved);
+ nua_event_data_t const *data = nua_event_data(saved);
+
+ sip_trace_header(NULL, inst->interface_name, "OPTIONS", DIRECTION_IN);
+ end_trace();
+
+ sip_trace_header(NULL, inst->interface_name, "RESPOND", DIRECTION_OUT);
+ add_trace("respond", "value", "200 OK");
+ end_trace();
+
+ nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(data->e_msg), TAG_END());
+ nua_handle_destroy(nh);
+ inst->register_handle = NULL;
+}
+
static void i_register(struct sip_inst *inst, int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[])
{
#define NUTAG_WITH_THIS_MSG(msg) nutag_with, tag_ptr_v(msg)
nua_save_event(nua, saved);
nua_event_data_t const *data = nua_event_data(saved);
+ if (!inst->allow_register) {
+ sip_trace_header(NULL, inst->interface_name, "REGISTER", DIRECTION_IN);
+ add_trace("error", NULL, "forbidden, because we don't accept registration");
+ end_trace();
+ nua_respond(nh, SIP_403_FORBIDDEN, NUTAG_WITH_THIS_MSG(data->e_msg), TAG_END());
+ nua_handle_destroy(nh);
+ inst->register_handle = NULL;
+ return;
+ }
+
if (contact->m_url->url_host)
SCPY(inst->remote_peer, contact->m_url->url_host);
if (contact->m_url->url_port && contact->m_url->url_port[0]) {
class Endpoint *epoint;
struct lcr_msg *message;
struct interface *interface;
+ const char *sdp_str = NULL;
int media_types[32];
uint8_t payload_types[32];
int payloads = 0;
+ unsigned char payload_type;
int media_type;
interface = getinterfacebyname(inst->interface_name);
return;
}
- if (p_state != PORT_STATE_IDLE) {
-#warning fixme: select new RTP and respond with SDP
- sip_trace_header(this, inst->interface_name, "RE-INVITE", DIRECTION_IN);
- end_trace();
- nua_respond(p_s_handle, SIP_200_OK,
- NUTAG_MEDIA_ENABLE(0),
- TAG_END());
- return;
- }
-
if (sip->sip_from) {
if (sip->sip_from->a_url)
from = sip->sip_from->a_url->url_user;
add_trace("respond", "value", "400 Bad Request");
add_trace("reason", NULL, "offered codec does not match");
end_trace();
+ if (p_state != PORT_STATE_IDLE) {
+ message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
+ message->param.disconnectinfo.cause = 41;
+ message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
+ message_put(message);
+ }
new_state(PORT_STATE_RELEASE);
trigger_work(&p_s_delete);
return;
}
+ /* handle re-invite */
+ if (p_state != PORT_STATE_IDLE) {
+ sip_trace_header(this, inst->interface_name, "RE-INVITE", DIRECTION_IN);
+ end_trace();
+ if (p_s_rtp_bridge) {
+ PDEBUG(DEBUG_SIP, "RE-INVITE not implemented for RTP forwarding\n");
+ nua_respond(nh, SIP_501_NOT_IMPLEMENTED, TAG_END());
+ sip_trace_header(this, inst->interface_name, "RESPOND", DIRECTION_OUT);
+ add_trace("respond", "value", "501 NOT IMPLEMENTED");
+ add_trace("reason", NULL, "RE-INVITE not implemented for RTP forwarding");
+ end_trace();
+ } else {
+ PDEBUG(DEBUG_SIP, "RTP info given by remote, forward that\n");
+ media_type = (options.law=='a') ? MEDIA_TYPE_ALAW : MEDIA_TYPE_ULAW;
+ payload_type = (options.law=='a') ? PAYLOAD_TYPE_ALAW : PAYLOAD_TYPE_ULAW;
+ if (rtp_connect() < 0) {
+ goto rtp_failed;
+ }
+ sdp_str = generate_sdp(p_s_rtp_ip_local, p_s_rtp_port_local, 1, &payload_type, &media_type);
+ PDEBUG(DEBUG_SIP, "Using SDP response: %s\n", sdp_str);
+ nua_respond(p_s_handle, SIP_200_OK,
+ NUTAG_MEDIA_ENABLE(0),
+ SIPTAG_CONTENT_TYPE_STR("application/sdp"),
+ SIPTAG_PAYLOAD_STR(sdp_str), TAG_END());
+ }
+ return;
+ }
+
/* open local RTP peer (if not bridging) */
if (!p_s_rtp_bridge && rtp_open() < 0) {
nua_respond(nh, SIP_500_INTERNAL_SERVER_ERROR, TAG_END());
/* send progress, if tones are available and if we don't bridge */
if (!p_s_rtp_bridge && interface->is_tones == IS_YES) {
- char sdp_str[256];
- struct in_addr ia;
- unsigned char payload_type;
-
PDEBUG(DEBUG_SIP, "Connecting audio, since we have tones available\n");
media_type = (options.law=='a') ? MEDIA_TYPE_ALAW : MEDIA_TYPE_ULAW;
payload_type = (options.law=='a') ? PAYLOAD_TYPE_ALAW : PAYLOAD_TYPE_ULAW;
/* open local RTP peer (if not bridging) */
if (rtp_connect() < 0) {
+rtp_failed:
nua_respond(nh, SIP_500_INTERNAL_SERVER_ERROR, TAG_END());
nua_handle_destroy(nh);
p_s_handle = NULL;
add_trace("respond", "value", "500 Internal Server Error");
add_trace("reason", NULL, "failed to connect RTP/RTCP sockts");
end_trace();
- new_state(PORT_STATE_RELEASE);
- trigger_work(&p_s_delete);
message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
message->param.disconnectinfo.cause = 41;
message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
return;
}
- memset(&ia, 0, sizeof(ia));
- ia.s_addr = htonl(get_local_ip(p_s_rtp_ip_local));
- SPRINT(sdp_str,
- "v=0\r\n"
- "o=LCR-Sofia-SIP 0 0 IN IP4 %s\r\n"
- "s=SIP Call\r\n"
- "c=IN IP4 %s\r\n"
- "t=0 0\r\n"
- "m=audio %d RTP/AVP %d\r\n"
- "a=rtpmap:%d %s/8000\r\n"
- , inet_ntoa(ia), inet_ntoa(ia), p_s_rtp_port_local, payload_type, payload_type, media_type2name(media_type));
+ sdp_str = generate_sdp(p_s_rtp_ip_local, p_s_rtp_port_local, 1, &payload_type, &media_type);
PDEBUG(DEBUG_SIP, "Using SDP response: %s\n", sdp_str);
nua_respond(p_s_handle, SIP_183_SESSION_PROGRESS,
sip_trace_header(this, inst->interface_name, "RESPOND", DIRECTION_OUT);
add_trace("respond", "value", "183 SESSION PROGRESS");
add_trace("reason", NULL, "audio available");
+ struct in_addr ia;
+ memset(&ia, 0, sizeof(ia));
+ ia.s_addr = htonl(get_local_ip(p_s_rtp_ip_local));
add_trace("rtp", "ip", "%s", inet_ntoa(ia));
add_trace("rtp", "port", "%d,%d", p_s_rtp_port_local, p_s_rtp_port_local + 1);
add_trace("rtp", "payload", "%s:%d", media_type2name(media_type), payload_type);
}
/* connect to remote RTP (if not bridging) */
- if (!p_s_rtp_bridge && !p_s_rtp_is_connected && rtp_connect() < 0) {
+ if (!p_s_rtp_bridge && rtp_connect() < 0) {
nua_cancel(nh, TAG_END());
sip_trace_header(this, inst->interface_name, "CANCEL", DIRECTION_OUT);
add_trace("reason", NULL, "failed to open RTP/RTCP sockts");
trigger_work(&p_s_delete);
}
+void Psip::i_state(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[])
+{
+ struct sip_inst *inst = (struct sip_inst *) p_s_sip_inst;
+
+ PDEBUG(DEBUG_SIP, "state change received\n");
+ sip_trace_header(this, inst->interface_name, "STATUS", DIRECTION_OUT);
+ add_trace("value", NULL, "%d", status);
+ add_trace("phrase", NULL, "%s", phrase);
+ end_trace();
+}
+
static void sip_callback(nua_event_t event, int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[])
{
struct sip_inst *inst = (struct sip_inst *) magic;
psip = NULL;
/* new handle */
- if (!psip && inst->register_handle != nh) {
+ if (!psip && !inst->register_handle) {
switch (event) {
+ case nua_i_options:
+ PDEBUG(DEBUG_SIP, "New options instance\n");
+ inst->register_handle = nh;
+ break;
case nua_i_register:
PDEBUG(DEBUG_SIP, "New register instance\n");
inst->register_handle = nh;
break;
interface = interface->next;
}
- if (!interface) {
- PERROR("Cannot find interface %s.\n", inst->interface_name);
- return;
- }
+ if (!interface)
+ FATAL("Cannot find interface %s.\n", inst->interface_name);
if (!(psip = new Psip(PORT_TYPE_SIP_IN, name, NULL, interface)))
FATAL("Cannot create Port instance.\n");
break;
/* handle register process */
if (inst->register_handle == nh) {
switch (event) {
+ case nua_i_options:
+ i_options(inst, status, phrase, nua, magic, nh, hmagic, sip, tags);
+ break;
case nua_i_register:
i_register(inst, status, phrase, nua, magic, nh, hmagic, sip, tags);
break;
return;
}
- if (status) {
- sip_trace_header(psip, inst->interface_name, "STATUS", DIRECTION_OUT);
- add_trace("value", NULL, "%d", status);
- add_trace("phrase", NULL, "%s", phrase);
- end_trace();
- }
-
switch (status) {
case 401:
case 407:
PDEBUG(DEBUG_SIP, "error received\n");
break;
case nua_i_state:
- PDEBUG(DEBUG_SIP, "state change received\n");
+ psip->i_state(status, phrase, nua, magic, nh, hmagic, sip, tags);
break;
case nua_i_invite:
psip->i_invite(status, phrase, nua, magic, nh, hmagic, sip, tags);
SCPY(inst->interface_name, interface->name);
SCPY(inst->local_peer, interface->sip_local_peer);
SCPY(inst->remote_peer, interface->sip_remote_peer);
+ if (!inst->remote_peer[0])
+ inst->allow_register = 1;
SCPY(inst->asserted_id, interface->sip_asserted_id);
if (interface->sip_register) {
inst->register_state = REGISTER_STATE_UNREGISTERED;