⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 connection.c

📁 网络端口的服务程序
💻 C
📖 第 1 页 / 共 2 页
字号:
      if (connection->flags & CONNECTION_GOT_COMMAND_START) {
         connection->flags &= ~CONNECTION_GOT_COMMAND_START;
         connection->flags |= CONNECTION_COMMAND_MODE;
         continue;
      }

      /* At this point, the first char in the buffer could be the
         command char, but if it is, it's because it's actually the
         second consecutive one, therefore we should send it through.
         If it's any other char, we'll be sending it through, so we
         start scanning for another command char at the second char. */
      end_of_data = 1;
      while (end_of_data < buf->data_length) {
         if (buf->data[end_of_data] == COMMAND_START) {
            break;
         }
         end_of_data++;
      }

      /* Now, i points to the command char for the next command, or
         just past the end of the data.  Send this much through to 
         the port */

      if (connection->port != NULL) {
         bytes_sent = PortSendData(connection->port, buf->data, end_of_data);
      } else {
         bytes_sent = end_of_data;
      }

      BufferRemove(connection->read_buffer, bytes_sent);

      /* if not all data was sent, then the port output buffer is full, we
         don't want to read any more data until it empties a bit */
      if (bytes_sent != end_of_data) {
         FD_CLR(connection->fd, &read_fds);

         /* Jump out of the loop, leaving data in the buffer.  When select()
            says the port is ready for more data, the PortReady() function
            will call us to deal with any pending data */
         return;
      }
   }

   /* Signal that we're happy to get more data */
   FD_SET(connection->fd, &read_fds);

}

/* This is called when we're in command mode and data is read from the socket. */

static void HandleCommandData(struct Connection *connection)
{
   char *p;
   char *new_buf;
   int i;
   int end_of_command;
   int space_required;

   p = connection->read_buffer->data;
   i = 0;

   end_of_command = FALSE;
   while (i < connection->read_buffer->data_length) {
      if (p[i] == COMMAND_END) {
         end_of_command = TRUE;
         break;
      }
      i++;
   }

   /* At this point, i points to the end-of-command char, or one past the end of data */

   /* First check if we need to expand the command buffer */
   space_required = connection->command_len + i;
   if (space_required > connection->command_buf_size) {

      int new_size;

      new_size = (((space_required / COMMAND_BUFFER_CHUNK_SIZE) + 1) * COMMAND_BUFFER_CHUNK_SIZE);

      new_buf = realloc(connection->command_buf, new_size);
      if (new_buf == NULL) {
         syslog(LOG_ERR, "Cannot extend command buffer for fd=%d"
                         " - dropping data\n", connection->fd);
         BufferRemove(connection->read_buffer, i);
         return;
      }

      connection->command_buf = new_buf;
      connection->command_buf_size = new_size;
   }

   memcpy(connection->command_buf + connection->command_len, p, i);

   connection->command_len += i;

   if (end_of_command) {
      /* Have to remove the end-of-command character */
      BufferRemove(connection->read_buffer, i+1);
      HandleCommand(connection);
   } else {
      BufferRemove(connection->read_buffer, i);
   }

}


STATUS AssignPort(struct Connection *connection, struct Port *port)
{
   STATUS status;

   if (port->connection != NULL) {
      syslog(LOG_ERR, "Connection fd=%d, cannot assign port: port busy",
                          connection->fd);
      return ERR_INUSE;
   }

   status = OpenPort(port);
   if (IS_FAILURE(status)) {
      return status;;
   }

   connection->port = port;
   port->connection = connection;

   return SUCCESS;
}


void DeassignPort(struct Connection *connection)
{
   struct Port *port;

   port = connection->port;

   if (port->connection != connection) {
      syslog(LOG_CRIT, "Warning: port->connection != connection->port!!!");
   }

   ClosePort(port);

   port->connection = NULL;
   connection->port = NULL;
}

int SocketSendData(struct Connection *connection, char *data, int data_len)
{
   int space;
   struct Buffer *buf;
   int bytes_to_move;
   int bytes_moved;
   int data_end;

   if (connection->response_len != 0) {

      /* We have a command response waiting to get through,
         don't send any data... */

      return 0;
   }

   buf = connection->write_buffer;
   space = buf->length - buf->data_length;

   /* Now we have two possibilities - the first char can be a
      RESPONSE_START or any other char */

   if (data[0] != RESPONSE_START) {

      /* Search for a RESPONSE_START and grab everything
         up to that */

      data_end = 0;
      while (data_end < data_len) {
         if (data[data_end] == RESPONSE_START) {
            break;
         }
         data_end++;
      }

      if (space < data_end) {
         bytes_to_move = space;
      } else {
         bytes_to_move = data_end;
      }

      BufferAdd(buf, data, bytes_to_move, &bytes_moved);

   } else {

      /* Do we have enough space in the write buffer for
         two RESPONSE_START chars?  If not, we'll wait until
         we do */
      if (space >= 2) {

         char tmp[2] = { RESPONSE_START, RESPONSE_START };

         BufferAdd(buf, tmp, 2, &bytes_moved);

         /* We say one, because we've only effectively sent
            a single char as far as the port is concerned */
         bytes_moved = 1;

      } else {
         
         bytes_moved = 0;
      }
   }

   /* It would be nice to loop around here and see if we can
      grab more data and stuff it into the write buffer, but
      this way makes the code easier...  Eventually, SocketReady()
      will tell the port to give us more data, and we'll 
      continue then */

   if (buf->data_length > 0) {
      FD_SET(connection->fd, &write_fds);
   } else {
      FD_CLR(connection->fd, &write_fds);
   }

   return bytes_moved;
}

void SocketReady(struct Connection *connection)
{
   struct Buffer *buf;
   int bytes_written;
   

   buf = connection->write_buffer;

   bytes_written = write(connection->fd, buf->data, buf->data_length);
   if (bytes_written == -1) {
      syslog(LOG_ERR, "Connection fd=%d, Cannot write to socket: %m",
                          connection->fd);
   }

   BufferRemove(buf, bytes_written);

   /* Stuff any pending response into the output buffer */
   if (connection->response_len > 0) {
      BufferAdd(buf, connection->response_buf, connection->response_len,
                   &bytes_written);

      memmove(connection->response_buf, 
              connection->response_buf+bytes_written, 
              connection->response_len - bytes_written);

      connection->response_len -= bytes_written;

   }

   /* If we have more data available, signal our interest 
      in writing to the socket */

   if (buf->data_length != 0) {
      FD_SET(connection->fd, &write_fds);
   } else {
      FD_CLR(connection->fd, &write_fds);
   }

   /* If we have no response data left pending and there is space
      in the buffer, notify the port to give us more data, 
      if it has any waiting.  */
   if (connection->response_len == 0) {
      if (buf->data_length < buf->length) {
         if (connection->port != NULL) {
            HandlePortData(connection->port);
         }
      }
   }
}

void SendResponse(struct Connection *connection, char *response)
{
   int resp_len;
   int space_required;
   char *new_buf;

   resp_len = strlen(response);

   space_required = connection->response_len + resp_len;
   if (space_required > connection->response_buf_size) {

      int new_size;

      new_size = (((space_required / RESPONSE_BUFFER_CHUNK_SIZE) + 1) * 
                    RESPONSE_BUFFER_CHUNK_SIZE);

      new_buf = realloc(connection->response_buf, new_size);
      if (new_buf == NULL) {
         syslog(LOG_ERR, "Cannot extend response buffer for fd=%d"
                         " - dropping data\n", connection->fd);
         return;
      }

      connection->response_buf = new_buf;
      connection->response_buf_size = new_size;
   }

   memcpy(connection->response_buf + connection->response_len,
          response, resp_len);

   connection->response_len += resp_len;

   if (connection->response_len > 0) {
      FD_SET(connection->fd, &write_fds);
   } 

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -