fb:porticula NoPaste
TSNE_V2.bi
Uploader: | ThePuppetMaster |
Datum/Zeit: | 31.12.2007 03:38:18 |
'#####################################################################################################
'#####################################################################################################
' TSNE_V2 - TCP Socket Networking [Eventing] Version: 2
'#####################################################################################################
'#####################################################################################################
' 2007 By.: /_\ DeltaLab's - Deutschland
' Autor: Martin Wiemann
'#####################################################################################################
'##############################################################################################################
#IFDEF __FB_LINUX__
#INCLUDE "crt/stdlib.bi"
#INCLUDE "crt/unistd.bi"
#INCLUDE "crt/sys/types.bi"
#INCLUDE "crt/sys/socket.bi"
#INCLUDE "crt/netinet/in.bi"
#INCLUDE "crt/arpa/inet.bi"
#INCLUDE "crt/netdb.bi"
#DEFINE h_addr h_addr_list[0]
#DEFINE CloseSocket_(_a_) close_(_a_)
#DEFINE INVALID_SOCKET (Cast(Socket, -1))
#ELSE
#DEFINE WIN_INCLUDEALL
#INCLUDE "windows.bi"
#INCLUDE "win\winsock.bi"
#DEFINE close_(_a_) closesocket(_a_)
#DEFINE memcpy(x__, y__, z__) movememory(x__, y__, z__)
SUB StartWinsock() CONSTRUCTOR
DIM xwsa AS WSADATA
WSAStartup(MAKEWORD(2,0),@xwsa)
END SUB
SUB EndWinsock DESTRUCTOR
WSAcleanup()
END SUB
#Endif
'##############################################################################################################
Const TSNE_BufferSize as Long = 8000
'##############################################################################################################
Enum TSNE_Event
TSNEE_Disconnect = 0
TSNEE_Connect = 1
TSNEE_NewConnection = 2
TSNEE_NewData = 3
End Enum
'--------------------------------------------------------------------------------------------------------------
Type TSNE_Event_Type
TSNE_Disconnected as Sub (ByVal V_TSNEID as UInteger)
TSNE_Connected as Sub (ByVal V_TSNEID as UInteger)
TSNE_NewConnection as Sub (ByVal V_TSNEID as UInteger, ByVal V_RequestID as Socket)
TSNE_NewData as Sub (ByVal V_TSNEID as UInteger, ByRef V_Data as String)
End Type
Type TSNE_Socket
V_Event as TSNE_Event_Type
V_Socket as Socket
V_IsServer as Long
V_IPA as String
V_Port as USHORT
T_DataIn as ULongInt
T_DataOut as ULongInt
T_ThreadOn as Long
End Type
Dim Shared TSNED() as TSNE_Socket
Dim Shared TSNEC as UInteger
Dim Shared TSNEMux as any PTR
'##############################################################################################################
SUB TSNE_Init() CONSTRUCTOR
TSNEMux = MutexCreate
END SUB
'--------------------------------------------------------------------------------------------------------------
SUB TSNE_Term() DESTRUCTOR
MutexDestroy(TSNEMux)
END SUB
'##############################################################################################################
Declare Sub Thread_Event (ByVal V_TSNEID as UInteger)
Declare Function TSNE_Stats (ByVal V_TSNEID as UInteger, ByRef B_RX as ULongInt, ByRef B_TX as ULongInt) as Long
Declare Function TSNE_Disconnect (ByVal V_TSNEID as UInteger) as Long
Declare Function TSNE_Create_Server (ByRef B_TSNEID as UInteger, ByRef V_Port as USHORT, ByRef MaxSimultanConnectionRequests as Long = 10, ByVal V_EventNewConPTR as any PTR) as Long
Declare Function TSNE_Create_Client (ByRef B_TSNEID as UInteger, ByVal V_IPA as String, ByVal V_Port as USHORT, ByVal V_EventDisconPTR as any PTR, ByVal V_EventConPTR as any PTR, ByVal V_EventNewDataPTR as any PTR) as Long
Declare Function TSNE_Create_Accept (ByVal V_RequestID as Socket, ByRef B_TSNEID as UInteger, ByRef B_IPA as String, ByVal V_EventDisconPTR as any PTR, ByVal V_EventConPTR as any PTR, ByVal V_EventNewDataPTR as any PTR) as Long
Declare Function TSNE_Data_Send (ByVal V_TSNEID as UInteger, ByRef V_Data as String) as Long
Declare Sub TSNE_WaitClose (ByRef V_TSNEID as UInteger)
Declare Function TSNE_IsClosed (ByRef V_TSNEID as UInteger) as Long
'##############################################################################################################
Function TSNE_Stats(ByVal V_TSNEID as UInteger, ByRef B_RX as ULongInt, ByRef B_TX as ULongInt) as Long
TSNE_Stats = -1
If V_TSNEID <= 0 or V_TSNEID > TSNEC Then Return -12
MutexLock(TSNEMux)
B_RX = TSNED(V_TSNEID).T_DataIn
B_TX = TSNED(V_TSNEID).T_DataOut
MutexUnLock(TSNEMux)
Return 0
End Function
'##############################################################################################################
Function TSNE_Disconnect(ByVal V_TSNEID as UInteger) as Long
TSNE_Disconnect = -1
If V_TSNEID <= 0 or V_TSNEID > TSNEC Then Return -12
Dim TT as TSNE_Socket
MutexLock(TSNEMux)
TT = TSNED(V_TSNEID)
MutexUnLock(TSNEMux)
If TT.V_Socket <> INVALID_SOCKET Then
close_(TT.V_Socket)
MutexLock(TSNEMux)
TSNED(V_TSNEID).V_Socket = INVALID_SOCKET
MutexUnLock(TSNEMux)
If TT.V_Event.TSNE_Disconnected <> 0 Then TT.V_Event.TSNE_Disconnected(V_TSNEID)
Return 0
Else
MutexLock(TSNEMux)
TSNED(V_TSNEID).V_Socket = INVALID_SOCKET
MutexUnLock(TSNEMux)
Return -3
End If
Return -1
End Function
'--------------------------------------------------------------------------------------------------------------
Function TSNE_Create_Server(ByRef B_TSNEID as UInteger, ByRef V_Port as USHORT, ByRef MaxSimultanConnectionRequests as Long = 10, ByVal V_EventNewConPTR as any PTR) as Long
TSNE_Create_Server = -1
B_TSNEID = 0
If MaxSimultanConnectionRequests <= 0 or MaxSimultanConnectionRequests > 4096 Then Return -8
If V_Port < 0 or V_Port > 65535 Then Return -9
DIM BV AS LONG
Dim TSID as UInteger
Dim X as UInteger
MutexLock(TSNEMux)
For X = 1 to TSNEC
If TSNED(X).V_Socket = INVALID_SOCKET Then TSID = X: Exit For
Next
MutexUnLock(TSNEMux)
DIM TSock AS Socket
TSock = opensocket(AF_INET, SOCK_STREAM, IPPROTO_IP)
IF TSock = INVALID_SOCKET THEN Return -4
DIM TADDR AS SOCKADDR_IN
TADDR.sin_family = AF_INET
TADDR.sin_port = htons(V_Port)
TADDR.sin_addr.s_addr = INADDR_ANY
BV = bind(TSock, CPTR(SOCKADDR PTR, @TADDR), SIZEOF(SOCKADDR_IN))
IF BV = SOCKET_ERROR THEN Return - 5
BV = listen(TSock, MaxSimultanConnectionRequests)
IF BV = SOCKET_ERROR THEN Return -6
Dim TSD as TSNE_Socket
With TSD
.V_Socket = TSock
.V_IPA = ""
.V_Port = V_Port
.V_IsServer = 1
.T_ThreadOn = 1
.V_Event.TSNE_NewConnection = V_EventNewConPTR
End With
MutexLock(TSNEMux)
If TSID = 0 Then
TSNEC += 1
TSID = TSNEC
Redim Preserve TSNED(TSNEC) as TSNE_Socket
End if
TSNED(TSID) = TSD
MutexUnLock(TSNEMux)
B_TSNEID = TSID
ThreadCreate(cast(Any Ptr, @Thread_Event), cast(Any Ptr, B_TSNEID))
Return 0
End Function
'--------------------------------------------------------------------------------------------------------------
Function TSNE_Create_Client(ByRef B_TSNEID as UInteger, ByVal V_IPA as String, ByVal V_Port as USHORT, ByVal V_EventDisconPTR as any PTR, ByVal V_EventConPTR as any PTR, ByVal V_EventNewDataPTR as any PTR) as Long
TSNE_Create_Client = -1
B_TSNEID = 0
If V_Port < 0 or V_Port > 65535 Then Return -9
DIM TSock AS Socket
DIM TADDR AS SOCKADDR_IN
DIM TADDRIN AS in_addr
DIM XHost AS hostent PTR
DIM BV AS USHORT
Dim TSID as UInteger
Dim X as UInteger
MutexLock(TSNEMux)
For X = 1 to TSNEC
If TSNED(X).V_Socket = INVALID_SOCKET Then TSID = X: Exit For
Next
MutexUnLock(TSNEMux)
TADDRIN.s_addr = inet_addr(STRPTR(V_IPA))
IF (TADDRIN.s_addr = -1) THEN
XHost = gethostbyname(STRPTR(V_IPA))
IF XHost = 0 THEN RETURN -10
TADDRIN = *CAST(in_addr PTR, XHost->h_addr_list[0])
IF TADDRIN.s_addr = INADDR_NONE THEN RETURN -10
END IF
TADDR.sin_family = AF_INET
TADDR.sin_port = htons(V_Port)
TADDR.sin_addr = TADDRIN
TSock = opensocket(PF_INET, SOCK_STREAM, 0)
IF TSock = INVALID_SOCKET THEN RETURN -4
BV = connect(TSock, CPTR(SOCKADDR PTR,@TADDR), SIZEOF(SOCKADDR))
IF BV = SOCKET_ERROR THEN RETURN -11
Dim TSD as TSNE_Socket
With TSD
.V_Socket = TSock
.V_IPA = V_IPA
.V_Port = V_Port
.V_IsServer = 0
.T_ThreadOn = 1
.V_Event.TSNE_Disconnected = V_EventDisconPTR
.V_Event.TSNE_Connected = V_EventConPTR
.V_Event.TSNE_NewData = V_EventNewDataPTR
End With
MutexLock(TSNEMux)
If TSID = 0 Then
TSNEC += 1
TSID = TSNEC
Redim Preserve TSNED(TSNEC) as TSNE_Socket
End if
TSNED(TSID) = TSD
MutexUnLock(TSNEMux)
B_TSNEID = TSID
ThreadCreate(cast(Any Ptr, @Thread_Event), cast(Any Ptr, B_TSNEID))
RETURN 0
End Function
'--------------------------------------------------------------------------------------------------------------
Function TSNE_Create_Accept(ByVal V_RequestID as Socket, ByRef B_TSNEID as UInteger, ByRef B_IPA as String, ByVal V_EventDisconPTR as any PTR, ByVal V_EventConPTR as any PTR, ByVal V_EventNewDataPTR as any PTR) as Long
TSNE_Create_Accept = -1
DIM TADDR AS SOCKADDR_IN
DIM XSize AS LONG = 16
Dim TSD as TSNE_Socket
Dim TSID as UInteger
Dim X as UInteger
MutexLock(TSNEMux)
For X = 1 to TSNEC
If TSNED(X).V_Socket = INVALID_SOCKET Then TSID = X: Exit For
Next
MutexUnLock(TSNEMux)
With TSD
.V_Socket = V_RequestID
.V_Event.TSNE_Disconnected = V_EventDisconPTR
.V_Event.TSNE_Connected = V_EventConPTR
.V_Event.TSNE_NewData = V_EventNewDataPTR
IF getpeername (V_RequestID, CAST(sockaddr PTR, @TADDR), @XSize) = 0 THEN .V_IPA = *inet_ntoa(TADDR.sin_addr)
B_IPA = .V_IPA
.T_ThreadOn = 1
End With
MutexLock(TSNEMux)
If TSID = 0 Then
TSNEC += 1
TSID = TSNEC
Redim Preserve TSNED(TSNEC) as TSNE_Socket
End if
TSNED(TSID) = TSD
MutexUnLock(TSNEMux)
B_TSNEID = TSID
ThreadCreate(cast(Any Ptr, @Thread_Event), cast(Any Ptr, B_TSNEID))
RETURN 0
End Function
'--------------------------------------------------------------------------------------------------------------
Function TSNE_Data_Send(ByVal V_TSNEID as UInteger, ByRef V_Data as String) as Long
TSNE_Data_Send = -1
If V_TSNEID <= 0 or V_TSNEID > TSNEC Then Return -12
MutexLock(TSNEMux)
If TSNED(V_TSNEID).V_Socket = INVALID_SOCKET Then
MutexUnLock(TSNEMux)
Return -12
End If
MutexUnLock(TSNEMux)
DIM XTemp AS STRING
DIM XSC AS LONG
DIM XLen AS LONG
DIM BV AS LONG
Dim TSock as Socket
MutexLock(TSNEMux)
TSock = TSNED(V_TSNEID).V_Socket
MutexUnLock(TSNEMux)
XTemp = V_Data
XLen = Len(XTemp)
DO
BV = send(TSock, STRPTR(XTemp) + XSC, XLen - XSC, MSG_NOSIGNAL)
IF BV > 0 THEN
XSC += BV
ELSEIF BV = 0 THEN
ELSE: exit do
END IF
LOOP UNTIL XSC = XLen
MutexLock(TSNEMux)
TSNED(V_TSNEID).T_DataOut += XSC
MutexUnLock(TSNEMux)
RETURN XSC
End Function
'--------------------------------------------------------------------------------------------------------------
Sub TSNE_WaitClose(ByRef V_TSNEID as UInteger)
If V_TSNEID <= 0 or V_TSNEID > TSNEC Then Exit Sub
MutexLock(TSNEMux)
If TSNED(V_TSNEID).V_Socket = INVALID_SOCKET Then
MutexUnLock(TSNEMux)
Exit Sub
End If
MutexUnLock(TSNEMux)
Do
MutexLock(TSNEMux)
If TSNED(V_TSNEID).T_ThreadOn = 0 Then Exit Do
MutexUnLock(TSNEMux)
Sleep 1
Loop
MutexUnLock(TSNEMux)
End Sub
'--------------------------------------------------------------------------------------------------------------
Function TSNE_IsClosed(ByRef V_TSNEID as UInteger) as Long
If V_TSNEID <= 0 or V_TSNEID > TSNEC Then Return 0
MutexLock(TSNEMux)
If TSNED(V_TSNEID).V_Socket = INVALID_SOCKET Then MutexUnLock(TSNEMux): Return 1
If TSNED(V_TSNEID).T_ThreadOn = 0 Then MutexUnLock(TSNEMux): Return 1
MutexUnLock(TSNEMux)
Return 0
End Function
'##############################################################################################################
Sub Thread_Event(ByVal V_TSNEID as UInteger)
Dim GSID as UInteger = V_TSNEID
Dim TSID as UInteger
DIM TTV AS TimeVal
DIM TFDSet AS fd_Set
Dim TSock as Socket
Dim TNSock as Socket
DIM TLenB AS UINTEGER
DIM TBuffer AS ZSTRING * TSNE_BufferSize
DIM T AS STRING
Dim TT as TSNE_Socket
TTV.tv_sec = 0
TTV.tv_usec = 0
TSID = GSID
MutexLock(TSNEMux)
TT = TSNED(V_TSNEID)
TSock = TSNED(TSID).V_Socket
MutexUnLock(TSNEMux)
Sleep 1
If TT.V_IsServer <> 1 Then
If TT.V_Event.TSNE_Connected <> 0 Then TT.V_Event.TSNE_Connected(TSID)
Do
TSID = GSID
MutexLock(TSNEMux)
If TSNED(TSID).V_Socket = INVALID_SOCKET Then
MutexUnLock(TSNEMux)
Exit Do
End If
MutexUnLock(TSNEMux)
fd_set_(TSock, @TFDSet)
If select_(TSock + 1, @TFDSet, 0, 0, @TTV) <> -1 Then
IF (FD_ISSET(TSock, @TFDSet)) <> 0 THEN
TLenB = recv(TSock, STRPTR(TBuffer), TSNE_BufferSize, 0)
IF TLenB <= 0 THEN Exit Do
IF TLenB > 0 THEN
TBuffer[TLenB] = 0
T = STRING(TLenB + 1, Chr(0))
MemCpy(STRPTR(T), STRPTR(TBuffer), TLenB)
MutexLock(TSNEMux)
TSNED(TSID).T_DataIn += TLenB
MutexUnLock(TSNEMux)
If TT.V_Event.TSNE_NewData <> 0 Then TT.V_Event.TSNE_NewData(TSID, T)
END IF
END IF
ELSE: Exit Do
END IF
sleep 1
Loop
Else
Do
TSID = GSID
MutexLock(TSNEMux)
If TSNED(TSID).V_Socket = INVALID_SOCKET Then Exit Do
MutexUnLock(TSNEMux)
fd_set_(TSock, @TFDSet)
IF selectsocket(TSock + 1, @TFDSet, 0, 0, @TTV) = SOCKET_ERROR THEN Exit Do
IF (FD_ISSET(TSock, @TFDSet)) THEN
TNSock = accept(TSock, 0, 0)
IF TNSock = INVALID_SOCKET THEN Exit Do
If TT.V_Event.TSNE_NewConnection <> 0 Then TT.V_Event.TSNE_NewConnection(TSID, TNSock)
End If
sleep 1
Loop
End If
MutexUnLock(TSNEMux)
TSID = GSID
TSNE_Disconnect(TSID)
TSID = GSID
MutexLock(TSNEMux)
TSNED(TSID).T_ThreadOn = 0
TSNED(TSID).V_Socket = INVALID_SOCKET
MutexUnLock(TSNEMux)
End Sub
'##############################################################################################################
Function TSNE_GetGURUCode(ByRef V_GURUID as Long) as String
Select Case V_GURUID
case 0: Return "No error"
case -1: Return "Unknow error in function"
case -2: Return "Unknow EVENT-ID"
case -3: Return "No Socket found in V_SOCKET"
case -4: Return "Can't create socket"
case -5: Return "Can't bind port on socket"
case -6: Return "Can't set socket into listening-mode"
case -7: Return "Socket is already initalized"
case -8: Return "MaxSimultanConnectionRequests out of valid range"
case -9: Return "Port out of valid range"
case -10: Return "Can't resolve IP from Host"
case -11: Return "Can't connect to remote computer"
case -12: Return "TSNE-ID not found"
case else: Return "Unknow GURU-Code"
End Select
End Function