1 | import errno
|
---|
2 | import select
|
---|
3 | import socket
|
---|
4 | import time
|
---|
5 | import email
|
---|
6 | from io import StringIO
|
---|
7 |
|
---|
8 | from src.HTTPParser import *
|
---|
9 | from src.ogRest import *
|
---|
10 | from enum import Enum
|
---|
11 |
|
---|
12 | class State(Enum):
|
---|
13 | CONNECTING = 0
|
---|
14 | RECEIVING = 1
|
---|
15 | FORCE_DISCONNECTED = 2
|
---|
16 |
|
---|
17 | class ogClient:
|
---|
18 | def __init__(self, ip, port):
|
---|
19 | self.ip = ip
|
---|
20 | self.port = port
|
---|
21 | self.ogrest = ogRest()
|
---|
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):
|
---|
30 | print ('connecting')
|
---|
31 | self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
---|
32 | self.sock.setblocking(0)
|
---|
33 | self.state = State.CONNECTING
|
---|
34 | self.data = ""
|
---|
35 | self.trailer = False
|
---|
36 | self.content_len = 0
|
---|
37 |
|
---|
38 | try:
|
---|
39 | self.sock.connect((self.ip, self.port))
|
---|
40 | except socket.error as err:
|
---|
41 | if err.errno == errno.EINPROGRESS:
|
---|
42 | return
|
---|
43 | elif err.errno == errno.ECONNREFUSED:
|
---|
44 | return
|
---|
45 |
|
---|
46 | print ('Error connect ' + str(err))
|
---|
47 |
|
---|
48 | def send(self, msg):
|
---|
49 | self.sock.send(bytes(msg, 'utf-8'))
|
---|
50 | return len(msg)
|
---|
51 |
|
---|
52 | def connect2(self):
|
---|
53 | try:
|
---|
54 | self.sock.connect((self.ip, self.port))
|
---|
55 | except socket.error as err:
|
---|
56 | if err.errno == errno.EISCONN:
|
---|
57 | print ('connected')
|
---|
58 | self.state = State.RECEIVING
|
---|
59 | else:
|
---|
60 | print ('connection refused, retrying...')
|
---|
61 | self.state = State.CONNECTING
|
---|
62 | self.sock.close()
|
---|
63 | self.connect()
|
---|
64 |
|
---|
65 | def receive(self):
|
---|
66 | try:
|
---|
67 | data = self.sock.recv(1024).decode('utf-8')
|
---|
68 | except socket.err as err:
|
---|
69 | print ('Error3 ' + str(err))
|
---|
70 |
|
---|
71 | if len(data) == 0:
|
---|
72 | self.state = State.CONNECTING
|
---|
73 | self.sock.close()
|
---|
74 | self.connect()
|
---|
75 |
|
---|
76 | self.data = self.data + data
|
---|
77 | httpparser = HTTPParser()
|
---|
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)
|
---|
83 | headers = email.message_from_file(StringIO(headers_alone))
|
---|
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:
|
---|
91 | httpparser.parser(self.data)
|
---|
92 | self.ogrest.processOperation(httpparser, self)
|
---|
93 |
|
---|
94 | # Cleanup state information from request
|
---|
95 | self.data = ""
|
---|
96 | self.content_len = 0
|
---|
97 | self.trailer = False
|
---|
98 |
|
---|
99 | def disconnect(self):
|
---|
100 | self.state = State.FORCE_DISCONNECTED
|
---|
101 | self.sock.close()
|
---|
102 |
|
---|
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 ]
|
---|
111 | elif state == State.FORCE_DISCONNECTED:
|
---|
112 | return 0
|
---|
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:
|
---|
123 | print ('bad state' + str(state))
|
---|