int tcp_rcv(PACKET pkt) /* NOTE: pkt has nb_prot pointing to IP header */ { struct mbuf * m_in; struct ip * bip; /* IP header, berkeley version */ struct tcphdr * tcpp; unshort len; /* scratch length holder */ /* For TCP, the netport IP layer is modified to set nb_prot to the * start of the IP header (not TCP). We need to do some further * mods which the BSD code expects: */ bip = (struct ip *)pkt->nb_prot; /* get ip header */ len = ntohs(bip->ip_len); /* get length in local endian */ /* verify checksum of received packet */ tcpp = (struct tcphdr *)ip_data(bip); if (tcp_cksum(bip) != tcpp->th_sum) { TCP_MIB_INC(tcpInErrs); /* keep MIB stats */ tcpstat.tcps_rcvbadsum++; /* keep BSD stats */ LOCK_NET_RESOURCE(FREEQ_RESID); pk_free(pkt); /* punt packet */ UNLOCK_NET_RESOURCE(FREEQ_RESID); return ENP_BAD_HEADER; } m_in = m_getnbuf(MT_RXDATA, 0); if (!m_in){ LOCK_NET_RESOURCE(FREEQ_RESID); pk_free(pkt); UNLOCK_NET_RESOURCE(FREEQ_RESID); return ENP_RESOURCE; } IN_PROFILER(PF_TCP, PF_ENTRY); /* measure time in TCP */ /* subtract IP header length from total IP packet length */ len -= ((unshort)(bip->ip_ver_ihl & 0x0f) << 2); bip->ip_len = len; /* put TCP length in struct for TCP code to use */ /* set mbuf to point to start of IP header (not TCP) */ m_in->pkt = pkt; m_in->m_data = pkt->nb_prot; m_in->m_len = pkt->nb_plen; m_in->m_base = pkt->nb_buff; /* ??? */ m_in->m_memsz = pkt->nb_blen; /* ??? */ tcp_input(m_in, pkt->net); IN_PROFILER(PF_TCP, PF_EXIT); /* measure time in TCP */ return 0; }
int t_recv (long s, char * buf, int len, int flag) { #ifdef SOCKDEBUG char logbuf[10]; #endif struct socket * so; int err; int sendlen = len; so = LONG2SO(s); #ifdef SOC_CHECK_ALWAYS SOC_CHECK(so); #endif if ((so->so_state & SO_IO_OK) != SS_ISCONNECTED) { so->so_error = EPIPE; #ifdef SOCKDEBUG sprintf(logbuf, "t_recv: %d", so->so_error); glog_with_type(LOG_TYPE_DEBUG, logbuf, 1); #endif return SOCKET_ERROR; } so->so_error = 0; LOCK_NET_RESOURCE(NET_RESID); IN_PROFILER(PF_TCP, PF_ENTRY); /* measure time in TCP */ INET_TRACE (INETM_IO, ("INET:recv: so %x, len %d\n", so, len)); err = soreceive(so, NULL, buf, &len, flag); IN_PROFILER(PF_TCP, PF_EXIT); /* measure time in TCP */ UNLOCK_NET_RESOURCE(NET_RESID); if(err) { so->so_error = err; #ifdef SOCKDEBUG sprintf(logbuf, "t_recv: %d", so->so_error); glog_with_type(LOG_TYPE_DEBUG, logbuf, 1); #endif return SOCKET_ERROR; } /* return bytes we sent - the amount we wanted to send minus * the amount left in the buffer. */ return (sendlen - len); }
void tk_block () { char msg[255]; task * tk = tk_cur; /* the next task to run */ /* check if the guard word is still intact */ if (*(tk->tk_guard) != GUARDWORD) { sprintf(msg, "tk_block stack: task name = %s", tk->tk_name); panic(msg); return; } #ifdef NPDEBUG if (TDEBUG) dprintf("TASK: Task %s blocking.\n", tk->tk_name); #endif IN_PROFILER(PF_IDLE, PF_ENTRY); /* measure time in the idle loop */ /* find the next ready to run task */ do { tk = tk->tk_next; /* see if a sleeping task is ready to wake */ if (tk->tk_waketick && tk->tk_waketick < cticks) { tk->tk_waketick = 0; /* clear wakeup tick flag */ break; /* go run this task */ } } while ((tk->tk_flags & TF_AWAKE) == 0); IN_PROFILER(PF_IDLE, PF_EXIT); tk->tk_flags &= ~TF_AWAKE; /* clear wake flag before it runs */ tk_switch (tk); /* Run the next task. */ #ifdef NPDEBUG if (TDEBUG) dprintf("TASK: Task %s running\n", tk_cur->tk_name); #endif if (tk_died) { tk_del(tk_died); /* delete dead task */ tk_died = NULL; /* clear pointer/flag */ } }
int t_send(long s, char * buf, int len, int flags) { struct socket * so; int e; /* error holder */ int total_sent = 0; int maxpkt; int sendlen; int sent; so = LONG2SO(s); #ifdef SOC_CHECK_ALWAYS SOC_CHECK(so); #endif if ((so->so_state & SO_IO_OK) != SS_ISCONNECTED) { so->so_error = EPIPE; return SOCKET_ERROR; } so->so_error = 0; /* If this is not a stream socket, assume it is bound and pass to * t_sendto() with a null sockaddr */ if (so->so_type != SOCK_STREAM) return(t_sendto(s, buf, len, flags, NULL, 0)); maxpkt = TCP_MSS; if(so->so_pcb) { struct tcpcb * tp; tp = intotcpcb(so->so_pcb); /* get tcp structure with mss */ if(tp->t_maxseg) /* Make sure it's set */ maxpkt = tp->t_maxseg; } IN_PROFILER(PF_TCP, PF_ENTRY); /* measure time in TCP */ while (len) { if (len > maxpkt) sendlen = maxpkt; /* take biggest block we can */ else sendlen = len; sent = sendlen; LOCK_NET_RESOURCE(NET_RESID); e = sosend (so, NULL, buf, &sendlen, flags); UNLOCK_NET_RESOURCE(NET_RESID); if (e != 0) /* sock_sendit failed? */ { /* if we simply ran out of bufs, report back to caller. */ if ((e == ENOBUFS) || (e == EWOULDBLOCK)) { /* if we actually sent something before running out * of buffers, report what we sent; * else, report the error and let the application * retry the call later */ if (total_sent != 0) { so->so_error = 0; break; /* break out of while(len) loop */ } } so->so_error = e; return SOCKET_ERROR; } /* if we can't send anymore, return now */ if (sendlen != 0) break; /* break out of while(len) loop */ /* adjust numbers & pointers, and go do next send loop */ sent -= sendlen; /* subtract anything that didn't get sent */ buf += sent; len -= sent; total_sent += sent; } IN_PROFILER(PF_TCP, PF_EXIT); /* measure time in TCP */ return total_sent; }
/* FUNCTION: tk_block() * * Block the currently running task and run the next task in the * circular list of tasks that is awake. Before returning, see if any * cleanup has to be done for another task. * * PARAMS: task * pointer to currently executing task or NULL * * RETURN: none */ void tk_block(TASK *tk_old) { TASK *tk, *tk_prev; /* check the stack of the currently executing task for overflow */ if (tk_old != (TASK *)NULL) { /* check if the guard word is still intact */ if (*(tk_cur->tk_guard) != GUARDWORD) { dprintf("tk_block stack: task name = %s", tk_cur->tk_name); dtrap(); return; } } #ifdef NPDEBUG if (TDEBUG) dprintf("TASK: Task %s blocking.\n", tk_cur->tk_name); #endif IN_PROFILER(PF_IDLE, PF_ENTRY); /* measure time in the idle loop */ /* find the next ready to run task */ tk = tk_cur; #ifdef DEBUG_TASK_STATE dprintf("tk_block: %s, flags = %lx, event = %p\n", tk->tk_name, tk->tk_flags, tk->tk_event); #endif do { tk_prev = tk; tk = tk->tk_next; /* TODO: check for deleted task here */ /* see if a sleeping task is ready to wake */ if ((tk->tk_flags & TF_TIMER) && TIME_EXP(tk->tk_waketick, CTICKS)) { tk_timeout(tk); /* clean up after timeout */ } } while (!(tk->tk_flags & TF_AWAKE)); IN_PROFILER(PF_IDLE, PF_EXIT); tk->tk_count++; /* increment wakeup count */ tk_cur = tk; /* update current task pointer */ #ifdef NPDEBUG if (TDEBUG) dprintf("TASK: Task %s running\n", tk->tk_name); #endif #ifdef DEBUG_TASK_STATE dprintf("tk_ready: %s, flags = %lx, event = %p\n", tk->tk_name, tk->tk_flags, tk->tk_event); #endif tk_switch (tk, tk_old); /* Run the next task. */ if (tk_died) { tk_del(tk_died); /* delete dead task */ tk_died = NULL; /* clear pointer/flag */ } }