Skip to content
0
  • Категории
  • Последние
  • Метки
  • Популярные
  • Пользователи
  • Группы
  • Категории
  • Последние
  • Метки
  • Популярные
  • Пользователи
  • Группы
Collapse
technodragonT

technodragon

@technodragon
Сводка
Сообщения
59
Темы
11
Поделиться
0
Группы
2
Подписчики
1
Подписки
0

Сообщения

Последние Лучшие сообщения Спорные

  • Надувная O2
    technodragonT technodragon

    20e52ee5-2043-4ddc-a96f-3d132b3d547c-image.jpeg
    https://www.reddit.com/r/SiliconGraphics/comments/1upscjc/found_this_inflatable_o2_in_my_junk/

    Silicon Graphics - MIPS, Itanium, x86

  • Документация на всякое.
    technodragonT technodragon

    Трансформатор строчной разветрки ТВС-110ПЦ18-1
    ТВС-110ПЦ18-1.jpg
    ТВС-110ПЦ18-2.jpg

    Флуд

  • Документация на всякое.
    technodragonT technodragon

    Здесь можно выкладывать инструкции и прочие документы, не относящиеся к остальной тематике форума. Из принципа - если бумажка уникальная и ее нет где то еще, то пусть будет здесь.

    Флуд

  • Простейший "мессенджер" на python через протокол UDP
    technodragonT technodragon

    Особенно в случае с сервером - да, похоже
    Ибо так как тут нет обратной связи, то после того как сервер тебя запомнил можно ему ничего не передавать а просто его слушать. Можно вручную вписать в базу сервера IP (юзернейм любой при этом. Я не реализовал механизма фильтрации по именам пользователя так как здесь нет авторизации а значит одинаковые юзернеймы вполне возможны, что к слову приведет к одному неприятному багу который я постараюсь устранить)
    Но суть примерно такова - сервер просто рассылает пакеты всем кого знает, кроме того кто отправил пакет (а точнее тут такой прикол что кроме любого юзернейма совпадающего с отправителем. Потому и надо сделать пару доработок.)
    Короче - если хочешь - поиграйся: это интересно. Программу для перехвата пакетов можно использовать wireshark - там реально увидишь что плейнтекстом все без кодировок и шифров.

    Флуд

  • Простейший "мессенджер" на python через протокол UDP
    technodragonT technodragon

    Кстати я думаю что лучше не цитировать сообщения в ответах - получается дубль текста.

    Флуд

  • Простейший "мессенджер" на python через протокол UDP
    technodragonT technodragon

    Ну, в любом случае рад стараться. Если хоть кому то это будет полезно это уже хорошо.

    Флуд

  • Простейший "мессенджер" на python через протокол UDP
    technodragonT technodragon

    Итак небольшое обновление как клиента так и новая часть - сервер.
    Сервер представляет собой довольно простую релейную программу которая просто пересылает пакеты всем кроме отправителя. Есть функция запрета пересылки крупных передач (одна такая передача может превратиться в кошмар для всех пользователей)

    клиент:

    """
     This is free and unencumbered software released into the public domain.
    
     Anyone is free to copy, modify, publish, use, compile, sell, or
     distribute this software, either in source code form or as a compiled
     binary, for any purpose, commercial or non-commercial, and by any
     means.
    
     In jurisdictions that recognize copyright laws, the author or authors
     of this software dedicate any and all copyright interest in the
     software to the public domain. We make this dedication for the benefit
     of the public at large and to the detriment of our heirs and
     successors. We intend this dedication to be an overt act of
     relinquishment in perpetuity of all present and future rights to this
     software under copyright law.
    
     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     OTHER DEALINGS IN THE SOFTWARE.
    
     For more information, please refer to <http://unlicense.org/>
    """
    # Default settings. You may edit these to make startup easier.
    destipaddr = "127.0.0.1"
    username = "owo"
    destport = 15001
    listport = 15002
    DoInitSetup = False
    inputprompt = (f"\x1b[1;32m{username}> \x1b[0m")
    maxmessagelength = 32768
    
    class UserError(Exception):
        pass
    
    class PacketError(Exception):
    	pass
    
    import socket, threading, queue, time, sys, base64, os
    
    BigMessage = ""
    packetdatatype = "PlainText"
    
    q = queue.Queue()
    
    def UDPsend(ipaddr: str, portnumber: int, userdatagram: str) -> None:   # Send a UDP packet with payload to an IP and a port
    	payload = userdatagram.encode('utf-8')                              # We use unicode, more compatibility more better
    	with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:         # It will use a random port to send
    		s.sendto(payload, (ipaddr, portnumber))
    
    def FormDatagram(usname = "Anonymous", packetnumber = "0", contents = "PlainText", thedatagram = "Placeholder."):
    	completedatagram = f"Username: {usname.strip()} PacketNumber: {packetnumber.strip()} ContentType: {contents.strip()}\n{thedatagram}"
    	return completedatagram
    
    def IsValidIP(s: str) -> bool:                                          # IP addr checker.
    	if not isinstance(s, str) or not s:
    		return False
    	parts = s.split('.')
    	if len(parts) != 4:
    		return False
    	for p in parts:                                                     # no empty parts, no leading '+' or '-' signs
    		if not p or (p[0] in '+-'):
    			return False
    		if len(p) > 1 and p[0] == '0':                                  # disallow leading zeros unless the part is exactly "0"
    			return False
    		if not p.isdigit():                                             # all characters must be digits
    			return False
    		val = int(p)
    		if val < 0 or val > 255:                                        # numeric range 0-255
    			return False
    
    	return True
    
    def initialsetup():
    	try:                                                                # Initial setup dialog
    		global destipaddr, username, destport, listport, inputprompt
    		usname = input("Username: ").strip()
    		if usname == "":
    			print(f"None given, you'll be {username}")
    		elif len(usname) <=3 or len(usname) >= 24:
    			 raise UserError("username is too long or too short. Please use a sane name.")
    		elif any(not (ch.isalnum() or ch == '_') for ch in usname):
    			raise UserError("Username may contain numbers, letters and underscore. Please use a sane name.")
    		else:
    			username = usname
    			print(f"You'll be seen as {username}")
    			inputprompt = (f"\x1b[1;32m{username}> \x1b[0m")
    		destip = input("Destination IP address: ").strip()
    		if destip=="":
    			print(f"You'll talk to (IP: {destipaddr})")
    		elif IsValidIP(destip):
    			destipaddr = destip
    		else:
    			raise UserError("This is not a valid IP address")
    		dstport = input("Destination port: ").strip()
    		if dstport =="":
    			print(f"None given, using {destport}")
    		elif any(not ch.isdigit() for ch in dstport):
    			raise UserError("Non-numeric string entered.")
    		elif int(dstport) >= 65535 or int(dstport)<= 0:
    			raise UserError("Port number should be from 1 to 65534 but please keep it within reason.")
    		else:
    			destport = int(dstport)
    		lstport = input("Listening port: ").strip()
    		if lstport =="":
    			print(f"None given, using {listport}")
    		elif any(not ch.isdigit() for ch in lstport):
    			raise UserError("Non-numeric string entered.")
    		elif int(lstport) >= 65535 or int(lstport)<= 0:
    			raise UserError("Port number should be from 1 to 65534 but please keep it within reason.")
    		else:
    			listport = int(lstport)
    	except UserError as e:
    		print (e)
    		exit (1)
    
    def base64ify(filepath):                                                # Encode a file into base64
    	try:
    		with open(filepath.strip(), "rb") as inputfile:
    			return base64.b64encode(inputfile.read()).decode()
    	except FileNotFoundError:
    		print (f"File {filepath} does not exist.")
    		return None
    	except Exception as e:
    		print ("Error encoding a file:", e)
    		return None
    
    def unbase64ify(s):                                                     # Decode base64 into bytes
    	try:
    		return base64.b64decode(s.strip())
    	except Exception as e:
    		print("Invalid base64 data:", e)
    		return None
    
    def savefile(path, data):                                               # Save bytes into file
    	path = path.strip()
    	if not path:
    		print ("Error: wrong path!")
    		return False
    	if os.path.exists(path):
    		print ("Error! File exists!")
    		return False
    	with open(path, "wb") as f:
    		f.write(data)
    	return True        
    
    def input_thread():                                                     # Chat input prompt
    	global packetdatatype
    	while True:
    		try:
    			chatmessage = ""
    			time.sleep(0.1)
    			chatpart = input(inputprompt)
    			if chatpart[:len("file://")] == "file://":
    				packetdatatype = "Base64File"
    				chatmessage=base64ify(chatpart[len("file://"):])
    			elif chatpart[:len(":clear")] == ":clear":
    				BigMessage = ""
    				print ("sliced message buffer cleared.")
    			else:
    				packetdatatype = "PlainText"
    				while not(chatpart == ""):
    					chatmessage += (f"{chatpart}\n")
    					chatpart = input()
    			if not chatmessage == None:
    				q.put(chatmessage)
    		except Exception as e:
    			print(f"[ERROR] {e}")
    
    
    if DoInitSetup:
    	print ("initial setup. You may adjust config to not do it all the time")
    	initialsetup()
    else:
    	print("Initial setup disabled. Built in defaults used:")
    	print(f"Username: {username}\nDestination IP: {destipaddr}\nDestination port: {destport}\nListening port: {listport}")
    
    t = threading.Thread(target=input_thread, daemon=True)
    t.start()
    
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.bind(("0.0.0.0", int(listport)))
    sock.setblocking(False)
    
    
    while True:
    	try:
    		try:
    			data, rcvaddr = sock.recvfrom(65535)
    		except BlockingIOError:
    			try:
    				chatmessage = q.get_nowait()
    			except queue.Empty:
    				time.sleep(0.1)
    				continue
    		else:                                                           # We need to parse a message.
    			gottext         = data.decode(errors="replace")             # Decode UDP packet. It should be plain text.
    			possender       = gottext.find("Username: ")                # We find first field of a header - the username
    			pospacketnum    = gottext.find("PacketNumber: ")            # We find the packet number. 0 for single packets, non-zero real for multiple, -1 for a terminator.
    			posdatatype     = gottext.find("ContentType: ")             # Type of contents in a packet. Currently there're PlainText and Base64File
    			posfirstnewline = gottext.find(f"\n")                       # Actual contents begin from new line to the end of a packet
    			if possender == -1 or pospacketnum == -1 or posdatatype == -1 or posfirstnewline == -1: # handle if header s bad.
    				raise PacketError("Got malformed or unintended packet.")
    			sendername   = gottext[possender+len("Username: "):pospacketnum -1 ].strip()
    			gotpacketnum = gottext[pospacketnum+len("PacketNumber: "):posdatatype - 1].strip()
    			rcvdatatype  = gottext[posdatatype+len("ContentType: "):posfirstnewline].strip()
    			gotdatagram  = gottext[posfirstnewline + 1:].rstrip()
    			if gotpacketnum == "0":
    				if rcvdatatype == "PlainText":
    					print(f"\n\x1b[1;36m{sendername}@{rcvaddr[0]}:\x1b[0m \x1b[36m{gotdatagram}\x1b[0m")
    				elif rcvdatatype == "Base64File":
    					print(f"\n\x1b[1;36m{sendername}@{rcvaddr[0]}:\x1b[0m \x1b[36msent you a file!\x1b[0m")
    					savefilepath = input("Enter file path and name to save, press enter to discard.\nfilepath: ")
    					if not savefilepath == "":
    						savefile(savefilepath,unbase64ify(gotdatagram))
    				else:
    					raise PacketError("Wrong data type! Data dropped!")
    			elif int(gotpacketnum) == 1:
    				print (f"\x1b[36mGot partial content from\x1b[0m \x1b[1;36m{sendername}@{rcvaddr[0]}:\x1b[0m \x1b[36mGot part {gotpacketnum}\x1b[0m")
    				BigMessage = gotdatagram
    			elif int(gotpacketnum) > 1:
    				print (f"\x1b[36mGot partial content from\x1b[0m \x1b[1;36m{sendername}@{rcvaddr[0]}:\x1b[0m \x1b[36mGot part {gotpacketnum}\x1b[0m")
    				BigMessage += gotdatagram
    			elif int(gotpacketnum) == -1:
    				print (f"\x1b[36mBig transmission complete!\x1b[0m")
    				if rcvdatatype == "PlainText":
    					print(f"\n\x1b[1;36m{sendername}@{rcvaddr[0]}:\x1b[0m \x1b[36m{BigMessage}\x1b[0m")
    				elif rcvdatatype == "Base64File":
    					print(f"\n\x1b[1;36m{sendername}@{rcvaddr[0]}:\x1b[0m \x1b[36msent you a file!\x1b[0m")
    					savefilepath = input("Enter file path and name to save, press enter to discard.\nfilepath: ")
    					if not savefilepath == "":
    						savefile(savefilepath,unbase64ify(BigMessage))
    				BigMessage = ""
    			else:
    				raise PacketError("Got wrong packet number. Buffer cleared.")
    			continue
    		if chatmessage == "":
    			time.sleep(0.1)
    		else:
    			try:
    				if len(chatmessage) >= maxmessagelength:
    					print ("Message is too big! Slicing message!")
    					sentlength = 0
    					slicecounter = 1
    					while not sentlength > len(chatmessage):
    						print (f"Sending slice number {slicecounter}")
    						UDPsend(destipaddr, destport, FormDatagram(username, str(slicecounter), packetdatatype, chatmessage[sentlength:sentlength+maxmessagelength]))
    						sentlength += maxmessagelength
    						slicecounter += 1
    						time.sleep(0.2)
    					UDPsend(destipaddr, destport, FormDatagram(username, "-1", packetdatatype, ""))	
    				else:
    					UDPsend(destipaddr, destport, FormDatagram(username, "0", packetdatatype, chatmessage))
    			except Exception as e:
    				print(f"[ERROR] {e}")
    	except PacketError as e:
    		gottext = ""
    		BigMessage = ""
    		del data
    		print (e)
    		continue
    	except KeyboardInterrupt:
    		print(f"\nTerminated by the user.")
    		exit (0)
    	except Exception as e:
    		print(f"[ERROR] {e}")
    	
    
    

    Ну и сервер:

    # Server implementaion of UDPChat_aplha
    # It's a relay server. It just forwards packets.
    # Be sure to configure the server. Do not run defaults.
    
    """
     This is free and unencumbered software released into the public domain.
    
     Anyone is free to copy, modify, publish, use, compile, sell, or
     distribute this software, either in source code form or as a compiled
     binary, for any purpose, commercial or non-commercial, and by any
     means.
    
     In jurisdictions that recognize copyright laws, the author or authors
     of this software dedicate any and all copyright interest in the
     software to the public domain. We make this dedication for the benefit
     of the public at large and to the detriment of our heirs and
     successors. We intend this dedication to be an overt act of
     relinquishment in perpetuity of all present and future rights to this
     software under copyright law.
    
     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     OTHER DEALINGS IN THE SOFTWARE.
    
     For more information, please refer to <http://unlicense.org/>
    """
    
    # Default settings. You may edit these to make startup easier.
    servername = "server"
    destport = 15002
    listport = 15001
    dbfile   = "userbase.txt"
    allow_multipacket = False
    
    class PacketError(Exception):
    	pass
    
    import socket, threading, queue, time, sys, os
    
    def loadbase(dbpath):
    	ipdatabase = {}
    	try:
    		if os.path.exists(dbfile):
    			with open (dbfile, "r") as db:
    				for lineno, line in enumerate(db, start=1):
    					if not line.strip():
    						continue
    					try:
    						username, ip = line.strip().split()
    						ipdatabase[username]  =ip
    					except ValueError:
    						continue
    			print ("Loaded user database: ", ipdatabase)
    			return ipdatabase
    	except Exception as e:
    		print(e)
    		return None
    
    def updateaddr(ipbase, username, ipaddr):
    	oldip = ipbase.get(username)
    	if oldip == None:
    		ipbase[username] = ipaddr
    		return True
    	elif not oldip == ipaddr:
    		ipbase[username] = ipaddr
    		return True
    	return False
    
    def savedb(ipbase,filename):
    	with open (dbfile, "w") as db:
    		for user, ip in sorted(ipbase.items()):
    			db.write(f"{user} {ip}\n")
    
    ipbase = {}
    q = queue.Queue()
    ipbase = loadbase(dbfile)
    
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.bind(("0.0.0.0", int(listport)))
    sock.setblocking(False)
    
    print ("UDPChat server. Just a relay server.")
    
    while True:
    	try:
    		try:
    			data, rcvaddr = sock.recvfrom(65535)
    		except BlockingIOError:
    			try:
    				chatmessage = q.get_nowait()
    			except queue.Empty:
    				time.sleep(0.1)
    				continue
    		else:                                                           # We need to parse a message.
    			gottext         = data.decode(errors="replace")             # Decode UDP packet. It should be plain text.
    			possender       = gottext.find("Username: ")                # We find first field of a header - the username
    			pospacketnum    = gottext.find("PacketNumber: ")            # We find the packet number. 0 for single packets, non-zero real for multiple, -1 for a terminator.
    			posdatatype     = gottext.find("ContentType: ")             # Type of contents in a packet. Currently there're PlainText and Base64File
    			posfirstnewline = gottext.find(f"\n")                       # Actual contents begin from new line to the end of a packet
    			if possender == -1 or pospacketnum == -1 or posdatatype == -1 or posfirstnewline == -1: # handle if header s bad.
    				raise PacketError("Got malformed or unintended packet.")
    			sendername   = gottext[possender+len("Username: "):pospacketnum -1 ].strip()
    			gotpacketnum = gottext[pospacketnum+len("PacketNumber: "):posdatatype - 1].strip()
    			rcvdatatype  = gottext[posdatatype+len("ContentType: "):posfirstnewline].strip()
    			if int(gotpacketnum) == 1 and allow_multipacket:
    				raise PacketError(f"Multi-packet transmission from {sendername}@{rcvaddr[0]}")
    			elif int(gotpacketnum) > 1:
    				raise PacketError(f"Multi-packet transmission from {sendername}@{rcvaddr[0]}")
    			elif int(gotpacketnum) == -1:
    				with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
    						s.sendto(bytes(f"Username: {servername} PacketNumber: 0 ContentType: PlainText\nMulti-packet transmissions are not allowed on this server.","utf-8"), (rcvaddr[0], destport))
    				raise PacketError(f"Multi-packet transmission from {sendername}@{rcvaddr[0]}")
    			if updateaddr(ipbase, sendername, rcvaddr[0]):              # Update db if we have a new user or user changed their ip
    				savedb(ipbase, dbfile)
    				print (f"New user or user changed IP: {sendername}@{rcvaddr[0]}")
    			for user, ip in sorted(ipbase.items()):                     # relay to all other users
    				if not user == sendername:
    					with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
    						s.sendto(data, (ip, destport))
    	except PacketError as e:
    		print (e)
    		continue
    	except KeyboardInterrupt:
    		print("saving and exiting.")
    		savedb(ipbase, dbfile)
    		exit (0)
    	except Exception as e:
    		print(e)
    	
    
    
    Флуд

  • Простейший "мессенджер" на python через протокол UDP
    technodragonT technodragon

    Да ладно... Кажется ты мне льстишь: этот код очень далек от звания лаконичного. Или ты про саму концепцию?

    Флуд

  • Простейший "мессенджер" на python через протокол UDP
    technodragonT technodragon

    Изучаю сети и потребовалась простая программа которая будет гонять плейнтекст через сеть. Просто пинги - скучно. iperf3 - дает нагрузку но тоже не интересно. А здесь идет то что ты послал, и это можно посмотреть.

    Недолго думая написал сей велосипед. Надеюсь никому в голову не придет использовать его на серьезных основаниях: здесь нет никакой безопасности, нет и шифрования. Данные передаются открытым текстом без авторизации или прочих механизмов защиты. Нет даже банального отчета о том получил ли собеседник пакет.
    Предлагаю использовать это в образовательных целях, ну или как уж вашей душе угодно.

    Я не сторонник копирайта, но один знакомый попросил применять к написанному коду ну хоть какую-то лицензию. Потому получите-распишитесь.

    Версия 0.1 Alpha
    возможно я буду делать доработанные варианты.

    """
     This is free and unencumbered software released into the public domain.
    
     Anyone is free to copy, modify, publish, use, compile, sell, or
     distribute this software, either in source code form or as a compiled
     binary, for any purpose, commercial or non-commercial, and by any
     means.
    
     In jurisdictions that recognize copyright laws, the author or authors
     of this software dedicate any and all copyright interest in the
     software to the public domain. We make this dedication for the benefit
     of the public at large and to the detriment of our heirs and
     successors. We intend this dedication to be an overt act of
     relinquishment in perpetuity of all present and future rights to this
     software under copyright law.
    
     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     OTHER DEALINGS IN THE SOFTWARE.
    
     For more information, please refer to <http://unlicense.org/>
    """
    # Default settings. You may edit these to make startup easier.
    destipaddr = "127.0.0.1"
    username = "Anonymous"
    destport = 15000
    listport = 15000
    DoInitSetup = False
    inputprompt = (f"\x1b[1;32m{username}> \x1b[0m")
    maxmessagelength = 32768
    
    import socket, threading, queue, time, sys, base64, os
    
    BigMessage = ""
    packetdatatype = "PlainText"
    
    q = queue.Queue()
    
    def UDPsend(ipaddr: str, portnumber: int, userdatagram: str) -> None:   # Send a UDP packet with payload to an IP and a port
    	payload = userdatagram.encode('utf-8')                              # We use unicode, more compatibility more better
    	with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:         # It will use a random port to send
    		s.sendto(payload, (ipaddr, portnumber))
    
    def FormDatagram(usname = "Anonymous", packetnumber = "0", contents = "PlainText", thedatagram = "Placeholder."):
    	completedatagram = f"Username: {usname.strip()} PacketNumber: {packetnumber.strip()} ContentType: {contents.strip()}\n{thedatagram}"
    	return completedatagram
    
    def IsValidIP(s: str) -> bool:                                          # IP addr checker.
    	if not isinstance(s, str) or not s:
    		return False
    	parts = s.split('.')
    	if len(parts) != 4:
    		return False
    	for p in parts:                                                     # no empty parts, no leading '+' or '-' signs
    		if not p or (p[0] in '+-'):
    			return False
    		if len(p) > 1 and p[0] == '0':                                  # disallow leading zeros unless the part is exactly "0"
    			return False
    		if not p.isdigit():                                             # all characters must be digits
    			return False
    		val = int(p)
    		if val < 0 or val > 255:                                        # numeric range 0-255
    			return False
    
    	return True
    
    def initialsetup():                                                     # Initial setup dialog
    	global destipaddr, username, destport, listport
    	usname = input("Username: ").strip()
    	if usname == "":
    		print(f"None given, you'll be {username}")
    	else:
    		username = usname
    		print(f"You'll be seen as {username}")
    	destip = input("Destination IP address: ").strip()
    	if destip=="":
    		print(f"You'll talk to (IP: {destipaddr})")
    	elif IsValidIP(destip):
    		destipaddr = destip
    	else:
    		print("W.T.F. Did you just enter?! Screw you!")
    		exit(1)
    	dstport = input("Destination port: ").strip()
    	if dstport =="":
    		print(f"None given, using {destport}")
    	elif any(not ch.isdigit() for ch in dstport):
    		print("W.T.F. Did you just enter?! Screw you!")
    		exit(1)
    	else:
    		destport = int(dstport)
    	lstport = input("Listening port: ").strip()
    	if lstport =="":
    		print(f"None given, using {listport}")
    	elif any(not ch.isdigit() for ch in lstport):
    		print("W.T.F. Did you just enter?! Screw you!")
    		exit(1)
    	else:
    		listport = int(lstport)
    
    def base64ify(filepath):                                                # Encode a file into base64
    	try:
    		with open(filepath.strip(), "rb") as inputfile:
    			return base64.b64encode(inputfile.read()).decode()
    	except FileNotFoundError:
    		print (f"File {filepath} does not exist.")
    		return None
    	except Exception as e:
    		print ("Error encoding a file:", e)
    		return None
    
    def unbase64ify(s):                                                     # Decode base64 into bytes
    	try:
    		return base64.b64decode(s.strip())
    	except Exception as e:
    		print("Invalid base64 data:", e)
    		return None
    
    def savefile(path, data):                                               # Save bytes into file
    	path = path.strip()
    	if not path:
    		print ("Error: wrong path!")
    		return False
    	if os.path.exists(path):
    		print ("Error! File exists!")
    		return False
    	with open(path, "wb") as f:
    		f.write(data)
    	return True        
    
    def input_thread():                                                     # Chat input prompt
    	global packetdatatype
    	while True:
    		chatmessage = ""
    		time.sleep(0.1)
    		chatpart = input(inputprompt)
    		if chatpart[:len("file://")] == "file://":
    			packetdatatype = "Base64File"
    			chatmessage=base64ify(chatpart[len("file://"):])
    		else:
    			packetdatatype = "PlainText"
    			while not(chatpart == ""):
    				chatmessage += (f"{chatpart}\n")
    				chatpart = input()
    		if not chatmessage == None:
    			q.put(chatmessage)
    
    
    if DoInitSetup:
    	initialsetup()
    else:
    	print("Initial setup disabled. Built in defaults used:")
    	print(f"Username: {username}\nDestination IP: {destipaddr}\nDestination port: {destport}\nListening port: {listport}")
    
    t = threading.Thread(target=input_thread, daemon=True)
    t.start()
    
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.bind(("0.0.0.0", int(listport)))
    sock.setblocking(False)
    
    
    while True:
    	try:
    		try:
    			data, rcvaddr = sock.recvfrom(65535)
    		except BlockingIOError:
    			try:
    				chatmessage = q.get_nowait()
    			except queue.Empty:
    				time.sleep(0.1)
    				continue
    		else:                                                           # We need to parse a message.
    			gottext         = data.decode(errors="replace")
    			possender       = gottext.find("Username: ")
    			pospacketnum    = gottext.find("PacketNumber: ")
    			posdatatype     = gottext.find("ContentType: ")
    			posfirstnewline = gottext.find(f"\n")
    			if possender == -1 or pospacketnum == -1 or posdatatype == -1 or posfirstnewline == -1:
    				print("Got malformed or unintended packet.")
    				continue
    			sendername   = gottext[possender+len("Username: "):pospacketnum -1 ].strip()
    			gotpacketnum = gottext[pospacketnum+len("PacketNumber: "):posdatatype - 1].strip()
    			rcvdatatype  = gottext[posdatatype+len("ContentType: "):posfirstnewline].strip()
    			gotdatagram  = gottext[posfirstnewline + 1:].rstrip()
    			if gotpacketnum == "0":
    				if rcvdatatype == "PlainText":
    					print(f"\n\x1b[1;36m{sendername}@{rcvaddr[0]}:\x1b[0m \x1b[36m{gotdatagram}\x1b[0m")
    				elif rcvdatatype == "Base64File":
    					print(f"\n\x1b[1;36m{sendername}@{rcvaddr[0]}:\x1b[0m \x1b[36msent you a file!\x1b[0m")
    					savefilepath = input("Enter file path and name to save, press enter to discard.\nfilepath: ")
    					if not savefilepath == "":
    						savefile(savefilepath,unbase64ify(gotdatagram))
    			elif int(gotpacketnum) >= 1:
    				print (f"\x1b[36mGot partial content from\x1b[0m \x1b[1;36m{sendername}@{rcvaddr[0]}:\x1b[0m \x1b[36mGot part {gotpacketnum}\x1b[0m")
    				BigMessage += gotdatagram
    			elif int(gotpacketnum) == -1:
    				print (f"\x1b[36mBig transmission complete!\x1b[0m")
    				if rcvdatatype == "PlainText":
    					print(f"\n\x1b[1;36m{sendername}@{rcvaddr[0]}:\x1b[0m \x1b[36m{BigMessage}\x1b[0m")
    				elif rcvdatatype == "Base64File":
    					print(f"\n\x1b[1;36m{sendername}@{rcvaddr[0]}:\x1b[0m \x1b[36msent you a file!\x1b[0m")
    					savefilepath = input("Enter file path and name to save, press enter to discard.\nfilepath: ")
    					if not savefilepath == "":
    						savefile(savefilepath,unbase64ify(BigMessage))
    				BigMessage = ""
    			continue
    		if chatmessage == "":
    			time.sleep(0.1)
    		else:
    			try:
    				if len(chatmessage) >= maxmessagelength:
    					print ("Message is too big! Slicing message!")
    					sentlength = 0
    					slicecounter = 1
    					while not sentlength > len(chatmessage):
    						print (f"Sending slice number {slicecounter}")
    						UDPsend(destipaddr, destport, FormDatagram(username, str(slicecounter), packetdatatype, chatmessage[sentlength:sentlength+maxmessagelength]))
    						sentlength += maxmessagelength
    						slicecounter += 1
    						time.sleep(0.2)
    					UDPsend(destipaddr, destport, FormDatagram(username, str(-1), packetdatatype, ""))	
    				else:
    					UDPsend(destipaddr, destport, FormDatagram(username, "0", packetdatatype, chatmessage))
    			except Exception as e:
    				print(f"[ERROR] {e}")
    	except Exception as e:
    		print(f"[ERROR] {e}")
    	except KeyboardInterrupt:
    		print(f"\nTerminated by the user.")
    		exit (0)
    	
    
    Флуд

  • Аккумуляторная подставка для Thinkpad X220 и X230
    technodragonT technodragon

    Заполучил весьма редкий артефакт: аккумулятор-подставка для ноутбуков thinkpad X220 и X230: ThinkPad battery 19+ (6-cell)

    По сути это второй аккумулятор который присоединяется снизу ноутбука посредством разъема для док-станци.
    L1250004.JPG
    Упаковано в родную коробочку!!!
    L1250005.JPG
    Судя по всему ни разу не использовалось, однако продавец иногда заряжал батарею, потому она и выжила!
    L1250006.JPG
    L1250007.JPG
    L1250008.JPG
    L1250009.JPG
    Фиксатор тут с блокировкой - случайно батарея не отстегнется!
    L1250010.JPG
    L1250011.JPG
    L1250012.JPG

    Единственное чего я никак не пойму: почему нельзя было добавить на эту подставку портов. Сюда бы без вопросов вообще влезло несколько USB разъемов, порты для наушников\микрофона отдельные или еще что нибудь полезное.
    В любом случае это очень прикольный и весьма редкий артефакт, который к тому же еще и в прекрасном состоянии!

    Lenovo ThinkPad 2009-2018

  • Х220 который в этой жизни настолько преисполнился...
    technodragonT technodragon

    А еще с этой антенной прием намного лучше!

    Lenovo ThinkPad 2009-2018

  • Х220 который в этой жизни настолько преисполнился...
    technodragonT technodragon

    L1250001.JPG
    L1250002.JPG
    L1250003.JPG

    Lenovo ThinkPad 2009-2018

  • RAD ASM-40
    technodragonT technodragon

    Эпичный G.703 модем из прошлого, найден был в комплекте со старой циской.
    Запустить удалось но только в паре с диагностическим прибором: для второго конца линии у меня нет подходящего модема.
    Устройство до безумия тупое - я не нашел инструкции, но судя по всему модем сам даже фреймы не формирует - просто посылает поток данных.
    Также он умеет:

    1. включать обратную петлю по линии для диагностики линии
    2. включать обратную петлю по последовательному интерфейсу V.35
    3. посылать тестовый паттерн в линию

    L1240004.JPG
    L1240005.JPG
    L1240006.JPG
    Начинка у него куда более плотная чем изначально думается: несколько многоногих микросхем, плотный монтаж. В глаза бросается залитый в "кирпич" сетевой трансформатор который распаян непосредственно на плате, а также мезонинная плата последовательного порта. При помощи поворотного переключателя внутри можно выставить скорость последовательного интерфейса.
    L1240007.JPG
    L1240008.JPG

    Сетевое оборудование и модемы

  • Обновления и исправления
    technodragonT technodragon

    07 июня:

    1. устранен баг из-за которого была невозможна регистрация на форуме: система защиты от не-ascii никнеймов срабатывала даже тогда, когда имя пользователя было полностью в порядке.
    2. увеличены размеры фотографии для загрузки на форум. Размер фотографии увеличен до 16384*16384 а размер файла увеличен до 8 мегабайт.
    Новости и объявления администрации

  • Обновления и исправления
    technodragonT technodragon

    В этой теме будут публиковаться обновления форума, исправления багов и прочие технические детали.

    Новости и объявления администрации

  • Харддиски разные, но в основном маленькие:
    technodragonT technodragon

    hdd_smol_1.JPG
    hdd_smol_2.JPG
    Для сравнения обычный ноутбучный жесткий диск.
    Не особо много чего могу о них рассказать кроме того что они просто очень прикольные, и вызывают вау-эффект когда задумываешься о том как они вообще это сделали (особенно микродрайв)

    Хранение данных

  • Телеком Древних: Е1
    technodragonT technodragon

    @ereinion Хтонь еще та: ЭЛ дисплей, прочный алюминиевый корпус...
    Внутри полон старых ПЛИСин.

    Конкретно сейчас настроила два таких прибора через модем - один по V.35 второй по E1 - работает!
    То есть из этого можем сделать вывод что модем полностью исправен!

    Флуд

  • Телеком Древних: Е1
    technodragonT technodragon

    IMG_0072.JPG
    Ну и как же я могу оставить вас без начинки данного модема. Он неспроста довольно крупный по размерам - плата большая и на ней много в том числе дискретной электроники.

    Флуд

  • Телеком Древних: Е1
    technodragonT technodragon

    IMG_0070.JPG
    IMG_0068.JPG
    IMG_0067.JPG

    Модем E1: RAD ASM-40 - воистину эпичная шайтан-машина, тяжелый, суровый, работает. Никаких танцев с бубном не потребовалось - просто воткнул в розетку, присоединил loopback провод по E1 и диагностический прибор по V.35 и готово (к слову работает в обе стороны. То есть модем полностью исправен)

    Флуд

  • Телеком Древних: Е1
    technodragonT technodragon

    Насмотревшись некоторых каналов на ютубе решил и сам попробовать воспроизвести одну из первых технологий скоростного интернета. В америке это Т1, но в европе есть Е1 - он на треть быстрее, а оборудование достать проще!
    В общем пока не появится раздел по телеком и сетям - это будет здесь.

    Флуд
  • Войти

  • Нет учётной записи? Зарегистрироваться

  • Login or register to search.
  • Первое сообщение
    Последнее сообщение