socket.bmx 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. Strict
  2. Rem
  3. bbdoc: Networking/Sockets
  4. End Rem
  5. Module BRL.Socket
  6. ModuleInfo "Version: 1.03"
  7. ModuleInfo "Author: Mark Sibly and Bruce A Henderson"
  8. ModuleInfo "License: zlib/libpng"
  9. ModuleInfo "Copyright: Blitz Research Ltd"
  10. ModuleInfo "Modserver: BRL"
  11. ModuleInfo "History: 1.03"
  12. ModuleInfo "History: Added IPV6 support."
  13. ModuleInfo "History: 1.02 Release"
  14. ModuleInfo "History: Fixed socket name 0 failing"
  15. Import Pub.StdC
  16. Private
  17. Extern "os"
  18. ?Win32
  19. Const FIONREAD=$4004667F
  20. Function ioctl_( socket,opt,buf:Byte Ptr )="int ioctlsocket(SOCKET ,long ,u_long *)!"
  21. ?MacOS
  22. Const FIONREAD=$4004667F
  23. Function ioctl_( socket,opt,buf:Byte Ptr )="ioctl"
  24. ?Linux
  25. Const FIONREAD=$541b
  26. Function ioctl_( socket,opt,buf:Byte Ptr )="ioctl"
  27. ?emscripten
  28. Const FIONREAD=$541b
  29. Function ioctl_( socket,opt,buf:Byte Ptr )="ioctl"
  30. ?nx
  31. Const FIONREAD=$4004667F
  32. Function ioctl_( socket,opt,buf:Byte Ptr )="ioctl"
  33. ?
  34. End Extern
  35. Public
  36. Type TSocketException
  37. Method ToString$() Override
  38. Return "Internal socket error"
  39. End Method
  40. End Type
  41. Type TSocket
  42. Method Send:Size_T( buf:Byte Ptr, count:Size_T, flags:Int = 0 )
  43. Local n:Size_T=send_( _socket,buf,count,flags )
  44. If n<0 Return 0
  45. Return n
  46. End Method
  47. Method Recv:Size_T( buf:Byte Ptr, count:Size_T, flags:Int = 0 )
  48. Local n:Size_T=recv_( _socket,buf,count,flags )
  49. If n<0 Return 0
  50. Return n
  51. End Method
  52. Method Close()
  53. If _socket<0 Return
  54. If _autoClose closesocket_ _socket
  55. _socket=-1
  56. _localIp=""
  57. _localPort=-1
  58. _remoteIp=""
  59. _remotePort=-1
  60. End Method
  61. Method Connected()
  62. If _socket<0 Return False
  63. Local Read=_socket
  64. If select_( 1,Varptr Read,0,Null,0,Null,0 )<>1 Or ReadAvail()<>0 Return True
  65. Close
  66. Return False
  67. End Method
  68. Method Bind:Int( localPort:Int, family:Int = AF_INET_ )
  69. If bind_( _socket,family,localPort )<0 Return False
  70. UpdateLocalName
  71. Return True
  72. End Method
  73. Method Bind:Int( info:TAddrInfo )
  74. If bmx_stdc_bind_info( _socket, info.infoPtr ) < 0 Then
  75. Return False
  76. End If
  77. UpdateLocalName
  78. Return True
  79. End Method
  80. Method Connect:Int( AddrInfo:TAddrInfo )
  81. If connect_( _socket, AddrInfo.infoPtr )<0 Return False
  82. UpdateLocalName
  83. UpdateRemoteName
  84. Return True
  85. End Method
  86. Method Listen:Int( backlog:Int )
  87. Return listen_( _socket,backlog )>=0
  88. End Method
  89. Method Accept:TSocket( timeout:Int = -1, storage:TSockaddrStorage = Null )
  90. If timeout >= 0 Then
  91. Local Read:Int = _socket
  92. If select_( 1,Varptr Read,0,Null,0,Null,timeout )<>1 Then
  93. Return
  94. End If
  95. End If
  96. Local client:Int
  97. If storage Then
  98. client = bmx_stdc_accept_(_socket, storage.storagePtr)
  99. Else
  100. client = bmx_stdc_accept_(_socket, Null)
  101. End If
  102. If client > 0 Then
  103. Return Create( client )
  104. End If
  105. End Method
  106. Method ReadAvail:Int()
  107. Local n
  108. Local t=ioctl_( _socket,FIONREAD,Varptr n )
  109. If t<0 Return 0
  110. Return n
  111. End Method
  112. Method SetTCPNoDelay( enable )
  113. Local flag=enable
  114. setsockopt_( _socket,IPPROTO_TCP,TCP_NODELAY,Varptr flag,4 )
  115. End Method
  116. Method SetSockOpt:Int(level:Int, optname:Int, enable:Int)
  117. Local flag:Int = enable
  118. If setsockopt_(_socket, level, optname, Varptr flag, 4) < 0 Then
  119. Return False
  120. End If
  121. Return True
  122. End Method
  123. Method Socket:Int()
  124. Return _socket
  125. End Method
  126. Method LocalIp:String()
  127. Return _localIp
  128. End Method
  129. Method LocalPort:Int()
  130. Return _localPort
  131. End Method
  132. Method RemoteIp:String()
  133. Return _remoteIp
  134. End Method
  135. Method RemotePort:Int()
  136. Return _remotePort
  137. End Method
  138. Method UpdateLocalName()
  139. _localIp = bmx_stdc_getsockname(_socket, _localPort)
  140. End Method
  141. Method UpdateRemoteName()
  142. _remoteIp = bmx_stdc_getpeername(_socket, _remotePort)
  143. End Method
  144. Function Create:TSocket( socket:Int, autoClose:Int = True )
  145. If socket < 0 Then
  146. Return
  147. End If
  148. Local addr:Byte[16],size:Int
  149. Local t:TSocket = New TSocket
  150. t._socket = socket
  151. t._autoClose = autoClose
  152. t.UpdateLocalName
  153. t.UpdateRemoteName
  154. Return t
  155. End Function
  156. Function CreateUDP:TSocket(family:Int = AF_INET_)
  157. Local socket=socket_( family,SOCK_DGRAM_,0 )
  158. If socket>=0 Return Create( socket,True )
  159. End Function
  160. Function CreateTCP:TSocket(family:Int = AF_INET_)
  161. Local socket=socket_( family,SOCK_STREAM_,0 )
  162. If socket>=0 Return Create( socket,True )
  163. End Function
  164. Rem
  165. bbdoc:
  166. End Rem
  167. Function Create:TSocket(info:TAddrInfo)
  168. Local socket:Int = socket_( info.family(),info.sockType(),info.protocol() )
  169. If socket >= 0 Then
  170. Return Create( socket, True )
  171. End If
  172. End Function
  173. Field _socket:Int,_autoClose:Int
  174. Field _localIp:String,_localPort:Int
  175. Field _remoteIp:String,_remotePort:Int
  176. End Type
  177. Rem
  178. bbdoc: Create a UDP socket
  179. returns: A new socket
  180. about:
  181. The new socket is not bound to any local or remote address.
  182. End Rem
  183. Function CreateUDPSocket:TSocket()
  184. Return TSocket.CreateUDP()
  185. End Function
  186. Rem
  187. bbdoc: Create a TCP socket
  188. returns: A new socket
  189. about:
  190. The new socket is not bound to any local or remote address.
  191. End Rem
  192. Function CreateTCPSocket:TSocket()
  193. Return TSocket.CreateTCP()
  194. End Function
  195. Rem
  196. bbdoc: Close a socket
  197. about:
  198. All sockets should eventually be closed. Once closed, a socket can no longer
  199. be used.
  200. End Rem
  201. Function CloseSocket( socket:TSocket )
  202. socket.Close
  203. End Function
  204. Rem
  205. bbdoc: Bind a socket to a local port
  206. returns: True if successful, otherwise false
  207. about:
  208. If @localPort is 0, a new local port will be allocated. If @localPort is not 0,
  209. #BindSocket will fail if there is already an application bound to @localPort.
  210. End Rem
  211. Function BindSocket( socket:TSocket, localPort, family:Int = AF_INET_)
  212. Return socket.Bind( localPort, family )
  213. End Function
  214. Rem
  215. bbdoc: Connect a socket to a remote ip and port
  216. returns: True if successful, otherwise false
  217. about:
  218. For both UDP and TCP sockets, #ConnectSocket will fail if the specified
  219. ip address could not be reached.
  220. In the case of TCP sockets, #ConnectSocket will also fail if there is
  221. no application listening at the remote port.
  222. End Rem
  223. Function ConnectSocket( socket:TSocket, AddrInfo:TAddrInfo )
  224. Return socket.Connect( AddrInfo )
  225. End Function
  226. Rem
  227. bbdoc: Start listening at a socket
  228. about:
  229. The specified socket must be a TCP socket, and must already be bound to a local port.
  230. End Rem
  231. Function SocketListen( socket:TSocket,backlog=0 )
  232. Return socket.Listen( backlog )
  233. End Function
  234. Rem
  235. bbdoc: Accept new connections on a listening socket
  236. returns: A new socket, or Null if no connection was made in the specified timeout
  237. about:
  238. The specified socket must be a TCP socket, and must be listening.
  239. End Rem
  240. Function SocketAccept:TSocket( socket:TSocket,timeout=0 )
  241. Return socket.Accept( timeout )
  242. End Function
  243. Rem
  244. bbdoc: Get socket connection status
  245. returns: True if socket is connected
  246. about:
  247. #SocketConnected allows you to determine if a TCP connection is still
  248. alive or has been remotely closed.
  249. #SocketConnected should only be used with TCP sockets that have already
  250. connected via #ConnectSocket or #SocketAccept.
  251. End Rem
  252. Function SocketConnected( socket:TSocket )
  253. Return socket.Connected()
  254. End Function
  255. Rem
  256. bbdoc: Get number of bytes available for reading from a socket
  257. returns: Number of bytes that may be read without causing the socket to block
  258. End Rem
  259. Function SocketReadAvail( socket:TSocket )
  260. Return socket.ReadAvail()
  261. End Function
  262. Rem
  263. bbdoc: Get local ip of a socket
  264. End Rem
  265. Function SocketLocalIP:String( socket:TSocket )
  266. Return socket.LocalIP()
  267. End Function
  268. Rem
  269. bbdoc: Get local port of a socket
  270. End Rem
  271. Function SocketLocalPort( socket:TSocket )
  272. Return socket.LocalPort()
  273. End Function
  274. Rem
  275. bbdoc: Get remote ip of a socket
  276. End Rem
  277. Function SocketRemoteIP:String( socket:TSocket )
  278. Return socket.RemoteIP()
  279. End Function
  280. Rem
  281. bbdoc: Get remote port of a socket
  282. End Rem
  283. Function SocketRemotePort( socket:TSocket )
  284. Return socket.RemotePort()
  285. End Function
  286. Rem
  287. bbdoc: Convert an ip address to a dotted string
  288. returns: Dotted string version of ip address
  289. End Rem
  290. Function DottedIP$( ip:Int )
  291. Return (ip Shr 24)+"."+(ip Shr 16 & 255)+"."+(ip Shr 8 & 255 )+"."+(ip & 255)
  292. End Function
  293. Rem
  294. bbdoc: Converts a dotted IPv4 string to an ip address.
  295. returns: An integer version of an ip address.
  296. End Rem
  297. Function DottedIPToInt:Int(addr:String)
  298. Local parts:String[] = addr.Split(".")
  299. Local num:Long
  300. For Local i:Int = 0 Until parts.length
  301. Local power:Int = 3 - i
  302. num :+ (parts[i].ToInt() Mod 256) * (256 ^ power)
  303. Next
  304. Return num
  305. End Function
  306. Rem
  307. bbdoc: Converts an IP address string into a binary representation.
  308. about: For AF_INET_, @dst should be an Int or 32-bit (4 bytes) in size.
  309. For AF_INET6_, @dst should be 128-bits (16 bytes) in size.
  310. End Rem
  311. Function InetPton:Int(family:Int, src:String, dst:Byte Ptr)
  312. Return inet_pton_(family, src, dst)
  313. End Function
  314. Rem
  315. bbdoc: Convert a host name to an ip address
  316. returns: Host ip address, or 0 if host not found
  317. End Rem
  318. Function HostIp:String( HostName$, index:Int=0, family:Int = AF_UNSPEC_ )
  319. If index<0 Return
  320. Local ips:String[]=HostIps( HostName, family )
  321. If index < ips.length Then
  322. Return ips[index]
  323. End If
  324. End Function
  325. Rem
  326. bbdoc: Get all ip addresses for a host name
  327. returns: Array of host ips, or Null if host not found
  328. End Rem
  329. Function HostIps:String[]( HostName$, family:Int = AF_UNSPEC_ )
  330. Local addr:TAddrInfo[] = AddrInfo(HostName, , family)
  331. Local ips:String[] = New String[addr.length]
  332. For Local i:Int = 0 Until addr.length
  333. ips[i] = addr[i].HostIp()
  334. Next
  335. Return ips
  336. End Function
  337. Rem
  338. bbdoc: Convert a host ip address to a name
  339. returns: Name of host, or Null if host not found
  340. End Rem
  341. Function HostName$( HostIp:String, family:Int = AF_UNSPEC_ )
  342. Local addr:TAddrInfo[] = AddrInfo(HostIp, , family)
  343. If addr Then
  344. Return addr[0].HostName()
  345. End If
  346. End Function
  347. Rem
  348. bbdoc: Returns an array of TAddrInfo objects.
  349. End Rem
  350. Function AddrInfo:TAddrInfo[](host:String, service:String = "http", family:Int = AF_UNSPEC_)
  351. Return getaddrinfo_(host, service, family)
  352. End Function
  353. Rem
  354. bbdoc: Returns an array of TAddrInfo objects.
  355. End Rem
  356. Function AddrInfo:TAddrInfo[](host:String, service:String, hints:TAddrInfo)
  357. Return getaddrinfo_hints(host, service, hints.infoPtr)
  358. End Function