VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
END
Attribute VB_Name = "CSocket"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit

Public SocketHandle As Long
Public State As Integer
Public LocalPort As Long
Public RemoteHost As String
Public RemotePort As Long
Public LocalRooterIP As Double

Public WindowProcOld As Long
Public WindowHandle As Long

'Public SSLEnable As Boolean
'Public SSLCipher As String
'Public SSLSubject As String
'Public SSLIssuer As String
'Public SSLServerCertificate As String
'Public SSLServerKey As String
'Public SSLTrusted As Boolean
'Public SSLCAFile As String
'Public SSLHandle As Long

Event Connected()
Event Closed()
Event SendComplete()
Event DataArrival()
Event LineDataArrival(LineData As String, RemoteHostIP As String)
Event Error(Error As Long, Description As String)
Event ConnectionRequest()

Private Sub Class_Initialize()
  Sockets.Add Me
  WindowProcOld = 0
  State = sockClosed
  SocketHandle = 0
  LocalPort = 0
  RemoteHost = ""
  RemotePort = 0
'  SSLEnable = True
End Sub

Private Sub Class_Terminate()
  Dim n As Integer
  Disconnect
  For n = 1 To Sockets.Count
    If Sockets(n) Is Me Then Sockets.Remove n: Exit For
  Next
End Sub

Private Sub StartWinsock()
  WindowHandle = CreateWindowEx(0&, "static", "tst", WS_OVERLAPPEDWINDOW, 5&, 1&, 200&, 100&, 0&, 0&, App.hInstance, ByVal 0&)
  
  If UsedCount = 0 Then
    Dim StartupData As WSADataType
    If WSAStartup(257, StartupData) Then
       MsgBox "Winsock is not installed or Setup properly.", vbCritical, "Winsock Error"
       End
    End If
  End If
  UsedCount = UsedCount + 1
  
  WindowProcOld = SetWindowProc(WindowHandle, 0)
End Sub

Private Sub EndWinsock()
  SetWindowProc WindowHandle, WindowProcOld
  WindowProcOld = 0
  DestroyWindow WindowHandle
  UsedCount = UsedCount - 1: If UsedCount = 0 Then WSACleanup
End Sub

Public Sub Connect(ByVal HOST As String, ByVal Port As Long)
  Dim saZero As sockaddr
  Dim sockin As sockaddr
    
  If SocketHandle Then Disconnect
  StartWinsock
  SocketHandle = 0
  State = sockConnecting
  
'  SSLHandle = 0
'  SSLCipher = ""
'  SSLSubject = ""
'  SSLIssuer = ""
'  SSLTrusted = False
  
  sockin = saZero
  sockin.sin_family = AF_INET
  sockin.sin_port = htons(Port)
  If sockin.sin_port = INVALID_SOCKET Then Disconnect: Exit Sub
  
  sockin.sin_addr = GetHostByNameAlias(HOST)
  If sockin.sin_addr = INADDR_NONE Then Disconnect: Exit Sub
  
  SocketHandle = Socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)
  If SocketHandle <= 0 Then Disconnect: Exit Sub
  
  If SetSockLinger(SocketHandle, 1, 0) = SOCKET_ERROR Then Disconnect: Exit Sub
'  If Not SSLEnable Then
    If WSAAsyncSelect(SocketHandle, WindowHandle, 2000&, FD_READ Or FD_WRITE Or FD_CONNECT Or FD_CLOSE) Then Disconnect: Exit Sub
    If connectsocket(SocketHandle, sockin, sockaddr_size) <> -1 Then Disconnect: Exit Sub
'  Else
'    If WSAAsyncSelect(SocketHandle, WindowHandle, 2000&, FD_READ Or FD_WRITE Or FD_CONNECT Or FD_CLOSE) Then Disconnect: Exit Sub
'    If connectsocket(SocketHandle, sockin, sockaddr_size) <> -1 Then Disconnect: Exit Sub
'    SSLHandle = ssl_init_client(SocketHandle, SSLCAFile): If SSLHandle = 0 Then Disconnect: Exit Sub
'    'WindowProc FD_CONNECT, 0
'    'If WSAAsyncSelect(SocketHandle, WindowHandle, 2000&, FD_READ Or FD_WRITE Or FD_CONNECT Or FD_CLOSE) Then Disconnect: Exit Sub
'    'If connectsocket(SocketHandle, sockin, sockaddr_size) <> -1 Then Disconnect: Exit Sub
'    SSLTrusted = ssl_getverify(SSLHandle) = 0
'  End If
End Sub

Public Sub Listen()
  Dim saZero As sockaddr
  Dim sockin As sockaddr
  
  If SocketHandle Then Disconnect
  StartWinsock
  SocketHandle = 0
  RemoteHost = ""
  RemotePort = 0
  
  sockin = saZero     'zero out the structure
  sockin.sin_family = AF_INET
  sockin.sin_port = htons(LocalPort)
  If sockin.sin_port = INVALID_SOCKET Then EndWinsock: Exit Sub
  sockin.sin_addr = htonl(INADDR_ANY)
  If sockin.sin_addr = INADDR_NONE Then EndWinsock: Exit Sub
  
  SocketHandle = Socket(PF_INET, SOCK_STREAM, IPPROTO_TCP): If SocketHandle <= 0 Then Disconnect: Exit Sub
  If bind(SocketHandle, sockin, sockaddr_size) Then Disconnect: Exit Sub
  If WSAAsyncSelect(SocketHandle, WindowHandle, 2000&, FD_READ Or FD_WRITE Or FD_CLOSE Or FD_ACCEPT) Then Disconnect: Exit Sub
  If listensocket(SocketHandle, 5) Then Disconnect: Exit Sub
  
  State = sockListening
End Sub

Public Function SendData(Data As Variant) As Long
  Dim Line As String
  Dim TheMsg() As Byte
  Dim sTemp As String
  
  SendData = 0
  If SocketHandle = 0 Then Exit Function
  Select Case VarType(Data)
    Case 8209   'byte array
      sTemp = Data
    Case 8      'string
      Line = Data
      sTemp = StrConv(Line, vbFromUnicode)
    Case Else
      sTemp = CStr(Data)
  End Select
  TheMsg = sTemp
  If UBound(TheMsg) > -1 Then
'    If SSLHandle = 0 Then
      SendData = Send(SocketHandle, TheMsg(0), (UBound(TheMsg) - LBound(TheMsg) + 1), 0)
'    Else
'      SendData = ssl_send(SSLHandle, TheMsg(0), (UBound(TheMsg) - LBound(TheMsg) + 1))
'    End If
  End If
End Function

Public Sub Disconnect()
  closesocket SocketHandle
  SocketHandle = 0
'  If SSLHandle Then ssl_cleanup SSLHandle: SSLHandle = 0
  State = sockClosed
  EndWinsock
End Sub
   
Public Sub Accept(Server As CSocket)
  Dim Sock As sockaddr
  Dim TempSockH As Long
  
'  SSLEnable = Server.SSLEnable
'  SSLServerCertificate = Server.SSLServerCertificate
'  SSLServerKey = Server.SSLServerKey

  If Not Me Is Server Then StartWinsock
  TempSockH = acceptsocket(Server.SocketHandle, Sock, sockaddr_size)
  
'  If SSLEnable Then
'    If WSAAsyncSelect(SocketHandle, WindowHandle, 0, 0) Then Disconnect: Exit Sub
'    'Dim l&: l& = 0
'    'If ioctlsocket(SocketHandle, FIONBIo, l&) Then Disconnect: Exit Sub
'    SSLHandle = ssl_init_server(SocketHandle, SSLServerCertificate, SSLServerKey): If SSLHandle <= 100 Then Disconnect: Exit Sub
'    If WSAAsyncSelect(SocketHandle, WindowHandle, CSocketMsg, FD_READ Or FD_WRITE Or FD_CLOSE Or FD_ACCEPT) Then Disconnect: Exit Sub
'  End If
  
  RemoteHost = GetPeerHostByAddr(TempSockH)
  RemotePort = GetPeerPort(TempSockH)
  If Me Is Server Then closesocket SocketHandle
  SocketHandle = TempSockH
  State = sockConnected
End Sub
   
Public Function Recive(buf() As Byte) As Long
  Dim buflen As Long
  
  ReDim buf(0 To 1024 - 1)
'  If SSLHandle = 0 Then
    buflen = recv(SocketHandle, buf(0), 1024, 0)
'  Else
'    buflen = ssl_recv(SSLHandle, buf(0), 1024)
'  End If
  If buflen > 0 Then
    If buflen < 1024 Then ReDim Preserve buf(0 To buflen - 1)
  Else
    buflen = 0
  End If
  Recive = buflen
End Function
   
Public Sub WindowProc(WSAEvent As Long, Data As Variant)
  Dim er As String
  
  Select Case WSAEvent
    Case 0
      er = Data
      State = sockClosed
      RaiseEvent Error(0, er)
    Case FD_CLOSE
      State = sockClosed
      RaiseEvent Closed
      Disconnect
    Case FD_CONNECT
      State = sockConnected
      RemoteHost = GetPeerHostByAddr(SocketHandle)
      RemotePort = GetPeerPort(SocketHandle)
'      If SSLHandle > 0 Then
'        Dim puffer As String * 1000
'        ssl_getcipher SSLHandle, puffer, 1000: SSLCipher = Parse(puffer, Chr$(0))
'        ssl_getsubject SSLHandle, puffer, 1000: SSLSubject = Parse(puffer, Chr$(0))
'        ssl_getissuer SSLHandle, puffer, 1000: SSLIssuer = Parse(puffer, Chr$(0))
'      End If
      RaiseEvent Connected
    Case FD_ACCEPT
      RaiseEvent ConnectionRequest
    Case FD_READ
      RaiseEvent DataArrival
    Case FD_WRITE
      RaiseEvent SendComplete
  End Select
End Sub
