int reginfo_handle_notify(struct sip_msg* msg, char* domain, char* s2) { str body; int result = 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(body, (udomain_t*)domain); return result; }
/** * initializes a vector of write buffers with the HTTP message information * * @param write_buffers vector of write buffers to initialize */ virtual void prepare_buffers_for_send(http::message::write_buffers_t& write_buffers) { if (get_content_length() > 0) m_http_request->set_content_length(get_content_length()); m_http_request->prepare_buffers_for_send(write_buffers, get_connection()->get_keep_alive(), sending_chunked_message()); }
std::size_t message::write(std::ostream& out, boost::system::error_code& ec, bool headers_only) { // reset error_code ec.clear(); // initialize write buffers for send operation using HTTP headers write_buffers_t write_buffers; prepare_buffers_for_send(write_buffers, true, false); // append payload content to write buffers (if there is any) if (!headers_only && get_content_length() > 0 && get_content() != NULL) write_buffers.push_back(boost::asio::buffer(get_content(), get_content_length())); // write message to the output stream std::size_t bytes_out = 0; for (write_buffers_t::const_iterator i=write_buffers.begin(); i!=write_buffers.end(); ++i) { const char *ptr = boost::asio::buffer_cast<const char*>(*i); size_t len = boost::asio::buffer_size(*i); out.write(ptr, len); bytes_out += len; } return bytes_out; }
/*! \brief * event specific publish handling - check if body format is ok */ int mwi_publ_handl(struct sip_msg* msg) { str body; char *at, *over; 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"); return -1; } /* content-length (if present) must be already parsed */ body.len = get_content_length(msg); at = body.s; over = body.s + body.len; /* check msg-status-line */ if (body.len <= 16) goto err; if (strncmp(body.s, "Messages-Waiting", 16) != 0) goto err; at = at + 16; at = eat_sp_tab(at, over); if ((at >= over) || (*at != ':')) goto err; at++; if ((at >= over) || ((*at != ' ') && (*at != '\t'))) goto err; at++; at = eat_sp_tab(at, over); if (at + 3 >= over) goto err; if (strncmp(at, "yes", 3) == 0) at = at + 3; else if (strncmp(at, "no", 2) == 0) at = at + 2; else goto err; if ((at + 1 >= over) || (*at != '\r') || (*(at + 1) != '\n')) goto err; at = at + 2; /* check that remaining body consists of lines that only contain * printable ascii chars */ while (at < over) { at = eat_printable(at, over); if ((at + 1 >= over) || (*at != '\r') || (*(at + 1) != '\n')) goto err; at = at + 2; } return 1; err: LM_ERR("check of body <%.*s> failed at character index %d (hexa: 0x%x)\n", body.len, body.s, (int)(at - body.s + 1), (int)(*at)); return -1; }
std::size_t message::send(tcp::connection& tcp_conn, boost::system::error_code& ec, bool headers_only) { // initialize write buffers for send operation using HTTP headers write_buffers_t write_buffers; prepare_buffers_for_send(write_buffers, tcp_conn.get_keep_alive(), false); // append payload content to write buffers (if there is any) if (!headers_only && get_content_length() > 0 && get_content() != NULL) write_buffers.push_back(boost::asio::buffer(get_content(), get_content_length())); // send the message and return the result return tcp_conn.write(write_buffers, ec); }
char* process_http_response_header(int sd, int *content_length){ char *header; char *line; char *buildheader; header = process_req_line(sd); int done = 0; int is_content_length_line = 0; int cont_length = 0; while(!done){ line = process_req_line(sd); buildheader = malloc(strlen(header) + 1 + strlen(line) + 1); memcpy(buildheader, header, strlen(header) + 1); free(header); strcat(buildheader, line); if(is_content_length_line = check_if_content_length_line(line)){ cont_length = get_content_length(line); *content_length = cont_length; } done = req_done_processing(line); free(line); header = malloc(strlen(buildheader) + 1); memcpy(header, buildheader, strlen(buildheader) + 1); free(buildheader); } return header; }
/* is this reply of interest for accounting ? */ static inline int should_acc_reply(struct sip_msg *req, struct sip_msg *rpl, int code) { unsigned int i; /* negative transactions reported otherwise only if explicitly * demanded */ if (code >= 300) { if (!is_failed_acc_on(req)) return 0; i = 0; while (failed_filter[i] != 0) { if (failed_filter[i] == code) return 0; i++; } return 1; } if ( !is_acc_on(req) ) return 0; if ( code<200 && !(early_media && parse_headers(rpl,HDR_CONTENTLENGTH_F, 0) == 0 && rpl->content_length && get_content_length(rpl) > 0)) return 0; return 1; /* seed is through, we will account this reply */ }
int mangle_message_cpim(struct sip_msg* _msg, char* _s1, char* _s2) { char *body = get_body(_msg); int parsed_content_type; struct hdr_field *content_type = _msg->content_type; int body_len = 0; parse_headers(_msg, HDR_CONTENTLENGTH_F|HDR_CONTENTTYPE_F, 0); parsed_content_type = parse_content_type_hdr(_msg); body_len = get_content_length(_msg); LOG(L_ERR, "mangle_message_cpim -1- content_type==%.*s %x (patching %x) bodylen=%d\n", content_type->body.len, content_type->body.s, parsed_content_type, MIMETYPE(MESSAGE,CPIM), body_len); if (body && (parsed_content_type == MIMETYPE(MESSAGE,CPIM))) { char *ptr = strstr(body, "\r\n\r\n"); char *new_content_type_str = strstr(body, "Content-Type: "); int new_content_type_len = 0; char *new_content_type_body; if (new_content_type_str) { char *new_content_type_end = strstr(new_content_type_str, "\r\n"); if (new_content_type_end) { new_content_type_str += 14; new_content_type_len = new_content_type_end - new_content_type_str; } else { new_content_type_len = 10; new_content_type_str = "text/plain"; } } else { new_content_type_len = 10; new_content_type_str = "text/plain"; } if (strncmp(new_content_type_str, "application/sip-iscomposing+xml", 31) == 0) { new_content_type_len = 30; new_content_type_str = "application/im-iscomposing+xml"; } new_content_type_body = pkg_malloc(new_content_type_len); strncpy(new_content_type_body, new_content_type_str, new_content_type_len); //LOG(L_ERR, "mangle_message_cpim -1- oldbody=%.*s\n", body_len, body); patch_msg(_msg, content_type->body.s, content_type->body.len, new_content_type_body, new_content_type_len); LOG(L_ERR, "mangle_message_cpim -1b- patched content-type=%.*s\n", new_content_type_len, new_content_type_str); if (ptr) { char *new_body = NULL; int new_body_len = body_len - (ptr + 4 - body); //LOG(L_ERR, "mangle_message_cpim -2- old_body_len=%d new_body_len=%d\n", body_len, new_body_len); new_body = pkg_malloc(new_body_len+1); strncpy(new_body, ptr+4, new_body_len+1); patch_msg(_msg, body, body_len, new_body, new_body_len); } } LOG(L_ERR, "mangle_message_cpim -3-\n"); return 1; }
/** * extract the node list from the body of a notification request SIP message * the SIP request will look something like: * KDMQ sip:10.0.0.0:5062 * To: ... * From: ... * Max-Forwards: ... * Content-Length: 22 * * sip:host1:port1;param1=value1 * sip:host2:port2;param2=value2 * ... */ int extract_node_list(dmq_node_list_t* update_list, struct sip_msg* msg) { int content_length, total_nodes = 0; str body; str tmp_uri; dmq_node_t *cur = NULL; char *tmp, *end, *match; if(!msg->content_length) { LM_ERR("no content length header found\n"); return -1; } content_length = get_content_length(msg); if(!content_length) { LM_DBG("content length is 0\n"); return total_nodes; } body.s = get_body(msg); body.len = content_length; tmp = body.s; end = body.s + body.len; /* acquire big list lock */ lock_get(&update_list->lock); while(tmp < end) { match = q_memchr(tmp, '\n', end - tmp); if(match) { match++; } else { /* for the last line - take all of it */ match = end; } /* create the orig_uri from the parsed uri line and trim it */ tmp_uri.s = tmp; tmp_uri.len = match - tmp - 1; tmp = match; /* trim the \r, \n and \0's */ trim_r(tmp_uri); if(!find_dmq_node_uri(update_list, &tmp_uri)) { LM_DBG("found new node %.*s\n", STR_FMT(&tmp_uri)); cur = build_dmq_node(&tmp_uri, 1); if(!cur) { LM_ERR("error creating new dmq node\n"); goto error; } cur->next = update_list->nodes; update_list->nodes = cur; update_list->count++; total_nodes++; } } /* release big list lock */ lock_release(&update_list->lock); return total_nodes; error: lock_release(&update_list->lock); return -1; }
long cscf_get_content_length (struct sip_msg* msg) { int cl = 0; if (!msg) return 0; if (parse_headers(msg, HDR_CONTENTLENGTH_F, 0) != -1 && msg->content_length && msg->content_length->parsed) cl = get_content_length(msg); return cl; }
/* * 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; }
bool server_response::write(std::ostream &os) { // Set "content-length" header auto i=headers.find("content-length"); if (i==headers.end()) { headers.insert(std::make_pair("Content-Length", boost::lexical_cast<std::string>(get_content_length()))); } else { i->second.assign(boost::lexical_cast<std::string>(get_content_length())); } // Write headers if (!write_header(os)) return false; // Write body os.write(&(raw_body_stream_.vector()[0]), raw_body_stream_.vector().size()); return !os.eof() && !os.fail() && !os.bad(); }
/** * Function to process post requests. * @param server_struct is the main structure for the server. * @param connection is the connection in MHD * @param url is the requested url * @param con_cls is a pointer used to know if this is the first call or not * @param upload_data is a char * pointer to the data being uploaded at this call * @param upload_size is a pointer to an size_t value that says how many data * is ti be copied from upload_data string. * @returns an int that is either MHD_NO or MHD_YES upon failure or not. */ static int process_post_request(server_struct_t *server_struct, struct MHD_Connection *connection, const char *url, void **con_cls, const char *upload_data, size_t *upload_data_size) { int success = MHD_NO; upload_t *pp = (upload_t *) *con_cls; guint64 len = 0; /* print_debug("%ld, %s, %p\n", *upload_data_size, url, pp); */ /* This is for early debug only ! */ if (pp == NULL) { /* print_headers(connection); */ /* Used for debugging */ /* Initialzing the structure at first connection */ len = get_content_length(connection); pp = (upload_t *) g_malloc(sizeof(upload_t)); pp->pos = 0; pp->buffer = g_malloc(sizeof(gchar) * (len + 1)); /* not using g_malloc0 here because it's 1000 times slower */ pp->number = 0; *con_cls = pp; success = MHD_YES; } else if (*upload_data_size != 0) { /* Getting data whatever they are */ memcpy(pp->buffer + pp->pos, upload_data, *upload_data_size); pp->pos = pp->pos + *upload_data_size; pp->number = pp->number + 1; *con_cls = pp; *upload_data_size = 0; success = MHD_YES; } else { /* reset when done */ *con_cls = NULL; pp->buffer[pp->pos] = '\0'; /* Do something with received_data */ success = process_received_data(server_struct, connection, url, pp->buffer); free_variable(pp->buffer); free_variable(pp); } return success; }
/* is this reply of interest for accounting ? */ static inline int should_acc_reply(struct sip_msg *req,struct sip_msg *rpl, int code) { /* negative transactions reported otherwise only if explicitly * demanded */ if ( !is_failed_acc_on(req) && code >=300 ) return 0; if ( !is_acc_on(req) ) return 0; if ( code<200 && !(early_media && rpl!=FAKED_REPLY && parse_headers(rpl,HDR_CONTENTLENGTH_F, 0)==0 && rpl->content_length && get_content_length(rpl)>0 ) ) return 0; return 1; /* seed is through, we will account this reply */ }
static void run_service(const char **argv, int buffer_input) { const char *encoding = getenv("HTTP_CONTENT_ENCODING"); const char *user = getenv("REMOTE_USER"); const char *host = getenv("REMOTE_ADDR"); int gzipped_request = 0; struct child_process cld = CHILD_PROCESS_INIT; ssize_t req_len = get_content_length(); if (encoding && !strcmp(encoding, "gzip")) gzipped_request = 1; else if (encoding && !strcmp(encoding, "x-gzip")) gzipped_request = 1; if (!user || !*user) user = "******"; if (!host || !*host) host = "(none)"; if (!getenv("GIT_COMMITTER_NAME")) argv_array_pushf(&cld.env_array, "GIT_COMMITTER_NAME=%s", user); if (!getenv("GIT_COMMITTER_EMAIL")) argv_array_pushf(&cld.env_array, "GIT_COMMITTER_EMAIL=%s@http.%s", user, host); cld.argv = argv; if (buffer_input || gzipped_request || req_len >= 0) cld.in = -1; cld.git_cmd = 1; cld.clean_on_exit = 1; cld.wait_after_clean = 1; if (start_command(&cld)) exit(1); close(1); if (gzipped_request) inflate_request(argv[0], cld.in, buffer_input, req_len); else if (buffer_input) copy_request(argv[0], cld.in, req_len); else if (req_len >= 0) pipe_fixed_length(argv[0], cld.in, req_len); else close(0); if (finish_command(&cld)) exit(1); }
int get_msg_body(struct sip_msg *msg, str *body) { body->s = get_body(msg); if (body->s == 0) { return -1; } body->len = (int) (msg->len - (body->s - msg->buf)); if (!msg->content_length) { return -1; } if (body->len != get_content_length(msg)) { WARN("Content length header value different than body size\n"); } return 0; }
int handle_s_p2( clidata_t *client, char *hdrs ) { int gotten=0; int expected = get_content_length(hdrs); char *pkt; int cnt=0; queue_t *recvq = client->recvq; int chan1 = client->chan1; if( !expected ) { lprintf(log, WARN, "Client sent no Content-Length. Dropping."); return -1; } while( gotten < expected ) { if( (pkt=get_packet(chan1)) == NULL ) { lprintf(log, WARN, "get_packet() failed. Dropping client."); fdprintf(chan1, RESPONSE_500_ERR); return -1; } cnt++; gotten += iplen(pkt); dprintf(log, DEBUG, "got %d of %d bytes from client", gotten, expected); if( (q_add(recvq, pkt, Q_WAIT, iplen(pkt))) == -1 ) { lprintf(log, WARN, "q_add() failed. Dropping client."); fdprintf(chan1, RESPONSE_500_ERR); return -1; } } lprintf(log, INFO, "Got %d bytes in %d pkts", gotten, cnt); fdprintf(chan1, RESPONSE_204); return 0; }
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; }
/* * Loop through all the headers (including the response code) from the * server. */ static int process_server_headers(struct conn_s *connptr) { static char *skipheaders[] = { "keep-alive", "proxy-authenticate", "proxy-authorization", "proxy-connection", "transfer-encoding", }; char *response_line; hashmap_t hashofheaders; hashmap_iter iter; char *data, *header; ssize_t len; int i; int ret; /* FIXME: Remember to handle a "simple_req" type */ /* Get the response line from the remote server. */ retry: len = readline(connptr->server_fd, &response_line); if (len <= 0) return -1; /* * Strip the new line and character return from the string. */ if (chomp(response_line, len) == len) { /* * If the number of characters removed is the same as the * length then it was a blank line. Free the buffer and * try again (since we're looking for a request line.) */ safefree(response_line); goto retry; } hashofheaders = hashmap_create(HEADER_BUCKETS); if (!hashofheaders) { safefree(response_line); return -1; } /* * Get all the headers from the remote server in a big hash */ if (get_all_headers(connptr->server_fd, hashofheaders) < 0) { log_message(LOG_WARNING, "Could not retrieve all the headers from the remote server."); hashmap_delete(hashofheaders); safefree(response_line); indicate_http_error(connptr, 503, "Could not retrieve all the headers", "detail", PACKAGE " was unable to retrieve and process headers from the remote web server.", NULL); return -1; } /* Send the saved response line first */ ret = write_message(connptr->client_fd, "%s\r\n", response_line); safefree(response_line); if (ret < 0) goto ERROR_EXIT; /* * If there is a "Content-Length" header, retrieve the information * from it for later use. */ connptr->content_length.server = get_content_length(hashofheaders); /* * See if there is a connection header. If so, we need to to a bit of * processing. */ remove_connection_headers(hashofheaders); /* * Delete the headers listed in the skipheaders list */ for (i = 0; i != (sizeof(skipheaders) / sizeof(char *)); i++) { hashmap_remove(hashofheaders, skipheaders[i]); } /* Send, or add the Via header */ ret = write_via_header(connptr->client_fd, hashofheaders, connptr->protocol.major, connptr->protocol.minor); if (ret < 0) goto ERROR_EXIT; /* * All right, output all the remaining headers to the client. */ iter = hashmap_first(hashofheaders); if (iter >= 0) { for ( ; !hashmap_is_end(hashofheaders, iter); ++iter) { hashmap_return_entry(hashofheaders, iter, &data, (void **)&header); ret = write_message(connptr->client_fd, "%s: %s\r\n", data, header); if (ret < 0) goto ERROR_EXIT; } } hashmap_delete(hashofheaders); /* Write the final blank line to signify the end of the headers */ if (safe_write(connptr->client_fd, "\r\n", 2) < 0) return -1; return 0; ERROR_EXIT: hashmap_delete(hashofheaders); return -1; }
/* * Here we loop through all the headers the client is sending. If we * are running in anonymous mode, we will _only_ send the headers listed * (plus a few which are required for various methods). * - rjkaes */ static int process_client_headers(struct conn_s *connptr, hashmap_t hashofheaders) { static char *skipheaders[] = { "host", "keep-alive", "proxy-authenticate", "proxy-authorization", "proxy-connection", "te", "trailers", "transfer-encoding", "upgrade" }; int i; hashmap_iter iter; int ret = 0; char *data, *header; /* * Don't send headers if there's already an error, if the request was * a stats request, or if this was a CONNECT method (unless upstream * proxy is in use.) */ if (connptr->server_fd == -1 || connptr->show_stats || (connptr->connect_method && (connptr->upstream_proxy == NULL))) { log_message(LOG_INFO, "Not sending client headers to remote machine"); return 0; } /* * See if there is a "Content-Length" header. If so, again we need * to do a bit of processing. */ connptr->content_length.client = get_content_length(hashofheaders); /* * See if there is a "Connection" header. If so, we need to do a bit * of processing. :) */ remove_connection_headers(hashofheaders); /* * Delete the headers listed in the skipheaders list */ for (i = 0; i != (sizeof(skipheaders) / sizeof(char *)); i++) { hashmap_remove(hashofheaders, skipheaders[i]); } /* Send, or add the Via header */ ret = write_via_header(connptr->server_fd, hashofheaders, connptr->protocol.major, connptr->protocol.minor); if (ret < 0) { indicate_http_error(connptr, 503, "Could not send data to remote server", "detail", "A network error occurred while trying to write data to the remote web server.", NULL); goto PULL_CLIENT_DATA; } /* * Output all the remaining headers to the remote machine. */ iter = hashmap_first(hashofheaders); if (iter >= 0) { for ( ; !hashmap_is_end(hashofheaders, iter); ++iter) { hashmap_return_entry(hashofheaders, iter, &data, (void**)&header); if (!is_anonymous_enabled() || anonymous_search(data) > 0) { ret = write_message(connptr->server_fd, "%s: %s\r\n", data, header); if (ret < 0) { indicate_http_error(connptr, 503, "Could not send data to remote server", "detail", "A network error occurred while trying to write data to the remote web server.", NULL); goto PULL_CLIENT_DATA; } } } } #if defined(XTINYPROXY_ENABLE) if (config.my_domain) add_xtinyproxy_header(connptr); #endif /* Write the final "blank" line to signify the end of the headers */ if (safe_write(connptr->server_fd, "\r\n", 2) < 0) return -1; /* * Spin here pulling the data from the client. */ PULL_CLIENT_DATA: if (connptr->content_length.client > 0) return pull_client_data(connptr, connptr->content_length.client); else return ret; }
/** * 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; }
/** * 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; }
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; }
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 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; }
/** * @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; }
int handle_r_p2( clidata_t *client, char *hdrs ) { int expected = get_content_length(hdrs); queue_t *sendq = client->sendq; int chan2 = client->chan2; struct timespec ts; char *body; int sex; char *pkt; if( !expected ) { lprintf(log, WARN, "Client sent no Content-Length. Dropping."); goto cleanup1; } if( (body=getbody(chan2, hdrs, &expected)) == NULL ) { lprintf(log, WARN, "getbody() failed. Dropping client."); goto cleanup1; } if( (sex=strtol(body, NULL, 0)) == 0 ) { lprintf(log, WARN, "Client sent invalid seconds spec."); fdprintf(chan2, RESPONSE_400); goto cleanup2; } ts.tv_nsec = 0; ts.tv_sec = sex; dprintf(log, DEBUG, "waiting up to %d seconds.", sex); if( q_timedwait(sendq, &ts) ) { int sent=0, total, cnt=0; dprintf(log, DEBUG, "returned from wait, with data"); total = sendq->totsize; fdprintf(chan2, RESPONSE_200_NOBODY, sendq->totsize); while( sent < total ) { if( (pkt=q_remove(sendq, 0, NULL)) == NULL ) { lprintf(log, WARN, "q_remove failed!"); goto cleanup2; } if( write(chan2, pkt, iplen(pkt)) < 0 ) { lprintf(log, INFO, "send failed: %s", strerror(errno)); free(pkt); goto cleanup2; } cnt++; sent += iplen(pkt); free(pkt); } lprintf(log, INFO, "Sent %d bytes in %d pkts", sent, cnt); } else { dprintf(log, DEBUG, "returned from wait, with NO data"); if( client->chan2 != -1 ) fdprintf(chan2, RESPONSE_204); } return 0; cleanup2: free(body); cleanup1: return -1; }
/*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; }
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; }
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; }