-
Notifications
You must be signed in to change notification settings - Fork 21
/
sample_rtmp_server.py
139 lines (125 loc) · 4.46 KB
/
sample_rtmp_server.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
""" Sample implementation of an RTMP server. """
import pyamf.util
import rtmp_protocol_base
import rtmp_protocol
import SocketServer
import time
class RTMPHandler(SocketServer.BaseRequestHandler):
""" Handles a client connection. """
WAITING_C1 = 0
WAITING_C2 = 1
WAITING_COMMAND_CONNECT = 2
WAITING_DATA = 3
def handle(self):
"""
This method gets called when a client connects to the RTMP server. It
implements a state machine.
"""
state = self.WAITING_C1
self.state2 = 0
f = self.request.makefile()
self.sock_stream = rtmp_protocol.FileDataTypeMixIn(f)
self.reader = rtmp_protocol.RtmpReader(self.sock_stream)
self.writer = rtmp_protocol.RtmpWriter(self.sock_stream)
while True:
if state == self.WAITING_C1:
self.handle_C1()
state += 1
elif state == self.WAITING_C2:
self.handle_C2()
state += 1
elif state == self.WAITING_COMMAND_CONNECT:
self.handle_command_connect()
state += 1
elif state == self.WAITING_DATA:
self.handle_data()
else:
assert False, state
def handle_C1(self):
"""
Handle version byte and first handshake packet sent by client. Send
version byte and two handshake packets to client.
"""
self.sock_stream.read_uchar()
c1 = rtmp_protocol_base.Packet()
c1.decode(self.sock_stream)
self.sock_stream.write_uchar(3)
s1 = rtmp_protocol_base.Packet(first=0,second=0,payload='x'*1528)
s1.encode(self.sock_stream)
s2 = rtmp_protocol_base.Packet(first=0,second=0,payload='x'*1528)
s2.encode(self.sock_stream)
self.sock_stream.flush()
def handle_C2(self):
""" Handle second handshake packet from client. """
c2 = rtmp_protocol_base.Packet()
c2.decode(self.sock_stream)
def handle_command_connect(self):
""" Handle the first RTMP message that initiates the connection. """
self.reader.next()
msg = {
'msg': rtmp_protocol.DataTypes.COMMAND,
'command':
[
u'_result',
1,
{'capabilities': 31, 'fmsVer': u'FMS/3,0,2,217'},
{
'code': u'NetConnection.Connect.Success',
'objectEncoding': 0,
'description': u'Connection succeeded.',
'level': u'status'
}
]
}
self.writer.write(msg)
self.writer.flush()
def handle_data(self):
"""
Handle additional RTMP messages from the client. In this sample
implementation the server waits for 2 shared object use events and
responds with the use_success, clear and change events for each one of
them.
"""
msg = {
'msg': rtmp_protocol.DataTypes.SHARED_OBJECT,
'curr_version': 0,
'flags': '\x00\x00\x00\x00\x00\x00\x00\x00',
'events':
[
{
'type':rtmp_protocol.SOEventTypes.USE_SUCCESS,
'data':''
},
{
'type':rtmp_protocol.SOEventTypes.CLEAR,
'data':''
},
{
'type': rtmp_protocol.SOEventTypes.CHANGE,
}
]
}
if self.state2 == 0:
self.state2 += 1
print self.reader.next()
time.sleep(2)
msg['obj_name'] = 'so_name'
msg['events'][2]['data'] = {'sparam':'1234567890 '*5}
self.writer.write(msg)
self.writer.flush()
elif self.state2 == 1:
self.state2 += 1
print self.reader.next()
time.sleep(2)
msg['obj_name'] = 'so2_name'
msg['events'][2]['data'] = {'sparam':'QWERTY '*20}
self.writer.write(msg)
self.writer.flush()
else:
print self.reader.next()
def main():
""" Start the RTMP server on 127.0.0.1 at port 80. """
server = SocketServer.TCPServer(('127.0.0.1', 80), RTMPHandler)
server.serve_forever()
if __name__ == '__main__':
main()