UDP.pbi for Linux

Share your advanced PureBasic knowledge/code with the community.
User avatar
Deeem2031
Enthusiast
Enthusiast
Posts: 216
Joined: Sat Sep 20, 2003 3:57 pm
Location: Germany
Contact:

UDP.pbi for Linux

Post by Deeem2031 »

Code updated For 5.20+

All Procs except EasyUDPSend() and UDPGetLocalIP() of the UDP-Lib by Purefan translated to Linux-PB:

Code: Select all

;UDP.pbi Version 1.2 by Deeem2031 (13.11.2005)

#SOCK_STREAM = 1
#SOCK_DGRAM = 2
#SOCK_RAW = 3
#SOCK_RDM = 4
#SOCK_SEQPACKET = 5
#SOCK_PACKET = 10

#PF_UNSPEC = 0	; Unspecified.  
#PF_LOCAL = 1 ; Local To host (pipes And file-domain).  
#PF_UNIX = #PF_LOCAL ; Old BSD name For PF_LOCAL.  
#PF_FILE = #PF_LOCAL ; Another non-standard name For PF_LOCAL.  
#PF_INET = 2 ; IP protocol family.  
#PF_AX25 = 3 ; Amateur Radio AX.25.  
#PF_IPX = 4 ; Novell Internet Protocol.  
#PF_APPLETALK = 5 ; Appletalk DDP.  
#PF_NETROM = 6 ; Amateur radio NetROM.  
#PF_BRIDGE = 7 ; Multiprotocol bridge.  
#PF_ATMPVC = 8 ; ATM PVCs.  
#PF_X25 = 9 ; Reserved For X.25 project.  
#PF_INET6 = 10 ; IP version 6.  
#PF_ROSE = 11 ; Amateur Radio X.25 PLP.  
#PF_DECnet = 12 ; Reserved For DECnet project.  
#PF_NETBEUI = 13 ; Reserved For 802.2LLC project.  
#PF_SECURITY = 14 ; Security callback pseudo AF.  
#PF_KEY = 15 ; PF_KEY key management API.  
#PF_NETLINK = 16
#PF_ROUTE = #PF_NETLINK ; Alias To emulate 4.4BSD.  
#PF_PACKET = 17 ; Packet family.  
#PF_ASH = 18 ; Ash.  
#PF_ECONET = 19 ; Acorn Econet.  
#PF_ATMSVC = 20 ; ATM SVCs.  
#PF_SNA = 22 ; Linux SNA Project 
#PF_IRDA = 23 ; IRDA sockets.  
#PF_PPPOX = 24 ; PPPoX sockets.  
#PF_WANPIPE = 25 ; Wanpipe API sockets.  
#PF_BLUETOOTH = 31 ; Bluetooth sockets.  
#PF_MAX = 32 ; For now..  

#AF_UNSPEC = #PF_UNSPEC
#AF_LOCAL = #PF_LOCAL
#AF_UNIX = #PF_UNIX
#AF_FILE = #PF_FILE
#AF_INET = #PF_INET
#AF_AX25 = #PF_AX25
#AF_IPX = #PF_IPX
#AF_APPLETALK = #PF_APPLETALK
#AF_NETROM = #PF_NETROM
#AF_BRIDGE = #PF_BRIDGE
#AF_ATMPVC = #PF_ATMPVC
#AF_X25 = #PF_X25
#AF_INET6 = #PF_INET6
#AF_ROSE = #PF_ROSE
#AF_DECnet = #PF_DECnet
#AF_NETBEUI = #PF_NETBEUI
#AF_SECURITY = #PF_SECURITY
#AF_KEY = #PF_KEY
#AF_NETLINK = #PF_NETLINK
#AF_ROUTE = #PF_ROUTE
#AF_PACKET = #PF_PACKET
#AF_ASH = #PF_ASH
#AF_ECONET = #PF_ECONET
#AF_ATMSVC = #PF_ATMSVC
#AF_SNA = #PF_SNA
#AF_IRDA = #PF_IRDA
#AF_PPPOX = #PF_PPPOX
#AF_WANPIPE = #PF_WANPIPE
#AF_BLUETOOTH = #PF_BLUETOOTH
#AF_MAX = #PF_MAX

#SOL_RAW = 255
#SOL_DECNET = 261
#SOL_X25 = 262
#SOL_PACKET = 263
#SOL_ATM = 264	; ATM layer (cell level). 
#SOL_AAL = 265	; ATM Adaption Layer (packet level). 
#SOL_IRDA = 266

#INADDR_ANY	= $00000000 ; Address To accept any incoming messages.
#INADDR_BROADCAST = $ffffffff ; Address To send To all hosts.
#INADDR_NONE = $ffffffff ; Address indicating an error Return.

#__SOCKADDR_COMMON_SIZE = 2 ;SizeOf(unsigned short int)

#MSG_PEEK = 2

Structure in_addr
  s_addr.l
EndStructure

Structure sockaddr
  sa_family.w ;(unsigned short int)
  sa_data.b[14]
EndStructure

Structure sockaddr_in
  sin_family.w ;(unsigned short int)
  sin_port.w;			/* Port number.
  sin_addr.in_addr ;		/* Internet address.

  sin_zero.b[SizeOf(sockaddr)-#__SOCKADDR_COMMON_SIZE-SizeOf(word)-SizeOf(in_addr)] ; Pad To size of `struct sockaddr'.  
EndStructure

Structure pin_addr ;pointer to in_addr
  *in_addr.in_addr
EndStructure

Structure hostent
  h_name.s
  *h_aliases
  h_addrtype.l
  h_length.l
  StructureUnion
    *h_addrlist.pin_addr[0]
    *h_addr.pin_addr
  EndStructureUnion
EndStructure

Structure UDPConnect
  name.sockaddr_in
  socket.l
  hThread.l
  dataavailable.l
EndStructure

Structure UDPUserID
  port.w
  addr.in_addr
EndStructure

Procedure.l UDPHostByAlias(host.s)
  Protected *result.hostent
  
  *result = inet_addr_(host)
  If *result <> #INADDR_NONE
    ProcedureReturn *result
  EndIf
  *result = gethostbyname_(host)
  If *result <> 0
    ProcedureReturn *result\h_addr\in_addr\s_addr
  EndIf
  ProcedureReturn #INADDR_NONE
EndProcedure

Procedure UDPCaptureEventsThread(*ConnectID.UDPConnect)
  Protected length
  Repeat
    Repeat
      Delay(1)
      length = recv_(*ConnectID\socket,@r,0,#MSG_PEEK)
      Debug length
    Until length <> -1
    *ConnectID\dataavailable = 1
    Repeat
    Until *ConnectID\dataavailable = 0
  ForEver
EndProcedure

Procedure.l UDPInitNetwork()
  ProcedureReturn #True ;for win-compatibility
EndProcedure

Procedure.l UDPIsAvailable()
  ProcedureReturn #True ;for win-compatibility
EndProcedure

Procedure.l UDPCreateServer(Port, *ConnectID.UDPConnect)
  Protected sock, name.sockaddr_in

  sock = socket_(#PF_Inet, #SOCK_DGRAM, 0)
  If sock <> -1
    *ConnectID\name\sin_family = #AF_INET
    *ConnectID\name\sin_port = htons_(Port)
    *ConnectID\name\sin_addr\s_addr = htonl_(#INADDR_ANY)
    If bind_(sock, *ConnectID\name, SizeOf(sockaddr_in)) = 0
      *ConnectID\socket = sock
      ProcedureReturn #True
    EndIf
  EndIf
  ProcedureReturn #false
EndProcedure

Procedure.l UDPConnectServer(Port,host.s,*ConnectID.UDPConnect)
  *ConnectID\name\sin_port = htons_(port)
  *ConnectID\name\sin_family = #AF_INET
  *ConnectID\name\sin_addr\s_addr = UDPHostByAlias(host)
  *ConnectID\socket = socket_(#PF_INET,#SOCK_DGRAM,0)
  If *ConnectID\socket <> -1
    ProcedureReturn #True
  EndIf
  ProcedureReturn #False
EndProcedure

Procedure.l UDPStartCaptureEvents(*ConnectID.UDPConnect)
  If *ConnectID\hThread <> 0
    ProcedureReturn *ConnectID\hThread
  EndIf
  *ConnectID\hThread = CreateThread(@UDPCaptureEventsThread(),*ConnectID)
  ProcedureReturn *ConnectID\hThread
EndProcedure

Procedure UDPEndCaptureEvents(*ConnectID.UDPConnect)
  If *ConnectID\hThread <> 0
    KillThread(*ConnectID\hThread)
    *ConnectID\hThread = 0
  EndIf
EndProcedure

Procedure.l UDPReceive(*ConnectID.UDPConnect,Buffer,BufferLen)
  Protected fromlen
  If *ConnectID\hThread = 0 Or *ConnectID\Dataavailable = 0
    ProcedureReturn #False
  EndIf
  
  fromlen = SizeOf(sockaddr)
  *ConnectID\Dataavailable = 0
  ProcedureReturn recvfrom_(*ConnectID\socket,Buffer,BufferLen,0,*ConnectID\name,@fromlen)
EndProcedure

Procedure.l UDPWaitUntilReceive(*ConnectID.UDPConnect,Buffer,BufferLen)
  Protected fromlen
  
  fromlen = SizeOf(sockaddr)
  *ConnectID\Dataavailable = 0
  ProcedureReturn recvfrom_(*ConnectID\socket,Buffer,BufferLen,0,*ConnectID\name,@fromlen)
EndProcedure

Procedure.l UDPSend(*ConnectID.UDPConnect,Buffer,BufferLen)
  sendto_(*ConnectID\socket,Buffer,BufferLen,0,*ConnectID\name,SizeOf(sockaddr))
  ProcedureReturn #True
EndProcedure

Procedure UDPSaveUserID(*UserID.UDPUserID,*ConnectID.UDPConnect)
  *UserID\port = *ConnectID\name\sin_port
  *UserID\addr\s_addr = *ConnectID\name\sin_addr\s_addr
EndProcedure

Procedure UDPLoadUserID(*UserID.UDPUserID,*ConnectID.UDPConnect)
  *ConnectID\name\sin_port = *UserID\port
  *ConnectID\name\sin_addr\s_addr = *UserID\addr\s_addr
EndProcedure

Procedure.l UDPSendToUser(*ConnectID.UDPConnect,*UserID.UDPUserID,Buffer,BufferLen)
  *ConnectID\name\sin_port = *UserID\port
  *ConnectID\name\sin_addr\s_addr = *UserID\addr\s_addr
  sendto_(*ConnectID\socket,Buffer,BufferLen,0,*ConnectID\name,SizeOf(sockaddr))
  ProcedureReturn #True
EndProcedure

Procedure.l UDPDataAvailable(*ConnectID.UDPConnect)
  ProcedureReturn *ConnectID\DataAvailable
EndProcedure

Procedure.l UDPGetUserPort(*ConnectID.UDPConnect)
  ProcedureReturn htons_(*ConnectID\name\sin_port)
EndProcedure

Procedure.l UDPGetUserIP(*ConnectID.UDPConnect)
  ProcedureReturn *ConnectID\name\sin_addr\s_addr
EndProcedure

Procedure UDPCloseServer(*ConnectID.UDPConnect)
  UDPEndCaptureEvents(*ConnectID)
  close_(*ConnectID\socket)
EndProcedure

Procedure UDPCloseConnection(*ConnectID.UDPConnect)
  UDPEndCaptureEvents(*ConnectID)
  close_(*ConnectID\socket)
EndProcedure
Last edited by Deeem2031 on Sun Nov 13, 2005 8:49 pm, edited 1 time in total.
irc://irc.freenode.org/#purebasic
Nik
Addict
Addict
Posts: 1017
Joined: Fri May 13, 2005 11:45 pm
Location: Germany
Contact:

Post by Nik »

verry cool thx
Num3
PureBasic Expert
PureBasic Expert
Posts: 2812
Joined: Fri Apr 25, 2003 4:51 pm
Location: Portugal, Lisbon
Contact:

Post by Num3 »

RESPECT
DarkDragon
Addict
Addict
Posts: 2344
Joined: Mon Jun 02, 2003 9:16 am
Location: Germany
Contact:

Post by DarkDragon »

And my Server is on :D . But there is one problem: It often sends the same message more than once.
bye,
Daniel
Num3
PureBasic Expert
PureBasic Expert
Posts: 2812
Joined: Fri Apr 25, 2003 4:51 pm
Location: Portugal, Lisbon
Contact:

Post by Num3 »

DarkDragon wrote:And my Server is on :D . But there is one problem: It often sends the same message more than once.
That's because UDP is fire and forget... And the network propagation might duplicate the message ... Unlike TCP/IP there's no control if the message was received and how many times :P
dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

Post by dracflamloc »

Cool stuff, thanks

But hopefully with pb4 it wont be necessary anymore
DarkDragon
Addict
Addict
Posts: 2344
Joined: Mon Jun 02, 2003 9:16 am
Location: Germany
Contact:

Post by DarkDragon »

Num3 wrote:
DarkDragon wrote:And my Server is on :D . But there is one problem: It often sends the same message more than once.
That's because UDP is fire and forget... And the network propagation might duplicate the message ... Unlike TCP/IP there's no control if the message was received and how many times :P
Ohh yeah, but I thought it would only send it once and forget it.

[EDIT]

A little mod isn't that difficult, I'll make it for me.
bye,
Daniel
Tranquil
Addict
Addict
Posts: 952
Joined: Mon Apr 28, 2003 2:22 pm
Location: Europe

Post by Tranquil »

DarkDragon wrote:And my Server is on :D . But there is one problem: It often sends the same message more than once.
If you want to send datas that needs to be valid you should not use UDP, TCP is the right way for that kind of use.

UDP only makes sense if you send / receive datas that is not very critical to loose one package. Mediastreaming for example, searching for other Peers in a P2P network (it doent matter if you reach one or not).

Mike
Tranquil
DarkDragon
Addict
Addict
Posts: 2344
Joined: Mon Jun 02, 2003 9:16 am
Location: Germany
Contact:

Post by DarkDragon »

Tranquil wrote:
DarkDragon wrote:And my Server is on :D . But there is one problem: It often sends the same message more than once.
If you want to send datas that needs to be valid you should not use UDP, TCP is the right way for that kind of use.

UDP only makes sense if you send / receive datas that is not very critical to loose one package. Mediastreaming for example, searching for other Peers in a P2P network (it doent matter if you reach one or not).

Mike
I know I know, but I need it for a game, so it's better. Well, I need it also for the chat system, but I found the fault. UDP isn't the one who sends it more than once.
bye,
Daniel
Tranquil
Addict
Addict
Posts: 952
Joined: Mon Apr 28, 2003 2:22 pm
Location: Europe

Post by Tranquil »

For chat? maybe a message will not retrieve the recipient. or?
Tranquil
DarkDragon
Addict
Addict
Posts: 2344
Joined: Mon Jun 02, 2003 9:16 am
Location: Germany
Contact:

Post by DarkDragon »

Tranquil wrote:For chat? maybe a message will not retrieve the recipient. or?
-_- The chat is in the game and messages are mostly retrieved. And if it doesn't retrieve it it will send again if you move the player. But I like this thing!
bye,
Daniel
Post Reply