http_test.odin 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #import "fmt.odin";
  2. #foreign_system_library ws2 "Ws2_32.lib" when ODIN_OS == "windows";
  3. SOCKET :: #type uint;
  4. INVALID_SOCKET :: ~(cast(SOCKET)0);
  5. 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. SOCK_STREAM :: 1;
  36. SOCKET_ERROR :: -1;
  37. IPPROTO_TCP :: 6;
  38. AI_PASSIVE :: 0x0020;
  39. SOMAXCONN :: 128;
  40. SD_RECEIVE :: 0;
  41. SD_SEND :: 1;
  42. SD_BOTH :: 2;
  43. WSADESCRIPTION_LEN :: 256;
  44. WSASYS_STATUS_LEN :: 128;
  45. WSADATA :: struct #ordered {
  46. version: i16,
  47. high_version: i16,
  48. // NOTE(bill): This is x64 ordering
  49. max_sockets: u16,
  50. max_udp_dg: u16,
  51. vendor_info: ^byte,
  52. description: [WSADESCRIPTION_LEN+1]byte,
  53. system_status: [WSASYS_STATUS_LEN+1]byte,
  54. }
  55. addrinfo :: struct #ordered {
  56. flags: i32,
  57. family: i32,
  58. socktype: i32,
  59. protocol: i32,
  60. addrlen: uint,
  61. canonname: ^u8,
  62. addr: ^sockaddr,
  63. next: ^addrinfo,
  64. }
  65. sockaddr :: struct #ordered {
  66. family: u16,
  67. data: [14]byte,
  68. }
  69. WSAStartup :: proc(version_requested: i16, data: ^WSADATA) -> i32 #foreign ws2;
  70. WSACleanup :: proc() -> i32 #foreign ws2;
  71. getaddrinfo :: proc(node_name, service_name: ^u8, hints: ^addrinfo, result: ^^addrinfo) -> i32 #foreign ws2;
  72. freeaddrinfo :: proc(ai: ^addrinfo) #foreign ws2;
  73. socket :: proc(af, type_, protocol: i32) -> SOCKET #foreign ws2;
  74. closesocket :: proc(s: SOCKET) -> i32 #foreign ws2;
  75. bind :: proc(s: SOCKET, name: ^sockaddr, name_len: i32) -> i32 #foreign ws2;
  76. listen :: proc(s: SOCKET, back_log: i32) -> i32 #foreign ws2;
  77. accept :: proc(s: SOCKET, addr: ^sockaddr, addr_len: i32) -> SOCKET #foreign ws2;
  78. recv :: proc(s: SOCKET, buf: ^byte, len: i32, flags: i32) -> i32 #foreign ws2;
  79. send :: proc(s: SOCKET, buf: ^byte, len: i32, flags: i32) -> i32 #foreign ws2;
  80. shutdown :: proc(s: SOCKET, how: i32) -> i32 #foreign ws2;
  81. WSAGetLastError :: proc() -> i32 #foreign ws2;
  82. to_c_string :: proc(s: string) -> ^byte {
  83. c_str := new_slice(byte, s.count+1);
  84. assert(c_str.data != nil);
  85. copy(c_str, cast([]byte)s);
  86. c_str[s.count] = 0;
  87. return c_str.data;
  88. }
  89. run :: proc() {
  90. wsa: WSADATA;
  91. res: ^addrinfo = nil;
  92. hints: addrinfo;
  93. s, client: SOCKET;
  94. if WSAStartup(2 | (2 << 8), ^wsa) != 0 {
  95. fmt.println("WSAStartup failed: ", WSAGetLastError());
  96. return;
  97. }
  98. defer WSACleanup();
  99. hints.family = cast(i32)AF.INET;
  100. hints.socktype = SOCK_STREAM;
  101. hints.protocol = IPPROTO_TCP;
  102. hints.flags = AI_PASSIVE;
  103. if getaddrinfo(nil, to_c_string("8080"), ^hints, ^res) != 0 {
  104. fmt.println("getaddrinfo failed: ", WSAGetLastError());
  105. return;
  106. }
  107. defer freeaddrinfo(res);
  108. s = socket(res.family, res.socktype, res.protocol);
  109. if s == INVALID_SOCKET {
  110. fmt.println("socket failed: ", WSAGetLastError());
  111. return;
  112. }
  113. defer closesocket(s);
  114. bind(s, res.addr, cast(i32)res.addrlen);
  115. listen(s, SOMAXCONN);
  116. client = accept(s, nil, 0);
  117. if client == INVALID_SOCKET {
  118. fmt.println("socket failed: ", WSAGetLastError());
  119. return;
  120. }
  121. defer closesocket(client);
  122. html :=
  123. `HTTP/1.1 200 OK
  124. Connection: close
  125. Content-type: text/html
  126. <html>
  127. <head>
  128. <title>Demo Title</title>
  129. </head>
  130. <body>
  131. <h1 style="color: orange;">Odin Server Demo</h1>
  132. </body>
  133. </html>
  134. `;
  135. buf: [1024]byte;
  136. for {
  137. bytes := recv(client, ^buf[0], cast(i32)buf.count, 0);
  138. if bytes > 0 {
  139. // fmt.println(buf[:bytes] as string)
  140. bytes_sent := send(client, html.data, cast(i32)(html.count-1), 0);
  141. if bytes_sent == SOCKET_ERROR {
  142. fmt.println("send failed: ", WSAGetLastError());
  143. return;
  144. }
  145. break;
  146. } else if bytes == 0 {
  147. fmt.println("Connection closing...");
  148. break;
  149. } else {
  150. fmt.println("recv failed: ", WSAGetLastError());
  151. return;
  152. }
  153. }
  154. shutdown(client, SD_SEND);
  155. }