home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 5 / DATAFILE_PDCD5.iso / internet / netlite2 / NET / c / TCPUSER < prev    next >
Encoding:
Text File  |  1993-03-17  |  8.7 KB  |  293 lines

  1. /* User calls to TCP */
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <stdarg.h>
  6. #include "global.h"
  7. #include "timer.h"
  8. #include "mbuf.h"
  9. #include "netuser.h"
  10. #include "internet.h"
  11. #include "tcp.h"
  12.  
  13. int16 tcp_window = DEF_WND;
  14.  
  15. struct tcb *open_tcp(struct socket *lsocket, struct socket *fsocket,
  16.                      int mode, int16 window, void (*r_upcall)(),
  17.                      void (*t_upcall)(), void (*s_upcall)(),
  18.                      char tos, char *user)
  19. {
  20.         struct connection conn;
  21.         register struct tcb *tcb;
  22.  
  23.         if(lsocket == NULLSOCK){
  24.                 net_error = INVALID;
  25.                 return NULLTCB;
  26.         }
  27.         conn.local.address = lsocket->address;
  28.         conn.local.port = lsocket->port;
  29.         if(fsocket != NULLSOCK){
  30.                 conn.remote.address = fsocket->address;
  31.                 conn.remote.port = fsocket->port;
  32.         } else {
  33.                 conn.remote.address = 0;
  34.                 conn.remote.port = 0;
  35.         }
  36.         if((tcb = lookup_tcb(&conn)) == NULLTCB){
  37.                 if((tcb = create_tcb(&conn)) == NULLTCB){
  38.                         net_error = NO_SPACE;
  39.                         return NULLTCB;
  40.                 }
  41.         } else if(tcb->state != LISTEN){
  42.                 net_error = CON_EXISTS;
  43.                 return NULLTCB;
  44.         }
  45.         tcb->user = user;
  46.         if(window != 0)
  47.                 tcb->window = tcb->rcv.wnd = window;
  48.         else
  49.                 tcb->window = tcb->rcv.wnd = tcp_window;
  50.         tcb->r_upcall = r_upcall;
  51.         tcb->t_upcall = t_upcall;
  52.         tcb->s_upcall = s_upcall;
  53.         tcb->tos = tos;
  54.         switch(mode){
  55.         case TCP_SERVER:
  56.                 tcb->flags |= CLONE;
  57.         case TCP_PASSIVE:       /* Note fall-thru */
  58.                 setstate(tcb,LISTEN);
  59.                 break;
  60.         case TCP_ACTIVE:
  61.                 /* Send SYN, go into SYN_SENT state */
  62.                 tcb->flags |= ACTIVE;
  63.                 send_syn(tcb);
  64.                 setstate(tcb,SYN_SENT);
  65.                 tcp_output(tcb);
  66.                 tcp_stat.conout++;
  67.                 break;
  68.         }
  69.         return tcb;
  70. }
  71. /* User send routine */
  72. int send_tcp(register struct tcb *tcb, struct mbuf *bp)
  73. {
  74.         int16 cnt;
  75.  
  76.         if(tcb == NULLTCB || bp == NULLBUF){
  77.                 free_p(bp);
  78.                 net_error = INVALID;
  79.                 return -1;
  80.         }
  81.         cnt = len_mbuf(bp);
  82. #ifdef  TIGHT
  83.         /* If this would overfill our send queue, reject it entirely */
  84.         if(tcb->sndcnt + cnt > tcb->window){
  85.                 free_p(bp);
  86.                 net_error = WOULDBLK;
  87.                 return -1;
  88.         }
  89. #endif
  90.         switch(tcb->state){
  91.         case CLOSED:
  92.                 free_p(bp);
  93.                 net_error = NO_CONN;
  94.                 return -1;
  95.         case LISTEN:    /* Change state from passive to active */
  96.                 tcb->flags |= ACTIVE;
  97.                 send_syn(tcb);
  98.                 setstate(tcb,SYN_SENT); /* Note fall-thru */
  99.         case SYN_SENT:
  100.         case SYN_RECEIVED:
  101.         case ESTABLISHED:
  102.         case CLOSE_WAIT:
  103.                 append(&tcb->sndq,bp);
  104.                 tcb->sndcnt += cnt;
  105.                 tcp_output(tcb);
  106.                 break;
  107.         case FINWAIT1:
  108.         case FINWAIT2:
  109.         case CLOSING:
  110.         case LAST_ACK:
  111.         case TIME_WAIT:
  112.                 free_p(bp);
  113.                 net_error = CON_CLOS;
  114.                 return -1;
  115.         }
  116.         return cnt;
  117. }
  118. /* User receive routine */
  119. int recv_tcp(register struct tcb *tcb, struct mbuf **bp, int16 cnt)
  120. {
  121.         if(tcb == NULLTCB || bp == (struct mbuf **)NULL){
  122.                 net_error = INVALID;
  123.                 return -1;
  124.         }
  125.         /* cnt == 0 means "I want it all" */
  126.         if(cnt == 0)
  127.                 cnt = tcb->rcvcnt;
  128.         /* If there's something on the queue, just return it regardless
  129.          * of the state we're in.
  130.          */
  131.         if(tcb->rcvcnt != 0){
  132.                 /* See if the user can take all of it */
  133.                 if(tcb->rcvcnt <= cnt){
  134.                         cnt = tcb->rcvcnt;
  135.                         *bp = tcb->rcvq;
  136.                         tcb->rcvq = NULLBUF;
  137.                 } else {
  138.                         if((*bp = alloc_mbuf(cnt)) == NULLBUF){
  139.                                 net_error = NO_SPACE;
  140.                                 return -1;
  141.                         }
  142.                         pullup(&tcb->rcvq,(*bp)->data,cnt);
  143.                         (*bp)->cnt = cnt;
  144.                 }
  145.                 tcb->rcvcnt -= cnt;
  146.                 tcb->rcv.wnd += cnt;
  147.                 /* Do a window update if it was closed */
  148.                 if(cnt == tcb->rcv.wnd){
  149.                         tcb->flags |= FORCE;
  150.                         tcp_output(tcb);
  151.                 }
  152.                 return cnt;
  153.         } else {
  154.                 /* If there's nothing on the queue, our action depends on what state
  155.                  * we're in (i.e., whether or not we're expecting any more data).
  156.                  * If no more data is expected, then simply return 0; this is
  157.                  * interpreted as "end of file".
  158.                  */
  159.                 switch(tcb->state){
  160.                 case LISTEN:
  161.                 case SYN_SENT:
  162.                 case SYN_RECEIVED:
  163.                 case ESTABLISHED:
  164.                 case FINWAIT1:
  165.                 case FINWAIT2:
  166.                         *bp = NULLBUF;
  167.                         net_error = WOULDBLK;
  168.                         return -1;
  169.                 case CLOSED:
  170.                 case CLOSE_WAIT:
  171.                 case CLOSING:
  172.                 case LAST_ACK:
  173.                 case TIME_WAIT:
  174.                         *bp = NULLBUF;
  175.                         return 0;
  176.                 }
  177.         }
  178.         return 0;       /* Not reached, but lint doesn't know that */
  179. }
  180. /* This really means "I have no more data to send". It only closes the
  181.  * connection in one direction, and we can continue to receive data
  182.  * indefinitely.
  183.  */
  184. int close_tcp(register struct tcb *tcb)
  185. {
  186.         if(tcb == NULLTCB){
  187.                 net_error = INVALID;
  188.                 return -1;
  189.         }
  190.         switch(tcb->state){
  191.         case CLOSED:
  192.                 return 0;       /* Unlikely */
  193.         case LISTEN:
  194.         case SYN_SENT:
  195.                 close_self(tcb,NORMAL);
  196.                 return 0;
  197.         case SYN_RECEIVED:
  198.         case ESTABLISHED:
  199.                 tcb->sndcnt++;
  200.                 tcb->snd.nxt++;
  201.                 setstate(tcb,FINWAIT1);
  202.                 tcp_output(tcb);
  203.                 return 0;
  204.         case CLOSE_WAIT:
  205.                 tcb->sndcnt++;
  206.                 tcb->snd.nxt++;
  207.                 setstate(tcb,LAST_ACK);
  208.                 tcp_output(tcb);
  209.                 return 0;
  210.         case FINWAIT1:
  211.         case FINWAIT2:
  212.         case CLOSING:
  213.         case LAST_ACK:
  214.         case TIME_WAIT:
  215.                 net_error = CON_CLOS;
  216.                 return -1;
  217.         }
  218.         return -1;      /* "Can't happen" */
  219. }
  220. /* Delete TCB, free resources. The user is not notified, even if the TCB is
  221.  * not in the CLOSED state. This function should normally be called by the
  222.  * user only in response to a state change upcall to CLOSED state.
  223.  */
  224. int del_tcp(register struct tcb *tcb)
  225. {
  226.         struct reseq *rp,*rp1;
  227.  
  228.         if(tcb == NULLTCB){
  229.                 net_error = INVALID;
  230.                 return -1;
  231.         }
  232.         unlink_tcb(tcb);
  233.         stop_timer(&tcb->timer);
  234.         stop_timer(&tcb->rtt_timer);
  235.         for(rp = tcb->reseq;rp != NULLRESEQ;rp = rp1){
  236.                 rp1 = rp->next;
  237.                 free_p(rp->bp);
  238.                 free((char *)rp);
  239.         }
  240.         tcb->reseq = NULLRESEQ;
  241.         free_p(tcb->rcvq);
  242.         free_p(tcb->sndq);
  243.         free((char *)tcb);
  244.         return 0;
  245. }
  246. /* Do printf on a tcp connection */
  247. int tprintf(struct tcb *tcb, char *message, ...)
  248. {
  249.         va_list argptr;
  250.         struct mbuf *bp;
  251.         int len;
  252.  
  253.         if(tcb == NULLTCB)
  254.                 return 0;
  255.  
  256.         if ((bp = alloc_mbuf(160)) == NULLBUF)
  257.                 return 0;
  258.  
  259.         va_start(argptr,message);
  260.         len = vsprintf(bp->data,message,argptr);
  261.         va_end(argptr);
  262.         bp->cnt = strlen(bp->data);
  263.         send_tcp(tcb,bp);
  264.         return len;
  265. }
  266. /* Return 1 if arg is a valid TCB, 0 otherwise */
  267. int tcpval(struct tcb *tcb)
  268. {
  269.         register int i;
  270.         register struct tcb *tcb1;
  271.  
  272.         if(tcb == NULLTCB)
  273.                 return 0;       /* Null pointer can't be valid */
  274.         for(i=0;i<NTCB;i++){
  275.                 for(tcb1=tcbs[i];tcb1 != NULLTCB;tcb1 = tcb1->next){
  276.                         if(tcb1 == tcb)
  277.                                 return 1;
  278.                 }
  279.         }
  280.         return 0;
  281. }
  282. int kick_tcp(register struct tcb *tcb)
  283. {
  284.         if(!tcpval(tcb))
  285.                 return -1;
  286.         tcp_timeout((char *)tcb);
  287.         return 0;
  288. }
  289. void reset_tcp(register struct tcb *tcb)
  290. {
  291.         close_self(tcb,RESET);
  292. }
  293.