Commit 2b983f40 by Owo Sugiana

Versi 0.1.2: tambah fitur dan bug fixed

1 parent bdb39dd3
0.1.2 2019-07-11
----------------
- Tambah remove_if_old() agar connection manager tidak salah hapus saat new
connection.
- Tambah get_amount()
- Masa tunggu receive_raw() 5 detik saja agar kill tidak terlalu lama.
Sebelumnya sesuai timeout pada konfigurasi. Nilai timeout tetap digunakan
untuk menetapkan kapan echo request.
- Menyertakan conf saat Job.create_iso()
0.1.1 2019-05-24
----------------
- on_loop() mendukung beberapa transaksi dalam sebuah raw stream.
- class Doc ditambah abstract function terkait transaksi.
0.1 2019-02-04 0.1 2019-02-04
-------------- --------------
- Kali pertama - Kali pertama
...@@ -34,18 +34,13 @@ class BaseISO8583(ISO8583): ...@@ -34,18 +34,13 @@ class BaseISO8583(ISO8583):
return {} return {}
def get_value(self, bit): def get_value(self, bit):
v = self.getBit(bit) return self.getBit(bit)
type_ = self.getBitType(bit)
if type_.find('LL') < 0:
return v
size_length = len(type_)
return v[size_length:]
def get_values(self): def get_values(self):
r = {} r = {}
for item in self.getBitsAndValues(): for item in self.getBitsAndValues():
bit = int(item['bit']) bit = int(item['bit'])
r[bit] = self.get_value(bit) r[bit] = self.getBit(bit)
return r return r
def copy(self, bits=[], from_iso=None): def copy(self, bits=[], from_iso=None):
......
...@@ -13,19 +13,165 @@ from .structure import ( ...@@ -13,19 +13,165 @@ from .structure import (
) )
class StanGenerator:
def __init__(self):
self.stan = '0' * 6
def create(self):
kini = datetime.now()
new_stan = kini.strftime('%H%M%S')
if new_stan == self.stan:
new_stan = int(self.stan) + 1
self.stan = str(new_stan).zfill(6)
else:
self.stan = new_stan
return self.stan
stan_gen = StanGenerator()
class Doc(BaseISO8583): class Doc(BaseISO8583):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
if 'conf' in kwargs:
self.conf = kwargs['conf']
del kwargs['conf']
else:
self.conf = dict()
BaseISO8583.__init__(self, *args, **kwargs) BaseISO8583.__init__(self, *args, **kwargs)
self.transmission = DateTimeVar() self.transmission = DateTimeVar()
if self.from_iso: if self.from_iso:
self.set_response() self.set_response()
# Override
def get_bit_definition(self): def get_bit_definition(self):
return NETWORK_BITS return NETWORK_BITS
# Override, please
def get_inquiry_code(self):
pass
# Override, please
def get_payment_code(self):
pass
def is_network_request(self):
return self.getMTI() == '0800'
def is_network_response(self):
return self.getMTI() == '0810'
def is_transaction_request(self):
return self.getMTI() == '0200' # sebagai pemda
def is_transaction_response(self): # sebagai bank
return self.getMTI() == '0210'
def is_request(self):
return self.is_network_request() or \
self.is_transaction_request() or \
self.is_reversal_request()
def is_response(self):
return self.is_network_response() or \
self.is_transaction_response() or \
self.is_reversal_response()
def get_name(self):
return self.is_echo() or self.is_sign_on() or self.is_sign_off() or \
self.is_reversal() or self.is_inquiry() or self.is_payment()
def get_transaction_code(self):
return self.getBit(3)
def is_inquiry(self):
return self.get_transaction_code() == self.get_inquiry_code() and \
'inquiry'
def is_inquiry_request(self): # sebagai pemda
return self.is_transaction_request() and self.is_inquiry() and \
'inquiry_response'
def is_inquiry_response(self): # sebagai bank
return self.is_transaction_response() and self.is_inquiry() and \
'inquiry_done'
def is_payment(self):
return self.get_transaction_code() == self.get_payment_code() and \
'payment'
def is_payment_request(self): # sebagai pemda
return self.is_transaction_request() and self.is_payment() and \
'payment_response'
def is_payment_response(self): # sebagai bank
return self.is_transaction_request() and self.is_payment() and \
'payment_done'
def is_reversal(self):
return self.getMTI()[:2] == '04' and 'reversal'
def is_reversal_request(self): # sebagai pemda
return self.getMTI() == '0400' and 'reversal_response'
def is_reversal_response(self): # sebagai bank
return self.getMTI() == '0410' and 'reversal_done'
# Override, please
def copy_inquiry_bits(self):
#self.copy([2, 3, 11])
pass
# Override, please
def copy_payment_bits(self):
self.copy_inquiry_bits()
#self.copy([4, 48]) # amount, NTB
def set_transaction_request(self):
self.setMTI('0200')
def set_transaction_response(self):
self.setMTI('0210')
def set_inquiry_request(self): # sebagai bank
self.set_transaction_request()
self.setBit(3, self.get_inquiry_code())
def set_inquiry_response(self): # sebagai pemda
self.set_transaction_response()
self.copy_inquiry_bits()
def set_amount(self, value):
self.setBit(4, value)
def get_amount(self):
return int(self.getBit(4))
def set_payment_request(self): # sebagai bank
self.set_transaction_request()
self.setBit(3, self.get_payment_code())
def set_payment_response(self): # sebagai pemda
self.set_transaction_response()
self.copy_payment_bits()
def set_reversal_response(self): # sebagai pemda
self.setMTI('0410')
self.copy_payment_bits()
def get_func_name(self): def get_func_name(self):
return self.is_echo_request() or self.is_sign_on_request() or \ return self.is_echo_request() or \
self.is_sign_off_request() self.is_echo_response() or \
self.is_sign_on_request() or \
self.is_sign_on_response() or \
self.is_sign_off_request() or \
self.is_sign_off_response() or \
self.is_inquiry_request() or \
self.is_inquiry_response() or \
self.is_payment_request() or \
self.is_payment_response() or \
self.is_reversal_request() or \
self.is_reversal_response()
# Dipanggil Job.process() # Dipanggil Job.process()
def process(self): def process(self):
...@@ -36,12 +182,15 @@ class Doc(BaseISO8583): ...@@ -36,12 +182,15 @@ class Doc(BaseISO8583):
else: else:
self.ack_function_not_found() self.ack_function_not_found()
def is_response(self):
return self.is_network_response()
def set_response(self): def set_response(self):
if self.from_iso.is_network_request(): if self.from_iso.is_network_request():
self.set_network_response() self.set_network_response()
elif self.from_iso.is_inquiry_request():
self.set_inquiry_response()
elif self.from_iso.is_payment_request():
self.set_payment_response()
elif self.from_iso.is_reversal_request():
self.set_reversal_response()
def is_ok_response(self): def is_ok_response(self):
try: try:
...@@ -63,8 +212,8 @@ class Doc(BaseISO8583): ...@@ -63,8 +212,8 @@ class Doc(BaseISO8583):
t.year, t.month, t.day, t.hour, t.minute, t.second) t.year, t.month, t.day, t.hour, t.minute, t.second)
def set_stan(self): # System Trace Audit Number def set_stan(self): # System Trace Audit Number
kini = datetime.now() stan = stan_gen.create()
self.setBit(11, kini.strftime('%H%M%S')) self.setBit(11, stan)
def get_stan(self): def get_stan(self):
return self.get_value(11) return self.get_value(11)
...@@ -89,12 +238,6 @@ class Doc(BaseISO8583): ...@@ -89,12 +238,6 @@ class Doc(BaseISO8583):
def get_func_code(self): def get_func_code(self):
return self.getBit(70) return self.getBit(70)
def is_network_request(self):
return self.getMTI() == '0800'
def is_network_response(self):
return self.getMTI() == '0810'
################### ###################
# Network Sign On # # Network Sign On #
################### ###################
...@@ -105,7 +248,11 @@ class Doc(BaseISO8583): ...@@ -105,7 +248,11 @@ class Doc(BaseISO8583):
def is_sign_on_response(self): def is_sign_on_response(self):
return self.is_network_response() and \ return self.is_network_response() and \
self.get_func_code() == '001' self.get_func_code() == '001' and 'sign_on_done'
def is_sign_on(self):
return (self.is_sign_on_request() or self.is_sign_on_response()) and \
'sign on'
def sign_on_request(self): def sign_on_request(self):
self.set_func_code('001') self.set_func_code('001')
...@@ -114,6 +261,9 @@ class Doc(BaseISO8583): ...@@ -114,6 +261,9 @@ class Doc(BaseISO8583):
self.set_network_response() self.set_network_response()
self.ack() self.ack()
def sign_on_done(self): # Sebagai bank
pass
##################### #####################
# Network Echo Test # # Network Echo Test #
##################### #####################
...@@ -123,11 +273,11 @@ class Doc(BaseISO8583): ...@@ -123,11 +273,11 @@ class Doc(BaseISO8583):
'echo_response' 'echo_response'
def is_echo_response(self): def is_echo_response(self):
return self.is_network_response() and \ return self.is_network_response() and self.get_func_code() == '301' \
self.get_func_code() == '301' and 'echo_done'
def is_echo(self): def is_echo(self):
return self.is_echo_request() or self.is_echo_response() return (self.is_echo_request() or self.is_echo_response()) and 'echo'
def echo_request(self): def echo_request(self):
self.set_func_code('301') self.set_func_code('301')
...@@ -136,6 +286,9 @@ class Doc(BaseISO8583): ...@@ -136,6 +286,9 @@ class Doc(BaseISO8583):
self.set_network_response() self.set_network_response()
self.ack() self.ack()
def echo_done(self):
pass
#################### ####################
# Network Sign Off # # Network Sign Off #
#################### ####################
...@@ -145,10 +298,12 @@ class Doc(BaseISO8583): ...@@ -145,10 +298,12 @@ class Doc(BaseISO8583):
'sign_off_response' 'sign_off_response'
def is_sign_off_response(self): def is_sign_off_response(self):
return self.is_network_request() and self.get_func_code() == '002' return self.is_network_response() and self.get_func_code() == '002' \
and 'sign_off_done'
def is_sign_off(self): def is_sign_off(self):
return self.is_sign_off_request() or self.is_sign_off_response() return (self.is_sign_off_request() or self.is_sign_off_response()) \
and 'sign off'
def sign_off_request(self): def sign_off_request(self):
self.set_func_code('002') self.set_func_code('002')
...@@ -157,6 +312,30 @@ class Doc(BaseISO8583): ...@@ -157,6 +312,30 @@ class Doc(BaseISO8583):
self.set_network_response() self.set_network_response()
self.ack() self.ack()
def sign_off_done(self): # Sebagai bank
pass
###############
# Transaction #
###############
def inquiry_response(self): # Sebagai pemda
pass
def inquiry_done(self): # Sebagai bank
pass
def payment_response(self): # Sebagai pemda
pass
def payment_done(self): # Sebagai bank
pass
def reversal_response(self): # Sebagai pemda
pass
def reversal_done(self): # Sebagai bank
pass
################### ###################
# Acknowledgement # # Acknowledgement #
################### ###################
...@@ -165,6 +344,7 @@ class Doc(BaseISO8583): ...@@ -165,6 +344,7 @@ class Doc(BaseISO8583):
self.set_transmission() self.set_transmission()
self.ack_log(msg) self.ack_log(msg)
# Override, please
def ack_log(self, msg): def ack_log(self, msg):
pass pass
...@@ -173,6 +353,3 @@ class Doc(BaseISO8583): ...@@ -173,6 +353,3 @@ class Doc(BaseISO8583):
def ack_function_not_found(self): def ack_function_not_found(self):
self.ack_other('Fungsi tidak ditemukan') self.ack_other('Fungsi tidak ditemukan')
def ack_unknown(self):
self.ack_other('Unknown')
...@@ -15,7 +15,7 @@ class Job: ...@@ -15,7 +15,7 @@ class Job:
def create_iso(self, from_iso=None): def create_iso(self, from_iso=None):
cls = self.get_iso_class() cls = self.get_iso_class()
return cls(from_iso=from_iso) return cls(from_iso=from_iso, conf=self.conf)
def get_iso(self): def get_iso(self):
if self.do_echo: if self.do_echo:
...@@ -40,6 +40,8 @@ class Job: ...@@ -40,6 +40,8 @@ class Job:
if self.sign_on_time: if self.sign_on_time:
return return
return self.sign_on_request() return self.sign_on_request()
if from_iso.is_sign_on_request():
self.sign_on_time = time()
iso = self.create_iso(from_iso=from_iso) iso = self.create_iso(from_iso=from_iso)
iso.process() iso.process()
return iso return iso
......
import sys import sys
import socket import socket
import select
from time import ( from time import (
time, time,
sleep, sleep,
...@@ -15,6 +16,7 @@ class Connection: ...@@ -15,6 +16,7 @@ class Connection:
self.conf = conf self.conf = conf
self.connected_time = None self.connected_time = None
self.running = False self.running = False
self.created_time = time()
def process(self, raw): def process(self, raw):
return self.job.process(raw) return self.job.process(raw)
...@@ -61,16 +63,20 @@ class Connection: ...@@ -61,16 +63,20 @@ class Connection:
if self.is_timeout(): if self.is_timeout():
self.close_because_timeout() self.close_because_timeout()
return return
while True:
raw = self.streamer.get(raw) raw = self.streamer.get(raw)
if not raw: if not raw:
return return
raw = self.process(raw) raw = self.process(raw)
if raw: if raw:
self.send(raw) self.send(raw)
raw = ''
def receive_raw(self): def receive_raw(self):
try: try:
raw = self.request.recv(self.get_receive_size()) ready, _, _ = select.select([self.request], [], [], 5)
raw = ready and self.request.recv(
self.get_receive_size(), socket.MSG_DONTWAIT) or ''
if isinstance(raw, bytes): if isinstance(raw, bytes):
raw = raw.decode('utf-8') raw = raw.decode('utf-8')
if raw: if raw:
...@@ -104,6 +110,9 @@ class Connection: ...@@ -104,6 +110,9 @@ class Connection:
def send(self, raw): def send(self, raw):
raw = self.raw_for_send(raw) raw = self.raw_for_send(raw)
self.just_send(raw)
def just_send(self, raw):
if sys.version_info.major > 2: if sys.version_info.major > 2:
raw = raw.encode('utf-8') raw = raw.encode('utf-8')
try: try:
...@@ -182,6 +191,12 @@ class ConnectionManager: ...@@ -182,6 +191,12 @@ class ConnectionManager:
sleep(0.1) sleep(0.1)
count = self.count(ip_port) count = self.count(ip_port)
def remove_if_old(self, index):
ip_port, conn = self.conns[index]
if time() - conn.created_time > 5:
self.remove(index)
return True
def __iter__(self): # for loop def __iter__(self): # for loop
for ip_port, conn in self.conns: for ip_port, conn in self.conns:
yield [ip_port, conn] yield [ip_port, conn]
......
...@@ -19,7 +19,6 @@ requires = [ ...@@ -19,7 +19,6 @@ requires = [
packages = [ packages = [
'opensipkd', 'opensipkd',
'opensipkd.tcp', 'opensipkd.tcp',
'opensipkd.tcp',
'opensipkd.streamer', 'opensipkd.streamer',
'opensipkd.iso8583', 'opensipkd.iso8583',
'opensipkd.iso8583.network', 'opensipkd.iso8583.network',
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!