您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

hello.c 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #include <stddef.h>
  2. #include <string.h>
  3. #include <vsprintf.h>
  4. #include <assert.h>
  5. #include <gpxe/async.h>
  6. #include <gpxe/hello.h>
  7. /** @file
  8. *
  9. * "Hello world" TCP protocol
  10. *
  11. * This file implements a trivial TCP-based protocol. It connects to
  12. * the server specified in hello_request::server and transmits a
  13. * single message (hello_request::message). Any data received from
  14. * the server will be passed to the callback function,
  15. * hello_request::callback(), and once the connection has been closed,
  16. * the asynchronous operation associated with the request will be
  17. * marked as complete.
  18. *
  19. * To use this code, do something like:
  20. *
  21. * @code
  22. *
  23. * static void my_callback ( char *data, size_t len ) {
  24. * ... process data ...
  25. * }
  26. *
  27. * struct hello_request hello = {
  28. * .server = {
  29. * ...
  30. * },
  31. * .message = "hello world!",
  32. * .callback = my_callback,
  33. * };
  34. *
  35. * rc = async_wait ( say_hello ( &hello ) );
  36. *
  37. * @endcode
  38. *
  39. * It's worth noting that this trivial protocol would be entirely
  40. * adequate to implement a TCP-based version of TFTP; just use "RRQ
  41. * <filename>" as the message. Now, if only an appropriate server
  42. * existed...
  43. */
  44. static inline struct hello_request *
  45. tcp_to_hello ( struct tcp_application *app ) {
  46. return container_of ( app, struct hello_request, tcp );
  47. }
  48. static void hello_closed ( struct tcp_application *app, int status ) {
  49. struct hello_request *hello = tcp_to_hello ( app );
  50. async_done ( &hello->aop, status );
  51. }
  52. static void hello_connected ( struct tcp_application *app ) {
  53. struct hello_request *hello = tcp_to_hello ( app );
  54. hello->remaining = strlen ( hello->message );
  55. hello->state = HELLO_SENDING_MESSAGE;
  56. }
  57. static void hello_acked ( struct tcp_application *app, size_t len ) {
  58. struct hello_request *hello = tcp_to_hello ( app );
  59. hello->message += len;
  60. hello->remaining -= len;
  61. if ( hello->remaining == 0 ) {
  62. switch ( hello->state ) {
  63. case HELLO_SENDING_MESSAGE:
  64. hello->message = "\r\n";
  65. hello->remaining = 2;
  66. hello->state = HELLO_SENDING_ENDL;
  67. break;
  68. case HELLO_SENDING_ENDL:
  69. /* Nothing to do once we've finished sending
  70. * the end-of-line indicator.
  71. */
  72. break;
  73. default:
  74. assert ( 0 );
  75. }
  76. }
  77. }
  78. static void hello_newdata ( struct tcp_application *app, void *data,
  79. size_t len ) {
  80. struct hello_request *hello = tcp_to_hello ( app );
  81. hello->callback ( data, len );
  82. }
  83. static void hello_senddata ( struct tcp_application *app,
  84. void *buf __unused, size_t len __unused ) {
  85. struct hello_request *hello = tcp_to_hello ( app );
  86. tcp_send ( app, hello->message, hello->remaining );
  87. }
  88. static struct tcp_operations hello_tcp_operations = {
  89. .closed = hello_closed,
  90. .connected = hello_connected,
  91. .acked = hello_acked,
  92. .newdata = hello_newdata,
  93. .senddata = hello_senddata,
  94. };
  95. /**
  96. * Initiate a "hello world" connection
  97. *
  98. * @v hello "Hello world" request
  99. */
  100. struct async_operation * say_hello ( struct hello_request *hello ) {
  101. int rc;
  102. hello->tcp.tcp_op = &hello_tcp_operations;
  103. if ( ( rc = tcp_connect ( &hello->tcp, &hello->server, 0 ) ) != 0 )
  104. async_done ( &hello->aop, rc );
  105. return &hello->aop;
  106. }