PageRenderTime 34ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/js/lib/Socket.IO-node/support/expresso/deps/jscoverage/http-connection.c

http://github.com/onedayitwillmake/RealtimeMultiplayerNodeJs
C | 192 lines | 142 code | 26 blank | 24 comment | 36 complexity | c19bd02c9d3efba7f98c41e4c18db48a MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, BSD-3-Clause
  1. /*
  2. http-connection.c - TCP connection between HTTP client and server
  3. Copyright (C) 2008 siliconforks.com
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #include <config.h>
  17. #include "http-server.h"
  18. #include <assert.h>
  19. #include <string.h>
  20. #include "util.h"
  21. #define CONNECTION_BUFFER_CAPACITY 8192
  22. #ifdef _WIN32
  23. #define ERRNO (WSAGetLastError())
  24. #else
  25. #include <errno.h>
  26. #define ERRNO errno
  27. #endif
  28. struct HTTPConnection {
  29. SOCKET s;
  30. uint8_t input_buffer[CONNECTION_BUFFER_CAPACITY];
  31. size_t input_buffer_offset;
  32. size_t input_buffer_length;
  33. uint8_t output_buffer[CONNECTION_BUFFER_CAPACITY];
  34. size_t output_buffer_offset;
  35. size_t output_buffer_length;
  36. };
  37. static HTTPConnection * HTTPConnection_new(SOCKET s) {
  38. HTTPConnection * connection = xmalloc(sizeof(HTTPConnection));
  39. connection->s = s;
  40. connection->input_buffer_offset = 0;
  41. connection->input_buffer_length = 0;
  42. connection->output_buffer_offset = 0;
  43. connection->output_buffer_length = 0;
  44. return connection;
  45. }
  46. HTTPConnection * HTTPConnection_new_client(const char * host, uint16_t port) {
  47. struct in_addr ip_address;
  48. if (! inet_aton(host, &ip_address)) {
  49. /* it's a host name */
  50. if (xgethostbyname(host, &ip_address) != 0) {
  51. return NULL;
  52. }
  53. }
  54. SOCKET s = socket(PF_INET, SOCK_STREAM, 0);
  55. if (s == INVALID_SOCKET) {
  56. return NULL;
  57. }
  58. struct sockaddr_in a;
  59. a.sin_family = AF_INET;
  60. a.sin_port = htons(port);
  61. a.sin_addr = ip_address;
  62. if (connect(s, (struct sockaddr *) &a, sizeof(a)) < 0) {
  63. closesocket(s);
  64. return NULL;
  65. }
  66. return HTTPConnection_new(s);
  67. }
  68. HTTPConnection * HTTPConnection_new_server(SOCKET s) {
  69. return HTTPConnection_new(s);
  70. }
  71. int HTTPConnection_delete(HTTPConnection * connection) {
  72. int result = 0;
  73. if (closesocket(connection->s) == -1) {
  74. result = ERRNO;
  75. assert(result != 0);
  76. }
  77. free(connection);
  78. return result;
  79. }
  80. int HTTPConnection_get_peer(HTTPConnection * connection, struct sockaddr_in * peer) {
  81. int result = 0;
  82. socklen_t length = sizeof(struct sockaddr_in);
  83. if (getpeername(connection->s, (struct sockaddr *) peer, &length) == -1) {
  84. result = ERRNO;
  85. assert(result != 0);
  86. }
  87. return result;
  88. }
  89. int HTTPConnection_read_octet(HTTPConnection * connection, int * octet) {
  90. if (connection->input_buffer_offset >= connection->input_buffer_length) {
  91. ssize_t bytes_received = recv(connection->s, connection->input_buffer, CONNECTION_BUFFER_CAPACITY, 0);
  92. if (bytes_received == -1) {
  93. int result = ERRNO;
  94. assert(result != 0);
  95. return result;
  96. }
  97. else if (bytes_received == 0) {
  98. /* orderly shutdown */
  99. *octet = -1;
  100. return 0;
  101. }
  102. else {
  103. connection->input_buffer_offset = 0;
  104. connection->input_buffer_length = bytes_received;
  105. }
  106. }
  107. *octet = connection->input_buffer[connection->input_buffer_offset];
  108. connection->input_buffer_offset++;
  109. return 0;
  110. }
  111. int HTTPConnection_peek_octet(HTTPConnection * connection, int * octet) {
  112. int result = HTTPConnection_read_octet(connection, octet);
  113. /* check for error */
  114. if (result != 0) {
  115. return result;
  116. }
  117. /* check for end */
  118. if (*octet == -1) {
  119. return 0;
  120. }
  121. /* reset input buffer */
  122. connection->input_buffer_offset--;
  123. return 0;
  124. }
  125. int HTTPConnection_write(HTTPConnection * connection, const void * p, size_t size) {
  126. while (size > 0) {
  127. if (connection->output_buffer_length == CONNECTION_BUFFER_CAPACITY) {
  128. /* buffer full */
  129. ssize_t bytes_sent = send(connection->s, connection->output_buffer, CONNECTION_BUFFER_CAPACITY, 0);
  130. if (bytes_sent == -1) {
  131. int result = ERRNO;
  132. assert(result != 0);
  133. return result;
  134. }
  135. connection->output_buffer_length = 0;
  136. }
  137. size_t buffer_remaining = CONNECTION_BUFFER_CAPACITY - connection->output_buffer_length;
  138. size_t bytes_to_copy;
  139. if (size <= buffer_remaining) {
  140. bytes_to_copy = size;
  141. }
  142. else {
  143. bytes_to_copy = buffer_remaining;
  144. }
  145. memcpy(connection->output_buffer + connection->output_buffer_length, p, bytes_to_copy);
  146. connection->output_buffer_length += bytes_to_copy;
  147. p += bytes_to_copy;
  148. size -= bytes_to_copy;
  149. }
  150. return 0;
  151. }
  152. int HTTPConnection_flush(HTTPConnection * connection) {
  153. if (connection->output_buffer_length > 0) {
  154. ssize_t bytes_sent = send(connection->s, connection->output_buffer, connection->output_buffer_length, 0);
  155. if (bytes_sent == -1) {
  156. int result = ERRNO;
  157. assert(result != 0);
  158. return result;
  159. }
  160. connection->output_buffer_length = 0;
  161. }
  162. return 0;
  163. }