1
0

server.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. /* this server component is a TCP socket server that supports the connect,
  2. * request, respond, disconnect communication pattern. It is suitable for
  3. * things like a HTTP server or anything that follows this pattern.
  4. *
  5. * It supports most Operating Systems, timeouts, and offers two methods to
  6. * handle multiple clients. Non-pooled allows serial handling of clients where
  7. * a single client is connected at a one time. Pooling allows parallel
  8. * handling of clients.
  9. */
  10. #ifndef SOCKET_SERVER
  11. #define SOCKET_SERVER
  12. /* normally this server is a component of some larger software so
  13. * it is common for the faceItMetal routine to be called freqently,
  14. * maybe a couple times a second or minute, whatever the user wants.
  15. * if there are no clients during the time the server is active the
  16. * multiplexer will time out and can print a message to standard error
  17. */
  18. //#define PRINT_MULTIPLEXER_TIMEOUT
  19. // client disconnect detected when recv returns 0 on an active connection
  20. #define PRINT_CLIENT_DISCONNECT
  21. //#define PRINT_CLIENT_ACCEPTED
  22. // print time remaining whenever it is checked
  23. //#define DEBUG_REMAINING
  24. // print whatever data is in the client buffer on every accept event
  25. //#define PRINT_CLIENT_DATA
  26. //#define PRINT_SOCKET_ADD_TO_SET
  27. //#define PRINT_NO_SOCKETS_READY
  28. //#define PRINT_HOW_MANY_SOCKETS_READY
  29. #include <stdio.h>
  30. #include <time.h>
  31. #include <stdint.h>
  32. #include <limits.h>
  33. #include <unistd.h>
  34. #include <signal.h>
  35. #ifdef _WIN32
  36. // Msft Windows Ultra 365 Millennium XP Live Professional XBox
  37. #include <winsock2.h>
  38. /* ws2tcpip.h --
  39. * What a terrible filename. Like a badge of incompetence it proudly
  40. * misdirects users while the socket agnostic getaddrinfo() hides
  41. * unbeknownst the to those seeking non-TCP connections. And as a
  42. * matter of tradition of making things as worse as possible, users
  43. * are required to define a magical constant if they want the routine
  44. * to be exposed. Because the Earth would literally stop spinning if
  45. * someone on a non-sanctioned Windows version tried to get socket
  46. * information on a connection they have already made.
  47. *
  48. * [?] We could just use winsock.h and ignore ws2tcpip.h, but
  49. * supposedly getaddrinfo is the future...
  50. */
  51. #if (defined _WIN32_WINNT) && (_WIN32_WINNT < 0x0501)
  52. /* MinGW32 has this defined as Windows 2000 (0x0500) which
  53. * according to Msft is too old for winsock2.h getaddrinfo. So,
  54. * redefine to at least Windows XP (0x0501)
  55. */
  56. #pragma message ( "[!] needed to override _WIN_WINNT" )
  57. #undef _WIN32_WINNT
  58. #endif
  59. #ifndef _WIN32_WINNT
  60. // Windows XP (0x0501) is, good enough for winsock2
  61. #define _WIN32_WINNT 0x0501
  62. #endif
  63. // okay, finally we abscond with getaddrinfo, thanks a lot Msft
  64. #include <ws2tcpip.h>
  65. // and smash Msft's dream of proprietary vendor lock-in shackles
  66. int msftVendorLockInCode(WSADATA *w);
  67. int close(int fd);
  68. char * strWinsock(int e);
  69. /* Msft winsockets does not set errno like other system api calls
  70. *
  71. * redefine errno integer variable to the function WSAGetLastError()
  72. * in addition also redefine strerror to a custom error decoder
  73. *
  74. * On Msft systems redefining errno to a function makes it impossible
  75. * to set errno by other software, so this fix has limited
  76. * applicability. Said another way, watch out if using any other
  77. * Msft API that might set errno, because this is not going to work.
  78. */
  79. #ifdef errno
  80. #pragma message ( "[!] needed to override errno and strerror" )
  81. #undef errno
  82. #undef strerror
  83. #endif
  84. #define errno WSAGetLastError()
  85. #define strerror strWinsock
  86. /* Msft copied all the Unix error codes for the Berkeley sockets API,
  87. * well, some of them, and then renamed them. I guess the names that
  88. * were not changed were too scary for Msft so they scampered off.
  89. * For everything else, they prepended WSA to each error code, you
  90. * know, because branding. I am surprised that each pixel on my
  91. * computer screen isn't made up of tiny corporate logos. Thanks!
  92. */
  93. //#define EAGAIN [not supported]
  94. #define EWOULDBLOCK WSAEWOULDBLOCK
  95. #define ECONNABORTED WSAECONNABORTED
  96. #define EINTR WSAEINTR
  97. #define EMFILE WSAEMFILE
  98. //#define ENFILE [not supported]
  99. #define ENOBUFS WSAENOBUFS
  100. //#define ENOMEM [not supported]
  101. //#define EPROTO WSAEPROTO
  102. #define EOPNOTSUPP WSAEOPNOTSUPP
  103. #define EBADF WSAEBADF
  104. #define ENOTSOCK WSAENOTSOCK
  105. //#define EINVAL WSAEINVAL
  106. #define EFAULT WSAEFAULT
  107. // On Win10 Pro not needed, but Win10 Home for some reason
  108. #ifndef EINVAL
  109. #define EINVAL WSAEINVAL
  110. #endif
  111. typedef char optType;
  112. /* Msft poll is slow and built around Vista (0x0600) shenanigans. Use
  113. * Select based sleep call rather than trying to figure out what super-
  114. * rainbow-black-hole-summoning-ritual is needed to get poll working.
  115. */
  116. #define MULTIPLEX_USE_SELECT
  117. // they also rename the SHUT_RW as SD_SEND Wheeeeeendoz!!!
  118. #define SHUT_WR SD_SEND
  119. #else
  120. // Every other operating system (OS) in existence
  121. #include <sys/types.h>
  122. #include <sys/socket.h>
  123. #include <netdb.h>
  124. #include <errno.h>
  125. #include <fcntl.h>
  126. #include <poll.h>
  127. #include <string.h> // memset
  128. typedef int optType;
  129. #endif
  130. // [!] OSes deny non-privileged user bind requests to ports <1024
  131. #define MYPORT "9000"
  132. // [!] OSes usually reduce this number to a maximum of 20
  133. #define BACKLOG 7
  134. /* faceItMetal buffer constant
  135. * this routine will send data out to the world. Every routine should
  136. * make sure nothing critical leaks, but this is just a safety to limit
  137. * a potential leak to *only* some small amount of data
  138. * other programs can use this to determine if they are reaching this limit
  139. * and react accordingly
  140. */
  141. #define FIM_BUFFER_LEN 256
  142. /* faceItMetal and acceptOkay communicate the EWOULDBLOCK and EAGAIN
  143. * condition by sending a synonym for EWOULDBLOCK to hopefully remove some
  144. * confusion. At least for posix people who might vet the code.
  145. */
  146. #define DONE_FOR_NOW EWOULDBLOCK
  147. /* user defined callback function can instruct the faceItMetal routine
  148. * to perform some operations, currently implemented:
  149. */
  150. enum CALLBACK_ERROR_CODES {
  151. SEND_MORE = INT_MIN, // wait for more data, call again later
  152. SERVER_ERROR, // default, send "server error\n" and disconnect
  153. INVALID_DATA, // send client "invalid\n" and disconnect
  154. DROP_CLIENT // immediately disconnect the client
  155. };
  156. /* time a client has to send/recv data, 50ms is a good starting point
  157. * the time is evenly split in two, the first half waits to recive data
  158. * from the client and the remaining half is allocated waiting for the
  159. * client to close the connection
  160. */
  161. #define PER_CLIENT_TIMEOUT_MS 50
  162. #define INVALID_TEXT "invalid\n"
  163. #define TIMEOUT_TEXT "timeout\n"
  164. #define SERVER_ERROR_TEXT "server error\n"
  165. enum SocketStatus {
  166. READ_READY = (1 << 0),
  167. WRITE_CLOSED = (1 << 1),
  168. ACCEPT_LISTEN_TIME = (1 << 2)
  169. };
  170. enum ConnectionFlags {
  171. SERVER_WANTS_CLOSE = (1 << 0),
  172. CLOSE_IMMEDIATELY = (1 << 1),
  173. CLIENT_IS_CLOSED = (1 << 2)
  174. };
  175. // convenience symbol for clients irrevocably on their way out
  176. #define CLIENT_CLOSING (CLOSE_IMMEDIATELY | CLIENT_IS_CLOSED)
  177. struct client {
  178. // socket file descriptor
  179. int32_t fd;
  180. // client internet protocol address (either version 4 or 6)
  181. struct sockaddr_storage address;
  182. socklen_t addrSize;
  183. // remaining milliseconds before automatic disconnect
  184. uint32_t ms;
  185. // time that the client was initially accepted
  186. struct timespec t;
  187. // stores information about the socket read and write
  188. enum SocketStatus status;
  189. enum ConnectionFlags flags;
  190. // fill level for the buffer
  191. uint32_t count;
  192. // storage for client request
  193. char buf[FIM_BUFFER_LEN];
  194. };
  195. /* USE_CLIENT_POOL option
  196. * Instead of handling clients serially, a pool of clients is handled in the
  197. * same fashion. The slight difference may allow more throughput at the cost
  198. * of a tiny bit more memory and a tiny bit slowdown due to the requirement to
  199. * remember multiple client states and higher CPU usage.
  200. *
  201. * [!] The attack surface of the interface is increased as well so an
  202. * adversarial client can now cause denial of service attacks by opening
  203. * and closing a connection making this demo needing to recalculate client
  204. * state. In addition if state is not calculated well, eg: the fractional time
  205. * resolution is not good enough, an adversary could either cause the client
  206. * pool to be always full or always empty. Yay!
  207. */
  208. #define USE_CLIENT_POOL
  209. #ifdef USE_CLIENT_POOL
  210. // how many clients are handled at once, hard limit is less than 65535
  211. #define POOL_SIZE 10
  212. #else
  213. #define POOL_SIZE 2
  214. int handleClient(struct client p[],
  215. char * (*f)(char *s, int len, int *limit));
  216. #endif
  217. #ifndef _WIN32
  218. /* Sending/writing to a socket will eventually cause the Operating System
  219. * to send the server application a SIGPIPE signal. On Unix based operating
  220. * systems there is a flag that can be set in the socket API to request
  221. * that no signals be sent when attempting to write to a closed socket.
  222. * (see: MSG_NOSIGNAL on Unix based OSes)
  223. *
  224. * The alternative, and what was done here, is to just install a signal
  225. * handler and deal with the signal that the OS will send.
  226. */
  227. void handle_sigpipe(int s);
  228. #endif
  229. /* create a send reason so that we only need one use of send and the
  230. * cruft around it handling the somewhat rare events when a client decides
  231. * to break the pipe without sending a notification first.
  232. */
  233. typedef enum SendReason {
  234. TIME_OUT_MSG,
  235. INVALID_MSG,
  236. SERVER_ERROR_MSG,
  237. RESPONSE_MSG
  238. } sendReason;
  239. int sendResponse(struct client *c, char *buf, uint32_t len, sendReason reason);
  240. // determines if socket error is recoverable, and usually prints logs info
  241. int acceptOkay(int e);
  242. // provides OS agnostic method: set socket file descriptor non-blocking flag
  243. int setNonBlocking(int sockfd);
  244. // provides OS agnostic method: set socket file descriptor linger options
  245. static void setLinger(int sockfd) __attribute__((always_inline));
  246. // compares time now to specified time offset by some limit
  247. static uint32_t msRemaining(struct timespec t, uint32_t allowed)
  248. __attribute__((always_inline));
  249. // for debugging, the buffer is trashed after this call, so use carefully
  250. void convertToPrintable(char * s, uint32_t len);
  251. // inaccurate OS agnostic 1ms resolution sleep
  252. void spookySleep(uint32_t t);
  253. // refactor part of faceItMetal, sends a timeout message and sets linger
  254. static void sendTimeout(struct client *c) __attribute__((always_inline));
  255. // refactor part of faceItMetal, read/verify client messages, replies on success
  256. static int replyOnValid(struct client *c,
  257. char * (*f)(char *s, int len, int *limit)) __attribute__((always_inline));
  258. // refactor part of faceItMetal, non-pooled select/poll error debug
  259. static int wakeupError(int e, struct client * c) __attribute__((always_inline));
  260. // refactor part of faceItMetal, accepts clients and adds them to a pool
  261. static int waitForClients(uint32_t ms, struct client pool[])
  262. __attribute__((always_inline));
  263. #ifdef USE_CLIENT_POOL
  264. // refactor part of faceItMetal, scans pool for timed out clients
  265. static void checkTimeouts(struct client pool[], int len)
  266. __attribute__((always_inline));
  267. // refactor part of faceItMetal, low precision timeout tracking (uses milliseconds)
  268. static void prepayEstimates(struct client p[], uint32_t len, struct timespec t1)
  269. __attribute__((always_inline));
  270. // specialized connection routine, handles up to one client per call
  271. int faceItMetal(uint32_t ms, char * (*f)(char *s, int len,
  272. int *limit), struct client pool[]);
  273. #else
  274. int faceItMetal(int sock, uint32_t ms, char * (*f)(char *s, int len, int *limit));
  275. #endif
  276. // example prototype and definition of a faceItMetal (tm) callback
  277. char * alwaysGood(char *s, int len, int *limit);
  278. // example prototype and definition of a another faceItMetal (tm) callback
  279. char * alwaysBad(char *s, int len, int *limit);
  280. // example prototype and definition of a another faceItMetal (tm) callback
  281. char * alwaysNotEnough(char *s, int len, int *limit);
  282. // OS agnostic efficient blocking with timeout in milliseconds
  283. int socketReady(struct client pool[], int len, uint32_t ms);
  284. // a cute way to hide another bit of the Msft proprietary scheme
  285. int softCuteBunnies(int c);
  286. #endif