def handler(cnx, *args): '''Asynchronous cnxection handler. Processes each line from the socket.''' global sock_state, input_buf, rtmp_parser line = cnx.recv(4096) print "just received %d-byte in state %s" % (len(line), sock_state) # if the connection has been closed, return now if not len(line): print "Connection closed." return False # append the newly read data to the input buffer input_buf = pyamf.util.BufferedByteStream(input_buf.read() + line) if sock_state == "handshake_itor_wait": if input_buf.remaining() < 1537: return True # change the state sock_state = "handshake_resp_sent" # read the handshake itor handshake_itor = input_buf.read(1537) # send a handshake resp cnx.send("\3" + "\0" * 1536) cnx.send(handshake_itor[1:1537]) if sock_state == "handshake_resp_sent": if input_buf.remaining() < 1536: return True # change the state sock_state = "connected" # discard the whole, it is the 1536 \0 i sent input_buf.read(1536) # init the flv_output flv_init() if sock_state == "connected": # push all the input_buf in the rtmp_parser rtmp_parser.input_push( input_buf.read() ) packet = rtmp_parser.rtmp_packet() if packet == None: print "rtmp_packet no fully received. Current data:\n" tmp = rtmp_parser.input_peek(rtmp_parser.input_remaining()) #print hexdump(tmp) #open("/tmp/slota", "w+").write(tmp) #sys.exit(-1) return True body_type = packet['header']['body_type'] #pprint.pprint(packet) if body_type == rtmp_build_t.rtmp_t.body_types['invoke']: body_parser = rtmp_build_t.rtmp_parse_t(packet['body']) fct_name = body_parser.amf0_element() print "fct_name=" + fct_name + "() with the header" pprint.pprint(packet['header']) if fct_name == "connect": param0 = body_parser.amf0_element(); param1 = body_parser.amf0_element(); pprint.pprint(param0) pprint.pprint(param1) reply_data = '' #reply_data += build_serverbw() #reply_data += build_clientbw() reply_data += build_connect_resp() cnx.send(reply_data) print "reply to "+ fct_name + "():\n" + hexdump(reply_data) elif fct_name == "createStream": param0 = body_parser.amf0_element(); param1 = body_parser.amf0_element(); print "slota createStream=\n" + hexdump(packet['body']) reply_data = build_createstream_resp() cnx.send(reply_data) print "reply to "+ fct_name + "():\n" + hexdump(reply_data) elif body_type == rtmp_build_t.rtmp_t.body_types['videodata'] or body_type == rtmp_build_t.rtmp_t.body_types['audiodata']: body_type = packet['header']['body_type'] timestamp = packet['header']['timestamp'] body_data = packet['body'] print "body_type=" + str(packet['header']['body_type']) + " size=" + str(len(body_data)) + "\n" #print hexdump(body_data) flv_dump_tag(body_type, timestamp, body_data) print "sock_state is now %s and %s-byte remaing in the input buffer" % (sock_state, input_buf.remaining()) #print hexdump(input_buf.peek(input_buf.remaining())) return True
#! /usr/bin/env python # # \par Brief Description # this script is an experimentation to write dummy rtmp server # this is a prototype which aims to provide understanding of rtmp # to be able to code the rtmp webcam reading into webpack import gobject, socket, pyamf import StringIO, struct, sys, time import pprint import rtmp_build_t sock_state = "listening" input_buf = pyamf.util.BufferedByteStream() rtmp_parser = rtmp_build_t.rtmp_parse_t() flv_output = open("/tmp/rtmp_experiment.flv", "w+") flv_prev_chunksize = 0 flv_start_tstamp = None def server(host, port): '''Initialize server and start listening.''' sock = socket.socket() sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.bind((host, port)) sock.listen(1) print "Listening..." gobject.io_add_watch(sock, gobject.IO_IN, listener) def listener(sock, *args):