[29fe301] | 1 | import errno
|
---|
| 2 | import select
|
---|
| 3 | import socket
|
---|
| 4 | import time
|
---|
[7548870] | 5 | import email
|
---|
| 6 | from io import StringIO
|
---|
[bfdeae8] | 7 |
|
---|
[7548870] | 8 | from src.HTTPParser import *
|
---|
[dfc97ff] | 9 | from src.ogRest import *
|
---|
[076e15b] | 10 | from enum import Enum
|
---|
[29fe301] | 11 |
|
---|
[076e15b] | 12 | class State(Enum):
|
---|
| 13 | CONNECTING = 0
|
---|
| 14 | RECEIVING = 1
|
---|
[694bc49] | 15 | FORCE_DISCONNECTED = 2
|
---|
[29fe301] | 16 |
|
---|
| 17 | class ogClient:
|
---|
| 18 | def __init__(self, ip, port):
|
---|
| 19 | self.ip = ip
|
---|
| 20 | self.port = port
|
---|
[e20daf6] | 21 | self.ogrest = ogRest()
|
---|
[29fe301] | 22 |
|
---|
| 23 | def get_socket(self):
|
---|
| 24 | return self.sock
|
---|
| 25 |
|
---|
| 26 | def get_state(self):
|
---|
| 27 | return self.state
|
---|
| 28 |
|
---|
| 29 | def connect(self):
|
---|
[7548870] | 30 | print ('connecting')
|
---|
[29fe301] | 31 | self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
---|
| 32 | self.sock.setblocking(0)
|
---|
[076e15b] | 33 | self.state = State.CONNECTING
|
---|
[29fe301] | 34 | self.data = ""
|
---|
| 35 | self.trailer = False
|
---|
| 36 | self.content_len = 0
|
---|
| 37 |
|
---|
| 38 | try:
|
---|
| 39 | self.sock.connect((self.ip, self.port))
|
---|
[7548870] | 40 | except socket.error as err:
|
---|
[29fe301] | 41 | if err.errno == errno.EINPROGRESS:
|
---|
| 42 | return
|
---|
| 43 | elif err.errno == errno.ECONNREFUSED:
|
---|
| 44 | return
|
---|
| 45 |
|
---|
[7548870] | 46 | print ('Error connect ' + str(err))
|
---|
[29fe301] | 47 |
|
---|
[77906be] | 48 | def send(self, msg):
|
---|
| 49 | self.sock.send(bytes(msg, 'utf-8'))
|
---|
| 50 | return len(msg)
|
---|
| 51 |
|
---|
[29fe301] | 52 | def connect2(self):
|
---|
| 53 | try:
|
---|
| 54 | self.sock.connect((self.ip, self.port))
|
---|
[7548870] | 55 | except socket.error as err:
|
---|
[29fe301] | 56 | if err.errno == errno.EISCONN:
|
---|
[7548870] | 57 | print ('connected')
|
---|
[076e15b] | 58 | self.state = State.RECEIVING
|
---|
[29fe301] | 59 | else:
|
---|
[7548870] | 60 | print ('connection refused, retrying...')
|
---|
[076e15b] | 61 | self.state = State.CONNECTING
|
---|
[29fe301] | 62 | self.sock.close()
|
---|
| 63 | self.connect()
|
---|
| 64 |
|
---|
| 65 | def receive(self):
|
---|
| 66 | try:
|
---|
[7548870] | 67 | data = self.sock.recv(1024).decode('utf-8')
|
---|
| 68 | except socket.err as err:
|
---|
| 69 | print ('Error3 ' + str(err))
|
---|
[29fe301] | 70 |
|
---|
| 71 | if len(data) == 0:
|
---|
[076e15b] | 72 | self.state = State.CONNECTING
|
---|
[29fe301] | 73 | self.sock.close()
|
---|
| 74 | self.connect()
|
---|
| 75 |
|
---|
| 76 | self.data = self.data + data
|
---|
[bfdeae8] | 77 | httpparser = HTTPParser()
|
---|
[29fe301] | 78 |
|
---|
| 79 | if not self.trailer:
|
---|
| 80 | if self.data.find("\r\n") > 0:
|
---|
| 81 | # https://stackoverflow.com/questions/4685217/parse-raw-http-headers
|
---|
| 82 | request_line, headers_alone = self.data.split('\n', 1)
|
---|
[7548870] | 83 | headers = email.message_from_file(StringIO(headers_alone))
|
---|
[29fe301] | 84 |
|
---|
| 85 | if 'content-length' in headers.keys():
|
---|
| 86 | self.content_len = int(headers['content-length'])
|
---|
| 87 |
|
---|
| 88 | self.trailer = True
|
---|
| 89 |
|
---|
| 90 | if self.trailer and len(self.data) >= self.content_len:
|
---|
[bfdeae8] | 91 | httpparser.parser(self.data)
|
---|
[2fa8aa4] | 92 | self.ogrest.processOperation(httpparser, self)
|
---|
[29fe301] | 93 |
|
---|
| 94 | # Cleanup state information from request
|
---|
| 95 | self.data = ""
|
---|
| 96 | self.content_len = 0
|
---|
| 97 | self.trailer = False
|
---|
[9eabc7f] | 98 |
|
---|
[77906be] | 99 | def disconnect(self):
|
---|
| 100 | self.state = State.FORCE_DISCONNECTED
|
---|
| 101 | self.sock.close()
|
---|
| 102 |
|
---|
[9eabc7f] | 103 | def run(self):
|
---|
| 104 | while 1:
|
---|
| 105 | sock = self.get_socket()
|
---|
| 106 | state = self.get_state()
|
---|
| 107 |
|
---|
| 108 | if state == State.CONNECTING:
|
---|
| 109 | readset = [ sock ]
|
---|
| 110 | writeset = [ sock ]
|
---|
[694bc49] | 111 | elif state == State.FORCE_DISCONNECTED:
|
---|
| 112 | return 0
|
---|
[9eabc7f] | 113 | else:
|
---|
| 114 | readset = [ sock ]
|
---|
| 115 | writeset = [ ]
|
---|
| 116 |
|
---|
| 117 | readable, writable, exception = select.select(readset, writeset, [ ])
|
---|
| 118 | if state == State.CONNECTING and sock in writable:
|
---|
| 119 | self.connect2()
|
---|
| 120 | elif state == State.RECEIVING and sock in readable:
|
---|
| 121 | self.receive()
|
---|
| 122 | else:
|
---|
[7548870] | 123 | print ('bad state' + str(state))
|
---|