The recv-dataA() Function
When the reconnect process detects that the client has reestablished a connection, it spawns a process to receive the data from this connection. This new process calls the recv_data() function in Listing One. This function handles reading data from the network connection to the client and places it in an intermediate queue from which the gtelnet application reads. In this way, we have abstracted the underlying network connection uncoupling the state of the TCP connection from the state of the gtelnet daemon. The recv_data() function receives three variables as parameters. It requires the socket that the client is connected with (s_client), a FIFO buffer to write data that is read from the client (recv_data_fd), and the PID of the send data process to notify when the client goes to sleep (send_data_pid). Lines 13 through 15 read data from the client socket, s_client, and write the read data to recv_data_fd, which is the FIFO buffer that the server application reads data from. When the client is asleep and recv_data() is not invoked, the recv_data_fd has no new data placed into it, which appears as an idle connection to the server application. When a control message is detected from the client, we first determine whether or not it is a gtWSLE command, in which case, on line 23 or 42 we notify the send data process that the client has gone to sleep. At this point, the recv_data() function exits and data will not be read from the client until the client transitions back to an awake and operational state.
1. void recv_data(int s_client, int recv_data_fd, pid_t send_data_pid) { 2. struct gserver_msg client_message; 3. char gt_packet[BUF_SIZE]; 4. char * p; 5. int bytes_read = 0; 6. int i = 0; 7. char last = 1; 8. char *iacptr; 9. char tb[1]; 10. int temp_bytes_read = 0; 11. 12. while ((bytes_read = read(s_client, gt_packet, sizeof(gt_packet))) > 0) { 13. iacptr = memchr(gt_packet, 255, bytes_read); 14. if (!iacptr) { 15. write(recv_data_fd, gt_packet, bytes_read); 16. } else if (iacptr && iacptr > gt_packet) { 17. if (iacptr == >_packet[BUF_SIZE - 1]) { 18. write(recv_data_fd, gt_packet, bytes_read - 1); 19. temp_bytes_read = read(s_client, tb, 1); 20. if ((unsigned char)tb[0] == 255) { 21. bytes_read = read(s_client, &client_message, sizeof(client_message)); 22. if (client_message.command == gtWSLE) { 23. (void)kill(send_data_pid, SIGALRM); 24. return; 25. } 26. } else { 27. write(recv_data_fd, tb, temp_bytes_read); 28. } 29. } 30. } else if (iacptr) { 31. if (*((unsigned char *)(iacptr + 1)) == 255) { 32. if ((iacptr + 1 + sizeof(client_message)) <= >_packet[BUF_SIZE - 1]) { 33. p = (char *)&client_message; 34. iacptr+= 2; 35. for (i = 0; i < sizeof(client_message); i++) { 36. *p = *iacptr; 37. p++; 38. iacptr++; 39. } 40. } 41. if (client_message.command == gtWSLE) { 42. (void)kill(send_data_pid, SIGALRM); 43. return; 44. } 45. } 46. } 47. } 48. if (bytes_read < 1) 49. exit(1); 40. return; 41. }