// Get the SDP message from SIP message and check it's Content-Type // Return values: // 1 - success // -1 - error in getting body or invalid content type // -2 - empty message static int getSDPMessage(struct sip_msg *msg, str *sdp) { sdp->s = get_body(msg); if (sdp->s==NULL) { LM_ERR("cannot get the SDP body\n"); return -1; } sdp->len = msg->buf + msg->len - sdp->s; if (sdp->len == 0) return -2; if (!checkContentType(msg)) { LM_ERR("content type is not `application/sdp'\n"); return -1; } return 1; }
/* * in event specific publish handling - only check is good body format */ int xml_publ_handl(struct sip_msg* msg, int* sent_reply) { str body= {0, 0}; xmlDocPtr doc= NULL; *sent_reply= 0; if ( get_content_length(msg) == 0 ) return 1; body.s=get_body(msg); if (body.s== NULL) { LM_ERR("cannot extract body from msg\n"); goto error; } /* content-length (if present) must be already parsed */ body.len = get_content_length( msg ); doc= xmlParseMemory( body.s, body.len ); if(doc== NULL) { LM_ERR("bad body format\n"); if( xml_sigb.reply( msg, 415, &pu_415_rpl, 0)== -1) { LM_ERR("while sending '415 Unsupported media type' reply\n"); } *sent_reply = 1; goto error; } xmlFreeDoc(doc); xmlCleanupParser(); xmlMemoryDump(); return 1; error: xmlFreeDoc(doc); xmlCleanupParser(); xmlMemoryDump(); return -1; }
static int replace_body_f(struct sip_msg* msg, char* key, char* str2) { struct lump* l; regmatch_t pmatch; char* s; int len; char* begin; int off; str body; if ( get_body(msg,&body)!=0 || body.len==0) { LM_DBG("message body has zero length\n"); return -1; } begin=body.s; /* msg->orig previously .. uri problems */ if (regexec((regex_t*) key, begin, 1, &pmatch, 0)!=0) return -1; off=begin-msg->buf; if (pmatch.rm_so!=-1){ if ((l=del_lump(msg, pmatch.rm_so+off, pmatch.rm_eo-pmatch.rm_so, 0))==0) return -1; len=strlen(str2); s=pkg_malloc(len); if (s==0){ LM_ERR("memory allocation failure\n"); return -1; } memcpy(s, str2, len); if (insert_new_lump_after(l, s, len, 0)==0){ LM_ERR("could not insert new lump\n"); pkg_free(s); return -1; } return 1; } return -1; }
// Formulate and send world description to viewers void World::send_to_viewers(const boost::system::error_code& ec) { if (!ec) { std::string message; if (bodies_.size() > 0) { // Formulate message from bodies for (int i=0; i<num_bodies(); i++) message += get_body(i)->get_viewer_msg(); // Send to all viewers for (uint i=0; i<viewers_.size(); i++) viewers_[i]->send_message(message); } // Call self later viewer_timer_.expires_at(viewer_timer_.expires_at() + boost::posix_time::seconds(viewer_ts_)); viewer_timer_.async_wait(boost::bind(&World::send_to_viewers, this, boost::asio::placeholders::error)); } }
/* * Get message body and check Content-Type header field */ int extract_body(struct sip_msg *msg, str *body ) { char c; int skip; if ( get_body(msg,body)!=0 || body->len==0) { LM_ERR("failed to get the message body\n"); goto error; } /* no need for parse_headers(msg, EOH), get_body will * parse everything */ /*is the content type correct?*/ if (check_content_type(msg)==-1) { LM_ERR("content type mismatching\n"); goto error; } for (skip = 0; skip < body->len; skip++) { c = body->s[body->len - skip - 1]; if (c != '\r' && c != '\n') break; } if (skip == body->len) { LM_ERR("empty body\n"); goto error; } body->len -= skip; /*LM_DBG("DEBUG:extract_body:%d=|%.*s|\n",body->len,body->len,body->s);*/ return 1; error: body->s = NULL; body->len = 0; return -1; }
int complete_mes(char *mes, int size) { int cl = 0, headers = 0, len = 0; char *tmp = NULL; cl = get_cl(mes); #ifdef DEBUG printf("CL: %i\n", cl); #endif if (cl < 0){ printf("missing CL header; waiting for more bytes...\n"); return 0; } tmp = get_body(mes); #ifdef DEBUG printf("body: '%s'\n", tmp); #endif headers = tmp - mes; #ifdef DEBUG printf("length: %i, headers: %i\n", size, headers); #endif len = headers + cl; if (len == size) { printf("message is complete\n"); return 1; } else if (len > size) { printf("waiting for more bytes...\n"); return 0; } else { /* we received more then the sender claims to sent * for now we treat this as a complete message * FIXME: should we store the extra bytes in a buffer and * truncate the message at the calculated length !? */ printf("received too much bytes...\n"); return 1; } }
void Ex5::do_opt_unit(OptUnit *unit) { IdString name = get_name(get_proc_sym(unit)); printf("Processing procedure \"%s\"\n", name.chars()); // get the body of the OptUnit AnyBody *body = get_body(unit); // verify that it is an InstrList claim (is_a<InstrList>(body), "expected OptUnit's body in InstrList form"); InstrList *mil = (InstrList *)body; for (InstrHandle h = start(mil); h != end(mil); ) { InstrHandle cur_h = h++; // advance before possible instr removal Instr *mi = *cur_h; if (has_note(mi, k_reserved_reg_load) || has_note(mi, k_store_reserved_reg)) delete remove(mil, cur_h); } }
static int search_append_body_f(struct sip_msg* msg, char* key, char* str2) { struct lump* l; regmatch_t pmatch; char* s; int len; int off; str body; if ( get_body(msg,&body)!=0 || body.len==0) { LM_DBG("message body has zero length\n"); return -1; } off=body.s-msg->buf; if (regexec((regex_t*) key, body.s, 1, &pmatch, 0)!=0) return -1; if (pmatch.rm_so!=-1){ if ((l=anchor_lump(msg, off+pmatch.rm_eo, 0))==0) return -1; len=strlen(str2); s=pkg_malloc(len); if (s==0){ LM_ERR("memory allocation failure\n"); return -1; } memcpy(s, str2, len); if (insert_new_lump_after(l, s, len, 0)==0){ LM_ERR("could not insert new lump\n"); pkg_free(s); return -1; } return 1; } return -1; }
static int w_remove_body_f(struct sip_msg *msg, char *p1, char *p2) { str body = {0,0}; body.len = 0; body.s = get_body(msg); if (body.s==0) { LM_DBG("no body in the message\n"); return 1; } body.len = msg->buf + msg->len - body.s; if (body.len<=0) { LM_DBG("empty body in the message\n"); return 1; } if(del_lump(msg, body.s - msg->buf, body.len, 0) == 0) { LM_ERR("cannot remove body\n"); return -1; } return 1; }
int reginfo_handle_notify(struct sip_msg* msg, char* domain, char* s2) { LM_DBG("Handling notify\n"); str body; int result = 1; if(subscribe_to_reginfo != 1){ LM_ERR("Received a NOTIFY for reg-info but I have not SUBSCRIBED for them. Ignoring"); return -1; } /* If not done yet, parse the whole message now: */ if (parse_headers(msg, HDR_EOH_F, 0) == -1) { LM_ERR("Error parsing headers\n"); return -1; } if (get_content_length(msg) == 0) { LM_DBG("Content length = 0\n"); /* No Body? Then there is no published information available, which is ok. */ return 1; } else { body.s = get_body(msg); if (body.s == NULL) { LM_ERR("cannot extract body from msg\n"); return -1; } body.len = get_content_length(msg); } LM_DBG("Body is %.*s\n", body.len, body.s); result = process_body(msg, body, (udomain_t*) domain); return result; }
/* * Update existing presentity and watcher list */ static int publish_presentity_pidf(struct sip_msg* _m, struct pdomain* _d, struct presentity* presentity, int *pchanged) { char *body = get_body(_m); presence_tuple_t *tuple = NULL; str contact = { NULL, 0 }; str basic = { NULL, 0 }; str status = { NULL, 0 }; str location = { NULL, 0 }; str site = { NULL, 0 }; str floor = { NULL, 0 }; str room = { NULL, 0 }; str packet_loss = { NULL, 0 }; double x=0, y=0, radius=0; time_t expires = act_time + default_expires; double priority = default_priority; int prescaps = 0; int flags = 0; int changed = 0; int ret = 0; flags = parse_pidf(body, &contact, &basic, &status, &location, &site, &floor, &room, &x, &y, &radius, &packet_loss, &priority, &expires, &prescaps); if (contact.len) { find_presence_tuple(&contact, presentity, &tuple); if (!tuple && new_tuple_on_publish) { new_presence_tuple(&contact, expires, presentity, &tuple); add_presence_tuple(presentity, tuple); changed = 1; } } else { tuple = presentity->tuples; } if (!tuple) { LOG(L_ERR, "publish_presentity: no tuple for %.*s\n", presentity->uri.len, presentity->uri.s); return -1; } LOG(L_INFO, "publish_presentity_pidf: -1-\n"); if (basic.len && basic.s) { int origstate = tuple->state; tuple->state = ((strcasecmp(basic.s, "online") == 0) || (strcasecmp(basic.s, "open") == 0)) ? PS_ONLINE : PS_OFFLINE; if (tuple->state != origstate) changed = 1; } if (status.len && status.s) { if (tuple->status.len && str_strcasecmp(&tuple->status, &status) != 0) changed = 1; tuple->status.len = status.len; strncpy(tuple->status.s, status.s, status.len); tuple->status.s[status.len] = 0; } LOG(L_INFO, "publish_presentity: -2-\n"); if (location.len && location.s) { if (tuple->location.loc.len && str_strcasecmp(&tuple->location.loc, &location) != 0) changed = 1; tuple->location.loc.len = location.len; strncpy(tuple->location.loc.s, location.s, location.len); tuple->location.loc.s[location.len] = 0; } else if (flags & PARSE_PIDF_LOCATION_MASK) { tuple->location.loc.len = 0; } if (site.len && site.s) { if (tuple->location.site.len && str_strcasecmp(&tuple->location.site, &site) != 0) changed = 1; tuple->location.site.len = site.len; strncpy(tuple->location.site.s, site.s, site.len); tuple->location.site.s[site.len] = 0; } else if (flags & PARSE_PIDF_LOCATION_MASK) { tuple->location.site.len = 0; } if (floor.len && floor.s) { if (tuple->location.floor.len && str_strcasecmp(&tuple->location.floor, &floor) != 0) changed = 1; tuple->location.floor.len = floor.len; strncpy(tuple->location.floor.s, floor.s, floor.len); tuple->location.floor.s[floor.len] = 0; }else if (flags & PARSE_PIDF_LOCATION_MASK) { tuple->location.floor.len = 0; } if (room.len && room.s) { if (tuple->location.room.len && str_strcasecmp(&tuple->location.room, &room) != 0) changed = 1; tuple->location.room.len = room.len; strncpy(tuple->location.room.s, room.s, room.len); tuple->location.room.s[room.len] = 0; } else if (flags & PARSE_PIDF_LOCATION_MASK) { tuple->location.room.len = 0; } if (packet_loss.len && packet_loss.s) { if (tuple->location.packet_loss.len && str_strcasecmp(&tuple->location.packet_loss, &packet_loss) != 0) changed = 1; tuple->location.packet_loss.len = packet_loss.len; strncpy(tuple->location.packet_loss.s, packet_loss.s, packet_loss.len); tuple->location.packet_loss.s[packet_loss.len] = 0; } else if (flags & PARSE_PIDF_LOCATION_MASK) { tuple->location.packet_loss.len = 0; } if (x) { if (tuple->location.x != x) changed = 1; tuple->location.x = x; } else if (flags & PARSE_PIDF_LOCATION_MASK) { tuple->location.x = 0; } if (y) { if (tuple->location.y != y) changed = 1; tuple->location.y = y; } else if (flags & PARSE_PIDF_LOCATION_MASK) { tuple->location.y = 0; } if (radius) { if (tuple->location.radius != radius) changed = 1; tuple->location.radius = radius; } else if (flags & PARSE_PIDF_LOCATION_MASK) { tuple->location.radius = 0; } if (tuple->priority != priority) { changed = 1; tuple->priority = priority; } if (tuple->expires != expires) { changed = 1; tuple->expires = expires; } if (use_location_package) if (site.len && floor.len && room.len && changed) { location_package_location_add_user(_d, &site, &floor, &room, presentity); } if (flags & PARSE_PIDF_PRESCAPS) { if (tuple->prescaps != prescaps) changed = 1; tuple->prescaps = prescaps; } changed = 1; if (changed) presentity->flags |= PFLAG_PRESENCE_CHANGED; LOG(L_INFO, "publish_presentity: -3-: changed=%d\n", changed); if (pchanged && changed) { *pchanged = 1; } if ((ret = db_update_presentity(presentity)) < 0) { return ret; } LOG(L_INFO, "publish_presentity: -4-\n"); return 0; }
/** * sngtc_caller_answer - attaches an SDP body to ACK requests */ static int sngtc_caller_answer(struct sip_msg *msg) { char *p; str body; struct dlg_cell *dlg; struct lump *lump; struct sngtc_info *info; int len; LM_DBG("processing ACK\n"); if (get_body(msg, &body) != 0 || body.len > 0) { LM_ERR("ACK should not contain a SDP body\n"); return SNGTC_ERR; } dlg = dlg_binds.get_dlg(); if (!dlg) { LM_ERR("failed to fetch current dialog\n"); return SNGTC_ERR; } /* get the SDP body from the INVITE which was mangled at 200 OK */ if (dlg_binds.fetch_dlg_value(dlg, &dlg_key_sngtc_info, &body, 0) != 0) { LM_ERR("failed to fetch caller sdp\n"); return SNGTC_ERR; } info = *(struct sngtc_info **)(body.s); /* duplicate the SDP in pkg mem for the lumps mechanism */ if (pkg_str_dup(&body, &info->modified_caller_sdp) != 0) { LM_ERR("failed to dup in pkg mem\n"); return SNGTC_ERR; } LM_DBG("Duplicated SDP: '%.*s'\n", body.len, body.s); lump = anchor_lump(msg, msg->content_length->name.s - msg->buf, 0); if (!lump) { LM_ERR("failed to insert anchor lump\n"); return SNGTC_ERR; } p = pkg_malloc(SDP_CONTENT_TYPE_LEN); if (!p) { LM_ERR("no more pkg memory\n"); return SNGTC_ERR; } /* add the Content-Type header */ memcpy(p, "Content-Type: application/sdp\r\n", SDP_CONTENT_TYPE_LEN); if (!insert_new_lump_before(lump, p, SDP_CONTENT_TYPE_LEN, 0)) { LM_ERR("failed to insert Content-Type lump\n"); return SNGTC_ERR; } LM_DBG("blen: %d\n", msg->content_length->body.len); lump = del_lump(msg, msg->content_length->body.s - msg->buf, msg->content_length->body.len, HDR_OTHER_T); if (!lump) { LM_ERR("failed to insert del lump for the content length\n"); return SNGTC_ERR; } p = pkg_malloc(CONTENT_LEN_DIGITS); if (!p) { LM_ERR("no more pkg memory\n"); return SNGTC_ERR; } LM_DBG("len: %d\n", body.len); len = sprintf(p, "%d", body.len); if (!insert_new_lump_after(lump, p, len, HDR_OTHER_T)) { LM_ERR("failed to insert Content-Length lump\n"); return SNGTC_ERR; } lump = anchor_lump(msg, msg->len - CRLF_LEN, 0); if (!lump) { LM_ERR("failed to insert anchor lump\n"); return SNGTC_ERR; } if (!insert_new_lump_before(lump, body.s, body.len, 0)) { LM_ERR("failed to insert SDP body lump\n"); return SNGTC_ERR; } return 1; }
void cddbd_mail(int flags) { int ret; FILE *fp; FILE *tfp= (FILE *) 0; FILE *tfp2= (FILE *) 0; email_hdr_t eh; char *tmail; char *tmail2; char *tmail3; char buf[CDDBBUFSIZ]; char errstr[CDDBBUFSIZ]; errstr[0] = '\0'; /* Create a temporary file for the mail. */ tmail = cddbd_mktemp(); if((fp = fopen(tmail, "w+")) == NULL) { cddbd_snprintf(buf, sizeof(buf), "Can't open mail tmp file %s (%d)", tmail, errno); cddbd_log(LOG_ERR | LOG_MAIL, "%s", buf); /* Print to stderr so the bounced mail gets it. */ fprintf(stderr, "%s\n", buf); quit(QUIT_ERR); } /* Put the mail into the temp file. */ while(fgets(buf, sizeof(buf), stdin) != NULL) { if(fputs(buf, fp) == EOF) { cddbd_snprintf(buf, sizeof(buf), "Can't write mail tmp file %s (%d)", tmail, errno); cddbd_log(LOG_ERR | LOG_MAIL, "%s", buf); /* Print to stderr so the bounced mail gets it. */ fprintf(stderr, "%s\n", buf); quit(QUIT_ERR); } } /* Put the pointer back to the start of the file for reading. */ rewind(fp); /* parse the header, fill in "eh" structure */ ret = parse_header(fp, &eh, errstr); tmail2 = cddbd_mktemp(); if(ret == EE_OK && (tfp = get_body(fp, &eh, tmail2, errstr)) == NULL) ret = EE_ERROR; /* Put the pointer back to the start of the file for reading. */ rewind(fp); tmail3 = cddbd_mktemp(); if(ret == EE_OK && (tfp2=build_returnmail(fp, tfp, tmail3, errstr)) == NULL) ret = EE_ERROR; if(ret == EE_OK) { switch(eh.eh_class) { case EC_SUBMIT: ret = cddbd_submit(tfp, &eh, flags, errstr); /* Give back happy mail. */ if(ret == EE_OK && (flags & MF_TEST)) { ret = return_mail(tfp2, &eh, flags, errstr); if(ret != EE_OK) { cddbd_log(LOG_ERR | LOG_MAIL, "Couldn't send test response."); } } break; case EC_COMMAND: ret = cddbd_email_cmd(tfp, &eh, flags, errstr); break; case EC_NONE: default: ret = EE_ERROR; break; } } if(ret != EE_OK) { if(eh.eh_flags & EH_RCPT) { /* We have a sender, give him mail directly. */ if (tfp2 != NULL) ret = return_mail(tfp2, &eh, (flags | MF_FAIL), errstr); else ret = return_mail(fp, &eh, (flags | MF_FAIL), errstr); } if(ret != EE_OK) { /* We have no sender, give him mail indirectly. */ cddbd_snprintf(buf, sizeof(buf), "Unable to process email: %s", errstr); cddbd_log(LOG_ERR | LOG_MAIL, "%s", buf); /* Print to stderr so the bounced mail gets it. */ fprintf(stderr, "%s\n", buf); } } fclose(fp); if (tfp != (FILE *) 0) fclose(tfp); if (tfp2 != (FILE *) 0) fclose(tfp2); cddbd_freetemp(tmail); cddbd_freetemp(tmail2); cddbd_freetemp(tmail3); if(ret == EE_OK) quit(QUIT_OK); else quit(QUIT_ERR); }
/* * Function to decompress a compressed message */ static int mc_decompress(struct sip_msg* msg) { #define HDRS_TO_SKIP 4 int i; int j; int rc; int algo=-1; int hdrs_algo=-1; int b64_required=-1; str msg_body; str msg_final; str b64_decode={NULL, 0}; str hdr_b64_decode={NULL,0}; str uncomp_body={NULL,0}; str uncomp_hdrs={NULL,0}; char *new_buf; unsigned long temp; /* hdr_vec allows to sort the headers. This will help skipping these headers when building the new message */ struct hdr_field *hf; struct hdr_field *hdr_vec[HDRS_TO_SKIP]; /*hdr_vec : 0 Content-Length 1 Comp-Hdrs 2 Headers-Algo 3 Content-Encoding*/ memset(hdr_vec, 0, HDRS_TO_SKIP * sizeof(struct hdr_field*)); if (parse_headers(msg, HDR_EOH_F, 0) != 0) { LM_ERR("failed to parse SIP message\n"); return -1; } /*If compressed with this module there are great chances that Content-Encoding is last*/ hdr_vec[3] = msg->last_header; if (!is_content_encoding(hdr_vec[3])) { hdr_vec[3] = NULL; for (hf = msg->headers; hf; hf = hf->next) { if (is_content_encoding(hf)) { hdr_vec[3] = hf; continue; } if (hf->type == HDR_OTHER_T && !strncasecmp(hf->name.s, COMP_HDRS,COMP_HDRS_LEN)) { hdr_vec[1] = hf; continue; } if (hf->type == HDR_OTHER_T && !strncasecmp(hf->name.s, HDRS_ENCODING, sizeof(HDRS_ENCODING)-1)) { hdr_vec[2] = hf; } if (hdr_vec[1] && hdr_vec[2] && hdr_vec[3]) break; } } else { for (hf = msg->headers; hf; hf = hf->next) { if (!hdr_vec[1] && hf->type == HDR_OTHER_T && !strncasecmp(hf->name.s, COMP_HDRS,COMP_HDRS_LEN)) { hdr_vec[1] = hf; continue; } if (!hdr_vec[2] && hf->type == HDR_OTHER_T && !strncasecmp(hf->name.s, HDRS_ENCODING, sizeof(HDRS_ENCODING)-1)) hdr_vec[2] = hf; if (hdr_vec[2] && hdr_vec[3] && hdr_vec[1]) break; } } /* Only if content-encoding present, Content-Length will be replaced with the one in the compressed body or in compressed headers*/ if (hdr_vec[3]) { hdr_vec[0] = msg->content_length; parse_algo_hdr(hdr_vec[3], &algo, &b64_required); } if (b64_required > 0 && hdr_vec[3]) { msg_body.s = msg->last_header->name.s + msg->last_header->len + CRLF_LEN; msg_body.len = strlen(msg_body.s); /* Cutting CRLF'S at the end of the message */ while (WORD(msg_body.s + msg_body.len-CRLF_LEN) == PARSE_CRLF) { msg_body.len -= CRLF_LEN; } if (wrap_realloc(&body_in, calc_max_base64_decode_len(msg_body.len))) return -1; b64_decode.s = body_in.s; b64_decode.len = base64decode((unsigned char*)b64_decode.s, (unsigned char*)msg_body.s, msg_body.len); } else if (hdr_vec[3]) { if (get_body(msg, &msg_body) < 0) { LM_ERR("failed to get body\n"); return -1; } b64_decode.s = msg_body.s; b64_decode.len = msg_body.len; } b64_required=0; if (hdr_vec[2]) { parse_algo_hdr(hdr_vec[3], &algo, &b64_required); } if (b64_required > 0 && hdr_vec[1]) { if (wrap_realloc(&hdr_in, calc_max_base64_decode_len(hdr_vec[1]->body.len))) return -1; hdr_b64_decode.s = hdr_in.s; hdr_b64_decode.len = base64decode( (unsigned char*)hdr_b64_decode.s, (unsigned char*)hdr_vec[1]->body.s, hdr_vec[1]->body.len ); } else if (hdr_vec[1]) { hdr_b64_decode.s = hdr_vec[1]->body.s; hdr_b64_decode.len = hdr_vec[1]->body.len; } switch (hdrs_algo) { case 0: /* deflate */ temp = (unsigned long)BUFLEN; rc = uncompress((unsigned char*)hdr_buf, &temp, (unsigned char*)hdr_b64_decode.s, (unsigned long)hdr_b64_decode.len); uncomp_hdrs.s = hdr_buf; uncomp_hdrs.len = temp; if (check_zlib_rc(rc)) { LM_ERR("header decompression failed\n"); return -1; } break; case 1: /* gzip */ rc = gzip_uncompress( (unsigned char*)hdr_b64_decode.s, (unsigned long)hdr_b64_decode.len, &hdr_out, &temp); if (check_zlib_rc(rc)) { LM_ERR("header decompression failed\n"); return -1; } uncomp_hdrs.s = hdr_out.s; uncomp_hdrs.len = temp; break; case -1: break; default: return -1; } switch (algo) { case 0: /* deflate */ temp = (unsigned long)BUFLEN; rc = uncompress((unsigned char*)body_buf, &temp, (unsigned char*)b64_decode.s, (unsigned long)b64_decode.len); if (check_zlib_rc(rc)) { LM_ERR("body decompression failed\n"); return -1; } uncomp_body.s = body_buf; uncomp_body.len = temp; break; case 1: /* gzip */ rc = gzip_uncompress( (unsigned char*)b64_decode.s, (unsigned long)b64_decode.len, &body_out, &temp); if (check_zlib_rc(rc)) { LM_ERR("body decompression failed\n"); return -1; } uncomp_body.s = body_out.s; uncomp_body.len = temp; break; case -1: LM_DBG("no body\n"); break; default: LM_ERR("invalid algo\n"); return -1; } /* Sort to have the headers in order */ for (i = 0; i < HDRS_TO_SKIP - 1; i++) { for (j = i + 1; j < HDRS_TO_SKIP; j++) { if (!hdr_vec[j]) continue; if (!hdr_vec[i] && hdr_vec[j]) { hdr_vec[i] = hdr_vec[j]; hdr_vec[j] = NULL; } if ((hdr_vec[i] && hdr_vec[j]) && (hdr_vec[i]->name.s > hdr_vec[j]->name.s)) { hf = hdr_vec[i]; hdr_vec[i] = hdr_vec[j]; hdr_vec[j] = hf; } } } int msg_final_len = 0; int msg_ptr=0; for ( i = 0; i < HDRS_TO_SKIP; i++) { if (hdr_vec[i]) { msg_final_len += hdr_vec[i]->name.s - (msg->buf+msg_ptr); msg_ptr += hdr_vec[i]->name.s+hdr_vec[i]->len - (msg->buf+msg_ptr); } } msg_final_len += msg->last_header->name.s + msg->last_header->len - (msg->buf + msg_ptr); if (hdrs_algo >= 0) msg_final_len += uncomp_hdrs.len; if (algo >= 0) msg_final_len += uncomp_body.len; else msg_final_len += strlen(msg->eoh); if (wrap_realloc(&buf_out, msg_final_len)) return -1; msg_ptr = 0; msg_final.len = 0; msg_final.s = buf_out.s; for ( i = 0; i < HDRS_TO_SKIP; i++) { if (hdr_vec[i]) { wrap_copy_and_update(&msg_final.s, msg->buf+msg_ptr, hdr_vec[i]->name.s-(msg->buf+msg_ptr), &msg_final.len); msg_ptr += (hdr_vec[i]->name.s+hdr_vec[i]->len) - (msg->buf+msg_ptr); } } wrap_copy_and_update( &msg_final.s, msg->buf+msg_ptr, (msg->last_header->name.s+msg->last_header->len)- (msg->buf+msg_ptr), &msg_final.len ); if (hdrs_algo >= 0) { wrap_copy_and_update(&msg_final.s, uncomp_hdrs.s, uncomp_hdrs.len,&msg_final.len); } if (algo >= 0) { wrap_copy_and_update(&msg_final.s, uncomp_body.s, uncomp_body.len, &msg_final.len); } else { wrap_copy_and_update(&msg_final.s, msg->eoh, strlen(msg->eoh), &msg_final.len); } /* new buffer because msg_final(out_buf) will * be overwritten at next iteration */ #ifdef DYN_BUF new_buf = pkg_malloc(msg_final.len+1); if (new_buf == NULL) { LM_ERR("no more pkg mem\n"); return -1; } #else new_buf = msg->buf; #endif memcpy(new_buf, msg_final.s, msg_final.len); new_buf[msg_final.len] = '\0'; struct sip_msg tmp; memcpy(&tmp, msg, sizeof(struct sip_msg)); /*reset dst_uri and path_vec to avoid free*/ if (msg->dst_uri.s != NULL) { msg->dst_uri.s = NULL; msg->dst_uri.len = 0; } if (msg->path_vec.s != NULL) { msg->path_vec.s = NULL; msg->path_vec.len = 0; } free_sip_msg(msg); memset(msg, 0, sizeof(struct sip_msg)); /* restore msg fields */ msg->id = tmp.id; msg->rcv = tmp.rcv; msg->set_global_address = tmp.set_global_address; msg->set_global_port = tmp.set_global_port; msg->flags = tmp.flags; msg->msg_flags = tmp.msg_flags; msg->hash_index = tmp.hash_index; msg->force_send_socket = tmp.force_send_socket; msg->dst_uri = tmp.dst_uri; msg->path_vec = tmp.path_vec; /* set the new ones */ msg->buf = new_buf; msg->len = msg_final.len; /* reparse the message */ if (parse_msg(msg->buf, msg->len, msg) != 0) LM_ERR("parse_msg failed\n"); return 1; }
int rls_handle_notify(struct sip_msg* msg, char* c1, char* c2) { struct to_body *pto, TO = {0}, *pfrom = NULL; str body= {0, 0}; ua_pres_t dialog; str* res_id= NULL; db_key_t query_cols[8]; db_val_t query_vals[8]; int n_query_cols= 0; str auth_state= {0, 0}; int found= 0; str reason = {0, 0}; int auth_flag; struct hdr_field* hdr= NULL; int expires= -1; str content_type= {0, 0}; int reply_code = 500; str reply_str = pu_500_rpl; LM_DBG("start\n"); /* extract the dialog information and check if an existing dialog*/ if( parse_headers(msg,HDR_EOH_F, 0)==-1 ) { LM_ERR("parsing headers\n"); reply_code = 400; reply_str = pu_400_rpl; goto error; } if((!msg->event ) ||(msg->event->body.len<=0)) { LM_ERR("Missing event header field value\n"); reply_code = 400; reply_str = pu_400_rpl; goto error; } if( msg->to==NULL || msg->to->body.s==NULL) { LM_ERR("cannot parse TO header\n"); reply_code = 400; reply_str = pu_400_rpl; goto error; } if(msg->to->parsed != NULL) { pto = (struct to_body*)msg->to->parsed; LM_DBG("'To' header ALREADY PARSED: <%.*s>\n", pto->uri.len, pto->uri.s ); } else { parse_to(msg->to->body.s,msg->to->body.s + msg->to->body.len + 1, &TO); if(TO.uri.len <= 0) { LM_ERR(" 'To' header NOT parsed\n"); reply_code = 400; reply_str = pu_400_rpl; goto error; } pto = &TO; } memset(&dialog, 0, sizeof(ua_pres_t)); dialog.watcher_uri= &pto->uri; if (pto->tag_value.s==NULL || pto->tag_value.len==0 ) { LM_ERR("to tag value not parsed\n"); reply_code = 400; reply_str = pu_400_rpl; goto error; } dialog.from_tag= pto->tag_value; if( msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot parse callid header\n"); reply_code = 400; reply_str = pu_400_rpl; goto error; } dialog.call_id = msg->callid->body; if (!msg->from || !msg->from->body.s) { LM_ERR("cannot find 'from' header!\n"); reply_code = 400; reply_str = pu_400_rpl; goto error; } if (msg->from->parsed == NULL) { LM_DBG("'From' header not parsed\n"); /* parsing from header */ if ( parse_from_header( msg )<0 ) { LM_ERR("cannot parse From header\n"); reply_code = 400; reply_str = pu_400_rpl; goto error; } } pfrom = (struct to_body*)msg->from->parsed; dialog.pres_uri= &pfrom->uri; if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0) { LM_ERR("no from tag value present\n"); reply_code = 400; reply_str = pu_400_rpl; goto error; } dialog.to_tag= pfrom->tag_value; dialog.flag|= RLS_SUBSCRIBE; dialog.event= get_event_flag(&msg->event->body); if(dialog.event< 0) { LM_ERR("unrecognized event package\n"); reply_code = 489; reply_str = pu_489_rpl; goto error; } /* extract the subscription state */ hdr = msg->headers; while (hdr!= NULL) { if(cmp_hdrname_strzn(&hdr->name, "Subscription-State", 18)==0) { found = 1; break; } hdr = hdr->next; } if(found==0 ) { LM_ERR("'Subscription-State' header not found\n"); goto error; } auth_state = hdr->body; /* extract state and reason */ auth_flag= parse_subs_state(auth_state, &reason, &expires); if(auth_flag< 0) { LM_ERR("while parsing 'Subscription-State' header\n"); goto error; } if(pua_get_record_id(&dialog, &res_id)< 0) /* verify if within a stored dialog */ { LM_ERR("occured when trying to get record id\n"); goto error; } if(res_id==0) { LM_DBG("presence dialog record not found\n"); /* if it is a NOTIFY for a terminated SUBSCRIBE dialog in RLS, then * the module might not have the dialog structure anymore * - just send 200ok, it is harmless */ if(auth_flag==TERMINATED_STATE) goto done; LM_INFO("no presence dialog record for non-TERMINATED state uri pres_uri = %.*s watcher_uri = %.*s\n", dialog.pres_uri->len, dialog.pres_uri->s, dialog.watcher_uri->len, dialog.watcher_uri->s); reply_code = 481; reply_str = pu_481_rpl; goto error; } if(msg->content_type== NULL || msg->content_type->body.s== NULL) { LM_DBG("cannot find content type header header\n"); } else content_type= msg->content_type->body; /*constructing the xml body*/ if(get_content_length(msg) == 0 ) { goto done; } else { if(content_type.s== 0) { LM_ERR("content length != 0 and no content type header found\n"); goto error; } body.s=get_body(msg); if (body.s== NULL) { LM_ERR("cannot extract body from msg\n"); goto error; } body.len = get_content_length( msg ); } /* update in rlpres_table where rlsusb_did= res_id and resource_uri= from_uri*/ LM_DBG("body= %.*s\n", body.len, body.s); query_cols[n_query_cols]= &str_rlsubs_did_col; query_vals[n_query_cols].type = DB1_STR; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.str_val= *res_id; n_query_cols++; query_cols[n_query_cols]= &str_resource_uri_col; query_vals[n_query_cols].type = DB1_STR; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.str_val= *dialog.pres_uri; n_query_cols++; query_cols[n_query_cols]= &str_updated_col; query_vals[n_query_cols].type = DB1_INT; query_vals[n_query_cols].nul = 0; if (dbmode == RLS_DB_ONLY) query_vals[n_query_cols].val.int_val= core_hash(res_id, NULL, 0) % (waitn_time * rls_notifier_poll_rate * rls_notifier_processes); else query_vals[n_query_cols].val.int_val = UPDATED_TYPE; n_query_cols++; query_cols[n_query_cols]= &str_auth_state_col; query_vals[n_query_cols].type = DB1_INT; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.int_val= auth_flag; n_query_cols++; query_cols[n_query_cols]= &str_reason_col; query_vals[n_query_cols].type = DB1_STR; query_vals[n_query_cols].nul = 0; if(reason.len > 0) { query_vals[n_query_cols].val.str_val.s= reason.s; query_vals[n_query_cols].val.str_val.len= reason.len; } else { query_vals[n_query_cols].val.str_val.s = ""; query_vals[n_query_cols].val.str_val.len = 0; } n_query_cols++; query_cols[n_query_cols]= &str_content_type_col; query_vals[n_query_cols].type = DB1_STR; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.str_val= content_type; n_query_cols++; query_cols[n_query_cols]= &str_presence_state_col; query_vals[n_query_cols].type = DB1_STR; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.str_val= body; n_query_cols++; query_cols[n_query_cols]= &str_expires_col; query_vals[n_query_cols].type = DB1_INT; query_vals[n_query_cols].nul = 0; query_vals[n_query_cols].val.int_val= expires+ (int)time(NULL); n_query_cols++; if (rlpres_dbf.use_table(rlpres_db, &rlpres_table) < 0) { LM_ERR("in use_table\n"); goto error; } if (dbmode == RLS_DB_ONLY && rlpres_dbf.start_transaction) { if (rlpres_dbf.start_transaction(rlpres_db) < 0) { LM_ERR("in start_transaction\n"); goto error; } } if (rlpres_dbf.replace != NULL) { if(rlpres_dbf.replace(rlpres_db, query_cols, query_vals, n_query_cols, 2, 0)< 0) { LM_ERR("in sql replace\n"); goto error; } LM_DBG("Inserted/replace in database table new record\n"); } else { if(rlpres_dbf.update(rlpres_db, query_cols, 0, query_vals, query_cols+2, query_vals+2, 2, n_query_cols-2)< 0) { LM_ERR("in sql update\n"); goto error; } if (rlpres_dbf.affected_rows(rlpres_db) == 0) { if(rlpres_dbf.insert(rlpres_db, query_cols, query_vals, n_query_cols)< 0) { LM_ERR("in sql insert\n"); goto error; } LM_DBG("Inserted in database table new record\n"); } } if (dbmode == RLS_DB_ONLY && rlpres_dbf.end_transaction) { if (rlpres_dbf.end_transaction(rlpres_db) < 0) { LM_ERR("in end_transaction\n"); goto error; } } LM_DBG("Updated rlpres_table\n"); /* reply 200OK */ done: if(slb.freply(msg, 200, &su_200_rpl) < 0) { LM_ERR("while sending reply\n"); goto error; } if(res_id!=NULL) { pkg_free(res_id->s); pkg_free(res_id); } if (reason.s) pkg_free(reason.s); free_to_params(&TO); return 1; error: if(slb.freply(msg, reply_code, &reply_str) < 0) { LM_ERR("failed sending reply\n"); } if(res_id!=NULL) { pkg_free(res_id->s); pkg_free(res_id); } if (reason.s) pkg_free(reason.s); free_to_params(&TO); if (dbmode == RLS_DB_ONLY && rlpres_dbf.abort_transaction) { if (rlpres_dbf.abort_transaction(rlpres_db) < 0) LM_ERR("in abort_transaction\n"); } return -1; }
static int cmd_send_message(struct sip_msg* msg, char* _foo, char* _bar) { str body, from_uri, dst, tagid; int mime; LM_DBG("cmd_send_message\n"); /* extract body */ if (get_body(msg,&body)!=0 || body.len==0) { LM_ERR("failed to extract body\n"); return -1; } if ((mime = parse_content_type_hdr(msg)) < 1) { LM_ERR("failed parse content-type\n"); return -1; } if (mime != (TYPE_TEXT << 16) + SUBTYPE_PLAIN && mime != (TYPE_MESSAGE << 16) + SUBTYPE_CPIM) { LM_ERR("invalid content-type 0x%x\n", mime); return -1; } /* extract sender */ if (parse_headers(msg, HDR_TO_F | HDR_FROM_F, 0) == -1 || !msg->to || !msg->from) { LM_ERR("no To/From headers\n"); return -1; } if (parse_from_header(msg) < 0 || !msg->from->parsed) { LM_ERR("failed to parse From header\n"); return -1; } from_uri.s = uri_sip2xmpp(&((struct to_body *) msg->from->parsed)->uri); from_uri.len = strlen(from_uri.s); tagid = ((struct to_body *) msg->from->parsed)->tag_value; LM_DBG("message from <%.*s>\n", from_uri.len, from_uri.s); /* extract recipient */ dst.len = 0; if (msg->new_uri.len > 0) { LM_DBG("using new URI as destination\n"); dst = msg->new_uri; } else if (msg->first_line.u.request.uri.s && msg->first_line.u.request.uri.len > 0) { LM_DBG("using R-URI as destination\n"); dst = msg->first_line.u.request.uri; } else if (msg->to->parsed) { LM_DBG("using TO-URI as destination\n"); dst = ((struct to_body *) msg->to->parsed)->uri; } else { LM_ERR("failed to find a valid destination\n"); return -1; } dst.s = dst.s + 4; dst.len = dst.len - 4; if (!xmpp_send_pipe_cmd(XMPP_PIPE_SEND_MESSAGE, &from_uri, &dst, &body, &tagid)) return 1; return -1; }
int bla_handle_notify(struct sip_msg* msg, char* s1, char* s2) { publ_info_t publ; struct to_body *pto= NULL, TO, *pfrom = NULL; str body; ua_pres_t dialog; unsigned int expires= 0; struct hdr_field* hdr; str subs_state; str extra_headers= {0, 0}; static char buf[255]; str contact; memset(&publ, 0, sizeof(publ_info_t)); memset(&dialog, 0, sizeof(ua_pres_t)); if ( parse_headers(msg,HDR_EOH_F, 0)==-1 ) { LM_ERR("parsing headers\n"); return -1; } if( msg->to==NULL || msg->to->body.s==NULL) { LM_ERR("cannot parse TO header\n"); return -1; } /* examine the to header */ if(msg->to->parsed != NULL) { pto = (struct to_body*)msg->to->parsed; LM_DBG("'To' header ALREADY PARSED: <%.*s>\n", pto->uri.len, pto->uri.s ); } else { parse_to(msg->to->body.s,msg->to->body.s + msg->to->body.len + 1, &TO); if(TO.uri.len <= 0) { LM_DBG("'To' header NOT parsed\n"); return -1; } pto = &TO; } publ.pres_uri= &pto->uri; dialog.watcher_uri= publ.pres_uri; if (pto->tag_value.s==NULL || pto->tag_value.len==0 ) { LM_ERR("NULL to_tag value\n"); return -1; } dialog.from_tag= pto->tag_value; if( msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot parse callid header\n"); return -1; } dialog.call_id = msg->callid->body; if (!msg->from || !msg->from->body.s) { LM_ERR("cannot find 'from' header!\n"); return -1; } if (msg->from->parsed == NULL) { LM_DBG(" 'From' header not parsed\n"); /* parsing from header */ if ( parse_from_header( msg )<0 ) { LM_DBG(" ERROR cannot parse From header\n"); return -1; } } pfrom = (struct to_body*)msg->from->parsed; dialog.to_uri= pfrom->uri; if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0) { LM_ERR("no from tag value present\n"); return -1; } if ( get_content_length(msg) == 0 ) { LM_DBG("content length= 0\n"); return 1; } else { body.s=get_body(msg); if (body.s== NULL) { LM_ERR("cannot extract body from msg\n"); return -1; } body.len = get_content_length( msg ); if (!bla_body_is_valid( &body )) { LM_ERR("bad XML body!"); return -1; } } if(msg->contact== NULL || msg->contact->body.s== NULL) { LM_ERR("no contact header found"); return -1; } if( parse_contact(msg->contact) <0 ) { LM_ERR(" cannot parse contact header\n"); return -1; } if(msg->contact->parsed == NULL) { LM_ERR("cannot parse contact header\n"); return -1; } contact = ((contact_body_t* )msg->contact->parsed)->contacts->uri; dialog.to_tag= pfrom->tag_value; dialog.event= BLA_EVENT; dialog.flag= BLA_SUBSCRIBE; if(pua_is_dialog(&dialog)< 0) { LM_ERR("Notify in a non existing dialog\n"); return -2; } /* parse Subscription-State and extract expires if existing */ hdr = get_header_by_static_name( msg, "Subscription-State"); if( hdr==NULL ) { LM_ERR("No Subscription-State header found\n"); return -1; } subs_state= hdr->body; if(strncasecmp(subs_state.s, "terminated", 10)== 0) expires= 0; else { if(strncasecmp(subs_state.s, "active", 6)== 0 || strncasecmp(subs_state.s, "pending", 7)==0 ) { expires = DEFAULT_EXPIRES; char* sep= NULL; str exp= {NULL, 0}; sep= strchr(subs_state.s, ';'); if(sep) { if(strncasecmp(sep+1, "expires=", 8)== 0) { exp.s= sep+ 9; sep= exp.s; while((*sep)>='0' && (*sep)<='9') { sep++; exp.len++; } if( str2int(&exp, &expires)< 0) { LM_ERR("while parsing int\n"); return -1; } } } } else { LM_ERR("unknown Subscription-state token\n"); return -1; } } /* +2 for ": " between header name and value */ if ((header_name.len + 2 + contact.len + CRLF_LEN) >= sizeof(buf)) { LM_ERR("Sender header too large"); return -1; } /* build extra_headers with Sender*/ extra_headers.s= buf; memcpy(extra_headers.s, header_name.s, header_name.len); extra_headers.len= header_name.len; memcpy(extra_headers.s+extra_headers.len,": ",2); extra_headers.len+= 2; memcpy(extra_headers.s+ extra_headers.len, contact.s, contact.len); extra_headers.len+= contact.len; memcpy(extra_headers.s+ extra_headers.len, CRLF, CRLF_LEN); extra_headers.len+= CRLF_LEN; publ.id= contact; publ.body= &body; publ.source_flag= BLA_PUBLISH; publ.expires= expires; publ.event= BLA_EVENT; publ.extra_headers= &extra_headers; publ.outbound_proxy = presence_server; if(pua_send_publish(&publ)< 0) { LM_ERR("failed to send Publish message\n"); return -1; } return 1; }
/** * store message * mode = "0" -- look for outgoing URI starting with new_uri * = "1" -- look for outgoing URI starting with r-uri * = "2" -- look for outgoing URI only at to header */ static int m_store(struct sip_msg* msg, char* mode, char* str2) { str body, str_hdr, sruri, ctaddr; struct to_body to, *pto, *pfrom; db_key_t db_keys[NR_KEYS]; db_val_t db_vals[NR_KEYS]; int nr_keys = 0, val, lexpire; t_content_type ctype; char buf[512], buf1[1024], *p; int mime; DBG("MSILO: m_store: ------------ start ------------\n"); // extract message body - after that whole SIP MESSAGE is parsed /* get the message's body */ body.s = get_body( msg ); if (body.s==0) { LOG(L_ERR,"MSILO:m_store: ERROR cannot extract body from msg\n"); goto error; } /* content-length (if present) must be already parsed */ if (!msg->content_length) { LOG(L_ERR,"MSILO:m_store: ERROR no Content-Length header found!\n"); goto error; } body.len = get_content_length( msg ); // check if the body of message contains something if(body.len <= 0) { DBG("MSILO:m_store: body of the message is empty!\n"); goto error; } // check TO header if(!msg->to || !msg->to->body.s) { DBG("MSILO:m_store: cannot find 'to' header!\n"); goto error; } if(msg->to->parsed != NULL) { pto = (struct to_body*)msg->to->parsed; DBG("MSILO:m_store: 'To' header ALREADY PARSED: <%.*s>\n", pto->uri.len, pto->uri.s ); } else { DBG("MSILO:m_store: 'To' header NOT PARSED ->parsing ...\n"); memset( &to , 0, sizeof(to) ); parse_to(msg->to->body.s, msg->to->body.s+msg->to->body.len+1, &to); if(to.uri.len > 0) // && to.error == PARSE_OK) { DBG("MSILO:m_store: 'To' parsed OK <%.*s>.\n", to.uri.len, to.uri.s); pto = &to; } else { DBG("MSILO:m_store: ERROR 'To' cannot be parsed\n"); goto error; } } if(pto->uri.len == reg_addr.len && !strncasecmp(pto->uri.s, reg_addr.s, reg_addr.len)) { DBG("MSILO:m_store: message to MSILO REGISTRAR!\n"); goto error; } db_keys[nr_keys] = DB_KEY_TO; db_vals[nr_keys].type = DB_STR; db_vals[nr_keys].nul = 0; db_vals[nr_keys].val.str_val.s = pto->uri.s; db_vals[nr_keys].val.str_val.len = pto->uri.len; nr_keys++; // check FROM header if(!msg->from || !msg->from->body.s) { DBG("MSILO:m_store: ERROR cannot find 'from' header!\n"); goto error; } if(msg->from->parsed != NULL) DBG("MSILO:m_store: 'From' header ALREADY PARSED\n"); else { DBG("MSILO:m_store: 'From' header NOT PARSED\n"); /* parsing from header */ if ( parse_from_header( msg )==-1 ) { DBG("MSILO:m_store: ERROR cannot parse FROM header\n"); goto error; } } pfrom = (struct to_body*)msg->from->parsed; DBG("MSILO:m_store: 'From' header: <%.*s>\n",pfrom->uri.len,pfrom->uri.s); if(reg_addr.s && pfrom->uri.len == reg_addr.len && !strncasecmp(pfrom->uri.s, reg_addr.s, reg_addr.len)) { DBG("MSILO:m_store: message from MSILO REGISTRAR!\n"); goto error; } db_keys[nr_keys] = DB_KEY_FROM; db_vals[nr_keys].type = DB_STR; db_vals[nr_keys].nul = 0; db_vals[nr_keys].val.str_val.s = pfrom->uri.s; db_vals[nr_keys].val.str_val.len = pfrom->uri.len; nr_keys++; // chech for RURI sruri.len = 0; if(mode && mode[0]=='0' && msg->new_uri.len > 0) { DBG("MSILO:m_store: NEW R-URI found - check if is AoR!\n"); p = msg->new_uri.s; while((p < msg->new_uri.s+msg->new_uri.len) && *p!='@') p++; if(p < msg->new_uri.s+msg->new_uri.len && p > msg->new_uri.s) { DBG("MSILO:m_store: NEW R-URI used\n"); sruri.s = msg->new_uri.s; // check for parameters while((p < msg->new_uri.s+msg->new_uri.len) && *p!=';') p++; sruri.len = p - msg->new_uri.s; } } if(mode && mode[0]<='1' && sruri.len == 0 && msg->first_line.u.request.uri.len > 0 ) { DBG("MSILO:m_store: R-URI found - check if is AoR!\n"); p = msg->first_line.u.request.uri.s; while((p < msg->first_line.u.request.uri.s+ msg->first_line.u.request.uri.len) && *p!='@') p++; if(p<msg->first_line.u.request.uri.s+msg->first_line.u.request.uri.len && p > msg->first_line.u.request.uri.s) { DBG("MSILO:m_store: R-URI used\n"); sruri.s = msg->first_line.u.request.uri.s; // check for parameters while((p < msg->first_line.u.request.uri.s + msg->first_line.u.request.uri.len) && *p!=';') p++; sruri.len = p - msg->first_line.u.request.uri.s; } } if (sruri.len == 0) { DBG("MSILO:m_store: TO used as R-URI\n"); sruri.s = pto->uri.s; sruri.len = pto->uri.len; } db_keys[nr_keys] = DB_KEY_RURI; db_vals[nr_keys].type = DB_STR; db_vals[nr_keys].nul = 0; db_vals[nr_keys].val.str_val.s = sruri.s; db_vals[nr_keys].val.str_val.len = sruri.len; nr_keys++; /* add the message's body in SQL query */ db_keys[nr_keys] = DB_KEY_BODY; db_vals[nr_keys].type = DB_BLOB; db_vals[nr_keys].nul = 0; db_vals[nr_keys].val.blob_val.s = body.s; db_vals[nr_keys].val.blob_val.len = body.len; nr_keys++; lexpire = expire_time; // add 'content-type' /* parse the content-type header */ if ((mime=parse_content_type_hdr(msg))<1 ) { LOG(L_ERR,"MSILO:m_store: ERROR cannot parse Content-Type header\n"); goto error; } /** check the content-type value */ if( mime!=(TYPE_TEXT<<16)+SUBTYPE_PLAIN && mime!=(TYPE_MESSAGE<<16)+SUBTYPE_CPIM ) { if(m_extract_content_type(msg->content_type->body.s, msg->content_type->body.len, &ctype, CT_TYPE) != -1) { DBG("MSILO:m_store: 'content-type' found\n"); db_keys[nr_keys] = DB_KEY_CTYPE; db_vals[nr_keys].type = DB_STR; db_vals[nr_keys].nul = 0; db_vals[nr_keys].val.str_val.s = ctype.type.s; db_vals[nr_keys].val.str_val.len = ctype.type.len; nr_keys++; } } // check 'expires' // no more parseing - already done by get_body() // if(parse_headers(msg, HDR_EXPIRES,0)!=-1) if(msg->expires && msg->expires->body.len > 0) { DBG("MSILO:m_store: 'expires' found\n"); val = atoi(msg->expires->body.s); if(val > 0) lexpire = (expire_time<=val)?expire_time:val; } /** current time */ val = (int)time(NULL); /** add expiration time */ db_keys[nr_keys] = DB_KEY_EXP_TIME; db_vals[nr_keys].type = DB_INT; db_vals[nr_keys].nul = 0; db_vals[nr_keys].val.int_val = val+lexpire; nr_keys++; /** add incoming time */ db_keys[nr_keys] = DB_KEY_INC_TIME; db_vals[nr_keys].type = DB_INT; db_vals[nr_keys].nul = 0; db_vals[nr_keys].val.int_val = val; nr_keys++; if(db_insert(db_con, db_keys, db_vals, nr_keys) < 0) { LOG(L_ERR, "MSILO:m_store: error storing message\n"); goto error; } DBG("MSILO:m_store: message stored. T:<%.*s> F:<%.*s>\n", pto->uri.len, pto->uri.s, pfrom->uri.len, pfrom->uri.s); if(reg_addr.len > 0 && reg_addr.len+33+2*CRLF_LEN < 1024) { DBG("MSILO:m_store: sending info message.\n"); strcpy(buf1,"Content-Type: text/plain"CRLF"Contact: "); str_hdr.len = 24 + CRLF_LEN + 9; strncat(buf1,reg_addr.s,reg_addr.len); str_hdr.len += reg_addr.len; strcat(buf1, CRLF); str_hdr.len += CRLF_LEN; str_hdr.s = buf1; strncpy(buf, "User [", 6); body.len = 6; if(pto->uri.len+75 < 512) { strncpy(buf+body.len, pto->uri.s, pto->uri.len); body.len += pto->uri.len; } strncpy(buf+body.len, "] is offline.", 13); body.len += 12; strncpy(buf+body.len, " The message will be delivered", 30); body.len += 30; strncpy(buf+body.len, " when user goes online.", 23); body.len += 23; body.s = buf; // look for Contact header ctaddr.s = NULL; if(use_contact && parse_headers(msg,HDR_CONTACT,0)!=-1 && msg->contact && msg->contact->body.s && msg->contact->body.len>0) { ctaddr.s = msg->contact->body.s; ctaddr.len = msg->contact->body.len; p = ctaddr.s; while(p<ctaddr.s+ctaddr.len && *p!='<') p++; if(*p == '<') { p++; ctaddr.s = p; while(p<ctaddr.s+ctaddr.len && *p!='>') p++; if(p<ctaddr.s+ctaddr.len) ctaddr.len = p-ctaddr.s; } if(!ctaddr.s || ctaddr.len < 6 || strncmp(ctaddr.s, "sip:", 4) || ctaddr.s[4]==' ') ctaddr.s = NULL; else DBG("MSILO:m_store: feedback contact [%.*s]\n", ctaddr.len,ctaddr.s); } // tmb.t_uac(&msg_type,&pfrom->uri,&str_hdr,&body,®_addr,0,0,0); tmb.t_request(&msg_type, /* Type of the message */ (ctaddr.s)?&ctaddr:&pfrom->uri, /* Request-URI */ &pfrom->uri, /* To */ ®_addr, /* From */ &str_hdr, /* Optional headers including CRLF */ &body, /* Message body */ NULL, /* Callback function */ NULL /* Callback parameter */ ); } return 1; error: return -1; }
/** * sngtc_offer - will remove the SDP body of an early negotiation INVITE and * store it in the newly created dialog as a dlg_val. * * @return: 1 on success, negative on failure */ static int sngtc_offer(struct sip_msg *msg) { struct hdr_field *hf; struct lump *lump; struct dlg_cell *dlg; struct sngtc_info *info = NULL; str body, totag, st; if (dlg_binds.create_dlg(msg, 0) < 0) { LM_ERR("failed to create dialog\n"); return SNGTC_ERR; } dlg = dlg_binds.get_dlg(); if (!dlg) { LM_ERR("failed to fetch current dialog\n"); return SNGTC_ERR; } if (get_body(msg, &body) != 0 || body.len <= 0) { LM_ERR("can only do transcoding for early negotiation INVITES\n"); return SNGTC_SDP_ERR; } totag = get_to(msg)->tag_value; /* INVITE retransmissions will skip this part */ if (dlg_binds.fetch_dlg_value(dlg, &dlg_key_sngtc_info, &st, 0) != 0) { if (store_sngtc_info(dlg, &body) != 0) { LM_ERR("failed to create sngtc info struct\n"); return SNGTC_ERR; } /* register a callback to free the above */ if (dlg_binds.register_dlgcb(dlg, DLGCB_EXPIRED|DLGCB_FAILED|DLGCB_TERMINATED, sngtc_dlg_terminated, NULL, NULL) != 0) { LM_ERR("failed to register dialog callback\n"); return SNGTC_ERR; } /* for re-INVITES, just recreate the struct sngtc_info */ } else if (totag.s && totag.len != 0) { info = *(struct sngtc_info **)(st.s); free_transcoding_sessions(info->sessions); if (info->caller_sdp.s) shm_free(info->caller_sdp.s); if (info->modified_caller_sdp.s) shm_free(info->modified_caller_sdp.s); if (store_sngtc_info(dlg, &body) != 0) { LM_ERR("failed to create sngtc info struct\n"); return SNGTC_ERR; } shm_free(info); } LM_DBG("SDP body:\n"); LM_DBG("%.*s\n", body.len, body.s); hf = msg->content_type; /* delete the Content-Type header, we're setting up late negotiation */ lump = del_lump(msg, hf->name.s - msg->buf, hf->len, HDR_OTHER_T); if (!lump) { LM_ERR("no more pkg mem\n"); return SNGTC_ERR; } /* trim the entire SDP body */ lump = del_lump(msg, body.s - msg->buf, body.len, HDR_OTHER_T); if (!lump) { LM_ERR("no more pkg mem\n"); return SNGTC_ERR; } return 1; }
/** * @brief ht dmq callback */ int dlg_dmq_handle_msg(struct sip_msg* msg, peer_reponse_t* resp, dmq_node_t* node) { int content_length; str body; dlg_cell_t *dlg; int unref = 0; int ret; srjson_doc_t jdoc, prof_jdoc; srjson_t *it = NULL; dlg_dmq_action_t action = DLG_DMQ_NONE; dlg_iuid_t iuid; str profiles = {0, 0}, callid = {0, 0}, tag1 = {0,0}, tag2 = {0,0}, contact1 = {0,0}, contact2 = {0,0}, k={0,0}, v={0,0}; str cseq1 = {0,0}, cseq2 = {0,0}, route_set1 = {0,0}, route_set2 = {0,0}, from_uri = {0,0}, to_uri = {0,0}, req_uri = {0,0}; unsigned int init_ts = 0, start_ts = 0, lifetime = 0; unsigned int state = 1; srjson_t *vj; /* received dmq message */ LM_DBG("dmq message received\n"); if(!msg->content_length) { LM_ERR("no content length header found\n"); goto invalid2; } content_length = get_content_length(msg); if(!content_length) { LM_DBG("content length is 0\n"); goto invalid2; } body.s = get_body(msg); body.len = content_length; if (!body.s) { LM_ERR("unable to get body\n"); goto error; } /* parse body */ LM_DBG("body: %.*s\n", body.len, body.s); srjson_InitDoc(&jdoc, NULL); jdoc.buf = body; if(jdoc.root == NULL) { jdoc.root = srjson_Parse(&jdoc, jdoc.buf.s); if(jdoc.root == NULL) { LM_ERR("invalid json doc [[%s]]\n", jdoc.buf.s); goto invalid; } } for(it=jdoc.root->child; it; it = it->next) { if ((it->string == NULL) || (strcmp(it->string, "vars")==0)) continue; LM_DBG("found field: %s\n", it->string); if (strcmp(it->string, "action")==0) { action = SRJSON_GET_UINT(it); } else if (strcmp(it->string, "h_entry")==0) { iuid.h_entry = SRJSON_GET_UINT(it); } else if (strcmp(it->string, "h_id")==0) { iuid.h_id = SRJSON_GET_UINT(it); } else if (strcmp(it->string, "init_ts")==0) { init_ts = SRJSON_GET_UINT(it); } else if (strcmp(it->string, "start_ts")==0) { start_ts = SRJSON_GET_UINT(it); } else if (strcmp(it->string, "state")==0) { state = SRJSON_GET_UINT(it); } else if (strcmp(it->string, "lifetime")==0) { lifetime = SRJSON_GET_UINT(it); } else if (strcmp(it->string, "callid")==0) { callid.s = it->valuestring; callid.len = strlen(callid.s); } else if (strcmp(it->string, "profiles")==0) { profiles.s = it->valuestring; profiles.len = strlen(profiles.s); } else if (strcmp(it->string, "tag1")==0) { tag1.s = it->valuestring; tag1.len = strlen(tag1.s); } else if (strcmp(it->string, "tag2")==0) { tag2.s = it->valuestring; tag2.len = strlen(tag2.s); } else if (strcmp(it->string, "cseq1")==0) { cseq1.s = it->valuestring; cseq1.len = strlen(cseq1.s); } else if (strcmp(it->string, "cseq2")==0) { cseq2.s = it->valuestring; cseq2.len = strlen(cseq2.s); } else if (strcmp(it->string, "route_set1")==0) { route_set1.s = it->valuestring; route_set1.len = strlen(route_set1.s); } else if (strcmp(it->string, "route_set2")==0) { route_set2.s = it->valuestring; route_set2.len = strlen(route_set2.s); } else if (strcmp(it->string, "contact1")==0) { contact1.s = it->valuestring; contact1.len = strlen(contact1.s); } else if (strcmp(it->string, "contact2")==0) { contact2.s = it->valuestring; contact2.len = strlen(contact2.s); } else if (strcmp(it->string, "from_uri")==0) { from_uri.s = it->valuestring; from_uri.len = strlen(from_uri.s); } else if (strcmp(it->string, "to_uri")==0) { to_uri.s = it->valuestring; to_uri.len = strlen(to_uri.s); } else if (strcmp(it->string, "req_uri")==0) { req_uri.s = it->valuestring; req_uri.len = strlen(req_uri.s); } else { LM_ERR("unrecognized field in json object\n"); } } dlg = dlg_get_by_iuid(&iuid); if (dlg) { LM_DBG("found dialog [%u:%u] at %p\n", iuid.h_entry, iuid.h_id, dlg); unref++; } switch(action) { case DLG_DMQ_UPDATE: LM_DBG("Updating dlg [%u:%u] with callid [%.*s]\n", iuid.h_entry, iuid.h_id, callid.len, callid.s); if (!dlg) { dlg = build_new_dlg(&callid, &from_uri, &to_uri, &tag1, &req_uri); if (!dlg) { LM_ERR("failed to build new dialog\n"); goto error; } if(dlg->h_entry != iuid.h_entry){ LM_ERR("inconsistent hash data from peer: " "make sure all Kamailio's use the same hash size\n"); shm_free(dlg); goto error; } /* link the dialog */ link_dlg(dlg, 0, 0); dlg_set_leg_info(dlg, &tag1, &route_set1, &contact1, &cseq1, 0); /* override generated h_id */ dlg->h_id = iuid.h_id; /* prevent DB sync */ dlg->dflags &= ~(DLG_FLAG_NEW|DLG_FLAG_CHANGED); dlg->iflags |= DLG_IFLAG_DMQ_SYNC; } else { /* remove existing profiles */ if (dlg->profile_links!=NULL) { destroy_linkers(dlg->profile_links); dlg->profile_links = NULL; } } dlg->init_ts = init_ts; dlg->start_ts = start_ts; vj = srjson_GetObjectItem(&jdoc, jdoc.root, "vars"); if(vj!=NULL) { for(it=vj->child; it; it = it->next) { k.s = it->string; k.len = strlen(k.s); v.s = it->valuestring; v.len = strlen(v.s); set_dlg_variable(dlg, &k, &v); } } /* add profiles */ if(profiles.s!=NULL) { srjson_InitDoc(&prof_jdoc, NULL); prof_jdoc.buf = profiles; dlg_json_to_profiles(dlg, &prof_jdoc); srjson_DestroyDoc(&prof_jdoc); } if (state == dlg->state) { break; } /* intentional fallthrough */ case DLG_DMQ_STATE: if (!dlg) { LM_ERR("dialog [%u:%u] not found\n", iuid.h_entry, iuid.h_id); goto error; } if (state < dlg->state) { LM_NOTICE("Ignoring backwards state change on dlg [%u:%u]" " with callid [%.*s] from state [%u] to state [%u]\n", iuid.h_entry, iuid.h_id, dlg->callid.len, dlg->callid.s, dlg->state, state); break; } LM_DBG("State update dlg [%u:%u] with callid [%.*s] from state [%u]" " to state [%u]\n", iuid.h_entry, iuid.h_id, dlg->callid.len, dlg->callid.s, dlg->state, state); switch (state) { case DLG_STATE_EARLY: dlg->start_ts = start_ts; dlg->lifetime = lifetime; dlg_set_leg_info(dlg, &tag1, &route_set1, &contact1, &cseq1, 0); break; case DLG_STATE_CONFIRMED: dlg->start_ts = start_ts; dlg->lifetime = lifetime; dlg_set_leg_info(dlg, &tag1, &route_set1, &contact1, &cseq1, 0); dlg_set_leg_info(dlg, &tag2, &route_set2, &contact2, &cseq2, 1); if (insert_dlg_timer( &dlg->tl, dlg->lifetime ) != 0) { LM_CRIT("Unable to insert dlg timer %p [%u:%u]\n", dlg, dlg->h_entry, dlg->h_id); } else { /* dialog pointer inserted in timer list */ dlg_ref(dlg, 1); } break; case DLG_STATE_DELETED: if (dlg->state == DLG_STATE_CONFIRMED) { ret = remove_dialog_timer(&dlg->tl); if (ret == 0) { /* one extra unref due to removal from timer list */ unref++; } else if (ret < 0) { LM_CRIT("unable to unlink the timer on dlg %p [%u:%u]\n", dlg, dlg->h_entry, dlg->h_id); } } /* prevent DB sync */ dlg->dflags |= DLG_FLAG_NEW; /* keep dialog around for a bit, to prevent out-of-order * syncs to reestablish the dlg */ dlg->init_ts = time(NULL); break; default: LM_ERR("unhandled state update to state %u\n", state); dlg_unref(dlg, unref); goto error; } dlg->state = state; break; case DLG_DMQ_RM: if (!dlg) { LM_DBG("dialog [%u:%u] not found\n", iuid.h_entry, iuid.h_id); goto error; } LM_DBG("Removed dlg [%u:%u] with callid [%.*s] int state [%u]\n", iuid.h_entry, iuid.h_id, dlg->callid.len, dlg->callid.s, dlg->state); if (dlg->state==DLG_STATE_CONFIRMED || dlg->state==DLG_STATE_EARLY) { ret = remove_dialog_timer(&dlg->tl); if (ret == 0) { /* one extra unref due to removal from timer list */ unref++; } else if (ret < 0) { LM_CRIT("unable to unlink the timer on dlg %p [%u:%u]\n", dlg, dlg->h_entry, dlg->h_id); } } /* prevent DB sync */ dlg->dflags |= DLG_FLAG_NEW; unref++; break; case DLG_DMQ_SYNC: dmq_send_all_dlgs(0); break; case DLG_DMQ_NONE: break; } if (dlg && unref) dlg_unref(dlg, unref); srjson_DestroyDoc(&jdoc); resp->reason = dmq_200_rpl; resp->resp_code = 200; return 0; invalid: srjson_DestroyDoc(&jdoc); invalid2: resp->reason = dmq_400_rpl; resp->resp_code = 400; return 0; error: srjson_DestroyDoc(&jdoc); resp->reason = dmq_500_rpl; resp->resp_code = 500; return 0; }
int select_msg_body(str* res, select_t* s, struct sip_msg* msg) { res->s = get_body(msg); res->len = msg->buf+msg->len - res->s; return 0; }
int push_on_network(struct sip_msg *msg, int net) { str body; struct sip_uri uri; struct sms_msg *sms_messg; struct to_body *from; char *p; int len; int mime; /* get the message's body * anyhow we have to call this function, so let's do it at the beginning * to force the parsing of all the headers - like this we avoid separate * calls of parse_headers function for FROM, CONTENT_LENGTH, TO hdrs */ body.s = get_body( msg ); if (body.s==0) { LM_ERR("failed to extract body from msg!\n"); goto error; } /* content-length (if present) must be already parsed */ if (!msg->content_length) { LM_ERR("no Content-Length header found!\n"); goto error; } body.len = get_content_length( msg ); /* parse the content-type header */ if ( (mime=parse_content_type_hdr(msg))<1 ) { LM_ERR("failed to parse Content-Type header\n"); goto error; } /* check the content-type value */ if ( mime!=(TYPE_TEXT<<16)+SUBTYPE_PLAIN && mime!=(TYPE_MESSAGE<<16)+SUBTYPE_CPIM ) { LM_ERR("invalid content-type for a message request! type found=%d\n", mime); goto error; } /* we try to get the user name (phone number) first from the RURI (in our case means from new_uri or from first_line.u.request.uri); if it's missing there (like in requests generated by MSN MESSENGER), we go for "to" header */ LM_DBG("string to get user from new_uri\n"); if ( !msg->new_uri.s||parse_uri( msg->new_uri.s,msg->new_uri.len,&uri) || !uri.user.len ) { LM_DBG("string to get user from R_uri\n"); if ( parse_uri( msg->first_line.u.request.uri.s, msg->first_line.u.request.uri.len ,&uri)||!uri.user.len ) { LM_DBG("string to get user from To\n"); if ( (!msg->to&&((parse_headers(msg,HDR_TO_F,0)==-1) || !msg->to)) || parse_uri( get_to(msg)->uri.s, get_to(msg)->uri.len, &uri)==-1 || !uri.user.len) { LM_ERR("unable to extract user name from RURI and To header!\n"); goto error; } } } /* check the uri.user format = '+(inter code)(number)' */ if (uri.user.len<2 || uri.user.s[0]!='+' || uri.user.s[1]<'1' || uri.user.s[1]>'9') { LM_ERR("user tel number [%.*s] does not respect international format\n" ,uri.user.len,uri.user.s); goto error; } /* parsing from header */ if ( parse_from_header( msg )==-1 ) { LM_ERR("failed to get FROM header\n"); goto error; } from = (struct to_body*)msg->from->parsed; #if 0 /* adds contact header into reply */ if (add_contact(msg,&(uri.user))==-1) { LM_ERR("can't build contact for reply\n"); goto error; } #endif /*-------------BUILD AND FILL THE SMS_MSG STRUCTURE --------------------*/ /* computes the amount of memory needed */ len = SMS_HDR_BF_ADDR_LEN + from->uri.len + SMS_HDR_AF_ADDR_LEN + body.len + SMS_FOOTER_LEN /*text to send*/ + from->uri.len /* from */ + uri.user.len-1 /* to user (without '+') */ + sizeof(struct sms_msg) ; /* the sms_msg structure */ /* allocs a new sms_msg structure in shared memory */ sms_messg = (struct sms_msg*)shm_malloc(len); if (!sms_messg) { LM_ERR("failed to get shm memory!\n"); goto error; } p = (char*)sms_messg + sizeof(struct sms_msg); /* copy "from" into sms struct */ sms_messg->from.len = from->uri.len; sms_messg->from.s = p; append_str(p,from->uri.s,from->uri.len); /* copy "to.user" - we have to strip out the '+' */ sms_messg->to.len = uri.user.len-1; sms_messg->to.s = p; append_str(p,uri.user.s+1,sms_messg->to.len); /* copy (and composing) sms body */ sms_messg->text.len = SMS_HDR_BF_ADDR_LEN + sms_messg->from.len + SMS_HDR_AF_ADDR_LEN + body.len+SMS_FOOTER_LEN; sms_messg->text.s = p; append_str(p, SMS_HDR_BF_ADDR, SMS_HDR_BF_ADDR_LEN); append_str(p, sms_messg->from.s, sms_messg->from.len); append_str(p, SMS_HDR_AF_ADDR, SMS_HDR_AF_ADDR_LEN); append_str(p, body.s, body.len); append_str(p, SMS_FOOTER, SMS_FOOTER_LEN); if (*queued_msgs>MAX_QUEUED_MESSAGES) goto error; (*queued_msgs)++; if (write(net_pipes_in[net], &sms_messg, sizeof(sms_messg))!= sizeof(sms_messg) ) { LM_ERR("error when writing for net %d to pipe [%d] : %s\n", net,net_pipes_in[net],strerror(errno) ); shm_free(sms_messg); (*queued_msgs)--; goto error; } return 1; error: return -1; }
/** * @brief ht dmq callback */ int usrloc_dmq_handle_msg(struct sip_msg* msg, peer_reponse_t* resp, dmq_node_t* node) { int content_length; str body; srjson_doc_t jdoc; srjson_t *it = NULL; static ucontact_info_t ci; int action, expires, cseq, flags, cflags, q, last_modified, methods, reg_id; str aor, ruid, c, received, path, callid, user_agent, instance; parse_from_header(msg); body = ((struct to_body*)msg->from->parsed)->uri; LM_DBG("dmq message received from %.*s\n", body.len, body.s); if(!msg->content_length) { LM_ERR("no content length header found\n"); goto invalid; } content_length = get_content_length(msg); if(!content_length) { LM_DBG("content length is 0\n"); goto invalid; } body.s = get_body(msg); body.len = content_length; if (!body.s) { LM_ERR("unable to get body\n"); goto error; } srjson_InitDoc(&jdoc, NULL); jdoc.buf = body; if(jdoc.root == NULL) { jdoc.root = srjson_Parse(&jdoc, jdoc.buf.s); if(jdoc.root == NULL) { LM_ERR("invalid json doc [[%s]]\n", jdoc.buf.s); goto invalid; } } for(it=jdoc.root->child; it; it = it->next) { if (it->string == NULL) continue; if (strcmp(it->string, "action")==0) { action = it->valueint; } else if (strcmp(it->string, "aor")==0) { aor.s = it->valuestring; aor.len = strlen(aor.s); } else if (strcmp(it->string, "ruid")==0) { ruid.s = it->valuestring; ruid.len = strlen(ruid.s); } else if (strcmp(it->string, "c")==0) { c.s = it->valuestring; c.len = strlen(c.s); } else if (strcmp(it->string, "received")==0) { received.s = it->valuestring; received.len = strlen(received.s); } else if (strcmp(it->string, "path")==0) { path.s = it->valuestring; path.len = strlen(path.s); } else if (strcmp(it->string, "callid")==0) { callid.s = it->valuestring; callid.len = strlen(callid.s); } else if (strcmp(it->string, "user_agent")==0) { user_agent.s = it->valuestring; user_agent.len = strlen(user_agent.s); } else if (strcmp(it->string, "instance")==0) { instance.s = it->valuestring; instance.len = strlen(instance.s); } else if (strcmp(it->string, "expires")==0) { // expires = it->valueint; } else if (strcmp(it->string, "cseq")==0) { cseq = it->valueint; } else if (strcmp(it->string, "flags")==0) { flags = it->valueint; } else if (strcmp(it->string, "cflags")==0) { cflags = it->valueint; } else if (strcmp(it->string, "q")==0) { q = it->valueint; } else if (strcmp(it->string, "last_modified")==0) { last_modified = it->valueint; } else if (strcmp(it->string, "methods")==0) { methods = it->valueint; } else if (strcmp(it->string, "reg_id")==0) { reg_id = it->valueint; } else { LM_ERR("unrecognized field in json object\n"); } } memset( &ci, 0, sizeof(ucontact_info_t)); ci.ruid = ruid; ci.c = &c; ci.received = received; ci.path = &path; ci.expires = expires; ci.q = q; ci.callid = &callid; ci.cseq = cseq; ci.flags = flags; ci.flags |= FL_RPL; ci.cflags = cflags; ci.user_agent = &user_agent; ci.methods = methods; ci.instance = instance; ci.reg_id = reg_id; ci.tcpconn_id = -1; ci.last_modified = last_modified; switch(action) { case DMQ_UPDATE: LM_DBG("Received DMQ_UPDATE. Update contact info...\n"); add_contact(aor, &ci); break; case DMQ_RM: LM_DBG("Received DMQ_RM. Delete contact info...\n"); delete_contact(aor, &ci); break; case DMQ_SYNC: LM_DBG("Received DMQ_SYNC. Sending all contacts...\n"); usrloc_get_all_ucontact(node); break; case DMQ_NONE: LM_DBG("Received DMQ_NONE. Not used...\n"); break; default: goto invalid; } srjson_DestroyDoc(&jdoc); resp->reason = dmq_200_rpl; resp->resp_code = 200; return 0; invalid: srjson_DestroyDoc(&jdoc); resp->reason = dmq_400_rpl; resp->resp_code = 400; return 0; error: srjson_DestroyDoc(&jdoc); resp->reason = dmq_500_rpl; resp->resp_code = 500; return 0; }
/** * manage SIP message */ int xjab_manage_sipmsg(struct sip_msg *msg, int type) { str body, dst, from_uri; xj_sipmsg jsmsg; int pipe, fl; t_xj_jkey jkey, *p; int mime; body.len = 0; body.s = 0; // extract message body - after that whole SIP MESSAGE is parsed if (type==XJ_SEND_MESSAGE) { /* get the message's body */ body.s = get_body( msg ); if(body.s==0) { LM_ERR("cannot extract body from msg\n"); goto error; } /* content-length (if present) must be already parsed */ if(!msg->content_length) { LM_ERR("no Content-Length header found!\n"); goto error; } body.len = get_content_length(msg); /* parse the content-type header */ if((mime=parse_content_type_hdr(msg))<1) { LM_ERR("cannot parse Content-Type header\n"); goto error; } /* check the content-type value */ if(mime!=(TYPE_TEXT<<16)+SUBTYPE_PLAIN && mime!=(TYPE_MESSAGE<<16)+SUBTYPE_CPIM) { LM_ERR("invalid content-type for" " a message request! type found=%d\n", mime); goto error; } } // check for TO and FROM headers - if is not SIP MESSAGE if(parse_headers(msg,HDR_TO_F|HDR_FROM_F,0)==-1 || !msg->to || !msg->from) { LM_ERR("cannot find TO or FROM HEADERS!\n"); goto error; } /* parsing from header */ if ( parse_from_header( msg )<0 || msg->from->parsed==NULL) { LM_DBG("cannot get FROM header\n"); goto error; } from_uri.s = ((struct to_body*)msg->from->parsed)->uri.s; from_uri.len = ((struct to_body*)msg->from->parsed)->uri.len; if(xj_extract_aor(&from_uri, 0)) { LM_DBG("cannot get AoR from FROM header\n"); goto error; } jkey.hash = xj_get_hash(&from_uri, NULL); jkey.id = &from_uri; // get the communication pipe with the worker switch(type) { case XJ_SEND_MESSAGE: case XJ_JOIN_JCONF: case XJ_GO_ONLINE: if((pipe = xj_wlist_get(jwl, &jkey, &p)) < 0) { LM_DBG("cannot find pipe of the worker!\n"); goto error; } break; case XJ_EXIT_JCONF: case XJ_GO_OFFLINE: if((pipe = xj_wlist_check(jwl, &jkey, &p)) < 0) { LM_DBG("no open Jabber session for" " <%.*s>!\n", from_uri.len, from_uri.s); goto error; } break; default: LM_DBG("ERROR:strange SIP msg type!\n"); goto error; } // if is for going ONLINE/OFFLINE we do not need the destination if(type==XJ_GO_ONLINE || type==XJ_GO_OFFLINE) goto prepare_job; // determination of destination // - try to get it from new_uri, r-uri or to hdr, but check it against // jdomain and aliases dst.len = 0; if( msg->new_uri.len > 0) { dst.s = msg->new_uri.s; dst.len = msg->new_uri.len; if(xj_wlist_check_aliases(jwl, &dst)) dst.len = 0; #ifdef XJ_EXTRA_DEBUG else LM_DBG("using NEW URI for destination\n"); #endif } if (dst.len == 0 && msg->first_line.u.request.uri.s != NULL && msg->first_line.u.request.uri.len > 0 ) { dst.s = msg->first_line.u.request.uri.s; dst.len = msg->first_line.u.request.uri.len; if(xj_wlist_check_aliases(jwl, &dst)) dst.len = 0; #ifdef XJ_EXTRA_DEBUG else LM_DBG("using R-URI for destination\n"); #endif } if(dst.len == 0 && msg->to->parsed) { dst.s = ((struct to_body*)msg->to->parsed)->uri.s; dst.len = ((struct to_body*)msg->to->parsed)->uri.len; if(dst.s == NULL || xj_wlist_check_aliases(jwl, &dst)) dst.len = 0; #ifdef XJ_EXTRA_DEBUG else LM_DBG("using TO-URI for destination\n"); #endif } if(dst.len == 0) { LM_DBG("destination not found in SIP message\n"); goto error; } /** skip 'sip:' and parameters in destination address */ if(xj_extract_aor(&dst, 1)) { LM_ERR("cannot get AoR for destination\n"); goto error; } #ifdef XJ_EXTRA_DEBUG LM_DBG("destination after correction [%.*s].\n", dst.len, dst.s); #endif prepare_job: //putting the SIP message parts in share memory to be accessible by workers jsmsg = (xj_sipmsg)shm_malloc(sizeof(t_xj_sipmsg)); memset(jsmsg, 0, sizeof(t_xj_sipmsg)); if(jsmsg == NULL) return -1; switch(type) { case XJ_SEND_MESSAGE: jsmsg->msg.len = body.len; if((jsmsg->msg.s = (char*)shm_malloc(jsmsg->msg.len+1)) == NULL) { shm_free(jsmsg); goto error; } strncpy(jsmsg->msg.s, body.s, jsmsg->msg.len); break; case XJ_GO_ONLINE: case XJ_GO_OFFLINE: dst.len = 0; dst.s = 0; case XJ_JOIN_JCONF: case XJ_EXIT_JCONF: jsmsg->msg.len = 0; jsmsg->msg.s = NULL; break; default: LM_DBG("this SHOULD NOT appear\n"); shm_free(jsmsg); goto error; } if(dst.len>0) { jsmsg->to.len = dst.len; if((jsmsg->to.s = (char*)shm_malloc(jsmsg->to.len+1))==NULL) { if(type == XJ_SEND_MESSAGE) shm_free(jsmsg->msg.s); shm_free(jsmsg); goto error; } strncpy(jsmsg->to.s, dst.s, jsmsg->to.len); } else { jsmsg->to.len = 0; jsmsg->to.s = 0; } jsmsg->jkey = p; jsmsg->type = type; //jsmsg->jkey->hash = jkey.hash; LM_DBG("sending <%p> to worker through <%d>\n", jsmsg, pipe); // sending the SHM pointer of SIP message to the worker fl = write(pipe, &jsmsg, sizeof(jsmsg)); if(fl != sizeof(jsmsg)) { LM_ERR("failed to write to worker pipe!\n"); if(type == XJ_SEND_MESSAGE) shm_free(jsmsg->msg.s); shm_free(jsmsg->to.s); shm_free(jsmsg); goto error; } return 1; error: return -1; }
int ac_cancel(as_p the_as,unsigned char processor_id,unsigned int flags,char *action,int len) { unsigned int ret,cancelled_hashIdx,cancelled_label,i; struct sip_msg *my_msg; struct as_uac_param *the_param; struct cell* t_invite; int k,retval,uac_id; str headers,body; body.s=headers.s=NULL; my_msg=NULL; the_param=NULL; i=k=0; net2hostL(uac_id,action,k); net2hostL(cancelled_hashIdx,action,k); net2hostL(cancelled_label,action,k); if(!(headers.s=pkg_malloc(MAX_HEADER))){ LM_ERR("Out of Memory!!"); goto error; } headers.len=0; if(!(my_msg=pkg_malloc(sizeof(struct sip_msg)))){ LM_ERR("out of memory!\n"); goto error; } memset(my_msg,0,sizeof(struct sip_msg)); my_msg->buf=action+k; my_msg->len=len-k; LM_DBG("Action UAC Message: uac_id:%d processor_id=%d, message:[%.*s]\n", uac_id,processor_id,len-4,&action[4]); if(parse_msg(action+k,len-k,my_msg)<0){ LM_ERR("parsing sip_msg"); goto error; } if(my_msg->first_line.type==SIP_REPLY){ LM_ERR("trying to create a UAC with a SIP response!!\n"); goto error; } if(parse_headers(my_msg,HDR_EOH_F,0)==-1){ LM_ERR("parsing headers\n"); goto error; } if(0>(headers.len=extract_allowed_headers(my_msg,1,-1,HDR_CONTENTLENGTH_F|HDR_ROUTE_F|HDR_TO_F|HDR_FROM_F|HDR_CALLID_F|HDR_CSEQ_F,headers.s,MAX_HEADER))) { LM_ERR("Unable to extract allowed headers!!\n"); goto error; } if(flags & SPIRAL_FLAG){ memcpy(headers.s+headers.len,SPIRAL_HDR CRLF,SPIRAL_HDR_LEN + CRLF_LEN); headers.len+=SPIRAL_HDR_LEN+CRLF_LEN; /*headers.s[headers.len]=0; fake_uri.s=pkg_malloc(200); fake_uri.len=print_local_uri(the_as,processor_id,fake_uri.s,200); if(fake_uri.len<0){ SLM_ERR("printing local uri\n"); goto error; } my_dlg->hooks.next_hop=&fake_uri;*/ } headers.s[headers.len]=0; /*let's get the body*/ i=(unsigned int)get_content_length(my_msg); if(i!=0){ if(!(body.s=pkg_malloc(i))){ LM_ERR("Out of Memory!"); goto error; } memcpy(body.s,get_body(my_msg),i); body.len=i; LM_DBG("Trying to construct a Sip Request with: body:%d[%s]" " headers:%d[%s]\n", body.len,body.s,headers.len,headers.s); }else{ body.s=NULL; body.len=0; } if(!(the_param=shm_malloc(sizeof(struct as_uac_param)))){ LM_ERR("no more share memory\n"); goto error; } if(seas_f.tmb.t_lookup_ident(&t_invite,cancelled_hashIdx,cancelled_label)<0){ LM_ERR("failed to t_lookup_ident hash_idx=%d," "label=%d\n", cancelled_hashIdx,cancelled_label); goto error; } seas_f.tmb.unref_cell(t_invite); the_param->who=my_as; the_param->uac_id=uac_id; the_param->processor_id=processor_id; the_param->destroy_cb_set=0; /* registers TMCB_RESPONSE_IN|TMCB_LOCAL_COMPLETED tm callbacks */ ret=seas_f.tmb.t_cancel_uac(&headers,&body,cancelled_hashIdx,cancelled_label,uac_cb,(void*)the_param); if (ret == 0) { LM_ERR( "t_cancel_uac failed\n"); as_action_fail_resp(uac_id,SE_CANCEL,SE_CANCEL_MSG,SE_CANCEL_MSG_LEN); goto error; }else{ the_param->label=ret; } seas_f.tmb.unref_cell(t_invite); retval=0; goto exit; error: retval = -1; if(the_param) shm_free(the_param); exit: if(headers.s) pkg_free(headers.s); if(body.s) pkg_free(headers.s); if(my_msg){ if(my_msg->headers) free_hdr_field_lst(my_msg->headers); pkg_free(my_msg); } return retval; }
const char* mu_msg_get_body_text (MuMsg *self, MuMsgOptions opts) { g_return_val_if_fail (self, NULL); return free_later_str (self, get_body (self, opts, FALSE)); }
/* builds digest string of msg Return value: 1: success 0: else digestString must point to an array with at least MAX_DIGEST bytes */ static int makeDigestString(char * digestString, char * dateHF, struct sip_msg * msg) { struct to_body * from = NULL; struct to_body * to = NULL; struct cseq_body * cseq = NULL; struct hdr_field * date = NULL; contact_t * contact = NULL; unsigned int l; str tmp; if(!digestString || !msg) { LM_ERR("not all parameters set\n"); return 0; } l = 0; /* ###from### */ if(parse_from_header(msg) != 0) { LM_ERR("error parsing from header\n"); return 0; } from = get_from(msg); if(!from) { LM_ERR("error getting from header\n"); return 0; } if (l+from->uri.len+1>MAX_DIGEST) { LM_ERR("buffer to short 1\n"); return 0; } memcpy( digestString+l, from->uri.s, from->uri.len); l += from->uri.len; *(digestString+(l++)) = '|'; /* ###To### */ to = get_to(msg); if(!to) { LM_ERR("error getting to header\n"); return 0; } if (l+to->uri.len+1>MAX_DIGEST) { LM_ERR("buffer to short 2\n"); return 0; } memcpy( digestString+l, to->uri.s, to->uri.len); l += to->uri.len; *(digestString+(l++)) = '|'; /* ###callid### */ if(!msg->callid) { LM_ERR("error getting callid header\n"); return 0; } if (l+msg->callid->body.len+1>MAX_DIGEST) { LM_ERR("buffer to short 3\n"); return 0; } memcpy( digestString+l, msg->callid->body.s, msg->callid->body.len); l += msg->callid->body.len; *(digestString+(l++)) = '|'; /* ###CSeq### */ cseq = (struct cseq_body *)msg->cseq->parsed; if (!cseq) { LM_ERR("error getting cseq header\n"); return 0; } tmp.s = cseq->number.s; tmp.len = cseq->number.len; /* strip leading zeros */ while((*(tmp.s) == '0') && (tmp.len > 1)) { (tmp.s)++; (tmp.len)--; } if (l+tmp.len+cseq->method.len+2>MAX_DIGEST) { LM_ERR("buffer to short 4\n"); return 0; } memcpy( digestString+l, tmp.s, tmp.len); l += tmp.len; *(digestString+(l++)) = ' '; memcpy( digestString+l, cseq->method.s, cseq->method.len); l += cseq->method.len; *(digestString+(l++)) = '|'; /* ###Date### */ if(!dateHF) { /* Date header field is taken from msg: verifier */ date = get_header_by_static_name(msg,"Date"); if (!date) { LM_ERR("error getting date header\n"); return 0; } tmp = date->body; } else { /* Date header field is taken from dateHF: authentication service */ tmp.s = dateHF; tmp.len = strlen(tmp.s); } if (l+tmp.len+1>MAX_DIGEST) { LM_ERR("buffer to short 5\n"); return 0; } memcpy( digestString+l, tmp.s, tmp.len); l += tmp.len; *(digestString+(l++)) = '|'; /* ###Contact### */ if(msg->contact) { if(parse_contact(msg->contact) != 0) { LM_ERR("error parsing contact header\n"); return 0; } /* first contact in list */ contact = ((contact_body_t *)(msg->contact->parsed))->contacts; tmp = contact->uri; } else { tmp.len = 0; tmp.s = 0; } if (l+tmp.len+1>MAX_DIGEST) { LM_ERR("buffer to short 6\n"); return 0; } if (tmp.len) { memcpy( digestString+l, tmp.s, tmp.len); l += tmp.len; } *(digestString+(l++)) = '|'; /* ###body### */ if ( get_body(msg,&tmp)!=0 ) { LM_ERR("failed to inspect body\n"); return 0; } if (tmp.len != 0) { if (l+tmp.len+1>MAX_DIGEST) { LM_ERR("buffer to short 7\n"); return 0; } memcpy( digestString+l, tmp.s, tmp.len); l += tmp.len; *(digestString+(l++)) = 0; } LM_DBG("Digest-String=>%s<\n", digestString); return 1; }
/** * ac_reply: UAS transaction Reply action. It replies to an incoming request with a response. * @param the_as The App Server that sent this action. * @param action action * @param len length * * function description * * Returns: what */ int ac_reply(as_p the_as,unsigned char processor_id,unsigned int flags,char *action,int len) { unsigned int hash_index,label,contentlength; struct cell *c=NULL; struct sip_msg *my_msg; struct to_body *tb; str new_header,body,totag; char *ttag; int i,k,retval; static char headers[MAX_HEADER]; struct as_uac_param *the_param; contentlength=0; ttag=NULL; my_msg=NULL; i=k=0; the_param=NULL; net2hostL(hash_index,action,k); net2hostL(label,action,k); if(seas_f.tmb.t_lookup_ident(&c,hash_index,label)<0){ LM_ERR("Failed to t_lookup_ident hash_idx=%d,label=%d\n",hash_index,label); goto error; } if(use_stats) action_stat(c); if(c->uas.status>=200){ LM_ERR("ac_reply: trying to reply to a \"%.*s\" transaction" "that is already in completed state\n",REQ_LINE(c->uas.request).method.len,REQ_LINE(c->uas.request).method.s); goto error; } if (!(my_msg=parse_ac_msg(HDR_EOH_F,action+k,len-k))) { LM_ERR("Failed to parse_ac_msg hash_idx=%d,label=%d\n",hash_index,label); goto error; } tb=(struct to_body*)my_msg->to->parsed; if(tb->tag_value.s && tb->tag_value.len){ totag=tb->tag_value; }else{ totag.s=NULL; totag.len=0; /*if(!(ttag=pkg_malloc(TOTAG_VALUE_LEN))){ LM_ERR("Out of memory !!!\n"); goto error; } totag.s=ttag; calc_crc_suffix(c->uas.request,seas_tag_suffix); LM_DBG("seas_tags = %.*s\n",TOTAG_VALUE_LEN,seas_tags); memcpy(totag.s,seas_tags,TOTAG_VALUE_LEN); totag.len=TOTAG_VALUE_LEN;*/ } LM_DBG("Using totag=[%.*s]\n",totag.len,totag.s); if(my_msg->content_length) contentlength=(unsigned int)(long)my_msg->content_length->parsed; if(0>(i=recordroute_diff(c->uas.request,my_msg))){/*not likely..*/ LM_DBG("Seems that request had more RecordRoutes than response...\n"); /* This prevents host->proxy->host from working. TODO review recordroute_diff code. goto error; */ }else LM_DBG("Recordroute Diff = %d\n",i); if(0>(i=extract_allowed_headers(my_msg,0,i,HDR_VIA_F|HDR_TO_F|HDR_FROM_F|HDR_CSEQ_F|HDR_CALLID_F|HDR_CONTENTLENGTH_F,headers,MAX_HEADER))){ LM_ERR("ac_reply() filtering headers !\n"); goto error; } headers[i]=0; new_header.s=headers; new_header.len=i; /* If it is INVITE and response is success (>=200 && <300), we mark it as local so that * SER does NOT retransmit the final response (by default, SER retransmit local UAS final * responses...*/ if(is_invite(c) && my_msg->first_line.u.reply.statuscode>=200 && my_msg->first_line.u.reply.statuscode<300){ c->flags |= T_IS_LOCAL_FLAG; if(!(the_param=shm_malloc(sizeof(struct as_uac_param)))){ LM_ERR("no more share memory\n"); goto error; } the_param->processor_id=processor_id; the_param->who=my_as; the_param->destroy_cb_set=0; if (seas_f.tmb.register_tmcb( 0, c, TMCB_E2EACK_IN,uas_e2e_ack_cb, the_param,¶m_free)<=0) { LM_ERR("cannot register additional callbacks\n"); goto error; } } /*WARNING casting unsigned int to int*/ body.len=contentlength; body.s=get_body(my_msg); LM_DBG("Trying to construct a SipReply with: ReasonPhrase:[%.*s] body:[%.*s] headers:[%.*s] totag:[%.*s]\n",\ my_msg->first_line.u.reply.reason.len,my_msg->first_line.u.reply.reason.s,\ body.len,body.s,new_header.len,new_header.s,totag.len,totag.s); /* t_reply_with_body un-ref-counts the transaction, so dont use it anymore*/ if(seas_f.tmb.t_reply_with_body(c,my_msg->first_line.u.reply.statuscode,&(my_msg->first_line.u.reply.reason),&body,&new_header,&totag)<0){ LM_ERR("Failed to t_reply\n"); goto error; } retval=0; goto exit; error: retval = -1; if(c) seas_f.tmb.unref_cell(c); if(the_param) shm_free(the_param); exit: if(ttag) pkg_free(ttag); if(my_msg){ free_sip_msg_lite(my_msg); pkg_free(my_msg); } return retval; }
static int ki_imc_manager(struct sip_msg* msg) { imc_cmd_t cmd; str body; struct sip_uri from_uri, *pto_uri=NULL, *pfrom_uri=NULL; struct to_body *pfrom; int ret = -1; body.s = get_body( msg ); if (body.s==0) { LM_ERR("cannot extract body from msg\n"); goto error; } /* lungimea corpului mesajului */ if (!msg->content_length) { LM_ERR("no Content-Length\n"); goto error; } body.len = get_content_length( msg ); if(body.len <= 0) { LM_DBG("empty body!\n"); goto error; } if(parse_sip_msg_uri(msg)<0) { LM_ERR("failed to parse r-uri\n"); goto error; } pto_uri=&msg->parsed_uri; if(parse_from_header(msg)<0) { LM_ERR("failed to parse From header\n"); goto error; } pfrom = (struct to_body*)msg->from->parsed; if(parse_uri(pfrom->uri.s, pfrom->uri.len, &from_uri)<0){ LM_ERR("failed to parse From URI\n"); goto error; } pfrom_uri=&from_uri; if(body.s[0]== imc_cmd_start_char) { LM_DBG("found command\n"); if(imc_parse_cmd(body.s, body.len, &cmd)<0) { LM_ERR("failed to parse imc cmd!\n"); ret = -20; goto error; } switch(cmd.type) { case IMC_CMDID_CREATE: if(imc_handle_create(msg, &cmd, pfrom_uri, pto_uri)<0) { LM_ERR("failed to handle 'create'\n"); ret = -30; goto error; } break; case IMC_CMDID_JOIN: if(imc_handle_join(msg, &cmd, pfrom_uri, pto_uri)<0) { LM_ERR("failed to handle 'join'\n"); ret = -40; goto error; } break; case IMC_CMDID_INVITE: if(imc_handle_invite(msg, &cmd, pfrom_uri, pto_uri)<0) { LM_ERR("failed to handle 'invite'\n"); ret = -50; goto error; } break; case IMC_CMDID_ACCEPT: if(imc_handle_accept(msg, &cmd, pfrom_uri, pto_uri)<0) { LM_ERR("failed to handle 'accept'\n"); ret = -60; goto error; } break; case IMC_CMDID_DENY: if(imc_handle_deny(msg, &cmd, pfrom_uri, pto_uri)<0) { LM_ERR("failed to handle 'deny'\n"); ret = -70; goto error; } break; case IMC_CMDID_REMOVE: if(imc_handle_remove(msg, &cmd, pfrom_uri, pto_uri)<0) { LM_ERR("failed to handle 'remove'\n"); ret = -80; goto error; } break; case IMC_CMDID_EXIT: if(imc_handle_exit(msg, &cmd, pfrom_uri, pto_uri)<0) { LM_ERR("failed to handle 'exit'\n"); ret = -90; goto error; } break; case IMC_CMDID_LIST: if(imc_handle_list(msg, &cmd, pfrom_uri, pto_uri)<0) { LM_ERR("failed to handle 'list'\n"); ret = -100; goto error; } break; case IMC_CMDID_DESTROY: if(imc_handle_destroy(msg, &cmd, pfrom_uri, pto_uri)<0) { LM_ERR("failed to handle 'destroy'\n"); ret = -110; goto error; } break; case IMC_CMDID_HELP: if(imc_handle_help(msg, &cmd, &pfrom->uri, (msg->new_uri.s)?&msg->new_uri:&msg->first_line.u.request.uri)<0) { LM_ERR("failed to handle 'help'\n"); ret = -120; goto error; } break; default: if(imc_handle_unknown(msg, &cmd, &pfrom->uri, (msg->new_uri.s)?&msg->new_uri:&msg->first_line.u.request.uri)<0) { LM_ERR("failed to handle 'unknown'\n"); ret = -130; goto error; } } goto done; } if(imc_handle_message(msg, &body, pfrom_uri, pto_uri)<0) { LM_ERR("failed to handle 'message'\n"); ret = -200; goto error; } done: return 1; error: return ret; }
/*Actions are composed as follows: * (the action length and type as always= 5 bytes) * 4:uac_id * * int request(str* method, str* req_uri, str* to, str* from, str* headers, str* body, transaction_cb c, void* cp) * TODO performance speedup: instead of using * dynamically allocated memory for headers,body,totag,reason and my_msg * use static buffers. * */ int ac_uac_req(as_p the_as,unsigned char processor_id,unsigned int flags,char *action,int len) { unsigned int cseq; char err_buf[MAX_REASON_LEN]; struct sip_msg *my_msg; struct to_body *fb,*tb; struct cseq_body *cseqb; struct as_uac_param *the_param; dlg_t *my_dlg; int k,retval,uac_id,sip_error,ret,err_ret; long clen; str headers,body,fake_uri; uac_req_t uac_r; headers.s=body.s=fake_uri.s=NULL; my_dlg=NULL; my_msg=NULL; the_param=NULL; k=clen=0; net2hostL(uac_id,action,k); if(!(headers.s=pkg_malloc(MAX_HEADER))){ LM_ERR("Out of Memory!!"); goto error; } headers.len=0; LM_DBG("Action UAC Message: uac_id:%d processor_id=%d\n",uac_id,processor_id); if (!(my_msg = parse_ac_msg(HDR_EOH_F,action+k,len-k))) { LM_ERR("out of memory!\n"); goto error; } if(my_msg->first_line.type==SIP_REPLY){ LM_ERR("trying to create a UAC with a SIP response!!\n"); goto error; } if(parse_headers(my_msg,HDR_EOH_F,0)==-1){ LM_ERR("ERROR:seas:ac_uac_req:parsing headers\n"); goto error; } if(parse_from_header(my_msg)<0){ LM_ERR("parsing from header ! \n"); goto error; } if(check_transaction_quadruple(my_msg)==0){ as_action_fail_resp(uac_id,SE_UAC,"Headers missing (to,from,call-id,cseq)?",0); LM_ERR("Headers missing (to,from,call-id,cseq)?"); goto error; } if(!(get_from(my_msg)) || !(get_from(my_msg)->tag_value.s) || !(get_from(my_msg)->tag_value.len)){ as_action_fail_resp(uac_id,SE_UAC,"From tag missing",0); LM_ERR("From tag missing"); goto error; } fb=my_msg->from->parsed; tb=my_msg->to->parsed; cseqb=my_msg->cseq->parsed; if(0!=(str2int(&cseqb->number,&cseq))){ LM_DBG("unable to parse CSeq\n"); goto error; } if(my_msg->first_line.u.request.method_value != METHOD_ACK && my_msg->first_line.u.request.method_value != METHOD_CANCEL) { /** we trick req_within */ cseq--; } if(seas_f.tmb.new_dlg_uac(&(my_msg->callid->body),&(fb->tag_value),cseq,\ &(fb->uri),&(tb->uri),&my_dlg) < 0) { as_action_fail_resp(uac_id,SE_UAC,"Error creating new dialog",0); LM_ERR("Error while creating new dialog\n"); goto error; } if(seas_f.tmb.dlg_add_extra(my_dlg,&(fb->display),&(tb->display)) < 0 ) { as_action_fail_resp(uac_id,SE_UAC, "Error adding the display names to the new dialog",0); LM_ERR("failed to add display names to the new dialog\n"); goto error; } if(tb->tag_value.s && tb->tag_value.len) shm_str_dup(&my_dlg->id.rem_tag,&tb->tag_value); /**Awful hack: to be able to set our own CSeq, from_tag and call-ID we have * to use req_within instead of req_outside (it sets it's own CSeq,Call-ID * and ftag), so we have to simulate that the dialog is already in completed * state so... */ server_signature=0; my_dlg->state = DLG_CONFIRMED; if(0>(headers.len=extract_allowed_headers(my_msg,1,-1,HDR_CONTENTLENGTH_F|HDR_ROUTE_F|HDR_TO_F|HDR_FROM_F|HDR_CALLID_F|HDR_CSEQ_F,headers.s,MAX_HEADER))) { LM_ERR("Unable to extract allowed headers!!\n"); goto error; } headers.s[headers.len]=0; /*let's get the body*/ if(my_msg->content_length) clen=(long)get_content_length(my_msg); if(clen!=0){ if(!(body.s=pkg_malloc(clen))){ LM_ERR("Out of Memory!"); goto error; } memcpy(body.s,get_body(my_msg),clen); body.len=clen; body.s[clen]=0; LM_DBG("Trying to construct a Sip Request with: body:%d[%.*s] headers:%d[%.*s]\n",\ body.len,body.len,body.s,headers.len,headers.len,headers.s); /*t_reply_with_body un-ref-counts the transaction, so dont use it anymore*/ }else{ body.s=NULL; body.len=0; } /*Now... create the UAC !! * it would be great to know the hash_index and the label that have been assigned * to our newly created cell, but t_uac does not leave any way for us to know... * only that when that transaction transitions its state (ie. a response is received, * a timeout is reached, etc...) the callback will be called with the given parameter. * * So the only way we have to know who we are, is passing as a parameter a structure with * 2 pointers: one to the app_server and the other, the identifier of the UAC (uac_id). * */ if(!(the_param=shm_malloc(sizeof(struct as_uac_param)))){ LM_ERR("out of shared memory\n"); goto error; } the_param->who=my_as; the_param->uac_id=uac_id; the_param->processor_id=processor_id; the_param->destroy_cb_set=0; shm_str_dup(&my_dlg->rem_target,&my_msg->first_line.u.request.uri); if (my_msg->route) { if (parse_rr(my_msg->route) < 0) { LM_ERR( "Error while parsing Route body\n"); goto error; } /* TODO route_set should be a shm copy of my_msg->route->parsed */ my_dlg->route_set=(rr_t*)my_msg->route->parsed; /** this SHOULD be: shm_duplicate_rr(&my_dlg->route_set,my_msg->route->parsed); * but it will last more... */ } calculate_hooks(my_dlg); if(flags & SPIRAL_FLAG){ memcpy(headers.s+headers.len,SPIRAL_HDR CRLF,SPIRAL_HDR_LEN + CRLF_LEN); headers.len+=SPIRAL_HDR_LEN+CRLF_LEN; headers.s[headers.len]=0; fake_uri.s=pkg_malloc(200); fake_uri.len=print_local_uri(the_as,processor_id,fake_uri.s,200); if(fake_uri.len<0){ LM_ERR("printing local uri\n"); goto error; } my_dlg->hooks.next_hop=&fake_uri; } /* Kamailio and OpenSIPs seem to have diverged quite a bit on flags and events notified to UACs. Let's see if kamailio gets it right by now, if not this is a TODO: check PASS_PROVISIONAL my_dlg->T_flags=T_NO_AUTO_ACK|T_PASS_PROVISIONAL_FLAG ; this is the same as (TMCB_DONT_ACK|TMCB_LOCAL_RESPONSE_OUT) in Kamailio */ set_uac_req(&uac_r, &(my_msg->first_line.u.request.method), &headers, &body, my_dlg,TMCB_DONT_ACK|TMCB_LOCAL_RESPONSE_OUT, uac_cb, (void*)the_param); ret=seas_f.tmb.t_request_within(&uac_r); /** now undo all the fakes we have put in my_dlg*/ /*because my_dlg->route_set should be shm but we fake it (its pkg_mem)*/ my_dlg->route_set=(rr_t *)0; if (ret < 0) { err_ret = err2reason_phrase(ret,&sip_error,err_buf, sizeof(err_buf), "SEAS/UAC"); LM_ERR("failed to send the [%.*s] request\n",uac_r.method->len,uac_r.method->s); LM_ERR("Error on request_within %s\n",err_buf ); if(err_ret > 0) { as_action_fail_resp(uac_id,ret,err_buf,0); }else{ as_action_fail_resp(uac_id,E_UNSPEC,"500 SEAS/UAC error",0); } goto error; } retval=0; goto exit; error: retval = -1; if(the_param) shm_free(the_param); exit: seas_f.tmb.free_dlg(my_dlg); if(headers.s) pkg_free(headers.s); if(body.s) pkg_free(body.s); if(fake_uri.s) pkg_free(fake_uri.s); if(my_msg){ if(my_msg->headers) free_hdr_field_lst(my_msg->headers); pkg_free(my_msg); } return retval; }