home *** CD-ROM | disk | FTP | other *** search
/ Oracle Video Server 3.0.3.1 / OVS_3031_NT.iso / win32 / sqlnet / net23 / client / sendrecv.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-17  |  11.0 KB  |  459 lines

  1. /*
  2.   $Header: /netrcs/RCS/oracle/network/tns/tnsapi/RCS/sendrecv.c,v 1.3 1995/09/12 22:43:28 yzheng Exp $
  3. */
  4.  
  5. #include "tftpdef.h"
  6. #include <sys/stat.h>
  7. #include <ctype.h>
  8.  
  9. extern FILE *file_open();
  10. extern void file_close();
  11. extern int file_read();
  12. extern int file_write();
  13.  
  14. static void send_ERROR();
  15.  
  16. #ifdef CLIENT
  17.  
  18. /*
  19.  * Send a RRQ or WRQ to the other side. 
  20.  * These two packets are only sent by the client to the server.
  21.  */
  22.  
  23. void send_RQ(opcode, fname, mode)
  24. int opcode;  /* RRQ or WRQ */
  25. char *fname;
  26. int mode;
  27. {
  28.   register int len;
  29.   char *modestr;
  30.  
  31.   DEBUG2("sending RRQ/WRQ for %s, mode =%d", fname, mode);
  32.   
  33.   stshort(opcode, sendbuff);
  34.   strcpy(sendbuff+2, fname);
  35.   len = 2 + strlen(fname) + 1;    /* 1 for null byte at the end of fname */
  36.  
  37.   switch (mode)
  38.   {
  39.   case MODE_ASCII:  modestr="netascii"; break;
  40.   case MODE_BINARY: modestr="octet"; break;
  41.   default: err_dump("unknown mode");
  42.   }
  43.  
  44.   strcpy(sendbuff + len, modestr);
  45.   len +=strlen(modestr) + 1;
  46.  
  47.   sendlen = len;
  48.   net_send(sendbuff, sendlen);
  49.   op_sent = opcode;
  50. }
  51.  
  52. /*
  53.  * Error packet received in response to an RRQ or WRQ.
  54.  * Usually means the file we are asking for on the other system
  55.  * can't be accessed for some reason. We need to print the error
  56.  * message that is returned.
  57.  * called by finite state machine
  58.  */
  59.  
  60. int recv_RQERR(ptr, nbytes)
  61. char *ptr;   /* points just past received opcode */
  62. int nbytes;  /* does not include received opcode */
  63. {
  64.   register int ecode;
  65.  
  66.   ecode  = ldshort(ptr);
  67.   ptr += 2;
  68.   nbytes -= 2;
  69.   ptr[nbytes] = 0;  
  70.  
  71.   DEBUG2("ERROR received, %d bytes, error code %d", nbytes, ecode);
  72.   fflush(stdout);
  73.   fprintf(stderr, "Error# %d: %s\n", ecode, ptr);
  74.   fflush(stderr);
  75.   return(-1);
  76. }
  77.  
  78. /*
  79.  * Send a disconnect to the other side to inform it to disconnect
  80.  */
  81. void send_DISRQ()
  82. {
  83.   stshort(OP_DISCONNECT, sendbuff);
  84.   sendlen = 2;
  85.  
  86.   net_send(sendbuff, sendlen);
  87. }
  88.  
  89. #endif /* CLIENT */
  90.  
  91. /* 
  92.  * Send data to the other side
  93.  * The data must be stored in the "sendbuff" by the caller
  94.  * called by recv_ACK()
  95.  */
  96. void send_DATA(blocknum, nbytes)
  97. int blocknum;
  98. int nbytes;        /* #bytes of actual data to send */
  99. {
  100.   DEBUG2("sending %d bytes of DATA with block# %d", nbytes, blocknum);
  101.  
  102.   stshort(OP_DATA, sendbuff);
  103.   stshort(blocknum, sendbuff+2);
  104.   sendlen = nbytes + 4;
  105.   
  106.   net_send(sendbuff, sendlen);
  107.   op_sent = OP_DATA;
  108.  
  109. }
  110.  
  111. /*
  112.  * Send an acknowledgment packet to the other side
  113.  * called by recv_DATA) and recv_WRQ()
  114.  */
  115. void send_ACK(blocknum)
  116. int blocknum;
  117. {
  118.   DEBUG1("sending ACK for block # %d", blocknum);
  119.  
  120.   stshort(OP_ACK, sendbuff);
  121.   stshort(blocknum, sendbuff+2);
  122.  
  123.   sendlen = 4;
  124.   net_send(sendbuff, sendlen);
  125.   op_sent = OP_ACK;
  126. }
  127.  
  128. /* 
  129.  * Data packet received. Send an acknowledgment.
  130.  * called by finite state machine.
  131.  * This fucntion is called by both client and server
  132.  */
  133. int recv_DATA(ptr, nbytes)
  134. char *ptr;     /* points just past received opcode */
  135. int nbytes;    /* does not include received opcode */
  136. {
  137.   register int recvblknum;
  138.  
  139.   recvblknum = ldshort(ptr);
  140.   ptr += 2;
  141.   nbytes -= 2;
  142.  
  143.   DEBUG2("data received, %d bytes, block# %d", nbytes, recvblknum);
  144.  
  145.   if (nbytes > MAXDATA)
  146.   {
  147.     err_dump("data packet received with length = %d bytes", nbytes);
  148.   }
  149.  
  150.   if (recvblknum == nextblknum)
  151.   {
  152.     /*
  153.      * The data packet is the expected one. Increase our expected-block# for
  154.      * the next packet.
  155.      */
  156.     nextblknum++;
  157.     totnbytes += nbytes;
  158.  
  159.     if (nbytes > 0)
  160.     {
  161.       /*
  162.        * The final data packet can have a data length of zero, so we only
  163.        * write the data to the local file if there is data.
  164.        */
  165.       file_write(localfp, ptr, nbytes, modetype);
  166.     }
  167.  
  168.     send_ACK(recvblknum);
  169. #ifdef SERVER
  170.     /*
  171.      * if the length of the data is between 0-511, this is the last data
  172.      * block. For the server, here is where we have to close the file. 
  173.      * For the client, the "get" command processing will close the file.
  174.      */
  175.     if (nbytes < MAXDATA)
  176.     {
  177.       file_close(localfp);
  178.       op_sent = 0;      /* need to reset it for next operation */
  179.     }
  180. #endif
  181.   }
  182.   else
  183.   {
  184.     /* something is wrong */
  185.     err_dump("data block# and ACK block# mismatch");
  186.   }
  187.  
  188.  
  189.  
  190.   /*
  191.    * If the length of the data is between 0-511, we have just received
  192.    * the final data packet, else there is more to come 
  193.    */
  194.   /* 
  195.    * For server, it has to stay in fsm_loop() to wait for new incoming
  196.    * request, for client, it should exit fsm_loop()
  197.    */
  198. #ifdef SERVER
  199.   return (0);
  200. #else    /* client */
  201.   return( (nbytes == MAXDATA) ? 0 : -1);
  202. #endif
  203. }
  204.  
  205.   
  206. /*
  207.  * ACK packet received. Send some more data.
  208.  * Called by finite state machine. Also called by recv_RRQ() to start 
  209.  * the transmission of a file to the client.
  210.  * This function is called by both the client and the server.
  211.  */
  212. int recv_ACK(ptr, nbytes)
  213. char *ptr;         /* pointer to just past received code */
  214. int nbytes;        /* does not include received opcode */
  215. {
  216.   register int recvblknum;
  217.  
  218.   recvblknum = ldshort(ptr);
  219.   if (nbytes != 2)
  220.     err_dump("ACK packet received with length = %d bytes", nbytes + 2);
  221.  
  222.   DEBUG1("ACK received, block# %d", recvblknum);
  223.   if (recvblknum == nextblknum)
  224.   {
  225.     /*
  226.      * The received acknowledgement is for the expected data packet that
  227.      * we sent.
  228.      * Fill the transmit buffer with the next block of data to send.
  229.      * If there is not more data to send, then we might be finished.
  230.      * Note that we must send a final data packet containing 0-511 
  231.      * bytes of data. If the length of the last packet that we sent
  232.      * was exactly 512 bytes, there we must send a 0-length data packet.
  233.      */
  234.  
  235.     if (( nbytes = file_read(localfp, sendbuff+4, MAXDATA, modetype)) == 0)
  236.     {
  237.       if (lastsend < MAXDATA)
  238.       {
  239. /*
  240.  * This is the last data packet sent on the server side, server needs to 
  241.  * close the file. Server returns 0 so it will loop in fsm_loop() to wait
  242.  * for new incoming request.
  243.  */
  244. #ifdef SERVER
  245.         file_close(localfp);
  246.         op_sent = 0;    /* reset op_sent for server */
  247.         return(0);
  248. #else  /* client */
  249.         return(-1);  /* done */
  250. #endif
  251.       }
  252.     }
  253.     lastsend = nbytes;
  254.     nextblknum++;
  255.     totnbytes +=nbytes;
  256.     send_DATA(nextblknum, nbytes);
  257.     return(0);
  258.   }
  259.   else if (recvblknum == (nextblknum - 1))
  260.   {
  261.     /*
  262.      * We have received a duplicate ACK. This means either
  263.      * (1) the other side never received our last data packet
  264.      * (2) the other side's ACK got delayed somehow.
  265.      *
  266.      * Ignore the ACK, do NOT retransmit the data packet
  267.      * 
  268.      * This should not happen in a reliable transport
  269.      */
  270.     return(0);
  271.   }
  272.   else 
  273.   {
  274.     err_dump("data block # and ACK block # mismatch");
  275.   }
  276. }
  277.  
  278.         
  279.  
  280. #ifdef SERVER
  281.  
  282. /*
  283.  * RRQ received
  284.  */
  285. int recv_RRQ(ptr, nbytes)
  286. char *ptr;
  287. int nbytes;
  288. {
  289.   char ackbuff[2];
  290.   recv_xRQ(OP_RRQ, ptr, nbytes);
  291.  
  292.   /*
  293.    * set things up so we can just call recv_ACK() and pretend we 
  294.    * have received an ACK, so it will send the first data block to 
  295.    * the client.
  296.    */
  297.  
  298.   lastsend = MAXDATA;
  299.   stshort(0, ackbuff);  /* pretend it is an ACK of block #0 */
  300.  
  301.   recv_ACK(ackbuff, 2); /* this sends data block #1 */
  302.   return(0);            /* the state machine takes over from here */
  303.  
  304. }
  305.  
  306. /*
  307.  * WRQ received
  308.  */
  309. int recv_WRQ(ptr, nbytes)
  310. char *ptr;
  311. int nbytes;
  312. {
  313.   recv_xRQ(OP_WRQ, ptr, nbytes);
  314.  
  315.   /* 
  316.    * call send_ACK() to acknowledge block #0, which will cause the client
  317.    * to send data block #1.
  318.    */
  319.   nextblknum = 1;
  320.   send_ACK(0);
  321.   return(0);       /* the state machine takes over from here */
  322. }
  323.  
  324. /*
  325.  * Process the RRQ or WRQ received 
  326.  */
  327. int recv_xRQ(opcode, ptr, nbytes)
  328. int opcode;                 /* RRQ or WRQ */
  329. register char *ptr;         /* points just past received opcode */
  330. int nbytes;                 /* does not include received opcode */
  331. {
  332.   register int i;
  333.   register char *saveptr;
  334.   char filename[MAXFILENAME], dirname[MAXFILENAME], mode[MAXFILENAME];
  335.   struct stat statbuff;
  336.  
  337.   /*
  338.    * Assume the file name and mode are present and null-terminated
  339.    */
  340.   saveptr = ptr;    /* points to the beginning of file name */
  341.   for (i = 0; i < nbytes; i++)
  342.     if (*ptr++ == '\0')
  343.       goto FileOK;
  344.   err_dump("Invalid filename");
  345.  
  346.  FileOK:
  347.   strcpy(filename, saveptr);
  348.   saveptr = ptr;
  349.  
  350.   for ( ; i < nbytes; i++)
  351.     if (*ptr++ == '\0')
  352.       goto ModeOK;
  353.   err_dump("Invalid Mode");
  354.  
  355.  ModeOK:
  356.   strlccpy(mode, saveptr);
  357.  
  358.   if (strcmp(mode, "netascii") == 0)
  359.     modetype = MODE_ASCII;
  360.   else if (strcmp(mode, "octet") == 0)
  361.     modetype = MODE_BINARY;
  362.   else
  363.     send_ERROR(ERR_BADOP, "Mode is not netascii or octet");
  364.  
  365.   /*
  366.    * validate file name. File must have permission to be publicly accessed
  367.    * Filename must have its full pathname specified, i.e., it must begin
  368.    * with a slash
  369.    */
  370.     
  371. #ifndef WIN32
  372.   if (filename[0] != '/')
  373.     send_ERROR(ERR_ACCESS, "filename must begin with a '/'");
  374. #endif
  375.  
  376.   if (opcode == OP_RRQ)
  377.   {
  378.     /*
  379.      * read request - verify that the file exists and it has world
  380.      * read permission
  381.      */
  382.     if (stat(filename, &statbuff) < 0)
  383.       send_ERROR(ERR_ACCESS, sys_err_str());
  384.     if ((statbuff.st_mode & (S_IREAD >> 6)) == 0 )
  385.       send_ERROR(ERR_ACCESS, "File does not allow world read permission");
  386.   }
  387.   else if ( opcode == OP_WRQ)
  388.   {
  389.     /*
  390.      * write request - verify that the directory that the file is being
  391.      * written to has world write permission. 
  392.      */
  393.     char *strrchr();
  394.  
  395.     strcpy(dirname, filename);
  396. #ifdef WIN32
  397.     *(strrchr(dirname, '\\') + 1) = '\0';
  398. #else
  399.     *(strrchr(dirname, '/') + 1) = '\0';
  400. #endif
  401.     if (stat(dirname, &statbuff) < 0)
  402.       send_ERROR(ERR_ACCESS, sys_err_str());
  403.     if((statbuff.st_mode & (S_IWRITE >> 6)) == 0)
  404.       send_ERROR(ERR_ACCESS, "Directory does not have world write permission");
  405.   }
  406.   else
  407.     err_dump("Unknown request mode");
  408. #ifdef WIN32
  409.   if( modetype == MODE_ASCII )
  410.     localfp = file_open(filename, (opcode == OP_RRQ) ? "r" : "w",0);
  411.   else
  412.     localfp = file_open(filename, (opcode == OP_RRQ) ? "rb" : "wb",0);
  413. #else
  414.   localfp = file_open(filename, (opcode == OP_RRQ) ? "r" : "w",0);
  415. #endif
  416.   if (localfp == NULL)
  417.     send_ERROR(ERR_NOFILE, sys_err_str());  
  418. }
  419.  
  420.   
  421. /*
  422.  * Send an error packet.
  423.  */
  424. static void send_ERROR(ecode, string)
  425. int ecode;             /* error code, ERR_XXX from tftpdef.h */
  426. char *string;          /* error message */
  427. {
  428.   DEBUG2("sending ERROR, code = %d, string = %s", ecode, string);
  429.   
  430.   stshort(OP_ERROR, sendbuff);
  431.   stshort(ecode, sendbuff+2);
  432.  
  433.   strcpy(sendbuff+4, string);
  434.   sendlen = 4 + strlen(sendbuff+4) + 1; /* 1 for null-termination */
  435.  
  436.   net_send(sendbuff, sendlen);
  437. }
  438.  
  439.  
  440. /*
  441.  * Copy a string and convert it to lower case
  442.  */
  443. strlccpy(dest, src)
  444. register char *dest, *src;
  445. {
  446.   register char c;
  447.  
  448.   while ( (c = *src++) != '\0')
  449.   {
  450.     if (isupper(c))
  451.       c = tolower(c);
  452.     *dest++ = c;
  453.   }
  454.   *dest = '\0';
  455. }
  456.  
  457. #endif /* SERVER */
  458.     
  459.