Changeset 8f6ef478 in rtems


Ignore:
Timestamp:
Jul 18, 2011, 3:25:33 PM (8 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.11, master
Children:
2682dc9
Parents:
6f7a859
Message:

2011-07-18 Sebastian Huber <sebastian.huber@…>

  • libnetworking/lib/ftpfs.c: Fixed reply parsing.
Location:
cpukit
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • cpukit/ChangeLog

    r6f7a859 r8f6ef478  
     12011-07-18      Sebastian Huber <sebastian.huber@embedded-brains.de>
     2
     3        * libnetworking/lib/ftpfs.c: Fixed reply parsing.
     4
    152011-07-18      Sebastian Huber <sebastian.huber@embedded-brains.de>
    26
  • cpukit/libnetworking/lib/ftpfs.c

    r6f7a859 r8f6ef478  
    8080
    8181  /**
     82   * Current index into the reply buffer.
     83   */
     84  size_t reply_current;
     85
     86  /**
     87   * End index of the reply buffer.
     88   */
     89  size_t reply_end;
     90
     91  /**
     92   * Buffer for relpy data.
     93   */
     94  char reply_buffer [128];
     95
     96  /**
    8297   * End of file flag.
    8398   */
     
    219234  RTEMS_FTPFS_REPLY_START,
    220235  RTEMS_FTPFS_REPLY_SINGLE_LINE,
    221   RTEMS_FTPFS_REPLY_SINGLE_LINE_DONE,
     236  RTEMS_FTPFS_REPLY_DONE,
    222237  RTEMS_FTPFS_REPLY_MULTI_LINE,
    223   RTEMS_FTPFS_REPLY_NEW_LINE,
    224   RTEMS_FTPFS_REPLY_NEW_LINE_START
     238  RTEMS_FTPFS_REPLY_MULTI_LINE_START
    225239} rtems_ftpfs_reply_state;
    226240
     
    236250#define RTEMS_FTPFS_REPLY_SIZE 3
    237251
     252static bool rtems_ftpfs_is_reply_code_valid(unsigned char *reply)
     253{
     254  return isdigit(reply [0]) && isdigit(reply [1]) && isdigit(reply [2]);
     255}
     256
    238257static rtems_ftpfs_reply rtems_ftpfs_get_reply(
    239   int socket,
     258  rtems_ftpfs_entry *e,
    240259  rtems_ftpfs_reply_parser parser,
    241260  void *parser_arg,
     
    244263{
    245264  rtems_ftpfs_reply_state state = RTEMS_FTPFS_REPLY_START;
    246   unsigned char reply_first [RTEMS_FTPFS_REPLY_SIZE] = { 'a', 'a', 'a' };
    247   unsigned char reply_last [RTEMS_FTPFS_REPLY_SIZE] = { 'b', 'b', 'b' };
    248   size_t reply_first_index = 0;
    249   size_t reply_last_index = 0;
    250   char buf [128];
    251 
    252   while (true) {
     265  unsigned char reply_code [RTEMS_FTPFS_REPLY_SIZE] = { 'a', 'a', 'a' };
     266  size_t reply_code_index = 0;
     267
     268  while (state != RTEMS_FTPFS_REPLY_DONE) {
     269    char *buf = NULL;
     270    size_t i = 0;
     271    size_t n = 0;
     272
    253273    /* Receive reply fragment from socket */
    254     ssize_t i = 0;
    255     ssize_t rv = recv(socket, buf, sizeof(buf), 0);
    256 
    257     if (rv <= 0) {
    258       return RTEMS_FTPFS_REPLY_ERROR;
    259     }
    260 
    261     /* Be verbose if necessary */
    262     if (verbose) {
    263       write(STDERR_FILENO, buf, (size_t) rv);
    264     }
     274    if (e->reply_current == e->reply_end) {
     275      ssize_t rv = 0;
     276
     277      e->reply_current = 0;
     278      e->reply_end = 0;
     279
     280      rv = recv(
     281        e->ctrl_socket,
     282        &e->reply_buffer [0],
     283        sizeof(e->reply_buffer),
     284        0
     285      );
     286
     287      if (rv > 0) {
     288        e->reply_end = (size_t) rv;
     289      } else {
     290        return RTEMS_FTPFS_REPLY_ERROR;
     291      }
     292    }
     293
     294    buf = &e->reply_buffer [e->reply_current];
     295    n = e->reply_end - e->reply_current;
    265296
    266297    /* Invoke parser if necessary */
    267298    if (parser != NULL) {
    268       parser(buf, (size_t) rv, parser_arg);
     299      parser(buf, n, parser_arg);
    269300    }
    270301
    271302    /* Parse reply fragment */
    272     for (i = 0; i < rv; ++i) {
     303    for (i = 0; i < n && state != RTEMS_FTPFS_REPLY_DONE; ++i) {
    273304      char c = buf [i];
    274305
    275306      switch (state) {
    276307        case RTEMS_FTPFS_REPLY_START:
    277           if (reply_first_index < RTEMS_FTPFS_REPLY_SIZE) {
    278             reply_first [reply_first_index] = c;
    279             ++reply_first_index;
    280           } else if (c == '-') {
    281             state = RTEMS_FTPFS_REPLY_MULTI_LINE;
     308          if (reply_code_index < RTEMS_FTPFS_REPLY_SIZE) {
     309            reply_code [reply_code_index] = c;
     310            ++reply_code_index;
     311          } else if (rtems_ftpfs_is_reply_code_valid(reply_code)) {
     312            if (c == '-') {
     313              state = RTEMS_FTPFS_REPLY_MULTI_LINE;
     314            } else {
     315              state = RTEMS_FTPFS_REPLY_SINGLE_LINE;
     316            }
    282317          } else {
    283             state = RTEMS_FTPFS_REPLY_SINGLE_LINE;
     318            return RTEMS_FTPFS_REPLY_ERROR;
    284319          }
    285320          break;
    286321        case RTEMS_FTPFS_REPLY_SINGLE_LINE:
    287322          if (c == '\n') {
    288             state = RTEMS_FTPFS_REPLY_SINGLE_LINE_DONE;
     323            state = RTEMS_FTPFS_REPLY_DONE;
    289324          }
    290325          break;
    291326        case RTEMS_FTPFS_REPLY_MULTI_LINE:
    292327          if (c == '\n') {
    293             state = RTEMS_FTPFS_REPLY_NEW_LINE_START;
    294             reply_last_index = 0;
     328            state = RTEMS_FTPFS_REPLY_MULTI_LINE_START;
     329            reply_code_index = 0;
    295330          }
    296331          break;
    297         case RTEMS_FTPFS_REPLY_NEW_LINE:
    298         case RTEMS_FTPFS_REPLY_NEW_LINE_START:
    299           if (reply_last_index < RTEMS_FTPFS_REPLY_SIZE) {
    300             state = RTEMS_FTPFS_REPLY_NEW_LINE;
    301             reply_last [reply_last_index] = c;
    302             ++reply_last_index;
     332        case RTEMS_FTPFS_REPLY_MULTI_LINE_START:
     333          if (reply_code_index < RTEMS_FTPFS_REPLY_SIZE) {
     334            if (reply_code [reply_code_index] == c) {
     335              ++reply_code_index;
     336            } else {
     337              state = RTEMS_FTPFS_REPLY_MULTI_LINE;
     338            }
    303339          } else {
    304             state = RTEMS_FTPFS_REPLY_MULTI_LINE;
     340            if (c == ' ') {
     341              state = RTEMS_FTPFS_REPLY_SINGLE_LINE;
     342            } else {
     343              state = RTEMS_FTPFS_REPLY_MULTI_LINE;
     344            }
    305345          }
    306346          break;
     
    310350    }
    311351
    312     /* Check reply */
    313     if (state == RTEMS_FTPFS_REPLY_SINGLE_LINE_DONE) {
    314       if (
    315         isdigit(reply_first [0])
    316           && isdigit(reply_first [1])
    317           && isdigit(reply_first [2])
    318       ) {
    319         break;
    320       } else {
    321         return RTEMS_FTPFS_REPLY_ERROR;
    322       }
    323     } else if (state == RTEMS_FTPFS_REPLY_NEW_LINE_START) {
    324       bool ok = true;
    325 
    326       for (i = 0; i < RTEMS_FTPFS_REPLY_SIZE; ++i) {
    327         ok = ok
    328           && reply_first [i] == reply_last [i]
    329           && isdigit(reply_first [i]);
    330       }
    331 
    332       if (ok) {
    333         break;
    334       }
    335     }
    336   }
    337 
    338   return reply_first [0];
     352    /* Be verbose if necessary */
     353    if (verbose) {
     354      write(STDERR_FILENO, buf, i);
     355    }
     356
     357    /* Update reply index */
     358    e->reply_current += i;
     359  }
     360
     361  return reply_code [0];
    339362}
    340363
    341364static rtems_ftpfs_reply rtems_ftpfs_send_command_with_parser(
    342   int socket,
     365  rtems_ftpfs_entry *e,
    343366  const char *cmd,
    344367  const char *arg,
     
    365388
    366389    /* Send */
    367     n = send(socket, buf, len, 0);
     390    n = send(e->ctrl_socket, buf, len, 0);
    368391    if (n == (ssize_t) len) {
    369392      if (verbose) {
     
    372395
    373396      /* Reply */
    374       reply = rtems_ftpfs_get_reply(socket, parser, parser_arg, verbose);
     397      reply = rtems_ftpfs_get_reply(e, parser, parser_arg, verbose);
    375398    }
    376399
     
    382405
    383406static rtems_ftpfs_reply rtems_ftpfs_send_command(
    384   int socket,
     407  rtems_ftpfs_entry *e,
    385408  const char *cmd,
    386409  const char *arg,
     
    389412{
    390413  return rtems_ftpfs_send_command_with_parser(
    391     socket,
     414    e,
    392415    cmd,
    393416    arg,
     
    543566          && !error
    544567      ) {
    545         reply = rtems_ftpfs_get_reply(e->ctrl_socket, NULL, NULL, verbose);
     568        reply = rtems_ftpfs_get_reply(e, NULL, NULL, verbose);
    546569        if (reply != RTEMS_FTPFS_REPLY_2) {
    547570          eno = EIO;
     
    552575    /* Close control connection if necessary */
    553576    if (e->ctrl_socket >= 0) {
    554       reply = rtems_ftpfs_send_command(
    555         e->ctrl_socket,
    556         "QUIT",
    557         NULL,
    558         verbose
    559       );
     577      reply = rtems_ftpfs_send_command(e, "QUIT", NULL, verbose);
    560578      if (reply != RTEMS_FTPFS_REPLY_2) {
    561579        eno = EIO;
     
    645663
    646664  /* Now we should get a welcome message from the server */
    647   reply = rtems_ftpfs_get_reply(e->ctrl_socket, NULL, NULL, verbose);
     665  reply = rtems_ftpfs_get_reply(e, NULL, NULL, verbose);
    648666  if (reply != RTEMS_FTPFS_REPLY_2) {
    649667    return ENOENT;
     
    651669
    652670  /* Send USER command */
    653   reply = rtems_ftpfs_send_command(e->ctrl_socket, "USER ", user, verbose);
     671  reply = rtems_ftpfs_send_command(e, "USER ", user, verbose);
    654672  if (reply == RTEMS_FTPFS_REPLY_3) {
    655673    /* Send PASS command */
    656     reply = rtems_ftpfs_send_command(
    657       e->ctrl_socket,
    658       "PASS ",
    659       password,
    660       verbose
    661     );
     674    reply = rtems_ftpfs_send_command(e, "PASS ", password, verbose);
    662675    if (reply != RTEMS_FTPFS_REPLY_2) {
    663676      return EACCES;
     
    670683
    671684  /* Send TYPE command to set binary mode for all data transfers */
    672   reply = rtems_ftpfs_send_command(e->ctrl_socket, "TYPE I", NULL, verbose);
     685  reply = rtems_ftpfs_send_command(e, "TYPE I", NULL, verbose);
    673686  if (reply != RTEMS_FTPFS_REPLY_2) {
    674687    return EIO;
     
    740753    (data_port >> 0) & 0xffUL
    741754  );
    742   reply = rtems_ftpfs_send_command(
    743     e->ctrl_socket,
    744     port_command,
    745     NULL,
    746     verbose
    747   );
     755  reply = rtems_ftpfs_send_command(e, port_command, NULL, verbose);
    748756  if (reply != RTEMS_FTPFS_REPLY_2) {
    749757    eno = ENOTSUP;
     
    759767
    760768  /* Send RETR or STOR command with filename */
    761   reply = rtems_ftpfs_send_command(
    762     e->ctrl_socket,
    763     file_command,
    764     filename,
    765     verbose
    766   );
     769  reply = rtems_ftpfs_send_command(e, file_command, filename, verbose);
    767770  if (reply != RTEMS_FTPFS_REPLY_1) {
    768771    eno = EIO;
     
    889892  /* Send PASV command */
    890893  reply = rtems_ftpfs_send_command_with_parser(
    891     e->ctrl_socket,
     894    e,
    892895    "PASV",
    893896    NULL,
     
    926929
    927930  /* Send RETR or STOR command with filename */
    928   reply = rtems_ftpfs_send_command(
    929     e->ctrl_socket,
    930     file_command,
    931     filename,
    932     verbose
    933   );
     931  reply = rtems_ftpfs_send_command(e, file_command, filename, verbose);
    934932  if (reply != RTEMS_FTPFS_REPLY_1) {
    935933    return EIO;
     
    10071005
    10081006  /* Allocate connection entry */
    1009   e = malloc(sizeof(*e));
     1007  e = calloc(1, sizeof(*e));
    10101008  if (e == NULL) {
    10111009    rtems_set_errno_and_return_minus_one(ENOMEM);
     
    10151013  e->ctrl_socket = -1;
    10161014  e->data_socket = -1;
    1017   e->eof = false;
    10181015
    10191016  /* Save connection state */
     
    10951092      if (rv == 0) {
    10961093        rtems_ftpfs_reply reply =
    1097           rtems_ftpfs_get_reply(e->ctrl_socket, NULL, NULL, verbose);
     1094          rtems_ftpfs_get_reply(e, NULL, NULL, verbose);
    10981095
    10991096        if (reply == RTEMS_FTPFS_REPLY_2) {
Note: See TracChangeset for help on using the changeset viewer.