/* * 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; }
/* * 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; }
/* * 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; }
/* * 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; }