fileserver_example_external_select.pp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. (*
  2. This file is part of libmicrohttpd
  3. Copyright (C) 2007, 2008 Christian Grothoff (and other contributing authors)
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. This library 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 GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with this library; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  15. *)
  16. (**
  17. * @file fileserver_example_external_select.pp (Original: fileserver_example_external_select.c)
  18. * @brief minimal example for how to use libmicrohttpd to server files
  19. * @author Christian Grothoff / Silvio Clécio
  20. *)
  21. program fileserver_example_external_select;
  22. {$mode objfpc}{$H+}
  23. uses
  24. sysutils, BaseUnix, cutils, libmicrohttpd;
  25. const
  26. PAGE: Pcchar = '<html><head><title>File not found</title></head><body>File not found</body></html>';
  27. function file_reader(cls: Pointer; pos: cuint64; buf: Pcchar;
  28. max: size_t): ssize_t; cdecl;
  29. var
  30. &file: FILEptr;
  31. begin
  32. &file := cls;
  33. fseek(&file, pos, SEEK_SET);
  34. Result := fread(buf, 1, max, &file);
  35. end;
  36. procedure free_callback(cls: Pointer); cdecl;
  37. var
  38. &file: FILEptr;
  39. begin
  40. &file := cls;
  41. fclose(&file);
  42. end;
  43. function ahc_echo(cls: Pointer; connection: PMHD_Connection; url: Pcchar;
  44. method: Pcchar; version: Pcchar; upload_data: Pcchar;
  45. upload_data_size: Psize_t; ptr: PPointer): cint; cdecl;
  46. const
  47. aptr: cint = 0;
  48. var
  49. response: PMHD_Response;
  50. ret: cint;
  51. &file: FILEptr;
  52. buf: stat;
  53. begin
  54. if 0 <> strcomp(method, MHD_HTTP_METHOD_GET) then
  55. Exit(MHD_NO); (* unexpected method *)
  56. if @aptr <> ptr^ then
  57. begin
  58. (* do never respond on first call *)
  59. ptr^ := @aptr;
  60. Exit(MHD_YES);
  61. end;
  62. ptr^ := nil; (* reset when done *)
  63. if (0 = FpStat(@url[1], buf)) and fpS_ISREG(buf.st_mode) then
  64. &file := fopen(@url[1], fopenread)
  65. else
  66. &file := nil;
  67. if &file = nil then
  68. begin
  69. response := MHD_create_response_from_buffer(strlen(PAGE), Pointer(PAGE),
  70. MHD_RESPMEM_PERSISTENT);
  71. ret := MHD_queue_response(connection, MHD_HTTP_NOT_FOUND, response);
  72. MHD_destroy_response(response);
  73. end
  74. else
  75. begin
  76. response := MHD_create_response_from_callback(buf.st_size, 32 * 1024, (* 32k page size *)
  77. @file_reader, &file, @free_callback);
  78. if response = nil then
  79. begin
  80. fclose(&file);
  81. Exit(MHD_NO);
  82. end;
  83. ret := MHD_queue_response(connection, MHD_HTTP_OK, response);
  84. MHD_destroy_response(response);
  85. end;
  86. Result := ret;
  87. end;
  88. var
  89. d: PMHD_Daemon;
  90. &end: time_t;
  91. t: time_t;
  92. tv: timeval;
  93. rs: TFDSet;
  94. ws: TFDSet;
  95. es: TFDSet;
  96. max: MHD_socket;
  97. mhd_timeout: MHD_UNSIGNED_LONG_LONG;
  98. begin
  99. if argc <> 3 then
  100. begin
  101. WriteLn(argv[0], ' PORT SECONDS-TO-RUN');
  102. Halt(1);
  103. end;
  104. d := MHD_start_daemon(MHD_USE_DEBUG, StrToInt(argv[1]), nil, nil, @ahc_echo,
  105. PAGE, MHD_OPTION_END);
  106. if d = nil then
  107. Halt(1);
  108. &end := fptime + StrToInt(argv[2]);
  109. while True do
  110. begin
  111. t := fptime;
  112. if not (t < &end) then
  113. Break;
  114. tv.tv_sec := &end - t;
  115. tv.tv_usec := 0;
  116. max := 0;
  117. fpFD_ZERO(rs);
  118. fpFD_ZERO(ws);
  119. fpFD_ZERO(es);
  120. if MHD_YES <> MHD_get_fdset (d, @rs, @ws, @es, @max) then
  121. Break; (* fatal internal error *)
  122. if MHD_get_timeout(d, @mhd_timeout) = MHD_YES then
  123. begin
  124. if MHD_UNSIGNED_LONG_LONG(tv.tv_sec) < mhd_timeout div clonglong(1000) then
  125. begin
  126. tv.tv_sec := mhd_timeout div clonglong(1000);
  127. tv.tv_usec := (mhd_timeout - (tv.tv_sec * clonglong(1000))) * clonglong(1000);
  128. end;
  129. end;
  130. fpSelect(max + 1, @rs, @ws, @es, @tv);
  131. MHD_run(d);
  132. end;
  133. MHD_stop_daemon(d);
  134. end.