socket.bmx 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. Strict
  2. Rem
  3. bbdoc: Networking/Sockets
  4. End Rem
  5. Module BRL.Socket
  6. ModuleInfo "Version: 1.02"
  7. ModuleInfo "Author: Mark Sibly"
  8. ModuleInfo "License: zlib/libpng"
  9. ModuleInfo "Copyright: Blitz Research Ltd"
  10. ModuleInfo "Modserver: BRL"
  11. ModuleInfo "History: 1.02 Release"
  12. ModuleInfo "History: Fixed socket name 0 failing"
  13. Import Pub.StdC
  14. Private
  15. Extern "os"
  16. ?Win32
  17. Const FIONREAD=$4004667F
  18. Function ioctl_( socket,opt,buf:Byte Ptr )="ioctlsocket@12"
  19. ?MacOS
  20. Const FIONREAD=$4004667F
  21. Function ioctl_( socket,opt,buf:Byte Ptr )="ioctl"
  22. ?Linux
  23. Const FIONREAD=$541b
  24. Function ioctl_( socket,opt,buf:Byte Ptr )="ioctl"
  25. ?
  26. End Extern
  27. Public
  28. Type TSocketException
  29. Method ToString$()
  30. Return "Internal socket error"
  31. End Method
  32. End Type
  33. Type TSocket
  34. Method Send( buf:Byte Ptr,count,flags=0 )
  35. Local n=send_( _socket,buf,count,flags )
  36. If n<0 Return 0
  37. Return n
  38. End Method
  39. Method Recv( buf:Byte Ptr,count,flags=0 )
  40. Local n=recv_( _socket,buf,count,flags )
  41. If n<0 Return 0
  42. Return n
  43. End Method
  44. Method Close()
  45. If _socket<0 Return
  46. If _autoClose closesocket_ _socket
  47. _socket=-1
  48. _localIp=-1
  49. _localPort=-1
  50. _remoteIp=-1
  51. _remotePort=-1
  52. End Method
  53. Method Connected()
  54. If _socket<0 Return False
  55. Local read=_socket
  56. If select_( 1,Varptr read,0,Null,0,Null,0 )<>1 Or ReadAvail()<>0 Return True
  57. Close
  58. Return False
  59. End Method
  60. Method Bind( localPort )
  61. If bind_( _socket,AF_INET_,localPort )<0 Return False
  62. UpdateLocalName
  63. Return True
  64. End Method
  65. Method Connect( remoteIp,remotePort )
  66. Local addr=htonl_( remoteIp )
  67. If connect_( _socket,Varptr addr,AF_INET_,4,remotePort )<0 Return False
  68. UpdateLocalName
  69. UpdateRemoteName
  70. Return True
  71. End Method
  72. Method Listen( backlog )
  73. Return listen_( _socket,backlog )>=0
  74. End Method
  75. Method Accept:TSocket( timeout )
  76. Local read=_socket
  77. If select_( 1,Varptr read,0,Null,0,Null,timeout )<>1 Return
  78. Local client=accept_( _socket,Null,Null )
  79. If client>0 Return Create( client )
  80. End Method
  81. Method ReadAvail()
  82. Local n
  83. Local t=ioctl_( _socket,FIONREAD,Varptr n )
  84. If t<0 Return 0
  85. Return n
  86. End Method
  87. Method SetTCPNoDelay( enable )
  88. Local flag=enable
  89. setsockopt_( _socket,IPPROTO_TCP,TCP_NODELAY,Varptr flag,4 )
  90. End Method
  91. Method Socket()
  92. Return _socket
  93. End Method
  94. Method LocalIp()
  95. Return _localIp
  96. End Method
  97. Method LocalPort()
  98. Return _localPort
  99. End Method
  100. Method RemoteIp()
  101. Return _remoteIp
  102. End Method
  103. Method RemotePort()
  104. Return _remotePort
  105. End Method
  106. Method UpdateLocalName()
  107. Local addr:Byte[16],size=16
  108. If getsockname_( _socket,addr,size )<0
  109. _localIp=0
  110. _localPort=0
  111. EndIf
  112. _localIp=addr[4] Shl 24 | addr[5] Shl 16 | addr[6] Shl 8 | addr[7]
  113. _localPort=addr[2] Shl 8 | addr[3]
  114. End Method
  115. Method UpdateRemoteName()
  116. Local addr:Byte[16],size=16
  117. If getpeername_( _socket,addr,size )<0
  118. _remoteIp=0
  119. _remotePort=0
  120. Return
  121. EndIf
  122. _remoteIp=addr[4] Shl 24 | addr[5] Shl 16 | addr[6] Shl 8 | addr[7]
  123. _remotePort=addr[2] Shl 8 | addr[3]
  124. End Method
  125. Function Create:TSocket( socket,autoClose=True )
  126. If socket<0 Return
  127. Local addr:Byte[16],size
  128. Local t:TSocket=New TSocket
  129. t._socket=socket
  130. t._autoClose=autoClose
  131. t.UpdateLocalName
  132. t.UpdateRemoteName
  133. Return t
  134. End Function
  135. Function CreateUDP:TSocket()
  136. Local socket=socket_( AF_INET_,SOCK_DGRAM_,0 )
  137. If socket>=0 Return Create( socket,True )
  138. End Function
  139. Function CreateTCP:TSocket()
  140. Local socket=socket_( AF_INET_,SOCK_STREAM_,0 )
  141. If socket>=0 Return Create( socket,True )
  142. End Function
  143. Field _socket,_autoClose
  144. Field _localIp,_localPort
  145. Field _remoteIp,_remotePort
  146. End Type
  147. Rem
  148. bbdoc: Create a UDP socket
  149. returns: A new socket
  150. about:
  151. The new socket is not bound to any local or remote address.
  152. End Rem
  153. Function CreateUDPSocket:TSocket()
  154. Return TSocket.CreateUDP()
  155. End Function
  156. Rem
  157. bbdoc: Create a TCP socket
  158. returns: A new socket
  159. about:
  160. The new socket is not bound to any local or remote address.
  161. End Rem
  162. Function CreateTCPSocket:TSocket()
  163. Return TSocket.CreateTCP()
  164. End Function
  165. Rem
  166. bbdoc: Close a socket
  167. about:
  168. All sockets should eventually be closed. Once closed, a socket can no longer
  169. be used.
  170. End Rem
  171. Function CloseSocket( socket:TSocket )
  172. socket.Close
  173. End Function
  174. Rem
  175. bbdoc: Bind a socket to a local port
  176. returns: True if successful, otherwise false
  177. about:
  178. If @localPort is 0, a new local port will be allocated. If @localPort is not 0,
  179. #BindSocket will fail if there is already an application bound to @localPort.
  180. End Rem
  181. Function BindSocket( socket:TSocket,localPort )
  182. Return socket.Bind( localPort )
  183. End Function
  184. Rem
  185. bbdoc: Connect a socket to a remote ip and port
  186. returns: True if successful, otherwise false
  187. about:
  188. For both UDP and TCP sockets, #ConnectSocket will fail if the specified
  189. ip address could not be reached.
  190. In the case of TCP sockets, #ConnectSocket will also fail if there is
  191. no application listening at the remote port.
  192. End Rem
  193. Function ConnectSocket( socket:TSocket,remoteIp,remotePort )
  194. Return socket.Connect( remoteIp,remotePort )
  195. End Function
  196. Rem
  197. bbdoc: Start listening at a socket
  198. about:
  199. The specified socket must be a TCP socket, and must already be bound to a local port.
  200. End Rem
  201. Function SocketListen( socket:TSocket,backlog=0 )
  202. Return socket.Listen( backlog )
  203. End Function
  204. Rem
  205. bbdoc: Accept new connections on a listening socket
  206. returns: A new socket, or Null if no connection was made in the specified timeout
  207. about:
  208. The specified socket must be a TCP socket, and must be listening.
  209. End Rem
  210. Function SocketAccept:TSocket( socket:TSocket,timeout=0 )
  211. Return socket.Accept( timeout )
  212. End Function
  213. Rem
  214. bbdoc: Get socket connection status
  215. returns: True if socket is connected
  216. about:
  217. #SocketConnected allows you to determine if a TCP connection is still
  218. alive or has been remotely closed.
  219. #SocketConnected should only be used with TCP sockets that have already
  220. connected via #ConnectSocket or #SocketAccept.
  221. End Rem
  222. Function SocketConnected( socket:TSocket )
  223. Return socket.Connected()
  224. End Function
  225. Rem
  226. bbdoc: Get number of bytes available for reading from a socket
  227. returns: Number of bytes that may be read without causing the socket to block
  228. End Rem
  229. Function SocketReadAvail( socket:TSocket )
  230. Return socket.ReadAvail()
  231. End Function
  232. Rem
  233. bbdoc: Get local ip of a socket
  234. End Rem
  235. Function SocketLocalIP( socket:TSocket )
  236. Return socket.LocalIP()
  237. End Function
  238. Rem
  239. bbdoc: Get local port of a socket
  240. End Rem
  241. Function SocketLocalPort( socket:TSocket )
  242. Return socket.LocalPort()
  243. End Function
  244. Rem
  245. bbdoc: Get remote ip of a socket
  246. End Rem
  247. Function SocketRemoteIP( socket:TSocket )
  248. Return socket.RemoteIP()
  249. End Function
  250. Rem
  251. bbdoc: Get remote port of a socket
  252. End Rem
  253. Function SocketRemotePort( socket:TSocket )
  254. Return socket.RemotePort()
  255. End Function
  256. Rem
  257. bbdoc: Convert an ip address to a dotted string
  258. returns: Dotted string version of ip address
  259. End Rem
  260. Function DottedIP$( ip )
  261. Return (ip Shr 24)+"."+(ip Shr 16 & 255)+"."+(ip Shr 8 & 255 )+"."+(ip & 255)
  262. End Function
  263. Rem
  264. bbdoc: Convert a host name to an ip address
  265. returns: Host ip address, or 0 if host not found
  266. End Rem
  267. Function HostIp( HostName$,index=0 )
  268. If index<0 Return
  269. Local ips[]=HostIps( HostName )
  270. If index<ips.length Return ips[index]
  271. Return
  272. End Function
  273. Rem
  274. bbdoc: Get all ip addresses for a host name
  275. returns: Array of host ips, or Null if host not found
  276. End Rem
  277. Function HostIps:Int[]( HostName$ )
  278. Local addr_type,addr_len
  279. Local addrs:Byte Ptr Ptr=gethostbyname_( HostName,addr_type,addr_len )
  280. If addrs=Null Or addr_type<>AF_INET_ Or addr_len<>4 Return
  281. Local n
  282. While addrs[n]
  283. n:+1
  284. Wend
  285. Local ips[n]
  286. For Local i=0 Until n
  287. Local p:Byte Ptr=addrs[i]
  288. ips[i]=p[0] Shl 24 | p[1] Shl 16 | p[2] Shl 8 | p[3]
  289. Next
  290. Return ips
  291. End Function
  292. Rem
  293. bbdoc: Convert a host ip address to a name
  294. returns: Name of host, or Null if host not found
  295. End Rem
  296. Function HostName$( HostIp )
  297. Local addr=htonl_( HostIp )
  298. Local p:Byte Ptr=gethostbyaddr_( Varptr addr,4,AF_INET_ )
  299. If p Return String.FromCString(p)
  300. End Function