You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

stream.c 7.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. /*
  2. * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18. /**
  19. * @file
  20. *
  21. * Stream API
  22. */
  23. #include <stdint.h>
  24. #include <string.h>
  25. #include <errno.h>
  26. #include <assert.h>
  27. #include <gpxe/stream.h>
  28. /**
  29. * Associate application with connection
  30. *
  31. * @v app Stream application
  32. * @v conn Stream connection
  33. */
  34. void stream_associate ( struct stream_application *app,
  35. struct stream_connection *conn ) {
  36. DBGC ( app, "Stream %p associating with connection %p\n", app, conn );
  37. assert ( conn->app == NULL );
  38. assert ( app->conn == NULL );
  39. conn->app = app;
  40. app->conn = conn;
  41. }
  42. /**
  43. * Disassociate application from connection
  44. *
  45. * @v app Stream application
  46. * @v conn Stream connection
  47. */
  48. static void stream_disassociate ( struct stream_application *app,
  49. struct stream_connection *conn ) {
  50. DBGC ( app, "Stream %p disassociating from connection %p\n",
  51. app, conn );
  52. assert ( conn->app == app );
  53. assert ( app->conn == conn );
  54. conn->app = NULL;
  55. app->conn = NULL;
  56. }
  57. /**
  58. * Connection established
  59. *
  60. * @v conn Stream connection
  61. */
  62. void stream_connected ( struct stream_connection *conn ) {
  63. struct stream_application *app = conn->app;
  64. DBGC ( app, "Stream %p connected\n", app );
  65. /* Check connection actually exists */
  66. if ( ! app ) {
  67. DBGC ( conn, "Stream connection %p has no application\n",
  68. conn );
  69. return;
  70. }
  71. /* Hand off to application */
  72. if ( app->op->connected )
  73. app->op->connected ( app );
  74. }
  75. /**
  76. * Connection closed
  77. *
  78. * @v conn Stream connection
  79. * @v rc Error code, if any
  80. */
  81. void stream_closed ( struct stream_connection *conn, int rc ) {
  82. struct stream_application *app = conn->app;
  83. /* Check connection actually exists */
  84. if ( ! app ) {
  85. /* Not an error; don't display a debug message */
  86. return;
  87. }
  88. DBGC ( app, "Stream %p closed (%s)\n", app, strerror ( rc ) );
  89. /* Disassociate application from connection */
  90. stream_disassociate ( app, conn );
  91. /* Hand off to application */
  92. if ( app->op->closed )
  93. app->op->closed ( app, rc );
  94. }
  95. /**
  96. * Transmit data
  97. *
  98. * @v conn Stream connection
  99. * @v data Temporary data buffer
  100. * @v len Length of temporary data buffer
  101. */
  102. void stream_senddata ( struct stream_connection *conn,
  103. void *data, size_t len ) {
  104. struct stream_application *app = conn->app;
  105. DBGC2 ( app, "Stream %p sending data\n", app );
  106. /* Check connection actually exists */
  107. if ( ! app ) {
  108. DBGC ( conn, "Stream connection %p has no application\n",
  109. conn );
  110. return;
  111. }
  112. /* Hand off to application */
  113. if ( app->op->senddata )
  114. app->op->senddata ( app, data, len );
  115. }
  116. /**
  117. * Transmitted data acknowledged
  118. *
  119. * @v conn Stream connection
  120. * @v len Length of acknowledged data
  121. *
  122. * @c len must not exceed the outstanding amount of unacknowledged
  123. * data.
  124. */
  125. void stream_acked ( struct stream_connection *conn, size_t len ) {
  126. struct stream_application *app = conn->app;
  127. DBGC2 ( app, "Stream %p had %zd bytes acknowledged\n", app, len );
  128. /* Check connection actually exists */
  129. if ( ! app ) {
  130. DBGC ( conn, "Stream connection %p has no application\n",
  131. conn );
  132. return;
  133. }
  134. /* Ignore zero-length blocks */
  135. if ( len == 0 )
  136. return;
  137. /* Hand off to application */
  138. if ( app->op->acked )
  139. app->op->acked ( app, len );
  140. }
  141. /**
  142. * Receive new data
  143. *
  144. * @v conn Stream connection
  145. * @v data Data
  146. * @v len Length of data
  147. */
  148. void stream_newdata ( struct stream_connection *conn,
  149. void *data, size_t len ) {
  150. struct stream_application *app = conn->app;
  151. DBGC2 ( app, "Stream %p received %zd bytes\n", app, len );
  152. /* Check connection actually exists */
  153. if ( ! app ) {
  154. DBGC ( conn, "Stream connection %p has no application\n",
  155. conn );
  156. return;
  157. }
  158. /* Ignore zero-length blocks */
  159. if ( len == 0 )
  160. return;
  161. /* Hand off to application */
  162. if ( app->op->newdata )
  163. app->op->newdata ( app, data, len );
  164. }
  165. /**
  166. * Bind to local address
  167. *
  168. * @v app Stream application
  169. * @v local Local address
  170. * @ret rc Return status code
  171. */
  172. int stream_bind ( struct stream_application *app, struct sockaddr *local ) {
  173. struct stream_connection *conn = app->conn;
  174. int rc;
  175. DBGC2 ( app, "Stream %p binding\n", app );
  176. /* Check connection actually exists */
  177. if ( ! conn ) {
  178. DBGC ( app, "Stream %p has no connection\n", app );
  179. return -ENOTCONN;
  180. }
  181. /* Hand off to connection */
  182. if ( ! conn->op->bind )
  183. return -ENOTSUP;
  184. if ( ( rc = conn->op->bind ( conn, local ) ) != 0 ) {
  185. DBGC ( app, "Stream %p failed to bind: %s\n",
  186. app, strerror ( rc ) );
  187. return rc;
  188. }
  189. return 0;
  190. }
  191. /**
  192. * Connect to remote address
  193. *
  194. * @v app Stream application
  195. * @v peer Remote address
  196. * @ret rc Return status code
  197. */
  198. int stream_connect ( struct stream_application *app, struct sockaddr *peer ) {
  199. struct stream_connection *conn = app->conn;
  200. int rc;
  201. DBGC2 ( app, "Stream %p connecting\n", app );
  202. /* Check connection actually exists */
  203. if ( ! conn ) {
  204. DBGC ( app, "Stream %p has no connection\n", app );
  205. return -ENOTCONN;
  206. }
  207. /* Hand off to connection */
  208. if ( ! conn->op->connect )
  209. return -ENOTSUP;
  210. if ( ( rc = conn->op->connect ( conn, peer ) ) != 0 ) {
  211. DBGC ( app, "Stream %p failed to connect: %s\n",
  212. app, strerror ( rc ) );
  213. return rc;
  214. }
  215. return 0;
  216. }
  217. /**
  218. * Close connection
  219. *
  220. * @v app Stream application
  221. */
  222. void stream_close ( struct stream_application *app ) {
  223. struct stream_connection *conn = app->conn;
  224. DBGC2 ( app, "Stream %p closing\n", app );
  225. /* Check connection actually exists */
  226. if ( ! conn ) {
  227. /* Not an error; don't display a debug message */
  228. return;
  229. }
  230. /* Disassociate application from connection */
  231. stream_disassociate ( app, conn );
  232. /* Hand off to connection */
  233. if ( ! conn->op->close )
  234. return;
  235. conn->op->close ( conn );
  236. }
  237. /**
  238. * Send data via connection
  239. *
  240. * @v app Stream application
  241. * @v data Data to send
  242. * @v len Length of data
  243. * @ret rc Return status code
  244. *
  245. * This method should be called only in the context of an
  246. * application's senddata() method.
  247. */
  248. int stream_send ( struct stream_application *app,
  249. const void *data, size_t len ) {
  250. struct stream_connection *conn = app->conn;
  251. int rc;
  252. DBGC2 ( app, "Stream %p sending %zd bytes\n", app, len );
  253. /* Check connection actually exists */
  254. if ( ! conn ) {
  255. DBGC ( app, "Stream %p has no connection\n", app );
  256. return -ENOTCONN;
  257. }
  258. /* Ignore zero-length blocks */
  259. if ( len == 0 )
  260. return 0;
  261. /* Hand off to connection */
  262. if ( ! conn->op->send )
  263. return -ENOTSUP;
  264. if ( ( rc = conn->op->send ( conn, data, len ) ) != 0 ) {
  265. DBGC ( app, "Stream %p failed to send %zd bytes: %s\n",
  266. app, len, strerror ( rc ) );
  267. return rc;
  268. }
  269. return 0;
  270. }
  271. /**
  272. * Notify connection that data is available to send
  273. *
  274. * @v app Stream application
  275. * @ret rc Return status code
  276. */
  277. int stream_kick ( struct stream_application *app ) {
  278. struct stream_connection *conn = app->conn;
  279. int rc;
  280. DBGC2 ( app, "Stream %p kicking connection\n", app );
  281. /* Check connection actually exists */
  282. if ( ! conn ) {
  283. DBGC ( app, "Stream %p has no connection\n", app );
  284. return -ENOTCONN;
  285. }
  286. /* Hand off to connection */
  287. if ( ! conn->op->send )
  288. return -ENOTSUP;
  289. if ( ( rc = conn->op->kick ( conn ) ) != 0 ) {
  290. DBGC ( app, "Stream %p failed to kick connection: %s\n",
  291. app, strerror ( rc ) );
  292. return rc;
  293. }
  294. return 0;
  295. }