internal bool OnHandleRequest(Socket client, string username, string path, NameValueCollection query, int range)
{
int session = 0;
if (query["session-id"] != null) {
session = Int32.Parse (query["session-id"]);
}
if (!sessions.ContainsKey (session) && path != "/server-info" && path != "/content-codes" &&
path != "/login") {
ws.WriteResponse (client, HttpStatusCode.Forbidden, "invalid session id");
return true;
}
if (session != 0) {
sessions[session].LastActionTime = DateTime.Now;
}
int clientRev = 0;
if (query["revision-number"] != null) {
clientRev = Int32.Parse (query["revision-number"]);
}
int delta = 0;
if (query["delta"] != null) {
delta = Int32.Parse (query["delta"]);
}
if (path == "/server-info") {
ws.WriteResponse (client, GetServerInfoNode ());
} else if (path == "/content-codes") {
ws.WriteResponse (client, ContentCodeBag.Default.ToNode ());
} else if (path == "/login") {
ExpireSessions ();
if (maxUsers > 0 && sessions.Count + 1 > maxUsers) {
ws.WriteResponse (client, HttpStatusCode.ServiceUnavailable, "too many users");
return true;
}
session = random.Next ();
User user = new User (DateTime.Now, (client.RemoteEndPoint as IPEndPoint).Address, username);
lock (sessions) {
sessions[session] = user;
}
ws.WriteResponse (client, GetLoginNode (session));
OnUserLogin (user);
} else if (path == "/logout") {
User user = sessions[session];
lock (sessions) {
sessions.Remove (session);
}
ws.WriteResponse (client, HttpStatusCode.OK, new byte[0]);
OnUserLogout (user);
return false;
} else if (path == "/databases") {
ws.WriteResponse (client, GetDatabasesNode ());
} else if (dbItemsRegex.IsMatch (path)) {
int dbid = Int32.Parse (dbItemsRegex.Match (path).Groups[1].Value);
Database curdb = revmgr.GetDatabase (clientRev, dbid);
if (curdb == null) {
ws.WriteResponse (client, HttpStatusCode.BadRequest, "invalid database id");
return true;
}
ArrayList deletedIds = new ArrayList ();
if (delta > 0) {
Database olddb = revmgr.GetDatabase (clientRev - delta, dbid);
if (olddb != null) {
foreach (Track track in olddb.Tracks) {
if (curdb.LookupTrackById (track.Id) == null)
deletedIds.Add (track.Id);
}
}
}
ContentNode node = curdb.ToTracksNode (query["meta"].Split (','),
(int[]) deletedIds.ToArray (typeof (int)));
ws.WriteResponse (client, node);
} else if (dbTrackRegex.IsMatch (path)) {
Match match = dbTrackRegex.Match (path);
int dbid = Int32.Parse (match.Groups[1].Value);
int trackid = Int32.Parse (match.Groups[2].Value);
Database db = revmgr.GetDatabase (clientRev, dbid);
if (db == null) {
ws.WriteResponse (client, HttpStatusCode.BadRequest, "invalid database id");
return true;
}
Track track = db.LookupTrackById (trackid);
if (track == null) {
ws.WriteResponse (client, HttpStatusCode.BadRequest, "invalid track id");
return true;
}
try {
try {
if (TrackRequested != null)
TrackRequested (this, new TrackRequestedArgs (username,
(client.RemoteEndPoint as IPEndPoint).Address,
db, track));
} catch {}
if (track.FileName != null) {
ws.WriteResponseFile (client, track.FileName, range);
} else if (db.Client != null) {
long trackLength = 0;
Stream trackStream = db.StreamTrack (track, out trackLength);
try {
ws.WriteResponseStream (client, trackStream, trackLength);
} catch (IOException) {
}
} else {
ws.WriteResponse (client, HttpStatusCode.InternalServerError, "no file");
}
} finally {
client.Close ();
}
} else if (dbContainersRegex.IsMatch (path)) {
int dbid = Int32.Parse (dbContainersRegex.Match (path).Groups[1].Value);
Database db = revmgr.GetDatabase (clientRev, dbid);
if (db == null) {
ws.WriteResponse (client, HttpStatusCode.BadRequest, "invalid database id");
return true;
}
ws.WriteResponse (client, db.ToPlaylistsNode ());
} else if (dbContainerItemsRegex.IsMatch (path)) {
Match match = dbContainerItemsRegex.Match (path);
int dbid = Int32.Parse (match.Groups[1].Value);
int plid = Int32.Parse (match.Groups[2].Value);
Database curdb = revmgr.GetDatabase (clientRev, dbid);
if (curdb == null) {
ws.WriteResponse (client, HttpStatusCode.BadRequest, "invalid database id");
return true;
}
Playlist curpl = curdb.LookupPlaylistById (plid);
if (curdb == null) {
ws.WriteResponse (client, HttpStatusCode.BadRequest, "invalid playlist id");
return true;
}
ArrayList deletedIds = new ArrayList ();
if (delta > 0) {
Database olddb = revmgr.GetDatabase (clientRev - delta, dbid);
if (olddb != null) {
Playlist oldpl = olddb.LookupPlaylistById (plid);
if (oldpl != null) {
IList<Track> oldplTracks = oldpl.Tracks;
for (int i = 0; i < oldplTracks.Count; i++) {
int id = oldpl.GetContainerId (i);
if (curpl.LookupIndexByContainerId (id) < 0) {
deletedIds.Add (id);
}
}
}
}
}
ws.WriteResponse (client, curpl.ToTracksNode ((int[]) deletedIds.ToArray (typeof (int))));
} else if (path == "/update") {
int retrev;
lock (revmgr) {
// if they have the current revision, wait for a change
if (clientRev == revmgr.Current) {
Monitor.Wait (revmgr);
}
retrev = revmgr.Current;
}
if (!running) {
ws.WriteResponse (client, HttpStatusCode.NotFound, "server has been stopped");
} else {
ws.WriteResponse (client, GetUpdateNode (retrev));
}
} else {
ws.WriteResponse (client, HttpStatusCode.Forbidden, "GO AWAY");
}
return true;
}