Beispiel #1
0
/*
 *	Write or sendto a socket. We don't yet handle message addresses
 *	sensible and that needs fixing
 */
arg_t net_write(struct socket * s, uint8_t flag)
{
	usize_t n = 0;
	uint8_t p = 0;
	struct sockdata *sd = s->s_priv;
	irqflags_t irq;
	uint8_t st;


	irq = di();
	while (1) {

		netstat = s->s_num;
		st = status(s);

		if (s->s_state == SS_CLOSED || (s->s_iflag & SI_SHUTW)) {
		        udata.u_error = EPIPE;
			break;
                }

		/* Error or EOF */
		if (st & 0xC0)
			break;

		/* Good status after a write means byte ok */
		n += p;
		if (n == udata.u_count) {
		        irqrestore(irq);
			return n;
                }
		/* Can we send more bytes ? */
		p = 0;

		if (st & 2) {
			/* Count bytes sent. The byte we just loaded isn't
			   sent until we check the status of it and it is
			   clean */
			p = 1;
			netdata = ugetc(udata.u_base++);
			continue;
		}
		s->s_iflag |= SI_THROTTLE;
		if (psleep_flags_io(&s->s_iflag, flag, &n)) {
                        irqrestore(irq);
			return n;
                }
                di();
	}
	/* It broke mummy ! */
        irqrestore(irq);
	if (n) {
	        s->s_error = udata.u_error;
	        udata.u_error = 0;
		return n;
        }
	err_xlate(s);
	if (udata.u_error == EPIPE)
		ssig(udata.u_ptab, SIGPIPE);
	return -1;
}
Beispiel #2
0
/*
 *	A connect has been issued by the user. This message tells the
 *	stack to begin connecting. It should put the socket state into
 *	SS_CONNECTING before returning, or it can error.
 */
int net_connect(struct socket *s)
{
	/* This is in host big endian order already */
	uint8_t *p = &s->s_addr[SADDR_DST].addr;
	uint8_t err;
	irqflags_t irq = di();

	/* Select our socket and reset the address pointer */
	netstat = s->s_num | 0x10;
	/* Write the address */
	netctrl = *p++;
	netctrl = *p++;
	netctrl = *p++;
	netctrl = *p;
	p = &s->s_addr[SADDR_DST].port;
	/* Write the port */
	netctrl = *p++;
	netctrl = *p;
	/* The next status query will trigger the socket set up */
	err = status(s);
	irqrestore(irq);
	if (err & 0x80) {
		/* Error pending */
		err_xlate(s);
		return -1;
	}
	/* It worked. We may have received data or eof events but that
	   is fine, we'll get them again when we ask with data */
	s->s_state = SS_CONNECTING;
	kputs("Connecting\n");
	return 0;
}
Beispiel #3
0
/*
 *	Called from the core network layer when a socket is being
 *	allocated. We can either move the socket to SS_UNCONNECTED,
 *	or error. In our case the daemon will reply with an NE_INIT,
 *	or a state change to set an error.
 *
 *	This call is blocking but the BSD socket API users don't expect
 *	anything to block for long. Blocking here is however needed because
 *	some of the stacks (this one included) are asynchronous to the
 *	OS.
 */
int net_init(struct socket *s)
{
	/* For the moment */
	if (s->s_type != SOCKTYPE_TCP) {
		/* FIXME: EPROTONOSUPPORT ? */
		udata.u_error = EAFNOSUPPORT;
		return -1;
	}
	kprintf("Socket %d\n", s->s_num);
	/* For now keep the LCN matching the socket # */
	if (s->s_num < 16) {
		/* Select our new socket and turn off NDELAY bit flag */
		netstat = s->s_num | 0x20;
		/* Check allowed selection */
		if ((netstat & 0x80) == 0 || netctrl == 0x06) {
			s->s_state = SS_UNCONNECTED;
			return 0;
		}
		status(s);
		err_xlate(s);
		return -1;
	}
	udata.u_error = EBUSY;
	return -1;
}
Beispiel #4
0
/*
 *	Read or recvfrom a socket. We don't yet handle message addresses
 *	sensibly and that needs fixing
 */
arg_t net_read(struct socket *s, uint8_t flag)
{
	usize_t n = 0;
	struct sockdata *sd = s->s_priv;
	irqflags_t irq;
	uint8_t st;
	volatile uint8_t data;


	while (1)  {
		irq = di();

		netstat = s->s_num;
		st = status(s);
		/* Error */
		if (st & 0xC0)
			break;
		if (s->s_state < SS_CONNECTED) {
			irqrestore(irq);
			udata.u_error = EINVAL;
			return -1;
		}
		/* We hit the EOF */
		if (s->s_state > SS_CLOSEWAIT)
			break;
		/* Check our status */
		/* Data ready */
		if (st & 0x01) {
			data = netdata;
			/* Could be an error */
			if (data == 0) {
			        st = status(s);
			        if (st & 0xC0)
        				break;
                        }
			uputc(data, udata.u_base++);
			n++;
			if (n < udata.u_count)
			        continue;
		}
		if (n)
		        break;
		s->s_iflag &= ~SI_DATA;
		if (psleep_flags_io(&s->s_iflag, flag, &n)) {
        		irqrestore(irq);
			return -1;
                }
	}
	if (n)
		return n;
	if (st & 0x80) {
		err_xlate(s);
		return -1;
	}
	return 0;
}