int sdptag_session_snprintf(tagi_t const *t, char b[], size_t size) { sdp_session_t const *sdp; sdp_printer_t *print; size_t retval; assert(t); if (!t || !t->t_value) { if (size && b) b[0] = 0; return 0; } sdp = (sdp_session_t const *)t->t_value; print = sdp_print(NULL, sdp, b, size, 0); retval = sdp_message_size(print); sdp_printer_free(print); return (int)retval; }
char *janus_sdp_anonymize(const char *sdp) { if(sdp == NULL) return NULL; //~ su_home_t home[1] = { SU_HOME_INIT(home) }; sdp_session_t *anon = NULL; sdp_parser_t *parser = sdp_parse(home, sdp, strlen(sdp), 0); if(!(anon = sdp_session(parser))) { JANUS_DEBUG("Error parsing/merging SDP: %s\n", sdp_parsing_error(parser)); return NULL; } //~ /* o= */ //~ if(anon->sdp_origin && anon->sdp_origin->o_username) { //~ free(anon->sdp_origin->o_username); //~ anon->sdp_origin->o_username = strdup("JANUS"); //~ } /* c= */ if(anon->sdp_connection && anon->sdp_connection->c_address) { //~ free(anon->sdp_connection->c_address); anon->sdp_connection->c_address = strdup("1.1.1.1"); } /* a= */ if(anon->sdp_attributes) { /* FIXME These are attributes we handle ourselves, the plugins don't need them */ while(sdp_attribute_find(anon->sdp_attributes, "ice-ufrag")) sdp_attribute_remove(&anon->sdp_attributes, "ice-ufrag"); while(sdp_attribute_find(anon->sdp_attributes, "ice-pwd")) sdp_attribute_remove(&anon->sdp_attributes, "ice-pwd"); while(sdp_attribute_find(anon->sdp_attributes, "ice-options")) sdp_attribute_remove(&anon->sdp_attributes, "ice-options"); while(sdp_attribute_find(anon->sdp_attributes, "fingerprint")) sdp_attribute_remove(&anon->sdp_attributes, "fingerprint"); while(sdp_attribute_find(anon->sdp_attributes, "group")) sdp_attribute_remove(&anon->sdp_attributes, "group"); while(sdp_attribute_find(anon->sdp_attributes, "msid-semantic")) sdp_attribute_remove(&anon->sdp_attributes, "msid-semantic"); } /* m= */ int a_sendrecv = 0, v_sendrecv = 0; if(anon->sdp_media) { int audio = 0, video = 0; sdp_media_t *m = anon->sdp_media; while(m) { if(m->m_type == sdp_media_audio) { audio++; m->m_port = audio == 1 ? 1 : 0; } else if(m->m_type == sdp_media_video) { video++; m->m_port = audio == 1 ? 1 : 0; } else { m->m_port = 0; } /* c= */ if(m->m_connections) { sdp_connection_t *c = m->m_connections; while(c) { if(c->c_address) { //~ free(c->c_address); c->c_address = strdup("1.1.1.1"); } c = c->c_next; } } /* a= */ if(m->m_attributes) { /* FIXME These are attributes we handle ourselves, the plugins don't need them */ while(sdp_attribute_find(m->m_attributes, "ice-ufrag")) sdp_attribute_remove(&m->m_attributes, "ice-ufrag"); while(sdp_attribute_find(m->m_attributes, "ice-pwd")) sdp_attribute_remove(&m->m_attributes, "ice-pwd"); while(sdp_attribute_find(m->m_attributes, "ice-options")) sdp_attribute_remove(&m->m_attributes, "ice-options"); while(sdp_attribute_find(m->m_attributes, "crypto")) sdp_attribute_remove(&m->m_attributes, "crypto"); while(sdp_attribute_find(m->m_attributes, "fingerprint")) sdp_attribute_remove(&m->m_attributes, "fingerprint"); while(sdp_attribute_find(m->m_attributes, "setup")) sdp_attribute_remove(&m->m_attributes, "setup"); while(sdp_attribute_find(m->m_attributes, "connection")) sdp_attribute_remove(&m->m_attributes, "connection"); while(sdp_attribute_find(m->m_attributes, "group")) sdp_attribute_remove(&m->m_attributes, "group"); while(sdp_attribute_find(m->m_attributes, "msid-semantic")) sdp_attribute_remove(&m->m_attributes, "msid-semantic"); while(sdp_attribute_find(m->m_attributes, "rtcp")) sdp_attribute_remove(&m->m_attributes, "rtcp"); while(sdp_attribute_find(m->m_attributes, "rtcp-mux")) sdp_attribute_remove(&m->m_attributes, "rtcp-mux"); while(sdp_attribute_find(m->m_attributes, "candidate")) sdp_attribute_remove(&m->m_attributes, "candidate"); while(sdp_attribute_find(m->m_attributes, "ssrc")) sdp_attribute_remove(&m->m_attributes, "ssrc"); while(sdp_attribute_find(m->m_attributes, "extmap")) /* TODO Actually implement RTP extensions */ sdp_attribute_remove(&m->m_attributes, "extmap"); } /* FIXME sendrecv hack: sofia-sdp doesn't print sendrecv, but we want it to */ if(m->m_mode == sdp_sendrecv) { m->m_mode = sdp_inactive; if(m->m_type == sdp_media_audio) a_sendrecv = 1; else if(m->m_type == sdp_media_video) v_sendrecv = 1; } m = m->m_next; } } char buf[BUFSIZE]; sdp_printer_t *printer = sdp_print(home, anon, buf, BUFSIZE, 0); if(sdp_message(printer)) { int retval = sdp_message_size(printer); sdp_printer_free(printer); /* FIXME Take care of the sendrecv hack */ if(a_sendrecv || v_sendrecv) { char *replace = strstr(buf, "a=inactive"); while(replace != NULL) { memcpy(replace, "a=sendrecv", strlen("a=sendrecv")); replace++; replace = strstr(replace, "a=inactive"); } } JANUS_PRINT(" -------------------------------------------\n"); JANUS_PRINT(" >> Anonymized (%zu --> %d bytes)\n", strlen(sdp), retval); JANUS_PRINT(" -------------------------------------------\n"); JANUS_PRINT("%s\n", buf); return g_strdup(buf); } else { JANUS_DEBUG("Error anonymizing SDP: %s\n", sdp_printing_error(printer)); return NULL; } }
char *janus_sdp_anonymize(const char *sdp) { if(sdp == NULL) return NULL; sdp_session_t *anon = NULL; sdp_parser_t *parser = sdp_parse(home, sdp, strlen(sdp), 0); if(!(anon = sdp_session(parser))) { JANUS_LOG(LOG_ERR, "Error parsing/merging SDP: %s\n", sdp_parsing_error(parser)); sdp_parser_free(parser); return NULL; } /* c= */ if(anon->sdp_connection && anon->sdp_connection->c_address) { anon->sdp_connection->c_address = "1.1.1.1"; } /* a= */ if(anon->sdp_attributes) { /* These are attributes we handle ourselves, the plugins don't need them */ while(sdp_attribute_find(anon->sdp_attributes, "ice-ufrag")) sdp_attribute_remove(&anon->sdp_attributes, "ice-ufrag"); while(sdp_attribute_find(anon->sdp_attributes, "ice-pwd")) sdp_attribute_remove(&anon->sdp_attributes, "ice-pwd"); while(sdp_attribute_find(anon->sdp_attributes, "ice-options")) sdp_attribute_remove(&anon->sdp_attributes, "ice-options"); while(sdp_attribute_find(anon->sdp_attributes, "fingerprint")) sdp_attribute_remove(&anon->sdp_attributes, "fingerprint"); while(sdp_attribute_find(anon->sdp_attributes, "group")) sdp_attribute_remove(&anon->sdp_attributes, "group"); while(sdp_attribute_find(anon->sdp_attributes, "msid-semantic")) sdp_attribute_remove(&anon->sdp_attributes, "msid-semantic"); } /* m= */ if(anon->sdp_media) { int audio = 0, video = 0; #ifdef HAVE_SCTP int data = 0; #endif sdp_media_t *m = anon->sdp_media; while(m) { if(m->m_type == sdp_media_audio && m->m_port > 0) { audio++; m->m_port = audio == 1 ? 1 : 0; } else if(m->m_type == sdp_media_video && m->m_port > 0) { video++; m->m_port = video == 1 ? 1 : 0; #ifdef HAVE_SCTP } else if(m->m_type == sdp_media_application) { if(m->m_proto_name != NULL && !strcasecmp(m->m_proto_name, "DTLS/SCTP") && m->m_port != 0) { data++; m->m_port = data == 1 ? 1 : 0; } else { m->m_port = 0; } #endif } else { m->m_port = 0; } /* c= */ if(m->m_connections) { sdp_connection_t *c = m->m_connections; while(c) { if(c->c_address) { c->c_address = "1.1.1.1"; } c = c->c_next; } } /* a= */ if(m->m_attributes) { /* These are attributes we handle ourselves, the plugins don't need them */ while(sdp_attribute_find(m->m_attributes, "ice-ufrag")) sdp_attribute_remove(&m->m_attributes, "ice-ufrag"); while(sdp_attribute_find(m->m_attributes, "ice-pwd")) sdp_attribute_remove(&m->m_attributes, "ice-pwd"); while(sdp_attribute_find(m->m_attributes, "ice-options")) sdp_attribute_remove(&m->m_attributes, "ice-options"); while(sdp_attribute_find(m->m_attributes, "crypto")) sdp_attribute_remove(&m->m_attributes, "crypto"); while(sdp_attribute_find(m->m_attributes, "fingerprint")) sdp_attribute_remove(&m->m_attributes, "fingerprint"); while(sdp_attribute_find(m->m_attributes, "setup")) sdp_attribute_remove(&m->m_attributes, "setup"); while(sdp_attribute_find(m->m_attributes, "connection")) sdp_attribute_remove(&m->m_attributes, "connection"); while(sdp_attribute_find(m->m_attributes, "group")) sdp_attribute_remove(&m->m_attributes, "group"); while(sdp_attribute_find(m->m_attributes, "mid")) sdp_attribute_remove(&m->m_attributes, "mid"); while(sdp_attribute_find(m->m_attributes, "msid")) sdp_attribute_remove(&m->m_attributes, "msid"); while(sdp_attribute_find(m->m_attributes, "msid-semantic")) sdp_attribute_remove(&m->m_attributes, "msid-semantic"); while(sdp_attribute_find(m->m_attributes, "rtcp")) sdp_attribute_remove(&m->m_attributes, "rtcp"); while(sdp_attribute_find(m->m_attributes, "rtcp-mux")) sdp_attribute_remove(&m->m_attributes, "rtcp-mux"); while(sdp_attribute_find(m->m_attributes, "candidate")) sdp_attribute_remove(&m->m_attributes, "candidate"); while(sdp_attribute_find(m->m_attributes, "ssrc")) sdp_attribute_remove(&m->m_attributes, "ssrc"); while(sdp_attribute_find(m->m_attributes, "ssrc-group")) sdp_attribute_remove(&m->m_attributes, "ssrc-group"); while(sdp_attribute_find(m->m_attributes, "extmap")) /* TODO Actually implement RTP extensions */ sdp_attribute_remove(&m->m_attributes, "extmap"); while(sdp_attribute_find(m->m_attributes, "sctpmap")) sdp_attribute_remove(&m->m_attributes, "sctpmap"); } if(m->m_type != sdp_media_application && m->m_mode == sdp_sendrecv) { /* FIXME sendrecv hack: sofia-sdp doesn't print sendrecv, but we want it to */ sdp_attribute_t *fakedir = calloc(1, sizeof(sdp_attribute_t)); fakedir->a_size = sizeof(sdp_attribute_t); fakedir->a_name = g_strdup("jfmod"); fakedir->a_value = g_strdup("sr"); sdp_attribute_append(&m->m_attributes, fakedir); } m = m->m_next; } } char buf[BUFSIZE]; sdp_printer_t *printer = sdp_print(home, anon, buf, BUFSIZE, 0); if(sdp_message(printer)) { int retval = sdp_message_size(printer); sdp_printer_free(printer); sdp_parser_free(parser); /* FIXME Take care of the sendrecv hack, if needed */ char *replace = strstr(buf, "a=jfmod:sr"); while(replace != NULL) { memcpy(replace, "a=sendrecv", strlen("a=sendrecv")); replace++; replace = strstr(replace, "a=jfmod:sr"); } JANUS_LOG(LOG_VERB, " -------------------------------------------\n"); JANUS_LOG(LOG_VERB, " >> Anonymized (%zu --> %d bytes)\n", strlen(sdp), retval); JANUS_LOG(LOG_VERB, " -------------------------------------------\n"); JANUS_LOG(LOG_VERB, "%s\n", buf); return g_strdup(buf); } else { JANUS_LOG(LOG_ERR, "Error anonymizing SDP: %s\n", sdp_printing_error(printer)); sdp_printer_free(printer); sdp_parser_free(parser); return NULL; } }
void sdp_print(uint32_t level, uint8_t const *start, uint8_t const *end) { union { int8_t int8; int16_t int16; int32_t int32; int64_t int64; int128_t int128; uint8_t uint8; uint16_t uint16; uint32_t uint32; uint64_t uint64; } value; uint8_t type; uint32_t i; if (start == NULL || end == NULL) return; while (start < end) { for (i = 0; i < level; i++) printf("\t"); SDP_GET8(type, start); switch (type) { case SDP_DATA_NIL: printf("nil\n"); break; case SDP_DATA_UINT8: SDP_GET8(value.uint8, start); printf("uint8 %u\n", value.uint8); break; case SDP_DATA_UINT16: SDP_GET16(value.uint16, start); printf("uint16 %u\n", value.uint16); break; case SDP_DATA_UINT32: SDP_GET32(value.uint32, start); printf("uint32 %u\n", value.uint32); break; case SDP_DATA_UINT64: SDP_GET64(value.uint64, start); printf("uint64 %ju\n", value.uint64); break; case SDP_DATA_UINT128: case SDP_DATA_INT128: SDP_GET128(&value.int128, start); printf("u/int128 %#8.8x%8.8x%8.8x%8.8x\n", *(uint32_t *)&value.int128.b[0], *(uint32_t *)&value.int128.b[4], *(uint32_t *)&value.int128.b[8], *(uint32_t *)&value.int128.b[12]); break; case SDP_DATA_UUID128: SDP_GET_UUID128(&value.int128, start); printf("uuid128 %#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n", ntohl(*(uint32_t *)&value.int128.b[0]), ntohs(*(uint16_t *)&value.int128.b[4]), ntohs(*(uint16_t *)&value.int128.b[6]), ntohs(*(uint16_t *)&value.int128.b[8]), ntohs(*(uint16_t *)&value.int128.b[10]), ntohl(*(uint32_t *)&value.int128.b[12])); break; case SDP_DATA_INT8: SDP_GET8(value.int8, start); printf("int8 %d\n", value.int8); break; case SDP_DATA_INT16: SDP_GET16(value.int16, start); printf("int16 %d\n", value.int16); break; case SDP_DATA_INT32: SDP_GET32(value.int32, start); printf("int32 %d\n", value.int32); break; case SDP_DATA_INT64: SDP_GET64(value.int64, start); printf("int64 %ju\n", value.int64); break; case SDP_DATA_UUID16: SDP_GET16(value.uint16, start); printf("uuid16 %#4.4x - %s\n", value.uint16, sdp_uuid2desc(value.uint16)); break; case SDP_DATA_UUID32: SDP_GET32(value.uint32, start); printf("uuid32 %#8.8x\n", value.uint32); break; case SDP_DATA_STR8: SDP_GET8(value.uint8, start); printf("str8 %*.*s\n", value.uint8, value.uint8, start); start += value.uint8; break; case SDP_DATA_STR16: SDP_GET16(value.uint16, start); printf("str16 %*.*s\n", value.uint16, value.uint16, start); start += value.uint16; break; case SDP_DATA_STR32: SDP_GET32(value.uint32, start); printf("str32 %*.*s\n", value.uint32, value.uint32, start); start += value.uint32; break; case SDP_DATA_BOOL: SDP_GET8(value.uint8, start); printf("bool %d\n", value.uint8); break; case SDP_DATA_SEQ8: SDP_GET8(value.uint8, start); printf("seq8 %d\n", value.uint8); sdp_print(level + 1, start, start + value.uint8); start += value.uint8; break; case SDP_DATA_SEQ16: SDP_GET16(value.uint16, start); printf("seq16 %d\n", value.uint16); sdp_print(level + 1, start, start + value.uint16); start += value.uint16; break; case SDP_DATA_SEQ32: SDP_GET32(value.uint32, start); printf("seq32 %d\n", value.uint32); sdp_print(level + 1, start, start + value.uint32); start += value.uint32; break; case SDP_DATA_ALT8: SDP_GET8(value.uint8, start); printf("alt8 %d\n", value.uint8); sdp_print(level + 1, start, start + value.uint8); start += value.uint8; break; case SDP_DATA_ALT16: SDP_GET16(value.uint16, start); printf("alt16 %d\n", value.uint16); sdp_print(level + 1, start, start + value.uint16); start += value.uint16; break; case SDP_DATA_ALT32: SDP_GET32(value.uint32, start); printf("alt32 %d\n", value.uint32); sdp_print(level + 1, start, start + value.uint32); start += value.uint32; break; case SDP_DATA_URL8: SDP_GET8(value.uint8, start); printf("url8 %*.*s\n", value.uint8, value.uint8, start); start += value.uint8; break; case SDP_DATA_URL16: SDP_GET16(value.uint16, start); printf("url16 %*.*s\n", value.uint16, value.uint16, start); start += value.uint16; break; case SDP_DATA_URL32: SDP_GET32(value.uint32, start); printf("url32 %*.*s\n", value.uint32, value.uint32, start); start += value.uint32; break; default: printf("unknown data type: %#02x\n", *start ++); break; } } }