123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 |
- ' http.bi is part of Bliss (track editor for Stunts)
- ' Copyright (C) 2016-2018 Lucas Pedrosa
- ' Bliss is free software: you can redistribute it and/or modify
- ' it under the terms of the GNU General Public License as published by
- ' the Free Software Foundation, version 3 of the License.
- ' This program is distributed in the hope that it will be useful,
- ' but WITHOUT ANY WARRANTY; without even the implied warranty of
- ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ' GNU General Public License for more details.
- ' You should have received a copy of the GNU General Public License
- ' along with this program. If not, see <http://www.gnu.org/licenses/>.
- #ifdef __FB_WIN32__
- #include "windows.bi"
- #include "win/windef.bi"
- #include "win/winsock2.bi"
- #ifndef opensocket
- #define opensocket socket
- #endif
- #else
- #include "crt/unistd.bi"
- #include "crt/netinet/in.bi"
- #include "crt/sys/select.bi"
- #include "crt/netdb.bi"
- #include "crt/arpa/inet.bi"
- #endif
- #ifndef TCP_NODELAY
- #define TCP_NODELAY &H01
- #endif
- Declare Sub HTTP_Start
- Declare Sub HTTP_End
- Declare Function HTTP_StartServer(ByVal port As UShort, max_connections As Integer) As Byte
- Declare Function HTTP_GetClient As Long
- Declare Function HTTP_Connect(address As String, port As UShort) As Byte
- Declare Function HTTP_BuildGet(host As String, path As String, mimetype As String = "") As String
- Declare Function HTTP_BuildHead(host As String, path As String, mimetype As String = "") As String
- Declare Function HTTP_BuildPost(host As String, path As String, query As String, refer As Byte) As String
- Declare Function HTTP_ReadyToGet As Byte
- Declare Function HTTP_ReadyToPut As Byte
- Declare Function HTTP_GetData(ByRef dbuffer As Any Ptr) As Long
- Declare Function HTTP_PutData(ByVal dbuffer As Any Ptr, ByVal datasize As Long) As Long
- Dim Shared HTTP_Socket As Long, HTTP_addr As sockaddr_in
- Dim Shared As fd_set HTTP_writefds, HTTP_readfds, HTTP_readfd
- Dim Shared HTTP_timeout As timeval
- Function HTTP_BuildGet(host As String, path As String, mimetype As String = "") As String
- Dim s As String
-
- s = "GET " + path + " HTTP/1.1" + Chr(13, 10)
- s += "Host: " + host + Chr(13, 10)
- If Len(mimetype) Then s += "mime: " + mimetype + Chr(13, 10)
- s += Chr(13, 10)
-
- Return s
- End Function
- Function HTTP_BuildHead(host As String, path As String, mimetype As String = "") As String
- Dim s As String
-
- s = "HEAD " + path + " HTTP/1.1" + Chr(13, 10)
- s += "Host: " + host + Chr(13, 10)
- If Len(mimetype) Then s += "mime: " + mimetype + Chr(13, 10)
- s += Chr(13, 10)
-
- Return s
- End Function
- Function HTTP_BuildPost(host As String, path As String, query As String, refer As Byte) As String
- Dim s As String
-
- s = "POST " + path + " HTTP/1.1" + Chr(13, 10)
- s += "Host: " + host + Chr(13, 10)
-
- If refer Then s += "Referer: http://" + host + path + "?" + Chr(13, 10)
- s += "Content-type: application/x-www-form-urlencoded" + Chr(13, 10)
- s += "Content-length: " + Str(Len(query)) + Chr(13, 10)
- s += "Connection: close" + Chr(13, 10, 13, 10)
- s += query
-
- Return s
- End Function
- Function HTTP_Connect(address As String, port As UShort) As Byte
- HTTP_Start
- HTTP_Socket = opensocket(AF_INET, SOCK_STREAM, 0)
-
- If HTTP_Socket = -1 Then Return -1
-
- Dim he As hostent Ptr
- he = gethostbyname(StrPtr(address))
- If he = 0 Then Return -2
-
- HTTP_addr.sin_family = AF_INET
- HTTP_addr.sin_port = htons(port)
- HTTP_addr.sin_addr = *CPtr(in_addr Ptr, he->h_addr_list[0])
- If connect(HTTP_Socket, CPtr(sockaddr Ptr, @HTTP_addr), SizeOf(sockaddr)) < 0 Then
- Return -3
- End if
-
- Return 0
- End Function
- Function HTTP_Download(address As String, ByRef buffer As UByte Ptr, isawebpage As Byte = 0) As Long
- Dim request As String, n As Short
- Dim As String host, path, mime
- Dim t As Double, bytes As Long, newbuffer As UByte Ptr
- Dim header As ZString Ptr
- If isawebpage Then mime = "text/html;text/plain" Else mime = ""
-
- n = InStr(address, "/")
- If n Then
- host = Left(address, n - 1)
- path = Mid(address, n)
- Else
- host = address
- path = "/"
- End If
-
- If HTTP_Connect(host, 80) Then Return -1 'Could not connect
- request = HTTP_BuildGet(host, path, mime)
- t = Timer
- Do
- If HTTP_ReadyToPut Then Exit Do
- If Timer > t + 3 Then Return -2 'Time-out 3 seconds
- Sleep 100
- Loop
-
- HTTP_PutData StrPtr(request), Len(request)
- t = Timer
- Do
- If HTTP_ReadyToGet Then Exit Do
- If Timer > t + 3 Then Return -3 'Time-out 3 seconds
- Sleep 100
- Loop
- bytes = HTTP_GetData(newbuffer)
- header = newbuffer
- n = InStr(*header, Chr(13, 10, 13, 10)) + 3
-
- If buffer Then Deallocate buffer : buffer = 0
- If bytes - n >= 1 Then
- buffer = Allocate(bytes - n)
- For i As Long = 0 To bytes - n - 1
- buffer[i] = newbuffer[i + n]
- Next i
- End If
- Deallocate newbuffer
- Return bytes - n
- End Function
- Sub HTTP_End
- If HTTP_Socket >= 1 Then closesocket(HTTP_Socket)
- #ifdef __FB_WIN32__
- WSACleanup()
- #endif
- End Sub
- Function HTTP_GetData(ByRef dbuffer As Any Ptr) As Long
- Static chunk(8191) As UByte
-
- If HTTP_Socket < 0 Then Return -1
-
- Dim dsize As Long, bytes As Long, pwrite As UByte Ptr, i As Long
-
- If dbuffer Then Deallocate dbuffer : dbuffer = 0
- Do
- bytes = recv(HTTP_Socket, @chunk(0), 8192, 0)
-
- If bytes = 0 Then
- If dsize = 0 Then Return -1
- Exit Do
- End If
- If bytes < 0 Then Return -1
-
- dbuffer = Reallocate(dbuffer, dsize + bytes)
- pwrite = dbuffer + dsize
-
- For i = 0 To bytes - 1
- pwrite[i] = chunk(i)
- Next i
- dsize += bytes
-
- Sleep 20
- For i = 1 To 100
- If HTTP_ReadyToGet Then Exit For
- Sleep 10
- Next i
- Loop Until i > 100
-
- Return dsize
- End Function
- Function HTTP_PutData(ByVal dbuffer As Any Ptr, ByVal datasize As Long) As Long
- If HTTP_Socket < 0 Or dbuffer = 0 Or datasize < 1 Then Return -1
-
- Dim size As Long, dsize As Integer, bytes As Long
-
- dsize = datasize
- While (size < datasize)
- bytes = send(HTTP_Socket, dbuffer, dsize, 0)
- If bytes < 0 Then Return -1
- dbuffer += bytes
- dsize -= bytes
- size += bytes
- WEnd
-
- Return size
- End Function
- Function HTTP_ReadyToGet As Byte
- If HTTP_Socket < 0 Then Return -1
-
- FD_ZERO(@HTTP_readfds)
- FD_SET_(HTTP_Socket, @HTTP_readfds)
- If select_(HTTP_Socket + 1, @HTTP_readfds, 0, 0, @HTTP_timeout) = -1 Then Return -1
-
- Return IIf(FD_ISSET(HTTP_Socket, @HTTP_readfds), -1, 0)
- End Function
- Function HTTP_ReadyToPut As Byte
- If HTTP_Socket < 0 Then Return -1
-
- FD_ZERO(@HTTP_writefds)
- FD_SET_(HTTP_Socket, @HTTP_writefds)
- If select_(HTTP_Socket + 1, 0, @HTTP_writefds, 0, @HTTP_timeout) = -1 Then Return -1
-
- Return IIf(FD_ISSET(HTTP_Socket, @HTTP_writefds), -1, 0)
- End Function
- Sub HTTP_Start
- Static already_initialised As Byte = 0
- #ifdef __FB_WIN32__
- If Not already_initialised Then
- Dim wdata As WSAData
- WSAStartup(WINSOCK_VERSION, @wdata)
- already_initialised = -1
- End If
- #endif
- End Sub
- Function HTTP_GetClient As Long
- Dim ip As Long
-
- FD_ZERO(@HTTP_readfd)
- FD_SET_(HTTP_Socket, @HTTP_readfd)
-
- If select_(HTTP_Socket + 1, @HTTP_readfd, 0, 0, @HTTP_timeout) = -1 _
- Then Return 0
-
- If FD_ISSET(HTTP_Socket, @HTTP_readfd) Then
- ip = accept(HTTP_Socket, 0, 0)
- If ip = -1 Then Return 0
- Return ip
- Else
- Return 0
- End If
- End Function
|