Logo Search packages:      
Sourcecode: freetds version File versions

int tds_read_packet ( TDSSOCKET *  tds  ) 

Read in one 'packet' from the server. This is a wrapped outer packet of the protocol (they bundle resulte packets into chunks and wrap them at what appears to be 512 bytes regardless of how that breaks internal packet up. (tetherow@nol.org)

Returns:
bytes readed or -1 on failure

Definition at line 362 of file read.c.

References tds_client_msg(), and tds_read_packet().

Referenced by tds_get_n(), and tds_read_packet().

{
unsigned char header[8];
int len;
int x = 0, have, need;


      /* Read in the packet header.  We use this to figure out our packet 
       * length */

      /* Cast to int are needed because some compiler seem to convert
       * len to unsigned (as FreeBSD 4.5 one)*/
      if ((len = goodread(tds, header, sizeof(header))) < (int) sizeof(header)) {
            /* GW ADDED */
            if (len < 0) {
                  tds_client_msg(tds->tds_ctx, tds, 20004, 9, 0, 0, "Read from SQL server failed.");
                  tds_close_socket(tds);
                  tds->in_len = 0;
                  tds->in_pos = 0;
                  return -1;
            }
            /* GW ADDED */
            /*  Not sure if this is the best way to do the error 
             *  handling here but this is the way it is currently 
             *  being done. */
            tds->in_len = 0;
            tds->in_pos = 0;
            tds->last_packet = 1;
            if (len == 0) {
                  tds_close_socket(tds);
            }
            return -1;
      }
      tdsdump_log(TDS_DBG_NETWORK, "Received header @ %L\n%D\n", header, sizeof(header));

/* Note:
 * this was done by Gregg, I don't think its the real solution (it breaks
 * under 5.0, but I haven't gotten a result big enough to test this yet.
 */
      if (IS_TDS42(tds)) {
            if (header[0] != 0x04 && header[0] != 0x0f) {
                  tdsdump_log(TDS_DBG_ERROR, "Invalid packet header %d\n", header[0]);
                  /*  Not sure if this is the best way to do the error 
                   *  handling here but this is the way it is currently 
                   *  being done. */
                  tds->in_len = 0;
                  tds->in_pos = 0;
                  tds->last_packet = 1;
                  return (-1);
            }
      }

      /* Convert our packet length from network to host byte order */
      len = ((((unsigned int) header[2]) << 8) | header[3]) - 8;
      need = len;

      /* If this packet size is the largest we have gotten allocate 
       * space for it */
      if (len > tds->in_buf_max) {
unsigned char *p;

            if (!tds->in_buf) {
                  p = (unsigned char *) malloc(len);
            } else {
                  p = (unsigned char *) realloc(tds->in_buf, len);
            }
            if (!p)
                  return -1;  /* FIXME should close socket too */
            tds->in_buf = p;
            /* Set the new maximum packet size */
            tds->in_buf_max = len;
      }

      /* Clean out the in_buf so we don't use old stuff by mistake */
      memset(tds->in_buf, 0, tds->in_buf_max);

      /* Now get exactly how many bytes the server told us to get */
      have = 0;
      while (need > 0) {
            if ((x = goodread(tds, tds->in_buf + have, need)) < 1) {
                  /*  Not sure if this is the best way to do the error 
                   *  handling here but this is the way it is currently 
                   *  being done. */
                  tds->in_len = 0;
                  tds->in_pos = 0;
                  tds->last_packet = 1;
                  if (len == 0) {
                        tds_close_socket(tds);
                  }
                  return (-1);
            }
            have += x;
            need -= x;
      }
      if (x < 1) {
            /*  Not sure if this is the best way to do the error handling 
             *  here but this is the way it is currently being done. */
            tds->in_len = 0;
            tds->in_pos = 0;
            tds->last_packet = 1;
            /* return 0 if header found but no payload */
            return len ? -1 : 0;
      }

      /* Set the last packet flag */
      if (header[1]) {
            tds->last_packet = 1;
      } else {
            tds->last_packet = 0;
      }

      /* Set the length and pos (not sure what pos is used for now */
      tds->in_len = have;
      tds->in_pos = 0;
      tdsdump_log(TDS_DBG_NETWORK, "Received packet @ %L\n%D\n", tds->in_buf, tds->in_len);

      return (tds->in_len);
}


Generated by  Doxygen 1.6.0   Back to index