Beispiel #1
0
static int
viachan_trigger(kobj_t obj, void *data, int go)
{
	struct via_chinfo *ch = data;
	struct via_info *via = ch->parent;
	struct via_dma_op *ado;
	bus_addr_t sgd_addr = ch->sgd_addr;

	if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
		return 0;

	ado = ch->sgd_table;
	DEB(kprintf("ado located at va=%p pa=%x\n", ado, sgd_addr));

	snd_mtxlock(via->lock);
	if (go == PCMTRIG_START) {
		via_buildsgdt(ch);
		via_wr(via, ch->base, sgd_addr, 4);
		via_wr(via, ch->ctrl, VIA_RPCTRL_START, 1);
	} else
		via_wr(via, ch->ctrl, VIA_RPCTRL_TERMINATE, 1);
	snd_mtxunlock(via->lock);

	DEB(kprintf("viachan_trigger: go=%d\n", go));
	return 0;
}
static int
via8233chan_trigger(kobj_t obj, void* data, int go)
{
	struct via_chinfo *ch = data;
	struct via_info *via = ch->parent;

	snd_mtxlock(via->lock);
	switch(go) {
	case PCMTRIG_START:
		via_buildsgdt(ch);
		via8233chan_mute(via, ch, 0);
		via_wr(via, ch->rbase + VIA_RP_TABLE_PTR, ch->sgd_addr, 4);
		via_wr(via, ch->rbase + VIA_RP_CONTROL,
		       SGD_CONTROL_START | SGD_CONTROL_AUTOSTART |
		       SGD_CONTROL_I_EOL | SGD_CONTROL_I_FLAG, 1);
		break;
	case PCMTRIG_STOP:
	case PCMTRIG_ABORT:
		via_wr(via, ch->rbase + VIA_RP_CONTROL, SGD_CONTROL_STOP, 1);
		via8233chan_mute(via, ch, 1);
		via8233chan_reset(via, ch);
		break;
	}
	snd_mtxunlock(via->lock);
	return 0;
}
static void
via8233chan_reset(struct via_info *via, struct via_chinfo *ch)
{
	via_wr(via, ch->rbase + VIA_RP_CONTROL, SGD_CONTROL_STOP, 1);
	via_wr(via, ch->rbase + VIA_RP_CONTROL, 0x00, 1);
	via_wr(via, ch->rbase + VIA_RP_STATUS, 
	       SGD_STATUS_EOL | SGD_STATUS_FLAG, 1);
}
static void
via_intr(void *p)
{
	struct via_info *via = p;
	int i, reg, stat;

	/* Poll playback channels */
	snd_mtxlock(via->lock);
	for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++) {
		if (via->pch[i].channel == NULL)
			continue;
		reg = via->pch[i].rbase + VIA_RP_STATUS;
		stat = via_rd(via, reg, 1);
		if (stat & SGD_STATUS_INTR) {
			if (via->dma_eol_wake && ((stat & SGD_STATUS_EOL) ||
					!(stat & SGD_STATUS_ACTIVE))) {
				via_wr(via,
					via->pch[i].rbase + VIA_RP_CONTROL,
					SGD_CONTROL_START |
					SGD_CONTROL_AUTOSTART |
					SGD_CONTROL_I_EOL |
					SGD_CONTROL_I_FLAG, 1);
			}
			via_wr(via, reg, stat, 1);
			snd_mtxunlock(via->lock);
			chn_intr(via->pch[i].channel);
			snd_mtxlock(via->lock);
		}
	}

	/* Poll record channels */
	for (i = 0; i < NWRCHANS; i++) {
		if (via->rch[i].channel == NULL)
			continue;
		reg = via->rch[i].rbase + VIA_RP_STATUS;
		stat = via_rd(via, reg, 1);
		if (stat & SGD_STATUS_INTR) {
			if (via->dma_eol_wake && ((stat & SGD_STATUS_EOL) ||
					!(stat & SGD_STATUS_ACTIVE))) {
				via_wr(via,
					via->rch[i].rbase + VIA_RP_CONTROL,
					SGD_CONTROL_START |
					SGD_CONTROL_AUTOSTART |
					SGD_CONTROL_I_EOL |
					SGD_CONTROL_I_FLAG, 1);
			}
			via_wr(via, reg, stat, 1);
			snd_mtxunlock(via->lock);
			chn_intr(via->rch[i].channel);
			snd_mtxlock(via->lock);
		}
	}
	snd_mtxunlock(via->lock);
}
static void
via8233chan_mute(struct via_info *via, struct via_chinfo *ch, int muted)
{
	if (BASE_IS_VIA_DXS_REG(ch->rbase)) {
		int r;
		muted = (muted) ? VIA8233_DXS_MUTE : 0;
		via_wr(via, ch->rbase + VIA8233_RP_DXS_LVOL, muted, 1);
		via_wr(via, ch->rbase + VIA8233_RP_DXS_RVOL, muted, 1);
		r = via_rd(via, ch->rbase + VIA8233_RP_DXS_LVOL, 1) & VIA8233_DXS_MUTE;
		if (r != muted) {
			kprintf("via: failed to set dxs volume "
			       "(dxs base 0x%02x).\n", ch->rbase);
		}
	}
}
static void*
via8233wr_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
	       struct pcm_channel *c, int dir)
{
	struct via_info *via = devinfo;
	struct via_chinfo *ch = &via->rch[c->num];

	ch->parent = via;
	ch->channel = c;
	ch->buffer = b;
	ch->dir = dir;

	ch->rbase = VIA_WR_BASE(c->num);
	snd_mtxlock(via->lock);
	via_wr(via, ch->rbase + VIA_WR_RP_SGD_FORMAT, WR_FIFO_ENABLE, 1);
	snd_mtxunlock(via->lock);

	if (sndbuf_alloc(ch->buffer, via->parent_dmat, via->bufsz) != 0)
		return NULL;

	snd_mtxlock(via->lock);
	via8233chan_sgdinit(via, ch, c->num);
	via8233chan_reset(via, ch);
	snd_mtxunlock(via->lock);

	return ch;
}
Beispiel #7
0
static int
via_write_codec(kobj_t obj, void *addr, int reg, u_int32_t val)
{
	struct via_info *via = addr;

	if (via_waitready_codec(via)) return -1;

	via_wr(via, VIA_CODEC_CTL, VIA_CODEC_PRIVALID | VIA_CODEC_INDEX(reg) | val, 4);

	return 0;
}
static int
via_write_codec(kobj_t obj, void *addr, int reg, u_int32_t val)
{
	struct via_info *via = addr;

	if (via_waitready_codec(via)) return -1;

	via_wr(via, VIA_AC97_CONTROL, 
	       VIA_AC97_CODEC00_VALID | VIA_AC97_INDEX(reg) |
	       VIA_AC97_DATA(val), 4);

	return 0;
}
Beispiel #9
0
static void
via_intr(void *p)
{
	struct via_info *via = p;

	/* DEB(kprintf("viachan_intr\n")); */
	/* Read channel */
	snd_mtxlock(via->lock);
	if (via_rd(via, VIA_PLAY_STAT, 1) & VIA_RPSTAT_INTR) {
		via_wr(via, VIA_PLAY_STAT, VIA_RPSTAT_INTR, 1);
		snd_mtxunlock(via->lock);
		chn_intr(via->pch.channel);
		snd_mtxlock(via->lock);
	}

	/* Write channel */
	if (via_rd(via, VIA_RECORD_STAT, 1) & VIA_RPSTAT_INTR) {
		via_wr(via, VIA_RECORD_STAT, VIA_RPSTAT_INTR, 1);
		snd_mtxunlock(via->lock);
		chn_intr(via->rch.channel);
		return;
	}
	snd_mtxunlock(via->lock);
}
static int
via8233msgd_setformat(kobj_t obj, void *data, u_int32_t format)
{
	struct via_chinfo *ch = data;
	struct via_info *via = ch->parent;

	u_int32_t s = 0xff000000;
	u_int8_t  v = (format & AFMT_S16_LE) ? MC_SGD_16BIT : MC_SGD_8BIT;

	if (format & AFMT_STEREO) {
		v |= MC_SGD_CHANNELS(2);
		s |= SLOT3(1) | SLOT4(2);
	} else {
		v |= MC_SGD_CHANNELS(1);
		s |= SLOT3(1) | SLOT4(1);
	}

	snd_mtxlock(via->lock);
	via_wr(via, VIA_MC_SLOT_SELECT, s, 4);
	via_wr(via, VIA_MC_SGD_FORMAT, v, 1);
	snd_mtxunlock(via->lock);

	return 0;
}
Beispiel #11
0
static int
via_read_codec(kobj_t obj, void *addr, int reg)
{
	struct via_info *via = addr;

	if (via_waitready_codec(via))
		return -1;

	via_wr(via, VIA_CODEC_CTL, VIA_CODEC_PRIVALID | VIA_CODEC_READ | VIA_CODEC_INDEX(reg),4);

	if (via_waitready_codec(via))
		return -1;

	if (via_waitvalid_codec(via))
		return -1;

	return via_rd(via, VIA_CODEC_CTL, 2);
}
static int
via8233wr_setformat(kobj_t obj, void *data, u_int32_t format)
{
	struct via_chinfo *ch = data;
	struct via_info *via = ch->parent;

	u_int32_t f = WR_FORMAT_STOP_INDEX;

	if (format & AFMT_STEREO)
		f |= WR_FORMAT_STEREO;
	if (format & AFMT_S16_LE)
		f |= WR_FORMAT_16BIT;
	snd_mtxlock(via->lock);
	via_wr(via, VIA_WR0_FORMAT, f, 4);
	snd_mtxunlock(via->lock);

	return 0;
}
static int
via8233dxs_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
	struct via_chinfo *ch = data;
	struct via_info *via = ch->parent;
	u_int32_t r, v;

	r = ch->rbase + VIA8233_RP_DXS_RATEFMT;
	snd_mtxlock(via->lock);
	v = via_rd(via, r, 4) & ~VIA8233_DXS_RATEFMT_48K;

	/* Careful to avoid overflow (divide by 48 per vt8233c docs) */

	v |= VIA8233_DXS_RATEFMT_48K * (speed / 48) / (48000 / 48);
	via_wr(via, r, v, 4);
	snd_mtxunlock(via->lock);

	return speed;
}
static int
via8233dxs_setformat(kobj_t obj, void *data, u_int32_t format)
{
	struct via_chinfo *ch = data;
	struct via_info *via = ch->parent;
	u_int32_t r, v;

	r = ch->rbase + VIA8233_RP_DXS_RATEFMT;
	snd_mtxlock(via->lock);
	v = via_rd(via, r, 4);

	v &= ~(VIA8233_DXS_RATEFMT_STEREO | VIA8233_DXS_RATEFMT_16BIT);
	if (format & AFMT_STEREO)
		v |= VIA8233_DXS_RATEFMT_STEREO;
	if (format & AFMT_16BIT)  
		v |= VIA8233_DXS_RATEFMT_16BIT;
	via_wr(via, r, v, 4);
	snd_mtxunlock(via->lock);

	return 0;
}
Beispiel #15
0
static int
viachan_setformat(kobj_t obj, void *data, u_int32_t format)
{
	struct via_chinfo *ch = data;
	struct via_info *via = ch->parent;
	int mode, mode_set;

	mode_set = 0;
	if (format & AFMT_STEREO)
		mode_set |= VIA_RPMODE_STEREO;
	if (format & AFMT_S16_LE)
		mode_set |= VIA_RPMODE_16BIT;

	DEB(kprintf("set format: dir = %d, format=%x\n", ch->dir, format));
	snd_mtxlock(via->lock);
	mode = via_rd(via, ch->mode, 1);
	mode &= ~(VIA_RPMODE_16BIT | VIA_RPMODE_STEREO);
	mode |= mode_set;
	via_wr(via, ch->mode, mode, 1);
	snd_mtxunlock(via->lock);

	return 0;
}
void trans_layer::send_200_ack(sip_msg* reply, sip_trans* t)
{
    // Set request URI
    // TODO: use correct R-URI instead of just 'Contact'
    if(!get_contact(reply)) {
	DBG("Sorry, reply has no Contact header: could not send ACK\n");
	return;
    }
    
    sip_nameaddr na;
    const char* c = get_contact(reply)->value.s;
    if(parse_nameaddr(&na,&c,get_contact(reply)->value.len) < 0){
	DBG("Sorry, reply's Contact parsing failed: could not send ACK\n");
	return;
    }
    
    cstring r_uri = na.addr;
    list<sip_header*> route_hdrs;

    if(t && !t->msg->route.empty()){
	for(list<sip_header*>::iterator it = t->msg->route.begin();
	    it != t->msg->route.end(); ++it) {
	    
	    route_hdrs.push_back(new sip_header(0,"Route",(*it)->value));
	}
    }
    else {
	for(list<sip_header*>::reverse_iterator it = reply->record_route.rbegin();
	    it != reply->record_route.rend(); ++it) {
	    
	    route_hdrs.push_back(new sip_header(0,"Route",(*it)->value));
	}
    }

    sockaddr_storage remote_ip;
    set_next_hop(route_hdrs,r_uri,&remote_ip);

    int request_len = request_line_len(cstring("ACK",3),r_uri);
   
    char branch_buf[BRANCH_BUF_LEN];
    compute_branch(branch_buf,reply->callid->value,reply->cseq->value);
    cstring branch(branch_buf,BRANCH_BUF_LEN);

    sip_header* max_forward = new sip_header(0,cstring("Max-Forwards"),cstring("10"));

    cstring via((char*)transport->get_local_ip()); 

    request_len += via_len(via,branch);

    request_len += copy_hdrs_len(route_hdrs);

    request_len += copy_hdr_len(reply->to);
    request_len += copy_hdr_len(reply->from);
    request_len += copy_hdr_len(reply->callid);
    request_len += copy_hdr_len(max_forward);
    request_len += cseq_len(get_cseq(reply)->num_str,cstring("ACK",3));
    request_len += 2/* CRLF end-of-headers*/;

    // Allocate new message
    char* ack_buf = new char[request_len];

    // generate it
    char* msg = ack_buf;

    request_line_wr(&msg,cstring("ACK",3),r_uri);
    via_wr(&msg,via,branch);

    copy_hdrs_wr(&msg,route_hdrs);
    // clear route headers list
    for (list<sip_header*>::iterator it=route_hdrs.begin(); 
	 it!= route_hdrs.end(); it++)
	delete *it;
    
    copy_hdr_wr(&msg,reply->from);
    copy_hdr_wr(&msg,reply->to);
    copy_hdr_wr(&msg,reply->callid);
    copy_hdr_wr(&msg,max_forward);
    delete max_forward;
    cseq_wr(&msg,get_cseq(reply)->num_str,cstring("ACK",3));

    *msg++ = CR;
    *msg++ = LF;

    DBG("About to send 200 ACK\n");
    //    DBG("About to send 200 ACK: \n<%.*s>\n",request_len,ack_buf);

    assert(transport);
    int send_err = transport->send(&remote_ip,ack_buf,request_len);
    if(send_err < 0){
	ERROR("Error from transport layer\n");
	delete [] ack_buf;
    }
    else if(t){
	delete [] t->retr_buf;
	t->retr_buf = ack_buf;
	t->retr_len = request_len;
	memcpy(&t->retr_addr,&remote_ip,sizeof(sockaddr_storage));
    }
}
Beispiel #17
0
static int
via_attach(device_t dev)
{
	struct via_info *via = 0;
	char status[SND_STATUSLEN];
	u_int32_t data, cnt;

	via = kmalloc(sizeof *via, M_DEVBUF, M_WAITOK | M_ZERO);
	via->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc");

	/* Get resources */
	data = pci_read_config(dev, PCIR_COMMAND, 2);
	data |= (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN);
	pci_write_config(dev, PCIR_COMMAND, data, 2);
	data = pci_read_config(dev, PCIR_COMMAND, 2);

	/* Wake up and reset AC97 if necessary */
	data = pci_read_config(dev, VIA_AC97STATUS, 1);

	if ((data & VIA_AC97STATUS_RDY) == 0) {
		/* Cold reset per ac97r2.3 spec (page 95) */
		pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN, 1);			/* Assert low */
		DELAY(100);									/* Wait T_rst_low */
		pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN | VIA_ACLINK_NRST, 1);	/* Assert high */
		DELAY(5);									/* Wait T_rst2clk */
		pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN, 1);			/* Assert low */
	} else {
		/* Warm reset */
		pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN, 1);			/* Force no sync */
		DELAY(100);
		pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN | VIA_ACLINK_SYNC, 1);	/* Sync */
		DELAY(5);									/* Wait T_sync_high */
		pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN, 1);			/* Force no sync */
		DELAY(5);									/* Wait T_sync2clk */
	}

	/* Power everything up */
	pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_DESIRED, 1);	

	/* Wait for codec to become ready (largest reported delay here 310ms) */
	for (cnt = 0; cnt < 2000; cnt++) {
		data = pci_read_config(dev, VIA_AC97STATUS, 1);
		if (data & VIA_AC97STATUS_RDY) 
			break;
		DELAY(5000);
	}

	via->regid = PCIR_BAR(0);
	via->reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
		&via->regid, RF_ACTIVE);
	if (!via->reg) {
		device_printf(dev, "cannot allocate bus resource.");
		goto bad;
	}
	via->st = rman_get_bustag(via->reg);
	via->sh = rman_get_bushandle(via->reg);

	via->bufsz = pcm_getbuffersize(dev, 4096, VIA_DEFAULT_BUFSZ, 65536);

	via->irqid = 0;
	via->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &via->irqid,
		RF_ACTIVE | RF_SHAREABLE);
	if (!via->irq || snd_setup_intr(dev, via->irq, INTR_MPSAFE, via_intr, via, &via->ih)) {
		device_printf(dev, "unable to map interrupt\n");
		goto bad;
	}

	via_wr(via, VIA_PLAY_MODE, VIA_RPMODE_AUTOSTART | VIA_RPMODE_INTR_FLAG | VIA_RPMODE_INTR_EOL, 1);
	via_wr(via, VIA_RECORD_MODE, VIA_RPMODE_AUTOSTART | VIA_RPMODE_INTR_FLAG | VIA_RPMODE_INTR_EOL, 1);

	via->codec = AC97_CREATE(dev, via, via_ac97);
	if (!via->codec)
		goto bad;

	if (mixer_init(dev, ac97_getmixerclass(), via->codec))
		goto bad;

	via->codec_caps = ac97_getextcaps(via->codec);
	ac97_setextmode(via->codec, 
			via->codec_caps & (AC97_EXTCAP_VRA | AC97_EXTCAP_VRM));

	/* DMA tag for buffers */
	if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
		/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
		/*highaddr*/BUS_SPACE_MAXADDR,
		/*filter*/NULL, /*filterarg*/NULL,
		/*maxsize*/via->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
		/*flags*/0,
		&via->parent_dmat) != 0) {
		device_printf(dev, "unable to create dma tag\n");
		goto bad;
	}

	/*
	 *  DMA tag for SGD table.  The 686 uses scatter/gather DMA and
	 *  requires a list in memory of work to do.  We need only 16 bytes
	 *  for this list, and it is wasteful to allocate 16K.
	 */
	if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
		/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
		/*highaddr*/BUS_SPACE_MAXADDR,
		/*filter*/NULL, /*filterarg*/NULL,
		/*maxsize*/NSEGS * sizeof(struct via_dma_op),
		/*nsegments*/1, /*maxsegz*/0x3ffff,
		/*flags*/0,
		&via->sgd_dmat) != 0) {
		device_printf(dev, "unable to create dma tag\n");
		goto bad;
	}

	if (bus_dmamem_alloc(via->sgd_dmat, (void **)&via->sgd_table,
	    BUS_DMA_NOWAIT, &via->sgd_dmamap) != 0)
		goto bad;
	if (bus_dmamap_load(via->sgd_dmat, via->sgd_dmamap, via->sgd_table,
	    NSEGS * sizeof(struct via_dma_op), dma_cb, via, 0) != 0)
		goto bad;

	ksnprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s",
		 rman_get_start(via->reg), rman_get_start(via->irq),
		 PCM_KLDSTRING(snd_via82c686));

	/* Register */
	if (pcm_register(dev, via, 1, 1)) goto bad;
	pcm_addchan(dev, PCMDIR_PLAY, &viachan_class, via);
	pcm_addchan(dev, PCMDIR_REC, &viachan_class, via);
	pcm_setstatus(dev, status);
	return 0;
bad:
	if (via->codec) ac97_destroy(via->codec);
	if (via->reg) bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg);
	if (via->ih) bus_teardown_intr(dev, via->irq, via->ih);
	if (via->irq) bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq);
	if (via->parent_dmat) bus_dma_tag_destroy(via->parent_dmat);
	if (via->sgd_dmamap) bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap);
	if (via->sgd_table) bus_dmamem_free(via->sgd_dmat, via->sgd_table, via->sgd_dmamap);
	if (via->sgd_dmat) bus_dma_tag_destroy(via->sgd_dmat);
	if (via->lock) snd_mtxfree(via->lock);
	if (via) kfree(via, M_DEVBUF);
	return ENXIO;
}
int trans_layer::send_request(sip_msg* msg, char* tid, unsigned int& tid_len)
{
    // Request-URI
    // To
    // From
    // Call-ID
    // CSeq
    // Max-Forwards
    // Via
    // Contact
    // Supported / Require
    // Content-Length / Content-Type
    
    assert(transport);

    tid_len = 0;

    if(set_next_hop(msg->route,msg->u.request->ruri_str,
		    &msg->remote_ip) < 0){
	// TODO: error handling
	DBG("set_next_hop failed\n");
	//delete msg;
	return -1;
    }

    // assume that msg->route headers are not in msg->hdrs
    msg->hdrs.insert(msg->hdrs.begin(),msg->route.begin(),msg->route.end());

    int request_len = request_line_len(msg->u.request->method_str,
				       msg->u.request->ruri_str);

    char branch_buf[BRANCH_BUF_LEN];
    compute_branch(branch_buf,msg->callid->value,msg->cseq->value);
    cstring branch(branch_buf,BRANCH_BUF_LEN);
    
    string via(transport->get_local_ip());
    if(transport->get_local_port() != 5060)
	via += ":" + int2str(transport->get_local_port());

    request_len += via_len(stl2cstr(via),branch);

    request_len += copy_hdrs_len(msg->hdrs);

    string content_len = int2str(msg->body.len);

    request_len += content_length_len(stl2cstr(content_len));
    request_len += 2/* CRLF end-of-headers*/;

    if(msg->body.len){
	request_len += msg->body.len;
    }

    // Allocate new message
    sip_msg* p_msg = new sip_msg();
    p_msg->buf = new char[request_len];
    p_msg->len = request_len;

    // generate it
    char* c = p_msg->buf;
    request_line_wr(&c,msg->u.request->method_str,
		    msg->u.request->ruri_str);

    via_wr(&c,stl2cstr(via),branch);
    copy_hdrs_wr(&c,msg->hdrs);

    content_length_wr(&c,stl2cstr(content_len));

    *c++ = CR;
    *c++ = LF;

    if(msg->body.len){
	memcpy(c,msg->body.s,msg->body.len);

	// Not needed by now as the message is finished
	//c += body.len;
    }

    // and parse it
    if(parse_sip_msg(p_msg)){
	ERROR("Parser failed on generated request\n");
	ERROR("Message was: <%.*s>\n",p_msg->len,p_msg->buf);
	delete p_msg;
	return MALFORMED_SIP_MSG;
    }

    memcpy(&p_msg->remote_ip,&msg->remote_ip,sizeof(sockaddr_storage));

    DBG("Sending to %s:%i <%.*s>\n",
	get_addr_str(((sockaddr_in*)&p_msg->remote_ip)->sin_addr).c_str(),
	ntohs(((sockaddr_in*)&p_msg->remote_ip)->sin_port),
	p_msg->len,p_msg->buf);

    trans_bucket* bucket = get_trans_bucket(p_msg->callid->value,
					    get_cseq(p_msg)->num_str);
    bucket->lock();

    int send_err = transport->send(&p_msg->remote_ip,p_msg->buf,p_msg->len);
    if(send_err < 0){
	ERROR("Error from transport layer\n");
	delete p_msg;
    }
    else {

	sip_trans* t = bucket->add_trans(p_msg,TT_UAC);
	if(p_msg->u.request->method == sip_request::INVITE){
	    
	    // if transport == UDP
	    t->reset_timer(STIMER_A,A_TIMER,bucket->get_id());
	    // for any transport type
	    t->reset_timer(STIMER_B,B_TIMER,bucket->get_id());
	}
	else {
	    
	    // if transport == UDP
	    t->reset_timer(STIMER_E,E_TIMER,bucket->get_id());
	    // for any transport type
	    t->reset_timer(STIMER_F,F_TIMER,bucket->get_id());

	}

	string t_id = int2hex(bucket->get_id()).substr(5,string::npos) 
	    + ":" + long2hex((unsigned long)t);
	memcpy(tid,t_id.c_str(),t_id.length());
	tid_len = t_id.length();
    }

    bucket->unlock();
    
    return send_err;
}