-
Notifications
You must be signed in to change notification settings - Fork 1
/
server.py
149 lines (119 loc) · 4.25 KB
/
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
140
141
142
143
144
145
146
147
148
'''
Created on Sep 24, 2015
@author: abhinav
@lets_roll_babyo
'''
import time
from gevent import socket, greenlet
from gevent.server import StreamServer
import gevent.monkey
from gevent.greenlet import Greenlet
import os
import id3reader
import array
import config
import gevent
import re
from buffers import Buffer
from gevent_handlers.audio_streams import AudioStreamReader, handle_audio_stream
from models.polls import PollItem, Poll
from models.song import Song
from mongoengine.connection import connect
from bson import json_util
from bson.son import SON
from gevent_handlers import init_main_audio_streams
from requests.stream import do_stream_request
from mimetools import Message
from StringIO import StringIO
from helpers.auth import decode_signed_value
from models.user import User
import urlparse
from requests.polls import do_poll
from requests.users import do_register_user, do_dedicate_event
import urllib
from models import initDb
from requests import init_stream_event_handlers, print_stats
from requests.chat import do_chat_event
gevent.monkey.patch_all()
#audio chunksize
#TODO:
# read from main streaming socket that just reads and file and dump raw bytes ,
# put that into streams , for now just do it with files(consider them as sockets)
#
# write client handlers , handles clients , keep them in a list ,
# keep sending data from the streams continuously , break connection after sending few bytes
# send metadata at times
#libevent , keep writing audio data to clients
#libevent , keep reading from the main stream
#libevent , keep broadcasting events , new polls , new chats etc
#this should internally spawn
request_handlers = [(re.compile("/stream/([^/]+)/(.*)") , do_stream_request), #stream/telugu/audio or events
( re.compile("/poll/([^/]+)/([^/]+)/(.*)") , do_poll), #"/poll/telugu/123123/12312312"
( re.compile("/user/login") , do_register_user), #"/poll/telugu/123123/12312312"
( re.compile("/dedicate/(.+)") , do_dedicate_event),
( re.compile("/chat/(.+)") , do_chat_event),
( re.compile("/stats") , print_stats),
]
def read_line(socket):
data = ""
while(True):
byt = socket.recv(1)
data+=byt
if(byt=='\n' or not byt):
return data
# this handler will be run for each incoming connection in a dedicated greenlet
def handle_connection(socket, address):
request_line = read_line(socket)
try:
request_type , request_path , http_version = request_line.split(" ")
except:
socket.close()
print "new request", request_line
headers = {}
while(True):
l = read_line(socket)
if(l=='\r\n'):
break
if( not l):
return
header_type , data = l.split(": ",1)
headers[header_type] = data
post_data = None
if(request_type == "POST" and headers.get("Content-Length", None)):
n = int(headers.get("Content-Length","0").strip(" \r\n"))
if(n>0):
data = ""
while(len(data) < n):
bts = socket.recv(n)
if(not bts):
break
data +=bts
post_data = urlparse.parse_qs(data)
##app specific headers
auth_key = headers.get("auth-key", None)
user = None
if(auth_key):
#decode and get user
auth_key = urllib.unquote(auth_key).strip()
user = User.objects.get(pk = decode_signed_value(config.SERVER_SECRET , "auth_key", auth_key))
for handler in request_handlers:
args = handler[0].match(request_path)
func = handler[1]
kwargs = {"user":user}
if(post_data!=None):
kwargs["post"] = post_data
if(args!=None):
fargs = args.groups()
if(fargs):
func(socket, *fargs , **kwargs)
else:
func(socket, **kwargs)
if __name__ == "__main__":
initDb()
#initialize reading and file decoder
#keep reading streams , auto reconnecting
init_main_audio_streams()
init_stream_event_handlers()
server = StreamServer(
('', 8888), handle_connection)
server.serve_forever()