' Simple HTTP GET request via TCP Winsock DECLARE
#COMPILE EXE
#DIM ALL

DECLARE FUNCTION WSAStartup LIB "WS2_32.DLL" (BYVAL wVersionRequired AS LONG, BYREF lpWSAData As Byte) AS LONG
DECLARE FUNCTION WSACleanup LIB "WS2_32.DLL" () AS LONG
DECLARE FUNCTION socket LIB "WS2_32.DLL" (BYVAL af AS LONG, BYVAL type AS LONG, BYVAL protocol AS LONG) AS LONG
DECLARE FUNCTION closesocket LIB "WS2_32.DLL" (BYVAL s AS LONG) AS LONG
DECLARE FUNCTION connect LIB "WS2_32.DLL" (BYVAL s AS LONG, BYREF addr As Byte, BYVAL addrlen AS LONG) AS LONG
DECLARE FUNCTION send LIB "WS2_32.DLL" (BYVAL s AS LONG, BYVAL buf AS ASCIIZ, BYVAL len AS LONG, BYVAL flags AS LONG) AS LONG
DECLARE FUNCTION recv LIB "WS2_32.DLL" (BYVAL s AS LONG, BYVAL buf AS ASCIIZ, BYVAL len AS LONG, BYVAL flags AS LONG) AS LONG

%AF_INET = 2
%SOCK_STREAM = 1
%IPPROTO_TCP = 6

FUNCTION BuildHttpGet(BYVAL host AS STRING, BYVAL path AS STRING) AS STRING
    LOCAL req AS STRING
    req = "GET " + path + " HTTP/1.1" + CHR$(13) + CHR$(10)
    req = req + "Host: " + host + CHR$(13) + CHR$(10)
    req = req + "User-Agent: PBXB64/1.0" + CHR$(13) + CHR$(10)
    req = req + "Accept: */*" + CHR$(13) + CHR$(10)
    req = req + "Connection: close" + CHR$(13) + CHR$(10)
    req = req + CHR$(13) + CHR$(10)
    FUNCTION = req
END FUNCTION

FUNCTION ParseStatusLine(BYVAL response AS STRING) AS LONG
    LOCAL pos AS LONG
    pos = INSTR(response, " ")
    IF pos = 0 THEN FUNCTION = 0
    LOCAL codeStr AS STRING
    codeStr = MID$(response, pos + 1, 3)
    FUNCTION = VAL(codeStr)
END FUNCTION

FUNCTION FindHeader(BYVAL response AS STRING, BYVAL header AS STRING) AS STRING
    LOCAL pos AS LONG
    LOCAL search AS STRING
    search = header + ": "
    pos = INSTR(response, search)
    IF pos = 0 THEN FUNCTION = ""
    LOCAL startPos AS LONG
    startPos = pos + LEN(search)
    LOCAL endPos AS LONG
    endPos = INSTR(startPos, response, CHR$(13) + CHR$(10))
    IF endPos = 0 THEN FUNCTION = ""
    FUNCTION = MID$(response, startPos, endPos - startPos)
END FUNCTION

FUNCTION ExtractBody(BYVAL response AS STRING) AS STRING
    LOCAL pos AS LONG
    pos = INSTR(response, CHR$(13) + CHR$(10) + CHR$(13) + CHR$(10))
    IF pos = 0 THEN FUNCTION = ""
    FUNCTION = MID$(response, pos + 4)
END FUNCTION

SUB HttpSimulation()
    PRINT "HTTP GET simulation:"
    LOCAL host  AS STRING
    LOCAL path  AS STRING
    LOCAL request  AS STRING
    host = "example.com"
    path = "/index.html"
    request = BuildHttpGet(host, path)
    PRINT "Request:"
    PRINT request
    PRINT ""
    PRINT "Response (simulated):"
    LOCAL response AS STRING
    response = "HTTP/1.1 200 OK" + CHR$(13) + CHR$(10)
    response = response + "Content-Type: text/html" + CHR$(13) + CHR$(10)
    response = response + "Content-Length: 125" + CHR$(13) + CHR$(10)
    response = response + "Server: ECSF" + CHR$(13) + CHR$(10)
    response = response + CHR$(13) + CHR$(10)
    response = response + "<html><body><h1>Example</h1><p>This is a test response.</p></body></html>"
    LOCAL code  AS LONG
    LOCAL contentLen  AS LONG
    code = ParseStatusLine(response)
    PRINT "Status: "; code
    PRINT "Content-Type: "; FindHeader(response, "Content-Type")
    contentLen = VAL(FindHeader(response, "Content-Length"))
    PRINT "Content-Length: "; contentLen
    PRINT "Body: "; ExtractBody(response)
END SUB

SUB GetAndParse(BYVAL url AS STRING)
    PRINT ""
    PRINT "URL: "; url
    PRINT "  1. WSAStartup"
    PRINT "  2. socket() -> s"
    PRINT "  3. connect(s, host, 80)"
    PRINT "  4. send(s, request)"
    PRINT "  5. recv(s, buffer, 4096)"
    PRINT "  6. closesocket(s)"
    PRINT "  7. WSACleanup"
    PRINT "  Response received"
END SUB

SUB TestEndpoints()
    PRINT ""
    PRINT "Testing endpoints:"
    DIM hosts(0:2) AS STRING
    DIM paths(0:2) AS STRING
    hosts(0) = "api.example.com": paths(0) = "/v1/users"
    hosts(1) = "www.test.com": paths(1) = "/data.json"
    hosts(2) = "httpbin.org": paths(2) = "/get"
    LOCAL i AS LONG
    FOR i = 0 TO 2
        PRINT "  GET http://"; hosts(i); paths(i); " -> "
        PRINT LEN(BuildHttpGet(hosts(i), paths(i))); " bytes request"
    NEXT i
END SUB

FUNCTION PBMAIN() AS LONG
    PRINT "=== HTTP Client Demo ==="
    PRINT "Winsock: socket, connect, send, recv via DECLARE"
    HttpSimulation()
    GetAndParse("http://example.com/index.html")
    TestEndpoints()
    PRINT "=== End HTTP Client ==="
    FUNCTION = 0
END FUNCTION
