http_test.odin 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. import "fmt.odin";
  2. foreign_system_library ws2 "Ws2_32.lib" when ODIN_OS == "windows";
  3. type SOCKET uint;
  4. const INVALID_SOCKET = ~SOCKET(0);
  5. type AF enum i32 {
  6. UNSPEC = 0, // unspecified
  7. UNIX = 1, // local to host (pipes, portals)
  8. INET = 2, // internetwork: UDP, TCP, etc.
  9. IMPLINK = 3, // arpanet imp addresses
  10. PUP = 4, // pup protocols: e.g. BSP
  11. CHAOS = 5, // mit CHAOS protocols
  12. NS = 6, // XEROX NS protocols
  13. ISO = 7, // ISO protocols
  14. OSI = ISO, // OSI is ISO
  15. ECMA = 8, // european computer manufacturers
  16. DATAKIT = 9, // datakit protocols
  17. CCITT = 10, // CCITT protocols, X.25 etc
  18. SNA = 11, // IBM SNA
  19. DECnet = 12, // DECnet
  20. DLI = 13, // Direct data link interface
  21. LAT = 14, // LAT
  22. HYLINK = 15, // NSC Hyperchannel
  23. APPLETALK = 16, // AppleTalk
  24. ROUTE = 17, // Internal Routing Protocol
  25. LINK = 18, // Link layer interface
  26. XTP = 19, // eXpress Transfer Protocol (no AF)
  27. COIP = 20, // connection-oriented IP, aka ST II
  28. CNT = 21, // Computer Network Technology
  29. RTIP = 22, // Help Identify RTIP packets
  30. IPX = 23, // Novell Internet Protocol
  31. SIP = 24, // Simple Internet Protocol
  32. PIP = 25, // Help Identify PIP packets
  33. MAX = 26,
  34. };
  35. const (
  36. SOCK_STREAM = 1;
  37. SOCKET_ERROR = -1;
  38. IPPROTO_TCP = 6;
  39. AI_PASSIVE = 0x0020;
  40. SOMAXCONN = 128;
  41. )
  42. const (
  43. SD_RECEIVE = 0;
  44. SD_SEND = 1;
  45. SD_BOTH = 2;
  46. )
  47. const WSADESCRIPTION_LEN = 256;
  48. const WSASYS_STATUS_LEN = 128;
  49. type WSADATA struct #ordered {
  50. version: i16,
  51. high_version: i16,
  52. // NOTE(bill): This is x64 ordering
  53. max_sockets: u16,
  54. max_udp_dg: u16,
  55. vendor_info: ^u8,
  56. description: [WSADESCRIPTION_LEN+1]u8,
  57. system_status: [WSASYS_STATUS_LEN+1]u8,
  58. }
  59. type addrinfo struct #ordered {
  60. flags: i32,
  61. family: i32,
  62. socktype: i32,
  63. protocol: i32,
  64. addrlen: uint,
  65. canonname: ^u8,
  66. addr: ^sockaddr,
  67. next: ^addrinfo,
  68. }
  69. type sockaddr struct #ordered {
  70. family: u16,
  71. data: [14]u8,
  72. }
  73. foreign ws2 {
  74. proc WSAStartup (version_requested: i16, data: ^WSADATA) -> i32;
  75. proc WSACleanup () -> i32;
  76. proc getaddrinfo (node_name, service_name: ^u8, hints: ^addrinfo, result: ^^addrinfo) -> i32;
  77. proc freeaddrinfo (ai: ^addrinfo);
  78. proc socket (af, type_, protocol: i32) -> SOCKET;
  79. proc closesocket (s: SOCKET) -> i32;
  80. proc bind (s: SOCKET, name: ^sockaddr, name_len: i32) -> i32;
  81. proc listen (s: SOCKET, back_log: i32) -> i32;
  82. proc accept (s: SOCKET, addr: ^sockaddr, addr_len: i32) -> SOCKET;
  83. proc recv (s: SOCKET, buf: ^u8, len: i32, flags: i32) -> i32;
  84. proc send (s: SOCKET, buf: ^u8, len: i32, flags: i32) -> i32;
  85. proc shutdown (s: SOCKET, how: i32) -> i32;
  86. proc WSAGetLastError() -> i32;
  87. }
  88. proc to_c_string(s: string) -> ^u8 {
  89. var c_str = make([]u8, len(s)+1);
  90. copy(c_str, []u8(s));
  91. c_str[len(s)] = 0;
  92. return &c_str[0];
  93. }
  94. proc run() {
  95. var (
  96. wsa: WSADATA;
  97. res: ^addrinfo = nil;
  98. hints: addrinfo;
  99. s, client: SOCKET;
  100. )
  101. if WSAStartup(2 | (2 << 8), &wsa) != 0 {
  102. fmt.println("WSAStartup failed: ", WSAGetLastError());
  103. return;
  104. }
  105. defer WSACleanup();
  106. hints.family = i32(AF.INET);
  107. hints.socktype = SOCK_STREAM;
  108. hints.protocol = IPPROTO_TCP;
  109. hints.flags = AI_PASSIVE;
  110. if getaddrinfo(nil, to_c_string("8080"), &hints, &res) != 0 {
  111. fmt.println("getaddrinfo failed: ", WSAGetLastError());
  112. return;
  113. }
  114. defer freeaddrinfo(res);
  115. s = socket(res.family, res.socktype, res.protocol);
  116. if s == INVALID_SOCKET {
  117. fmt.println("socket failed: ", WSAGetLastError());
  118. return;
  119. }
  120. defer closesocket(s);
  121. bind(s, res.addr, i32(res.addrlen));
  122. listen(s, SOMAXCONN);
  123. client = accept(s, nil, 0);
  124. if client == INVALID_SOCKET {
  125. fmt.println("socket failed: ", WSAGetLastError());
  126. return;
  127. }
  128. defer closesocket(client);
  129. var html =
  130. `HTTP/1.1 200 OK
  131. Connection: close
  132. Content-type: text/html
  133. <html>
  134. <head>
  135. <title>Demo Title</title>
  136. </head>
  137. <body>
  138. <h1 style="color: orange;">Odin Server Demo</h1>
  139. </body>
  140. </html>
  141. `;
  142. var buf: [1024]u8;
  143. for {
  144. var bytes = recv(client, &buf[0], i32(len(buf)), 0);
  145. if bytes > 0 {
  146. // fmt.println(string(buf[0..<bytes]))
  147. var bytes_sent = send(client, &html[0], i32(len(html)-1), 0);
  148. if bytes_sent == SOCKET_ERROR {
  149. fmt.println("send failed: ", WSAGetLastError());
  150. return;
  151. }
  152. break;
  153. } else if bytes == 0 {
  154. fmt.println("Connection closing...");
  155. break;
  156. } else {
  157. fmt.println("recv failed: ", WSAGetLastError());
  158. return;
  159. }
  160. }
  161. shutdown(client, SD_SEND);
  162. }