PageRenderTime 59ms CodeModel.GetById 35ms RepoModel.GetById 0ms app.codeStats 0ms

/wifo/owsl/src/protocols/owsl_tcp.c

https://github.com/VoxOx/VoxOx
C | 330 lines | 263 code | 34 blank | 33 comment | 39 complexity | 09b12d11e159979cf64e49edfa36be77 MD5 | raw file
  1. /*
  2. * Open Wengo Socket Library
  3. * Copyright (C) 2007 Wengo
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. */
  19. #include "owsl_base.h"
  20. #include <memory.h>
  21. #define OWSL_TCP_PACKET_AVG_SIZE 1000
  22. #define OWSL_TCP_BUFFER_SIZE 2000
  23. static void
  24. owsl_tcp_system_socket_accept
  25. (
  26. OWSLSocketInfo_TCP * socket
  27. )
  28. {
  29. OWSLConnection connection ;
  30. int written_bytes ;
  31. /* if event is received, then monitoring is enabled */
  32. /* if monitoring is enabled, then queue is not full */
  33. /* if queue is not full, connection can be accepted and pushed */
  34. /* accept incoming connection */
  35. connection.remote_address_length = sizeof (connection.remote_address) ;
  36. connection.system_socket = accept (socket->system_socket, (struct sockaddr *) & connection.remote_address, & connection.remote_address_length) ;
  37. if (owsl_system_socket_is_valid (connection.system_socket))
  38. {
  39. /* push connection in the input queue */
  40. written_bytes = owqueue_write (socket->in_queue, & connection, sizeof (connection), NULL, OWQUEUE_NON_BLOCKING) ;
  41. if (written_bytes == sizeof (connection))
  42. {
  43. /* notify that the socket can accept a new connection */
  44. owsl_notify ((OWSLSocketInfo *) socket, OWSL_EVENT_READ) ;
  45. }
  46. }
  47. return ;
  48. }
  49. static void
  50. owsl_tcp_system_socket_recv
  51. (
  52. OWSLSocketInfo_TCP * socket
  53. )
  54. {
  55. int received_bytes, written_bytes ;
  56. char buffer [OWSL_TCP_BUFFER_SIZE] ;
  57. /* get packet and packet size */
  58. received_bytes = recv (socket->system_socket, buffer, OWSL_TCP_BUFFER_SIZE, MSG_PEEK) ;
  59. if (received_bytes > 0)
  60. {
  61. /* try to push packet in the input queue */
  62. written_bytes = owqueue_write (socket->in_queue, buffer, received_bytes, NULL, OWQUEUE_NON_BLOCKING | OWQUEUE_TRANSACTION_OPEN) ;
  63. if (written_bytes > 0)
  64. {
  65. /* remove packet from system socket buffer */
  66. received_bytes = recv (socket->system_socket, buffer, written_bytes, 0) ;
  67. /* commit or rollback transaction */
  68. owqueue_write_transaction_close (socket->in_queue, received_bytes == written_bytes ? received_bytes : 0) ;
  69. if (received_bytes == written_bytes)
  70. {
  71. /* notify that the socket can be read */
  72. owsl_notify ((OWSLSocketInfo *) socket, OWSL_EVENT_READ) ;
  73. }
  74. }
  75. }
  76. else if (received_bytes == 0)
  77. {
  78. socket->remotely_closed = 1 ;
  79. owsl_monitor_event_remove (socket->system_socket, OWSL_MONITOR_READ) ;
  80. }
  81. return ;
  82. }
  83. static void
  84. owsl_tcp_system_socket_send
  85. (
  86. OWSLSocketInfo_TCP * socket
  87. )
  88. {
  89. int read_bytes, sent_bytes ;
  90. char buffer [OWSL_TCP_BUFFER_SIZE] ;
  91. /* get packet and packet size */
  92. read_bytes = owqueue_read (socket->out_queue, buffer, OWSL_TCP_BUFFER_SIZE, NULL, OWQUEUE_NON_BLOCKING | OWQUEUE_TRANSACTION_OPEN) ;
  93. if (read_bytes > 0)
  94. {
  95. /* send packet */
  96. sent_bytes = send (socket->system_socket, buffer, read_bytes, 0) ;
  97. /* commit or rollback transaction */
  98. owqueue_read_transaction_close (socket->out_queue, sent_bytes > 0 ? sent_bytes : 0) ;
  99. }
  100. return ;
  101. }
  102. static void
  103. owsl_tcp_monitor_callback
  104. (
  105. OWSLSystemSocket system_socket,
  106. OWSLMonitorEvent event,
  107. void * _socket
  108. )
  109. {
  110. OWSLSocketInfo_TCP * socket = _socket ;
  111. if (event & OWSL_MONITOR_ERROR || socket->system_socket != system_socket)
  112. {
  113. owsl_notify ((OWSLSocketInfo *) socket, OWSL_EVENT_ERROR) ;
  114. return ;
  115. }
  116. if (event & OWSL_MONITOR_READ)
  117. {
  118. if (socket->listening > 0)
  119. {
  120. owsl_tcp_system_socket_accept (socket) ;
  121. }
  122. else
  123. {
  124. owsl_tcp_system_socket_recv (socket) ;
  125. }
  126. }
  127. if (event & OWSL_MONITOR_WRITE)
  128. {
  129. if (socket->connected == 0)
  130. {
  131. /* mark socket as connected */
  132. socket->connected = 1 ;
  133. owsl_notify ((OWSLSocketInfo *) socket, OWSL_EVENT_WRITE) ;
  134. }
  135. owsl_tcp_system_socket_send (socket) ;
  136. }
  137. return ;
  138. }
  139. static OWSLSocketInfo *
  140. owsl_tcp_socket
  141. (
  142. OWSLSocketType type
  143. )
  144. {
  145. OWSLSocketInfo * socket ;
  146. OWSLAddressFamily address_family ;
  147. switch (type)
  148. {
  149. case OWSL_TYPE_IPV4_TCP :
  150. {
  151. address_family = OWSL_AF_IPV4 ;
  152. break ;
  153. }
  154. case OWSL_TYPE_IPV6_TCP :
  155. {
  156. address_family = OWSL_AF_IPV6 ;
  157. break ;
  158. }
  159. default :
  160. {
  161. return NULL ;
  162. }
  163. }
  164. socket = owsl_socket_info_new
  165. (
  166. type, /* socket type */
  167. sizeof (OWSLSocketInfo_TCP), /* size of socket structure */
  168. OWSL_TCP_PACKET_AVG_SIZE * OWSL_QUEUE_PACKET_MAX, /* input queue usable size */
  169. OWQUEUE_NO_PACKET, /* input queue mode */
  170. OWSL_QUEUE_PACKET_MAX, /* input queue packet maximum */
  171. 0, /* input queue packet info size */
  172. OWSL_TCP_PACKET_AVG_SIZE * OWSL_QUEUE_PACKET_MAX, /* output queue usable size */
  173. OWQUEUE_NO_PACKET, /* output queue mode */
  174. OWSL_QUEUE_PACKET_MAX, /* output queue packet maximum */
  175. 0 /* output queue packet info size */
  176. ) ;
  177. if (socket != NULL)
  178. {
  179. if (owsl_base_tcp_open ((OWSLSocketInfo_TCP *) socket, address_family, owsl_tcp_monitor_callback))
  180. {
  181. owsl_socket_info_free (socket) ;
  182. return NULL ;
  183. }
  184. }
  185. return socket ;
  186. }
  187. static OWSLSocketInfo *
  188. owsl_tcp_accept
  189. (
  190. OWSLSocketInfo * listen_socket,
  191. struct sockaddr * address,
  192. socklen_t * address_length
  193. )
  194. {
  195. OWSLConnection connection ;
  196. OWSLSocketInfo * socket ;
  197. if (owqueue_read (listen_socket->in_queue, & connection, sizeof (connection), NULL, 0) != sizeof (connection))
  198. {
  199. return NULL ;
  200. }
  201. socket = owsl_socket_info_new
  202. (
  203. listen_socket->type_info->type, /* socket type */
  204. sizeof (OWSLSocketInfo_TCP), /* size of socket structure */
  205. OWSL_TCP_PACKET_AVG_SIZE * OWSL_QUEUE_PACKET_MAX, /* input queue usable size */
  206. OWQUEUE_NO_PACKET, /* input queue mode */
  207. OWSL_QUEUE_PACKET_MAX, /* input queue packet maximum */
  208. 0, /* input queue packet info size */
  209. OWSL_TCP_PACKET_AVG_SIZE * OWSL_QUEUE_PACKET_MAX, /* output queue usable size */
  210. OWQUEUE_NO_PACKET, /* output queue mode */
  211. OWSL_QUEUE_PACKET_MAX, /* output queue packet maximum */
  212. 0 /* output queue packet info size */
  213. ) ;
  214. if (socket != NULL)
  215. {
  216. if (owsl_base_tcp_set ((OWSLSocketInfo_TCP *) socket, & connection, owsl_tcp_monitor_callback))
  217. {
  218. owsl_socket_info_free (socket) ;
  219. return NULL ;
  220. }
  221. OW_MEMCPY (address, address_length, & connection.remote_address, connection.remote_address_length) ;
  222. }
  223. return socket ;
  224. }
  225. static int
  226. owsl_tcp_close
  227. (
  228. OWSLSocketInfo * socket
  229. )
  230. {
  231. int return_code = 0 ;
  232. return_code |= owsl_base_tcp_close ((OWSLSocketInfo_TCP *) socket) ;
  233. return_code |= owsl_socket_info_free (socket) ;
  234. return return_code ;
  235. }
  236. static int
  237. owsl_tcp_connect
  238. (
  239. OWSLSocketInfo * socket,
  240. const struct sockaddr * address,
  241. socklen_t address_length
  242. )
  243. {
  244. OWSLSocketInfo_TCP * socket_tcp = (OWSLSocketInfo_TCP *) socket ;
  245. int return_code = connect (socket_tcp->system_socket, address, address_length) ;
  246. if (return_code == 0 || OW_GET_ERROR == EINPROGRESS || OW_GET_ERROR == EWOULDBLOCK)
  247. {
  248. socket_tcp->remote_address_length = OWSL_ADDRESS_SIZE ;
  249. OW_MEMCPY (& socket_tcp->remote_address, & socket_tcp->remote_address_length, address, address_length) ;
  250. if (return_code == 0)
  251. {
  252. socket->connected = 1 ;
  253. }
  254. else /* OW_GET_ERROR == EINPROGRESS || EWOULDBLOCK */
  255. {
  256. owsl_monitor_event_add (socket_tcp->system_socket, OWSL_MONITOR_WRITE | OWSL_MONITOR_ONCE) ;
  257. OW_SET_ERROR (EINPROGRESS) ;
  258. }
  259. }
  260. return return_code ;
  261. }
  262. int
  263. owsl_tcp_initialize
  264. (void)
  265. {
  266. OWSLSocketTypeInfo type_ipv4 ;
  267. OWSLSocketTypeInfo type_ipv6 ;
  268. type_ipv4.type = OWSL_TYPE_IPV4_TCP ;
  269. type_ipv4.address_family = OWSL_AF_IPV4 ;
  270. type_ipv4.mode = OWSL_MODE_STREAM ;
  271. type_ipv4.ciphering = OWSL_CIPHERING_DISABLED ;
  272. type_ipv4.global_parameter_set = NULL ;
  273. type_ipv4.is_readable = NULL ;
  274. type_ipv4.is_writable = NULL ;
  275. type_ipv4.has_error = NULL ;
  276. type_ipv4.blocking_mode_set = owsl_base_system_socket_blocking_mode_set ;
  277. type_ipv4.parameter_set = NULL ;
  278. type_ipv4.reuse_set = owsl_base_system_socket_reuse_set ;
  279. type_ipv4.remote_address_get = owsl_base_remote_address_get ;
  280. type_ipv4.on_queue_event = owsl_base_in_out_queues_callback_with_monitor ;
  281. type_ipv4.socket = owsl_tcp_socket ;
  282. type_ipv4.accept = owsl_tcp_accept ;
  283. type_ipv4.close = owsl_tcp_close ;
  284. type_ipv4.bind = owsl_base_bind ;
  285. type_ipv4.connect = owsl_tcp_connect ;
  286. type_ipv4.listen = owsl_base_in_queue_listen ;
  287. type_ipv4.send = owsl_base_out_queue_send ;
  288. type_ipv4.recv = owsl_base_in_queue_connected_recv ;
  289. type_ipv4.sendto = owsl_base_out_queue_sendto ;
  290. type_ipv4.recvfrom = owsl_base_in_queue_connected_recvfrom ;
  291. memcpy (& type_ipv6, & type_ipv4, sizeof (OWSLSocketTypeInfo)) ;
  292. type_ipv6.type = OWSL_TYPE_IPV6_TCP ;
  293. type_ipv6.address_family = OWSL_AF_IPV6 ;
  294. return owsl_socket_type_initialize (& type_ipv4)
  295. || owsl_socket_type_initialize (& type_ipv6) ;
  296. }