from SocketTB import *
import ssl
import base64
import os
import threading
import io
import time
import locale
import email.utils
import webbrowser
import msvcrt

with ISocketGenerator() as IGen:
  ISock0 = IGen(family=socket.AF_INET, type=socket.SOCK_STREAM)
  sock2 = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
  ISock2 = IGen(sock2)
  ISock0.bind(('127.0.0.1', 9000))
  ISock0.listen()
  ISock2.connect(('127.0.0.1', 9000))
  ISock1 = ISock0.accept()[0]
  print(ISock0, ISock1, ISock2)
  ISock2.sendall(b'test')
  print(ISock1.recv(10))
  try:
    ISock1.recv(10, timeout=2)
  except TimeoutError:
    print('timeout')
  def r(n):
    try:
      ISock1.recv(n)
    except OSError as err:
      if err.winerror == 10038:
        print('interrupted')
      else:
        raise
  t = threading.Thread(target=r, args=(10, ))
  t.start()
  time.sleep(2)
  ISock1.shutclose()
  def a():
    try:
      ISock1 = ISock0.accept()[0]
    except OSError as err:
      if err.winerror == 10038:
        print('interrupted')
      else:
        raise
  t = threading.Thread(target=a)
  t.start()
  time.sleep(2)

with IDSocketGenerator() as IDGen:
  IDSock0 = IDGen(family=socket.AF_INET, type=socket.SOCK_STREAM)
  sock2 = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
  IDSock2 = IDGen(sock2)
  IDSock0.bind(('127.0.0.1', 9000))
  IDSock0.listen()
  IDSock2.connect(('127.0.0.1', 9000))
  IDSock1 = IDSock0.accept()[0]
  print(IDSock0, IDSock1, IDSock2)
  IDSock2.sendall(b'test2')
  IDSock1.sendall(b'test1')
  print(IDSock1.recv(10))
  print(IDSock2.recv(10))
  def r1(n):
    try:
      IDSock1.recv(n)
    except OSError as err:
      if err.winerror == 10038:
        print('interrupted1')
      else:
        raise
  def r2(n):
    try:
      IDSock2.recv(n)
    except OSError as err:
      if err.winerror == 10038:
        print('interrupted2')
      else:
        raise
  t1 = threading.Thread(target=r1, args=(10, ))
  t2 = threading.Thread(target=r2, args=(10, ))
  t1.start()
  t2.start()
  time.sleep(2)

ctxs = NestedSSLContext(ssl.PROTOCOL_TLS_SERVER)
ctxs.load_autogenerated_cert_chain()
ctxc = NestedSSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctxc.check_hostname = False
ctxc.verify_mode = ssl.CERT_NONE
with IDSocketGenerator() as IDGen:
  IDSock0 = IDGen(family=socket.AF_INET, type=socket.SOCK_STREAM)
  IDSock2 = IDGen(family=socket.AF_INET, type=socket.SOCK_STREAM)
  IDSock0S = ctxs.wrap_socket(IDSock0, server_side=True)
  IDSock0SS = ctxs.wrap_socket(IDSock0S, server_side=True)
  IDSock2S = ctxc.wrap_socket(IDSock2, server_side=False, server_hostname='127.0.0.1')
  IDSock2SS = ctxc.wrap_socket(IDSock2S, server_side=False, server_hostname='127.0.0.1')
  IDSock0SS.bind(('127.0.0.1', 9000))
  IDSock0SS.listen()
  def c():
    IDSock2SS.connect(('127.0.0.1', 9000))
  t = threading.Thread(target=c)
  t.start()
  IDSock1SS = IDSock0SS.accept()[0]
  print(IDSock0SS, IDSock1SS, IDSock2SS)
  IDSock2SS.sendall(b'test')
  print(IDSock1SS.recv(10))
  IDSock0SS.shutclose()
  IDSock1SS.shutclose()
  IDSock2SS.shutclose()
print(IDSock0SS, IDSock1SS, IDSock2SS)

UDPServer = MultiUDPIServer(1900, RequestHandler, True, ('239.255.255.250', 'ff02::c'))
UDPServer.start()
with ISocketGenerator() as IGen:
  ISock0 = IGen(family=socket.AF_INET, type=socket.SOCK_DGRAM)
  ISock0.sendto(b'test ipv4', ('239.255.255.250', 1900))
  ISock0.close()
  ISock0 = IGen(family=socket.AF_INET6, type=socket.SOCK_DGRAM)
  ISock0.sendto(b'test ipv6', ('ff02::c', 1900))
  ISock0.close()
  ISock0 = IGen(family=socket.AF_INET6, type=socket.SOCK_DGRAM)
  ISock0.bind(('::1',0))
  ISock0.sendto(b'test ipv6 lb', ('ff02::c', 1900))
time.sleep(2)
UDPServer.shutdown()

DS = WebSocketDataStore()
ctxs = NestedSSLContext(ssl.PROTOCOL_TLS_SERVER)
cid = base64.b32encode(os.urandom(10)).decode('utf-8')
with RSASelfSigned('TCPIServer' + cid, 1) as cert:
  cert.pipe_PEM('cert' + cid, 'key' + cid, 2)
  ctxs.load_cert_chain(r'\\.\pipe\cert%s.pem' % cid, r'\\.\pipe\key%s.pem' % cid)
WSSServer = WebSocketIDServer(('127.0.0.1', 9000), nssl_context=ctxs)
WSSServer.start()
WSSServer.open('/test')
WSSClient = WebSocketIDClient('wss://127.0.0.1:9000/test', DS)
WSSServer.broadcast('/test', 'welcome')
time.sleep(0.5)
print(DS.incoming)
WSSClient.close()
WSSServer.close('/test')
WSSServer.stop()

with IDSocketGenerator() as IDGen:
  HTTPRequest = HTTPRequestConstructor(IDGen)
  rep = HTTPRequest('https://www.python.org')
  print(rep)
  pcon = []
  rep = HTTPRequest('https://www.python.org', max_length=-1, pconnection=pcon)
  print(pcon)
  print(rep.body(20))
  print(rep.body(20))
  pcon[0].shutclose()
  rep = HTTPRequest('http://www.google.fr/search', max_length=-1, pconnection=pcon, process_cookies=True)
  print(pcon)
  print(rep.body(20))
  pcon[0].shutclose()

BA = HTTPBasicAuthenticator()
with HTTPIServer(9000, '', threaded=True, max_upload_size=10, dual_stack=True, basic_auth=BA), IDAltSocketGenerator() as IDGen:
  BA.set_realm('/', 'root')
  BA.set_credential('user', 'password', 'root')
  IDSock0 = IDGen(family=socket.AF_INET)
  IDSock0.connect(('127.0.0.1', 9000))
  IDSock0.send(b'OPTIONS * HTTP/1.1\r\nHost: 127.0.0.1:9000\r\n\r\n')
  print(IDSock0.recv(1024))
  IDSock0.close()
  IDSock0 = IDGen(family=socket.AF_INET6)
  IDSock0.connect(('[::1]', 9000))
  IDSock0.send(b'OPTIONS * HTTP/1.1\r\nHost: [::1]:9000\r\n\r\n')
  print(IDSock0.recv(1024))
  IDSock0.close()
  HTTPRequest = HTTPRequestConstructor(IDGen)
  pcon = []
  print(HTTPRequest('http://localhost:9000/*', method='OPTIONS', pconnection=pcon))
  print(HTTPRequest('http://localhost:9000/', pconnection=pcon))
  print(pcon)
  print(HTTPRequest('http://localhost:9000/', pconnection=pcon, basic_auth='user:password'))
  BA.set_realm('/', None)
  print(HTTPRequest('http://localhost:9000/nul', method='PUT', data=b'0' * 11, pconnection=pcon))
  print(pcon)
  u = HTTPIUpload('http://localhost:9000/nul', data=b'0' * 18)
  u.start()
  print(u.wait_finish(), u.progress['error'])
  u = HTTPIUpload('http://localhost:9000/nul', data=b'0' * 8)
  u.start()
  print(u.wait_finish())
  b = io.BytesIO()
  with HTTPIDownload('http://localhost:9000/test.py', b, max_workers=3, timeout=5, section_min=2, block_size=2) as d:
    while int(d.wait_progression().rstrip(' %')) <= 25:
      print(d.wait_sections(0))
    d.stop()
  print(d)
  with HTTPIDownload('http://localhost:9000/test.py', b, max_workers=2, timeout=5, section_min=4, block_size=4, resume=d) as d:
    while d.wait_finish(0) not in ('completed', 'aborted'):
      print(d.wait_sections())
    print(d)
  print(len(b.getvalue()))
  b.close()

locale.setlocale(locale.LC_TIME, '')
with NTPClient('time.google.com') as ntpc:
  print(ntpc.get_time(to_local=True))
  print(ntpc.get_offset())

with TOTPassword('AAAAAAAAAAAAAAAA') as totp:
  for i in range(10):
    p, r = totp.get(clipboard=True)
    print('', p, str(r).rjust(4), end ='\b'*12, flush=True)
    time.sleep(1)
  print('')

class TestRequestHandler(RequestHandler):
  def handle(self):
    if self.server.closed:
      return
    req = HTTPMessage(self.request)
    if req.method not in {'GET', 'HEAD'} or (body := bodies.get(req.path.lower())) is None:
      return
    resp = \
      'HTTP/1.1 200 OK\r\n' \
      'Date: %s\r\n' \
      'Server: SocketTB\r\n' \
      'Content-Length: %d\r\n' \
      'Content-Type: text/html; charset=utf-8\r\n' \
      'Connection: close\r\n' \
      '\r\n' % (email.utils.formatdate(time.time(), usegmt=True), len(body))
    self.request.sendall(resp.encode('ISO-8859-1'))
    if req.method != 'HEAD':
      self.request.sendall(body)
BA = WebRTCBasicAuthenticator()
code = BA.set_channel('test')
gist = 'https://gist.githubusercontent.com/PCigales/dc41dc6f499bfd49019b503857c0f57f/raw/'
for n in 'ABCer':
  BA.set_credential(n, 'WebRTC', 'test')
bodies = {}
for names in (('wrtc_mes.html',), ('wrtc_vid.html',), ('wrtc_capt_e.html', 'wrtc_capt_r.html')):
  with WebRTCSignalingServer(9000, basic_auth=BA) as SignalingServer, TCPIServer(9001, TestRequestHandler, threaded=True):
    SignalingServer.open('test')
    HTTPRequest = HTTPRequestConstructor(SignalingServer.idsocketgen)
    for name in names:
      print('http://127.0.0.1:9001/' + name)
      bodies['/' + name] = HTTPRequest(gist + name).body
      webbrowser.open('http://127.0.0.1:9001/' + name)
    print('Press "S" to stop...')
    while True:
      k = msvcrt.getch()
      if k == b'\xe0':
        k = msvcrt.getch()
        k = b''
      if k.upper() == b'S':
        break
    SignalingServer.close('test')
    bodies.clear()