gop_op_generic_t *ibp_version_gop(ibp_context_t *ic, ibp_depot_t *depot, char *buffer, int buffer_size, int timeout) { ibp_op_t *op = new_ibp_op(ic); if (op == NULL) return(NULL); char hoststr[MAX_HOST_SIZE]; char pchoststr[MAX_HOST_SIZE]; ibp_op_version_t *cmd = &(op->ops.ver_op); ibppc_form_host(op->ic, pchoststr, sizeof(pchoststr), depot->host, depot->rid); set_hostport(hoststr, sizeof(hoststr), pchoststr, depot->port, &(op->ic->cc[IBP_STATUS])); init_ibp_base_op(op, "depot_version", timeout, op->ic->other_new_command, strdup(hoststr), op->ic->other_new_command, IBP_STATUS, IBP_ST_VERSION); cmd->depot = depot; cmd->buffer = buffer; cmd->buffer_size = buffer_size; gop_op_generic_t *gop = ibp_get_gop(op); gop->op->cmd.send_command = depot_version_command; gop->op->cmd.send_phase = NULL; gop->op->cmd.recv_phase = depot_version_recv; return(ibp_get_gop(op)); }
gop_op_generic_t *ibp_query_resources_gop(ibp_context_t *ic, ibp_depot_t *depot, ibp_ridlist_t *rlist, int timeout) { ibp_op_t *op = new_ibp_op(ic); if (op == NULL) return(NULL); char hoststr[MAX_HOST_SIZE]; char pchoststr[MAX_HOST_SIZE]; ibp_op_rid_inq_t *cmd = &(op->ops.rid_op); ibppc_form_host(op->ic, pchoststr, sizeof(pchoststr), depot->host, depot->rid); set_hostport(hoststr, sizeof(hoststr), pchoststr, depot->port, &(op->ic->cc[IBP_STATUS])); init_ibp_base_op(op, "query_resources", timeout, op->ic->other_new_command, strdup(hoststr), op->ic->other_new_command, IBP_STATUS, IBP_ST_RES); cmd->depot = depot; cmd->rlist = rlist; gop_op_generic_t *gop = ibp_get_gop(op); gop->op->cmd.send_command = query_res_command; gop->op->cmd.send_phase = NULL; gop->op->cmd.recv_phase = query_res_recv; return(ibp_get_gop(op)); }
gop_op_generic_t *ibp_depot_inq_gop(ibp_context_t *ic, ibp_depot_t *depot, char *password, ibp_depotinfo_t *di, int timeout) { ibp_op_t *op = new_ibp_op(ic); if (op == NULL) return(NULL); char hoststr[MAX_HOST_SIZE]; char pchost[MAX_HOST_SIZE]; ibp_op_depot_inq_t *cmd = &(op->ops.depot_inq_op); ibppc_form_host(op->ic, pchost, sizeof(pchost), depot->host, depot->rid); set_hostport(hoststr, sizeof(hoststr), pchost, depot->port, &(op->ic->cc[IBP_STATUS])); init_ibp_base_op(op, "depot_inq", timeout, op->ic->other_new_command, strdup(hoststr), op->ic->other_new_command, IBP_STATUS, IBP_ST_INQ); cmd->depot = depot; cmd->password = password; cmd->di = di; gop_op_generic_t *gop = ibp_get_gop(op); gop->op->cmd.send_command = depot_inq_command; gop->op->cmd.send_phase = NULL; gop->op->cmd.recv_phase = depot_inq_recv; return(ibp_get_gop(op)); }
/* * Create Via header */ static inline int assemble_via(str* dest, struct cell* t, struct dest_info* dst, int branch) { static char branch_buf[MAX_BRANCH_PARAM_LEN]; char* via; int len; unsigned int via_len; str branch_str; struct hostport hp; if (!t_calc_branch(t, branch, branch_buf, &len)) { LM_ERR("branch calculation failed\n"); return -1; } branch_str.s = branch_buf; branch_str.len = len; #ifdef XL_DEBUG printf("!!!proto: %d\n", sock->proto); #endif set_hostport(&hp, 0); via = via_builder(&via_len, NULL, dst, &branch_str, 0, &hp); if (!via) { LM_ERR("via building failed\n"); return -2; } dest->s = via; dest->len = via_len; return 0; }
gop_op_generic_t *ibp_merge_alloc_gop(ibp_context_t *ic, ibp_cap_t *mcap, ibp_cap_t *ccap, int timeout) { ibp_op_t *op = new_ibp_op(ic); char hoststr[MAX_HOST_SIZE]; char host[MAX_HOST_SIZE]; char chost[MAX_HOST_SIZE]; ibp_op_merge_alloc_t *cmd; int port, cport; log_printf(15, "set_ibp_merge_op: start. ic=%p\n", op->ic); init_ibp_base_op(op, "rename", timeout, op->ic->other_new_command, NULL, 1, IBP_RENAME, IBP_NOP); cmd = &(op->ops.merge_op); parse_cap(op->ic, mcap, host, &port, cmd->mkey, cmd->mtypekey); set_hostport(hoststr, sizeof(hoststr), host, port, &(op->ic->cc[IBP_MERGE_ALLOCATE])); op->dop.cmd.hostport = strdup(hoststr); parse_cap(op->ic, ccap, chost, &cport, cmd->ckey, cmd->ctypekey); gop_op_generic_t *gop = ibp_get_gop(op); gop->op->cmd.send_command = merge_command; gop->op->cmd.send_phase = NULL; gop->op->cmd.recv_phase = status_get_recv; return(ibp_get_gop(op)); }
gop_op_generic_t *ibp_truncate_gop(ibp_context_t *ic, ibp_cap_t *cap, ibp_off_t size, int timeout) { ibp_op_t *op = new_ibp_op(ic); char hoststr[MAX_HOST_SIZE]; int port; char host[MAX_HOST_SIZE]; ibp_op_modify_alloc_t *cmd; init_ibp_base_op(op, "truncate_alloc", timeout, op->ic->other_new_command, NULL, 1, IBP_MANAGE, IBP_CHNG); cmd = &(op->ops.mod_alloc_op); parse_cap(op->ic, cap, host, &port, cmd->key, cmd->typekey); set_hostport(hoststr, sizeof(hoststr), host, port, &(op->ic->cc[IBP_MANAGE])); op->dop.cmd.hostport = strdup(hoststr); cmd->cap = cap; cmd->size = size; gop_op_generic_t *gop = ibp_get_gop(op); gop->op->cmd.send_command = truncate_command; gop->op->cmd.send_phase = NULL; gop->op->cmd.recv_phase = status_get_recv; return(ibp_get_gop(op)); }
ne_session *ne_session_create(const char *scheme, const char *hostname, unsigned int port) { ne_session *sess = ne_calloc(sizeof *sess); NE_DEBUG(NE_DBG_HTTP, "HTTP session to %s://%s:%d begins.\n", scheme, hostname, port); strcpy(sess->error, "Unknown error."); /* use SSL if scheme is https */ sess->use_ssl = !strcmp(scheme, "https"); /* set the hostname/port */ set_hostinfo(&sess->server, hostname, port); set_hostport(&sess->server, sess->use_ssl?443:80); #ifdef NE_HAVE_SSL if (sess->use_ssl) { sess->ssl_context = ne_ssl_context_create(0); sess->flags[NE_SESSFLAG_SSLv2] = 1; } #endif sess->scheme = ne_strdup(scheme); /* Set flags which default to on: */ sess->flags[NE_SESSFLAG_PERSIST] = 1; return sess; }
gop_op_generic_t *ibp_proxy_probe_gop(ibp_context_t *ic, ibp_cap_t *cap, ibp_proxy_capstatus_t *probe, int timeout) { ibp_op_t *op = new_ibp_op(ic); char hoststr[MAX_HOST_SIZE]; int port; char host[MAX_HOST_SIZE]; ibp_op_probe_t *cmd; init_ibp_base_op(op, "proxy_probe", timeout, op->ic->other_new_command, NULL, 1, IBP_PROXY_MANAGE, IBP_PROBE); cmd = &(op->ops.probe_op); parse_cap(op->ic, cap, host, &port, cmd->key, cmd->typekey); set_hostport(hoststr, sizeof(hoststr), host, port, &(op->ic->cc[IBP_PROXY_MANAGE])); op->dop.cmd.hostport = strdup(hoststr); cmd->cap = cap; cmd->proxy_probe = probe; gop_op_generic_t *gop = ibp_get_gop(op); gop->op->cmd.send_command = proxy_probe_command; gop->op->cmd.send_phase = NULL; gop->op->cmd.recv_phase = proxy_probe_recv; return(ibp_get_gop(op)); }
gop_op_generic_t *ibp_alloc_gop(ibp_context_t *ic, ibp_capset_t *caps, ibp_off_t size, ibp_depot_t *depot, ibp_attributes_t *attr, int disk_cs_type, ibp_off_t disk_blocksize, int timeout) { ibp_op_t *op = new_ibp_op(ic); char hoststr[MAX_HOST_SIZE]; char pchost[MAX_HOST_SIZE]; ibp_op_alloc_t *cmd; ibppc_form_host(op->ic, pchost, sizeof(pchost), depot->host, depot->rid); set_hostport(hoststr, sizeof(hoststr), pchost, depot->port, &(op->ic->cc[IBP_ALLOCATE])); init_ibp_base_op(op, "alloc", timeout, op->ic->other_new_command, strdup(hoststr), 1, IBP_ALLOCATE, IBP_NOP); cmd = &(op->ops.alloc_op); cmd->caps = caps; cmd->depot = depot; cmd->attr = attr; cmd->duration = cmd->attr->duration - time(NULL); //** This is in sec NOT APR time if (cmd->duration < 0) cmd->duration = cmd->attr->duration; cmd->size = size; cmd->disk_chksum_type = disk_cs_type; cmd->disk_blocksize = disk_blocksize; gop_op_generic_t *gop = ibp_get_gop(op); gop->op->cmd.send_command = allocate_command; gop->op->cmd.send_phase = NULL; gop->op->cmd.recv_phase = allocate_recv; return(ibp_get_gop(op)); }
gop_op_generic_t *ibp_validate_chksum_gop(ibp_context_t *ic, ibp_cap_t *mcap, int correct_errors, int *n_bad_blocks, int timeout) { ibp_op_t *op = new_ibp_op(ic); char hoststr[MAX_HOST_SIZE]; char host[MAX_HOST_SIZE]; ibp_op_validate_chksum_t *cmd; int port; init_ibp_base_op(op, "validate_chksum", timeout, op->ic->other_new_command, NULL, 1, IBP_VALIDATE_CHKSUM, IBP_NOP); gop_op_generic_t *gop = ibp_get_gop(op); cmd = &(op->ops.validate_op); parse_cap(op->ic, mcap, host, &port, cmd->key, cmd->typekey); set_hostport(hoststr, sizeof(hoststr), host, port, &(op->ic->cc[IBP_VALIDATE_CHKSUM])); op->dop.cmd.hostport = strdup(hoststr); cmd = &(op->ops.validate_op); cmd->correct_errors = correct_errors; cmd->n_bad_blocks = n_bad_blocks; gop->op->cmd.send_command = validate_chksum_command; gop->op->cmd.send_phase = NULL; gop->op->cmd.recv_phase = validate_chksum_recv; return(ibp_get_gop(op)); }
gop_op_generic_t *ibp_copy_gop(ibp_context_t *ic, int mode, int ns_type, char *path, ibp_cap_t *srccap, ibp_cap_t *destcap, ibp_off_t src_offset, ibp_off_t dest_offset, ibp_off_t size, int src_timeout, int dest_timeout, int dest_client_timeout) { ibp_op_t *op = new_ibp_op(ic); if (op == NULL) return(NULL); char hoststr[MAX_HOST_SIZE]; int port; char host[MAX_HOST_SIZE]; ibp_op_copy_t *cmd; init_ibp_base_op(op, "copy", src_timeout, op->ic->rw_new_command + size, NULL, size, IBP_SEND, IBP_NOP); cmd = &(op->ops.copy_op); parse_cap(op->ic, srccap, host, &port, cmd->src_key, cmd->src_typekey); set_hostport(hoststr, sizeof(hoststr), host, port, &(op->ic->cc[IBP_SEND])); op->dop.cmd.hostport = strdup(hoststr); cmd->ibp_command = mode; if (ns_type == NS_TYPE_PHOEBUS) { cmd->ctype = IBP_PHOEBUS; cmd->path = path; if (cmd->path == NULL) cmd->path = "auto"; //** If NULL default to auto } else { //** All other ns types don't use the path cmd->ctype = IBP_TCP; cmd->path = "\0"; } //** Want chksumming so tweak the command if (tbx_ns_chksum_is_valid(&(op->ncs)) == 1) { if (cmd->ibp_command == IBP_PUSH) { cmd->ibp_command = IBP_PUSH_CHKSUM; } else { cmd->ibp_command = IBP_PULL_CHKSUM; } } cmd->srccap = srccap; cmd->destcap = destcap; cmd->len = size; cmd->src_offset = src_offset; cmd->dest_offset = dest_offset; cmd->dest_timeout = dest_timeout; cmd->dest_client_timeout = dest_client_timeout; gop_op_generic_t *gop = ibp_get_gop(op); gop->op->cmd.send_command = pushpull_command; gop->op->cmd.send_phase = NULL; gop->op->cmd.recv_phase = copy_recv; return(ibp_get_gop(op)); }
void set_ibp_rw_gop(ibp_op_t *op, int rw_type, ibp_cap_t *cap, ibp_off_t offset, tbx_tbuf_t *buffer, ibp_off_t bpos, ibp_off_t len, int timeout) { char hoststr[MAX_HOST_SIZE]; int port; char host[MAX_HOST_SIZE]; ibp_op_rw_t *cmd; ibp_rw_buf_t *rwbuf; cmd = &(op->ops.rw_op); init_ibp_base_op(op, "rw", timeout, op->ic->rw_new_command + len, NULL, len, rw_type, IBP_NOP); gop_op_generic_t *gop = ibp_get_gop(op); parse_cap(op->ic, cap, host, &port, cmd->key, cmd->typekey); set_hostport(hoststr, sizeof(hoststr), host, port, &(op->ic->cc[rw_type])); op->dop.cmd.hostport = strdup(hoststr); cmd->cap = cap; cmd->size = len; //** This is the total size rwbuf = &(cmd->buf_single); cmd->bs_ptr = rwbuf; cmd->rwbuf = &(cmd->bs_ptr); cmd->n_ops = 1; cmd->n_tbx_iovec_total = 1; cmd->rw_mode = rw_type; rwbuf->iovec = &(rwbuf->iovec_single); rwbuf->n_iovec = 1; rwbuf->iovec->offset = offset; rwbuf->iovec->len = len; rwbuf->buffer = buffer; rwbuf->boff = bpos; rwbuf->size = len; if (rw_type == IBP_WRITE) { gop->op->cmd.send_command = write_command; gop->op->cmd.send_phase = write_send; gop->op->cmd.recv_phase = write_recv; gop->op->cmd.on_submit = ibp_rw_submit_coalesce; gop->op->cmd.before_exec = ibp_rw_coalesce; } else { gop->op->cmd.send_command = read_command; gop->op->cmd.send_phase = NULL; gop->op->cmd.recv_phase = read_recv; gop->op->cmd.on_submit = ibp_rw_submit_coalesce; gop->op->cmd.before_exec = ibp_rw_coalesce; } op->ncs = op->ic->ncs; //** Copy the default network chksum }
ne_session *ne_session_create(const char *scheme, const char *hostname, unsigned int port) { ne_session *sess = ne_calloc(sizeof *sess); NE_DEBUG(NE_DBG_HTTP, "HTTP session to %s://%s:%d begins.\n", scheme, hostname, port); strcpy(sess->error, "Unknown error."); /* use SSL if scheme is https */ sess->use_ssl = !strcmp(scheme, "https"); /* set the hostname/port */ set_hostinfo(&sess->server, PROXY_NONE, hostname, port); set_hostport(&sess->server, sess->use_ssl?443:80); #ifdef NE_HAVE_SSL if (sess->use_ssl) { ne_inet_addr *ia; sess->ssl_context = ne_ssl_context_create(0); sess->flags[NE_SESSFLAG_SSLv2] = 1; /* If the hostname parses as an IP address, don't * enable SNI by default. */ ia = ne_iaddr_parse(hostname, ne_iaddr_ipv4); if (ia == NULL) ia = ne_iaddr_parse(hostname, ne_iaddr_ipv6); if (ia) { ne_iaddr_free(ia); } else { sess->flags[NE_SESSFLAG_TLS_SNI] = 1; } NE_DEBUG(NE_DBG_SSL, "ssl: SNI %s by default.\n", sess->flags[NE_SESSFLAG_TLS_SNI] ? "enabled" : "disabled"); } #endif sess->scheme = ne_strdup(scheme); /* Set flags which default to on: */ sess->flags[NE_SESSFLAG_PERSIST] = 1; return sess; }
char *change_hostport_cc(char *old_hostport, ibp_connect_context_t *cc) { char host[MAX_HOST_SIZE], new_hostport[MAX_HOST_SIZE]; char *hp2 = strdup(old_hostport); char *bstate; int fin, port; strncpy(host, tbx_stk_string_token(hp2, HP_HOSTPORT_SEPARATOR, &bstate, &fin), sizeof(host)-1); host[sizeof(host)-1] = '\0'; port = atoi(bstate); set_hostport(new_hostport, sizeof(new_hostport), host, port, cc); free(hp2); return(strdup(new_hostport)); }
void set_ibp_generic_modify_count_op(int command, ibp_op_t *op, ibp_cap_t *cap, ibp_cap_t *mcap, int mode, int captype, int timeout) { char hoststr[MAX_HOST_SIZE]; int port; char host[MAX_HOST_SIZE]; ibp_op_probe_t *cmd; if ((command != IBP_MANAGE) && (command != IBP_PROXY_MANAGE)) { log_printf(0, "set_ibp_generic_modify_count_op: Invalid command! should be IBP_MANAGE or IBP_PROXY_MANAGE. Got %d\n", command); return; } if ((mode != IBP_INCR) && (mode != IBP_DECR)) { log_printf(0, "ibp_modify_count_gop: Invalid mode! should be IBP_INCR or IBP_DECR\n"); return; } if ((captype != IBP_WRITECAP) && (captype != IBP_READCAP)) { log_printf(0, "ibp_modify_count_gop: Invalid captype! should be IBP_READCAP or IBP_WRITECAP\n"); return; } init_ibp_base_op(op, "modify_count", timeout, op->ic->other_new_command, NULL, 1, command, mode); cmd = &(op->ops.probe_op); parse_cap(op->ic, cap, host, &port, cmd->key, cmd->typekey); set_hostport(hoststr, sizeof(hoststr), host, port, &(op->ic->cc[command])); op->dop.cmd.hostport = strdup(hoststr); if (command == IBP_PROXY_MANAGE) parse_cap(op->ic, mcap, host, &port, cmd->mkey, cmd->mtypekey); cmd->cmd = command; cmd->cap = cap; cmd->mode = mode; cmd->captype = captype; gop_op_generic_t *gop = ibp_get_gop(op); gop->op->cmd.send_command = modify_count_command; if (command == IBP_PROXY_MANAGE) gop->op->cmd.send_command = proxy_modify_count_command; gop->op->cmd.send_phase = NULL; gop->op->cmd.recv_phase = status_get_recv; }
gop_op_generic_t *ibp_proxy_alloc_gop(ibp_context_t *ic, ibp_capset_t *caps, ibp_cap_t *mcap, ibp_off_t offset, ibp_off_t size, int duration, int timeout) { ibp_op_t *op = new_ibp_op(ic); char hoststr[MAX_HOST_SIZE]; char host[MAX_HOST_SIZE]; ibp_op_alloc_t *cmd; int port; log_printf(15, "set_ibp_proxy_alloc_gop: start. ic=%p\n", op->ic); init_ibp_base_op(op, "rename", timeout, op->ic->other_new_command, NULL, 1, IBP_PROXY_ALLOCATE, IBP_NOP); cmd = &(op->ops.alloc_op); parse_cap(op->ic, mcap, host, &port, cmd->key, cmd->typekey); set_hostport(hoststr, sizeof(hoststr), host, port, &(op->ic->cc[IBP_PROXY_ALLOCATE])); op->dop.cmd.hostport = strdup(hoststr); cmd->offset = offset; cmd->size = size; if (duration == 0) { cmd->duration = 0; } else { cmd->duration = duration - time(NULL); //** This is in sec NOT APR time } cmd->caps = caps; gop_op_generic_t *gop = ibp_get_gop(op); gop->op->cmd.send_command = proxy_allocate_command; gop->op->cmd.send_phase = NULL; gop->op->cmd.recv_phase = allocate_recv; return(ibp_get_gop(op)); }
gop_op_generic_t *ibp_split_alloc_gop(ibp_context_t *ic, ibp_cap_t *mcap, ibp_capset_t *caps, ibp_off_t size, ibp_attributes_t *attr, int disk_cs_type, ibp_off_t disk_blocksize, int timeout) { ibp_op_t *op = new_ibp_op(ic); char hoststr[MAX_HOST_SIZE]; char host[MAX_HOST_SIZE]; ibp_op_alloc_t *cmd; int port; init_ibp_base_op(op, "split_allocate", timeout, op->ic->other_new_command, NULL, 1, IBP_SPLIT_ALLOCATE, IBP_NOP); cmd = &(op->ops.alloc_op); parse_cap(op->ic, mcap, host, &port, cmd->key, cmd->typekey); set_hostport(hoststr, sizeof(hoststr), host, port, &(op->ic->cc[IBP_SPLIT_ALLOCATE])); op->dop.cmd.hostport = strdup(hoststr); cmd = &(op->ops.alloc_op); cmd->caps = caps; cmd->attr = attr; cmd->duration = cmd->attr->duration - time(NULL); //** This is in sec NOT APR time if (cmd->duration < 0) cmd->duration = cmd->attr->duration; cmd->size = size; cmd->disk_chksum_type = disk_cs_type; cmd->disk_blocksize = disk_blocksize; gop_op_generic_t *gop = ibp_get_gop(op); gop->op->cmd.send_command = split_allocate_command; gop->op->cmd.send_phase = NULL; gop->op->cmd.recv_phase = allocate_recv; return(ibp_get_gop(op)); }
gop_op_generic_t *ibp_context_chksum_get_gop(ibp_context_t *ic, ibp_cap_t *mcap, int chksum_info_only, int *cs_type, int *cs_size, ibp_off_t *blocksize, ibp_off_t *nblocks, ibp_off_t *nbytes, char *buffer, ibp_off_t bufsize, int timeout) { ibp_op_t *op = new_ibp_op(ic); char hoststr[MAX_HOST_SIZE]; char host[MAX_HOST_SIZE]; ibp_op_get_chksum_t *cmd; int port; init_ibp_base_op(op, "get_chksum", timeout, op->ic->other_new_command, NULL, 1, IBP_VALIDATE_CHKSUM, IBP_NOP); gop_op_generic_t *gop = ibp_get_gop(op); cmd = &(op->ops.get_chksum_op); parse_cap(op->ic, mcap, host, &port, cmd->key, cmd->typekey); set_hostport(hoststr, sizeof(hoststr), host, port, &(op->ic->cc[IBP_VALIDATE_CHKSUM])); op->dop.cmd.hostport = strdup(hoststr); cmd->cap = mcap; cmd = &(op->ops.get_chksum_op); cmd->chksum_info_only = chksum_info_only; cmd->cs_type = cs_type; cmd->cs_size = cs_size; cmd->blocksize = blocksize; cmd->nblocks = nblocks; cmd->n_chksumbytes = nbytes; gop->op->cmd.send_command = get_chksum_command; gop->op->cmd.send_phase = NULL; gop->op->cmd.recv_phase = get_chksum_recv; return(ibp_get_gop(op)); }
/* * The function creates an ACK to 200 OK. Route set will be created * and parsed and the dst parameter will contain the destination to which * the request should be send. The function is used by tm when it * generates local ACK to 200 OK (on behalf of applications using uac) */ char *build_dlg_ack(struct sip_msg* rpl, struct cell *Trans, unsigned int branch, str *hdrs, str *body, unsigned int *len, struct dest_info* dst) { char *req_buf, *p, *via; unsigned int via_len; char branch_buf[MAX_BRANCH_PARAM_LEN]; int branch_len; str branch_str; struct hostport hp; struct rte* list; str contact, ruri, *cont; str next_hop; str body_len; str _to, *to = &_to; #ifdef USE_DNS_FAILOVER struct dns_srv_handle dns_h; #endif #ifdef WITH_AS_SUPPORT /* With AS support, TM allows for external modules to generate building of * the ACK; in this case, the ACK's retransmission buffer is built once * and kept in memory (to help when retransmitted 2xx are received and ACK * must be resent). * Allocation of the string raw buffer that holds the ACK is piggy-backed * with allocation of the retransmission buffer (since both have the same * life-cycle): both the string buffer and retransm. buffer are placed * into the same allocated chunk of memory (retr. buffer first, string * buffer follows).In this case, the 'len' param is used as in-out * parameter: 'in' to give the extra space needed by the retr. buffer, * 'out' to return the lenght of the allocated string buffer. */ unsigned offset = *len; #endif if (parse_headers(rpl, HDR_EOH_F, 0) == -1 || !rpl->to) { LM_ERR("Error while parsing headers.\n"); return 0; } else { _to.s = rpl->to->name.s; _to.len = rpl->to->len; } if (get_contact_uri(rpl, &contact) < 0) { return 0; } if (eval_uac_routing(rpl, &Trans->uac[branch].request, &contact, &list, &ruri, &next_hop) < 0) { LM_ERR("failed to evaluate routing elements.\n"); return 0; } LM_DBG("ACK RURI: `%.*s', NH: `%.*s'.\n", STR_FMT(&ruri), STR_FMT(&next_hop)); if ((contact.s != ruri.s) || (contact.len != ruri.len)) { /* contact != ruri means that the next * hop is a strict router, cont will be non-zero * and print_routeset will append it at the end * of the route set */ cont = &contact; } else { /* Next hop is a loose router, nothing to append */ cont = 0; } /* method, separators, version: "ACK sip:[email protected] SIP/2.0" */ *len = SIP_VERSION_LEN + ACK_LEN + 2 /* spaces */ + CRLF_LEN; *len += ruri.len; /* dst */ switch(cfg_get(tm, tm_cfg, local_ack_mode)){ case 1: /* send the local 200 ack to the same dst as the corresp. invite*/ *dst=Trans->uac[branch].request.dst; break; case 2: /* send the local 200 ack to the same dst as the 200 reply source*/ init_dst_from_rcv(dst, &rpl->rcv); dst->send_flags=rpl->fwd_send_flags; break; case 0: default: /* rfc conformant behaviour: use the next_hop determined from the * contact and the route set */ #ifdef USE_DNS_FAILOVER if (cfg_get(core, core_cfg, use_dns_failover)){ dns_srv_handle_init(&dns_h); if ((uri2dst(&dns_h , dst, rpl, &next_hop, PROTO_NONE)==0) || (dst->send_sock==0)){ dns_srv_handle_put(&dns_h); LM_ERR("no socket found\n"); goto error; } dns_srv_handle_put(&dns_h); /* not needed any more */ }else{ if ((uri2dst(0 , dst, rpl, &next_hop, PROTO_NONE)==0) || (dst->send_sock==0)){ LM_ERR("no socket found\n"); goto error; } } #else /* USE_DNS_FAILOVER */ if ( (uri2dst( dst, rpl, &next_hop, PROTO_NONE)==0) || (dst->send_sock==0)){ LM_ERR("no socket found\n"); goto error; } #endif /* USE_DNS_FAILOVER */ break; } /* via */ if (!t_calc_branch(Trans, branch, branch_buf, &branch_len)) goto error; branch_str.s = branch_buf; branch_str.len = branch_len; set_hostport(&hp, 0); via = via_builder(&via_len, NULL, dst, &branch_str, 0, &hp); if (!via) { LM_ERR("No via header got from builder\n"); goto error; } *len+= via_len; /* headers */ *len += Trans->from.len + Trans->callid.len + to->len + Trans->cseq_n.len + 1 + ACK_LEN + CRLF_LEN; /* copy'n'paste Route headers */ *len += calc_routeset_len(list, cont); /* User Agent */ if (server_signature) *len += user_agent_hdr.len + CRLF_LEN; /* extra headers */ if (hdrs) *len += hdrs->len; /* body */ if (body) { body_len.s = int2str(body->len, &body_len.len); *len += body->len; } else { body_len.len = 0; body_len.s = NULL; /*4gcc*/ *len += 1; /* for the (Cont-Len:) `0' */ } /* Content Length, EoM */ *len += CONTENT_LENGTH_LEN + body_len.len + CRLF_LEN + CRLF_LEN; #if WITH_AS_SUPPORT req_buf = shm_malloc(offset + *len + 1); req_buf += offset; #else req_buf = shm_malloc(*len + 1); #endif if (!req_buf) { LM_ERR("Cannot allocate memory (%u+1)\n", *len); goto error01; } p = req_buf; append_str( p, ACK, ACK_LEN ); append_str( p, " ", 1 ); append_str(p, ruri.s, ruri.len); append_str( p, " " SIP_VERSION CRLF, 1 + SIP_VERSION_LEN + CRLF_LEN); /* insert our via */ append_str(p, via, via_len); /*other headers*/ append_str(p, Trans->from.s, Trans->from.len); append_str(p, Trans->callid.s, Trans->callid.len); append_str(p, to->s, to->len); append_str(p, Trans->cseq_n.s, Trans->cseq_n.len); append_str( p, " ", 1 ); append_str( p, ACK, ACK_LEN); append_str(p, CRLF, CRLF_LEN); /* Routeset */ p = print_rs(p, list, cont); /* User Agent header */ if (server_signature) { append_str(p, user_agent_hdr.s, user_agent_hdr.len); append_str(p, CRLF, CRLF_LEN); } /* extra headers */ if (hdrs) append_str(p, hdrs->s, hdrs->len); /* Content Length, EoH, (body) */ if (body) { append_str(p, CONTENT_LENGTH, CONTENT_LENGTH_LEN); append_str(p, body_len.s, body_len.len); append_str(p, /*end crr. header*/CRLF /*EoH*/CRLF, CRLF_LEN + CRLF_LEN); append_str(p, body->s, body->len); } else { append_str(p, CONTENT_LENGTH "0" CRLF CRLF, CONTENT_LENGTH_LEN + 1 + CRLF_LEN + CRLF_LEN); } /* EoM */ *p = 0; pkg_free(via); free_rte_list(list); return req_buf; error01: pkg_free(via); error: free_rte_list(list); return 0; }
/* * The function creates an ACK for a local INVITE. If 200 OK, route set * will be created and parsed */ char *build_dlg_ack(struct sip_msg* rpl, struct cell *Trans, unsigned int branch, str* to, unsigned int *len) { char *req_buf, *p, *via; unsigned int via_len; char branch_buf[MAX_BRANCH_PARAM_LEN]; int branch_len; str branch_str; struct hostport hp; struct rte* list; str contact, ruri, *cont; struct socket_info* send_sock; str next_hop; if (rpl->first_line.u.reply.statuscode < 300 ) { /* build e2e ack for 2xx reply -> we need the route set */ if (get_contact_uri(rpl, &contact) < 0) { return 0; } if (process_routeset(rpl, &contact, &list, &ruri, &next_hop) < 0) { return 0; } if ((contact.s != ruri.s) || (contact.len != ruri.len)) { /* contact != ruri means that the next * hop is a strict router, cont will be non-zero * and print_routeset will append it at the end * of the route set */ cont = &contact; } else { /* Next hop is a loose router, nothing to append */ cont = 0; } } else { /* build hop-by-hop ack for negative reply -> * ruri is the same as in INVITE; no route set */ ruri = Trans->uac[branch].uri; cont = 0; list = 0; } /* method, separators, version: "ACK sip:[email protected] SIP/2.0" */ *len = SIP_VERSION_LEN + ACK_LEN + 2 /* spaces */ + CRLF_LEN; *len += ruri.len; /* use same socket as for INVITE -bogdan */ send_sock = Trans->uac[branch].request.dst.send_sock; if (!t_calc_branch(Trans, branch, branch_buf, &branch_len)) goto error; branch_str.s = branch_buf; branch_str.len = branch_len; set_hostport(&hp, 0); /* build via */ via = via_builder(&via_len, send_sock, &branch_str, 0, send_sock->proto, &hp); if (!via) { LM_ERR("no via header got from builder\n"); goto error; } *len+= via_len; /*headers*/ *len += Trans->from.len + Trans->callid.len + to->len + Trans->cseq_n.len + 1 + ACK_LEN + CRLF_LEN; /* copy'n'paste Route headers */ *len += calc_routeset_len(list, cont); /* User Agent */ if (server_signature) *len += user_agent_header.len + CRLF_LEN; /* Content Length, EoM */ *len += CONTENT_LENGTH_LEN + 1 + CRLF_LEN + CRLF_LEN; req_buf = shm_malloc(*len + 1); if (!req_buf) { LM_ERR("no more share memory\n"); goto error01; } p = req_buf; append_string( p, ACK " ", ACK_LEN+1 ); append_string(p, ruri.s, ruri.len ); append_string( p, " " SIP_VERSION CRLF, 1 + SIP_VERSION_LEN + CRLF_LEN); /* insert our via */ append_string(p, via, via_len); /*other headers*/ append_string(p, Trans->from.s, Trans->from.len); append_string(p, Trans->callid.s, Trans->callid.len); append_string(p, to->s, to->len); append_string(p, Trans->cseq_n.s, Trans->cseq_n.len); *(p++) = ' '; append_string(p, ACK CRLF, ACK_LEN+CRLF_LEN); /* Routeset */ p = print_rs(p, list, cont); /* User Agent header, Content Length, EoM */ if (server_signature) { append_string(p, user_agent_header.s, user_agent_header.len); append_string(p, CRLF CONTENT_LENGTH "0" CRLF CRLF, CRLF_LEN+CONTENT_LENGTH_LEN + 1 + CRLF_LEN + CRLF_LEN); } else { append_string(p, CONTENT_LENGTH "0" CRLF CRLF, CONTENT_LENGTH_LEN + 1 + CRLF_LEN + CRLF_LEN); } *p = 0; pkg_free(via); free_rte_list(list); return req_buf; error01: pkg_free(via); error: free_rte_list(list); return 0; }
/** * build CANCEL from UAC side */ char *build_uac_cancel(str *headers,str *body,struct cell *cancelledT, unsigned int branch, unsigned int *len, struct dest_info* dst) { char *cancel_buf, *p; char branch_buf[MAX_BRANCH_PARAM_LEN]; str branch_str; struct hostport hp; str content_length, via; LM_DBG("sing FROM=<%.*s>, TO=<%.*s>, CSEQ_N=<%.*s>\n", cancelledT->from.len, cancelledT->from.s, cancelledT->to.len, cancelledT->to.s, cancelledT->cseq_n.len, cancelledT->cseq_n.s); branch_str.s=branch_buf; if (!t_calc_branch(cancelledT, branch, branch_str.s, &branch_str.len )){ LM_ERR("failed to create branch !\n"); goto error; } set_hostport(&hp,0); if (assemble_via(&via, cancelledT, dst, branch) < 0) { LM_ERR("Error while assembling Via\n"); return 0; } /* method, separators, version */ *len=CANCEL_LEN + 2 /* spaces */ +SIP_VERSION_LEN + CRLF_LEN; *len+=cancelledT->uac[branch].uri.len; /*via*/ *len+= via.len; /*From*/ *len+=cancelledT->from.len; /*To*/ *len+=cancelledT->to.len; /*CallId*/ *len+=cancelledT->callid.len; /*CSeq*/ *len+=cancelledT->cseq_n.len+1+CANCEL_LEN+CRLF_LEN; /* User Agent */ if (server_signature) { *len += USER_AGENT_LEN + CRLF_LEN; } /* Content Length */ if (print_content_length(&content_length, body) < 0) { LM_ERR("failed to print content-length\n"); return 0; } /* Content-Length */ *len += (body ? (CONTENT_LENGTH_LEN + content_length.len + CRLF_LEN) : 0); /*Additional headers*/ *len += (headers ? headers->len : 0); /*EoM*/ *len+= CRLF_LEN; /* Message body */ *len += (body ? body->len : 0); cancel_buf=shm_malloc( *len+1 ); if (!cancel_buf) { LM_ERR("no more share memory\n"); goto error01; } p = cancel_buf; memapp( p, CANCEL, CANCEL_LEN ); *(p++) = ' '; memapp( p, cancelledT->uac[branch].uri.s, cancelledT->uac[branch].uri.len); memapp( p, " " SIP_VERSION CRLF, 1+SIP_VERSION_LEN+CRLF_LEN ); /* insert our via */ memapp(p,via.s,via.len); /*other headers*/ memapp( p, cancelledT->from.s, cancelledT->from.len ); memapp( p, cancelledT->callid.s, cancelledT->callid.len ); memapp( p, cancelledT->to.s, cancelledT->to.len ); memapp( p, cancelledT->cseq_n.s, cancelledT->cseq_n.len ); *(p++) = ' '; memapp( p, CANCEL, CANCEL_LEN ); memapp( p, CRLF, CRLF_LEN ); /* User Agent header */ if (server_signature) { memapp(p,USER_AGENT CRLF, USER_AGENT_LEN+CRLF_LEN ); } /* Content Length*/ if (body) { memapp(p, CONTENT_LENGTH, CONTENT_LENGTH_LEN); memapp(p, content_length.s, content_length.len); memapp(p, CRLF, CRLF_LEN); } if(headers && headers->len){ memapp(p,headers->s,headers->len); } /*EoM*/ memapp(p,CRLF,CRLF_LEN); if(body && body->len){ memapp(p,body->s,body->len); } *p=0; pkg_free(via.s); return cancel_buf; error01: pkg_free(via.s); error: return NULL; }
/* Build a local request based on a previous request; main * customers of this function are local ACK and local CANCEL */ char *build_local(struct cell *Trans,unsigned int branch, unsigned int *len, char *method, int method_len, str *to #ifdef CANCEL_REASON_SUPPORT , struct cancel_reason* reason #endif /* CANCEL_REASON_SUPPORT */ ) { char *cancel_buf, *p, *via; unsigned int via_len; struct hdr_field *hdr; char branch_buf[MAX_BRANCH_PARAM_LEN]; int branch_len; str branch_str; str via_id; struct hostport hp; #ifdef CANCEL_REASON_SUPPORT int reason_len, code_len; struct hdr_field *reas1, *reas_last; #endif /* CANCEL_REASON_SUPPORT */ /* init */ via_id.s=0; via_id.len=0; /* method, separators, version: "CANCEL sip:[email protected] SIP/2.0" */ *len=SIP_VERSION_LEN + method_len + 2 /* spaces */ + CRLF_LEN; *len+=Trans->uac[branch].uri.len; /*via*/ if (!t_calc_branch(Trans, branch, branch_buf, &branch_len )) goto error; branch_str.s=branch_buf; branch_str.len=branch_len; set_hostport(&hp, (is_local(Trans))?0:(Trans->uas.request)); #ifdef USE_TCP if (!is_local(Trans) && ((Trans->uas.request->rcv.proto==PROTO_TCP) #ifdef USE_TLS || (Trans->uas.request->rcv.proto==PROTO_TLS) #endif /* USE_TLS */ )){ if ((via_id.s=id_builder(Trans->uas.request, (unsigned int*)&via_id.len))==0){ LM_ERR("id builder failed\n"); /* try to continue without id */ } } #endif /* USE_TCP */ via=via_builder(&via_len, NULL, &Trans->uac[branch].request.dst, &branch_str, via_id.s?&via_id:0 , &hp ); /* via_id.s not needed anylonger => free it */ if (via_id.s) { pkg_free(via_id.s); via_id.s=0; via_id.len=0; } if (!via) { LM_ERR("no via header got from builder\n"); goto error; } *len+= via_len; /*headers*/ *len+=Trans->from.len+Trans->callid.len+to->len+ +Trans->cseq_n.len+1+method_len+CRLF_LEN+MAXFWD_HEADER_LEN; /* copy'n'paste Route headers */ if (!is_local(Trans)) { for ( hdr=Trans->uas.request->headers ; hdr ; hdr=hdr->next ) if (hdr->type==HDR_ROUTE_T) *len+=hdr->len; } /* User Agent */ if (server_signature) { *len += user_agent_hdr.len + CRLF_LEN; } /* Content Length, EoM */ *len+=CONTENT_LENGTH_LEN+1 + CRLF_LEN; #ifdef CANCEL_REASON_SUPPORT reason_len = 0; reas1 = 0; reas_last = 0; /* compute reason size (if no reason or disabled => reason_len == 0)*/ if (reason && reason->cause != CANCEL_REAS_UNKNOWN){ if (likely(reason->cause > 0 && cfg_get(tm, tm_cfg, local_cancel_reason))){ /* Reason: SIP;cause=<reason->cause>[;text=<reason->u.text.s>] */ reason_len = REASON_PREFIX_LEN + USHORT2SBUF_MAX_LEN + (reason->u.text.s? REASON_TEXT_LEN + 1 + reason->u.text.len + 1 : 0) + CRLF_LEN; } else if (likely(reason->cause == CANCEL_REAS_PACKED_HDRS && !(Trans->flags & T_NO_E2E_CANCEL_REASON))) { reason_len = reason->u.packed_hdrs.len; } else if (reason->cause == CANCEL_REAS_RCVD_CANCEL && reason->u.e2e_cancel && !(Trans->flags & T_NO_E2E_CANCEL_REASON)) { /* parse the entire cancel, to get all the Reason headers */ if(parse_headers(reason->u.e2e_cancel, HDR_EOH_F, 0)<0) { LM_WARN("failed to parse headers\n"); } for(hdr=get_hdr(reason->u.e2e_cancel, HDR_REASON_T), reas1=hdr; hdr; hdr=next_sibling_hdr(hdr)) { /* hdr->len includes CRLF */ reason_len += hdr->len; reas_last=hdr; } } else if (unlikely(reason->cause < CANCEL_REAS_MIN)) LM_BUG("unhandled reason cause %d\n", reason->cause); } *len+= reason_len; #endif /* CANCEL_REASON_SUPPORT */ *len+= CRLF_LEN; /* end of msg. */ cancel_buf=shm_malloc( *len+1 ); if (!cancel_buf) { LM_ERR("cannot allocate memory\n"); goto error01; } p = cancel_buf; append_str( p, method, method_len ); append_str( p, " ", 1 ); append_str( p, Trans->uac[branch].uri.s, Trans->uac[branch].uri.len); append_str( p, " " SIP_VERSION CRLF, 1+SIP_VERSION_LEN+CRLF_LEN ); /* insert our via */ append_str(p,via,via_len); /*other headers*/ append_str( p, Trans->from.s, Trans->from.len ); append_str( p, Trans->callid.s, Trans->callid.len ); append_str( p, to->s, to->len ); append_str( p, Trans->cseq_n.s, Trans->cseq_n.len ); append_str( p, " ", 1 ); append_str( p, method, method_len ); append_str( p, CRLF, CRLF_LEN ); append_str( p, MAXFWD_HEADER, MAXFWD_HEADER_LEN ); if (!is_local(Trans)) { for ( hdr=Trans->uas.request->headers ; hdr ; hdr=hdr->next ) if(hdr->type==HDR_ROUTE_T) { append_str(p, hdr->name.s, hdr->len ); } } /* User Agent header */ if (server_signature) { append_str(p, user_agent_hdr.s, user_agent_hdr.len ); append_str(p, CRLF, CRLF_LEN ); } /* Content Length */ append_str(p, CONTENT_LENGTH "0" CRLF, CONTENT_LENGTH_LEN + 1 + CRLF_LEN); #ifdef CANCEL_REASON_SUPPORT /* add reason if needed */ if (reason_len) { if (likely(reason->cause > 0)) { append_str(p, REASON_PREFIX, REASON_PREFIX_LEN); code_len=ushort2sbuf(reason->cause, p, *len-(int)(p-cancel_buf)); if (unlikely(code_len==0)) LM_BUG("not enough space to write reason code"); p+=code_len; if (reason->u.text.s){ append_str(p, REASON_TEXT, REASON_TEXT_LEN); *p='"'; p++; append_str(p, reason->u.text.s, reason->u.text.len); *p='"'; p++; } append_str(p, CRLF, CRLF_LEN); } else if (likely(reason->cause == CANCEL_REAS_PACKED_HDRS)) { append_str(p, reason->u.packed_hdrs.s, reason->u.packed_hdrs.len); } else if (reason->cause == CANCEL_REAS_RCVD_CANCEL) { for(hdr=reas1; hdr; hdr=next_sibling_hdr(hdr)) { /* hdr->len includes CRLF */ append_str(p, hdr->name.s, hdr->len); if (likely(hdr==reas_last)) break; } } } #endif /* CANCEL_REASON_SUPPORT */ append_str(p, CRLF, CRLF_LEN); /* msg. end */ *p=0; pkg_free(via); return cancel_buf; error01: pkg_free(via); error: return NULL; }
/* Build a local request based on a previous request; the only customers of this function are local ACK and local CANCEL */ char *build_local(struct cell *Trans,unsigned int branch, str *method, str *extra, struct sip_msg* rpl, unsigned int *len) { char *cancel_buf, *p, *via; unsigned int via_len; struct hdr_field *buf_hdrs; struct hdr_field *hdr; struct sip_msg *req; char branch_buf[MAX_BRANCH_PARAM_LEN]; str branch_str; struct hostport hp; str from; str to; str cseq_n; req = Trans->uas.request; cseq_n = Trans->cseq_n; buf_hdrs = 0; if (rpl && rpl!=FAKED_REPLY) { /* take from and to hdrs from reply */ to.s = rpl->to->name.s; to.len = rpl->to->len; from.s = rpl->from->name.s; from.len = rpl->from->len; } else { to = Trans->to; from = Trans->from; if (req && req->msg_flags&(FL_USE_UAC_FROM|FL_USE_UAC_TO)) { if ( extract_ftc_hdrs( Trans->uac[branch].request.buffer.s, Trans->uac[branch].request.buffer.len, (req->msg_flags&FL_USE_UAC_FROM)?&from:0 , (req->msg_flags&FL_USE_UAC_TO)?&to:0 , 0 )!=0 ) { LM_ERR("build_local: failed to extract UAC hdrs\n"); goto error; } } } LM_DBG("using FROM=<%.*s>, TO=<%.*s>, CSEQ_N=<%.*s>\n", from.len,from.s , to.len,to.s , cseq_n.len,cseq_n.s); /* method, separators, version */ *len=SIP_VERSION_LEN + method->len + 2 /* spaces */ + CRLF_LEN; *len+=Trans->uac[branch].uri.len; /*via*/ branch_str.s=branch_buf; if (!t_calc_branch(Trans, branch, branch_str.s, &branch_str.len )) goto error; set_hostport(&hp, (is_local(Trans))?0:req); via=via_builder(&via_len, Trans->uac[branch].request.dst.send_sock, &branch_str, 0, Trans->uac[branch].request.dst.proto, &hp ); if (!via){ LM_ERR("no via header got from builder\n"); goto error; } *len+= via_len; /*headers*/ *len+=from.len+Trans->callid.len+to.len+cseq_n.len+1+method->len+CRLF_LEN; /* copy'n'paste Route headers that were sent out */ if (!is_local(Trans) && ( (req && req->route) || /* at least one route was received*/ (Trans->uac[branch].path_vec.len!=0)) ) /* path was forced */ { buf_hdrs = extract_parsed_hdrs(Trans->uac[branch].request.buffer.s, Trans->uac[branch].request.buffer.len ); if (buf_hdrs==NULL) { LM_ERR("failed to reparse the request buffer\n"); goto error01; } for ( hdr=buf_hdrs ; hdr ; hdr=hdr->next ) if (hdr->type==HDR_ROUTE_T) *len+=hdr->len; } /* User Agent */ if (server_signature) { *len += user_agent_header.len + CRLF_LEN; } /* Content Length, MaxFwd, EoM */ *len+=LOCAL_MAXFWD_HEADER_LEN + CONTENT_LENGTH_LEN+1 + (extra?extra->len:0) + (Trans->extra_hdrs.s?Trans->extra_hdrs.len:0) + CRLF_LEN + CRLF_LEN; cancel_buf=shm_malloc( *len+1 ); if (!cancel_buf) { LM_ERR("no more share memory\n"); goto error02; } p = cancel_buf; append_string( p, method->s, method->len ); *(p++) = ' '; append_string( p, Trans->uac[branch].uri.s, Trans->uac[branch].uri.len); append_string( p, " " SIP_VERSION CRLF, 1+SIP_VERSION_LEN+CRLF_LEN ); /* insert our via */ append_string(p,via,via_len); /*other headers*/ append_string( p, from.s, from.len ); append_string( p, Trans->callid.s, Trans->callid.len ); append_string( p, to.s, to.len ); append_string( p, cseq_n.s, cseq_n.len ); *(p++) = ' '; append_string( p, method->s, method->len ); append_string( p, CRLF LOCAL_MAXFWD_HEADER, CRLF_LEN+LOCAL_MAXFWD_HEADER_LEN ); /* add Route hdrs (if any) */ for ( hdr=buf_hdrs ; hdr ; hdr=hdr->next ) if(hdr->type==HDR_ROUTE_T) { append_string(p, hdr->name.s, hdr->len ); } if (extra) append_string(p, extra->s, extra->len ); if (Trans->extra_hdrs.s) append_string(p, Trans->extra_hdrs.s, Trans->extra_hdrs.len ); /* User Agent header, Content Length, EoM */ if (server_signature) { append_string(p, user_agent_header.s, user_agent_header.len); append_string(p, CRLF CONTENT_LENGTH "0" CRLF CRLF , CRLF_LEN+CONTENT_LENGTH_LEN+1 + CRLF_LEN + CRLF_LEN); } else { append_string(p, CONTENT_LENGTH "0" CRLF CRLF , CONTENT_LENGTH_LEN+1 + CRLF_LEN + CRLF_LEN); } *p=0; pkg_free(via); free_hdr_field_lst(buf_hdrs); return cancel_buf; error02: free_hdr_field_lst(buf_hdrs); error01: pkg_free(via); error: return NULL; }