1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "ARTSPConnection"
19 #include <utils/Log.h>
20 
21 #include "ARTSPConnection.h"
22 
23 #include <media/stagefright/foundation/ABuffer.h>
24 #include <media/stagefright/foundation/ADebug.h>
25 #include <media/stagefright/foundation/AMessage.h>
26 #include <media/stagefright/foundation/base64.h>
27 #include <media/stagefright/MediaErrors.h>
28 #include <media/stagefright/Utils.h>
29 
30 #include <arpa/inet.h>
31 #include <fcntl.h>
32 #include <netdb.h>
33 #include <openssl/md5.h>
34 #include <sys/socket.h>
35 
36 #include "include/HTTPBase.h"
37 
38 namespace android {
39 
40 // static
41 const int64_t ARTSPConnection::kSelectTimeoutUs = 1000ll;
42 
43 // static
44 const AString ARTSPConnection::sUserAgent =
45     AStringPrintf("User-Agent: %s\r\n", MakeUserAgent().c_str());
46 
ARTSPConnection(bool uidValid,uid_t uid)47 ARTSPConnection::ARTSPConnection(bool uidValid, uid_t uid)
48     : mUIDValid(uidValid),
49       mUID(uid),
50       mState(DISCONNECTED),
51       mAuthType(NONE),
52       mSocket(-1),
53       mConnectionID(0),
54       mNextCSeq(0),
55       mReceiveResponseEventPending(false) {
56 }
57 
~ARTSPConnection()58 ARTSPConnection::~ARTSPConnection() {
59     if (mSocket >= 0) {
60         ALOGE("Connection is still open, closing the socket.");
61         if (mUIDValid) {
62             HTTPBase::UnRegisterSocketUserTag(mSocket);
63             HTTPBase::UnRegisterSocketUserMark(mSocket);
64         }
65         close(mSocket);
66         mSocket = -1;
67     }
68 }
69 
connect(const char * url,const sp<AMessage> & reply)70 void ARTSPConnection::connect(const char *url, const sp<AMessage> &reply) {
71     sp<AMessage> msg = new AMessage(kWhatConnect, this);
72     msg->setString("url", url);
73     msg->setMessage("reply", reply);
74     msg->post();
75 }
76 
disconnect(const sp<AMessage> & reply)77 void ARTSPConnection::disconnect(const sp<AMessage> &reply) {
78     sp<AMessage> msg = new AMessage(kWhatDisconnect, this);
79     msg->setMessage("reply", reply);
80     msg->post();
81 }
82 
sendRequest(const char * request,const sp<AMessage> & reply)83 void ARTSPConnection::sendRequest(
84         const char *request, const sp<AMessage> &reply) {
85     sp<AMessage> msg = new AMessage(kWhatSendRequest, this);
86     msg->setString("request", request);
87     msg->setMessage("reply", reply);
88     msg->post();
89 }
90 
observeBinaryData(const sp<AMessage> & reply)91 void ARTSPConnection::observeBinaryData(const sp<AMessage> &reply) {
92     sp<AMessage> msg = new AMessage(kWhatObserveBinaryData, this);
93     msg->setMessage("reply", reply);
94     msg->post();
95 }
96 
onMessageReceived(const sp<AMessage> & msg)97 void ARTSPConnection::onMessageReceived(const sp<AMessage> &msg) {
98     switch (msg->what()) {
99         case kWhatConnect:
100             onConnect(msg);
101             break;
102 
103         case kWhatDisconnect:
104             onDisconnect(msg);
105             break;
106 
107         case kWhatCompleteConnection:
108             onCompleteConnection(msg);
109             break;
110 
111         case kWhatSendRequest:
112             onSendRequest(msg);
113             break;
114 
115         case kWhatReceiveResponse:
116             onReceiveResponse();
117             break;
118 
119         case kWhatObserveBinaryData:
120         {
121             CHECK(msg->findMessage("reply", &mObserveBinaryMessage));
122             break;
123         }
124 
125         default:
126             TRESPASS();
127             break;
128     }
129 }
130 
131 // static
ParseURL(const char * url,AString * host,unsigned * port,AString * path,AString * user,AString * pass)132 bool ARTSPConnection::ParseURL(
133         const char *url, AString *host, unsigned *port, AString *path,
134         AString *user, AString *pass) {
135     host->clear();
136     *port = 0;
137     path->clear();
138     user->clear();
139     pass->clear();
140 
141     if (strncasecmp("rtsp://", url, 7)) {
142         return false;
143     }
144 
145     const char *slashPos = strchr(&url[7], '/');
146 
147     if (slashPos == NULL) {
148         host->setTo(&url[7]);
149         path->setTo("/");
150     } else {
151         host->setTo(&url[7], slashPos - &url[7]);
152         path->setTo(slashPos);
153     }
154 
155     ssize_t atPos = host->find("@");
156 
157     if (atPos >= 0) {
158         // Split of user:pass@ from hostname.
159 
160         AString userPass(*host, 0, atPos);
161         host->erase(0, atPos + 1);
162 
163         ssize_t colonPos = userPass.find(":");
164 
165         if (colonPos < 0) {
166             *user = userPass;
167         } else {
168             user->setTo(userPass, 0, colonPos);
169             pass->setTo(userPass, colonPos + 1, userPass.size() - colonPos - 1);
170         }
171     }
172 
173     const char *colonPos = strchr(host->c_str(), ':');
174 
175     if (colonPos != NULL) {
176         unsigned long x;
177         if (!ParseSingleUnsignedLong(colonPos + 1, &x) || x >= 65536) {
178             return false;
179         }
180 
181         *port = x;
182 
183         size_t colonOffset = colonPos - host->c_str();
184         size_t trailing = host->size() - colonOffset;
185         host->erase(colonOffset, trailing);
186     } else {
187         *port = 554;
188     }
189 
190     return true;
191 }
192 
MakeSocketBlocking(int s,bool blocking)193 static status_t MakeSocketBlocking(int s, bool blocking) {
194     // Make socket non-blocking.
195     int flags = fcntl(s, F_GETFL, 0);
196 
197     if (flags == -1) {
198         return UNKNOWN_ERROR;
199     }
200 
201     if (blocking) {
202         flags &= ~O_NONBLOCK;
203     } else {
204         flags |= O_NONBLOCK;
205     }
206 
207     flags = fcntl(s, F_SETFL, flags);
208 
209     return flags == -1 ? UNKNOWN_ERROR : OK;
210 }
211 
onConnect(const sp<AMessage> & msg)212 void ARTSPConnection::onConnect(const sp<AMessage> &msg) {
213     ++mConnectionID;
214 
215     if (mState != DISCONNECTED) {
216         if (mUIDValid) {
217             HTTPBase::UnRegisterSocketUserTag(mSocket);
218             HTTPBase::UnRegisterSocketUserMark(mSocket);
219         }
220         close(mSocket);
221         mSocket = -1;
222 
223         flushPendingRequests();
224     }
225 
226     mState = CONNECTING;
227 
228     AString url;
229     CHECK(msg->findString("url", &url));
230 
231     sp<AMessage> reply;
232     CHECK(msg->findMessage("reply", &reply));
233 
234     AString host, path;
235     unsigned port;
236     if (!ParseURL(url.c_str(), &host, &port, &path, &mUser, &mPass)
237             || (mUser.size() > 0 && mPass.size() == 0)) {
238         // If we have a user name but no password we have to give up
239         // right here, since we currently have no way of asking the user
240         // for this information.
241 
242         ALOGE("Malformed rtsp url %s", uriDebugString(url).c_str());
243 
244         reply->setInt32("result", ERROR_MALFORMED);
245         reply->post();
246 
247         mState = DISCONNECTED;
248         return;
249     }
250 
251     if (mUser.size() > 0) {
252         ALOGV("user = '%s', pass = '%s'", mUser.c_str(), mPass.c_str());
253     }
254 
255     struct hostent *ent = gethostbyname(host.c_str());
256     if (ent == NULL) {
257         ALOGE("Unknown host %s", host.c_str());
258 
259         reply->setInt32("result", -ENOENT);
260         reply->post();
261 
262         mState = DISCONNECTED;
263         return;
264     }
265 
266     mSocket = socket(AF_INET, SOCK_STREAM, 0);
267 
268     if (mUIDValid) {
269         HTTPBase::RegisterSocketUserTag(mSocket, mUID,
270                                         (uint32_t)*(uint32_t*) "RTSP");
271         HTTPBase::RegisterSocketUserMark(mSocket, mUID);
272     }
273 
274     MakeSocketBlocking(mSocket, false);
275 
276     struct sockaddr_in remote;
277     memset(remote.sin_zero, 0, sizeof(remote.sin_zero));
278     remote.sin_family = AF_INET;
279     remote.sin_addr.s_addr = *(in_addr_t *)ent->h_addr;
280     remote.sin_port = htons(port);
281 
282     int err = ::connect(
283             mSocket, (const struct sockaddr *)&remote, sizeof(remote));
284 
285     reply->setInt32("server-ip", ntohl(remote.sin_addr.s_addr));
286 
287     if (err < 0) {
288         if (errno == EINPROGRESS) {
289             sp<AMessage> msg = new AMessage(kWhatCompleteConnection, this);
290             msg->setMessage("reply", reply);
291             msg->setInt32("connection-id", mConnectionID);
292             msg->post();
293             return;
294         }
295 
296         reply->setInt32("result", -errno);
297         mState = DISCONNECTED;
298 
299         if (mUIDValid) {
300             HTTPBase::UnRegisterSocketUserTag(mSocket);
301             HTTPBase::UnRegisterSocketUserMark(mSocket);
302         }
303         close(mSocket);
304         mSocket = -1;
305     } else {
306         reply->setInt32("result", OK);
307         mState = CONNECTED;
308         mNextCSeq = 1;
309 
310         postReceiveReponseEvent();
311     }
312 
313     reply->post();
314 }
315 
performDisconnect()316 void ARTSPConnection::performDisconnect() {
317     if (mUIDValid) {
318         HTTPBase::UnRegisterSocketUserTag(mSocket);
319         HTTPBase::UnRegisterSocketUserMark(mSocket);
320     }
321     close(mSocket);
322     mSocket = -1;
323 
324     flushPendingRequests();
325 
326     mUser.clear();
327     mPass.clear();
328     mAuthType = NONE;
329     mNonce.clear();
330 
331     mState = DISCONNECTED;
332 }
333 
onDisconnect(const sp<AMessage> & msg)334 void ARTSPConnection::onDisconnect(const sp<AMessage> &msg) {
335     if (mState == CONNECTED || mState == CONNECTING) {
336         performDisconnect();
337     }
338 
339     sp<AMessage> reply;
340     CHECK(msg->findMessage("reply", &reply));
341 
342     reply->setInt32("result", OK);
343 
344     reply->post();
345 }
346 
onCompleteConnection(const sp<AMessage> & msg)347 void ARTSPConnection::onCompleteConnection(const sp<AMessage> &msg) {
348     sp<AMessage> reply;
349     CHECK(msg->findMessage("reply", &reply));
350 
351     int32_t connectionID;
352     CHECK(msg->findInt32("connection-id", &connectionID));
353 
354     if ((connectionID != mConnectionID) || mState != CONNECTING) {
355         // While we were attempting to connect, the attempt was
356         // cancelled.
357         reply->setInt32("result", -ECONNABORTED);
358         reply->post();
359         return;
360     }
361 
362     struct timeval tv;
363     tv.tv_sec = 0;
364     tv.tv_usec = kSelectTimeoutUs;
365 
366     fd_set ws;
367     FD_ZERO(&ws);
368     FD_SET(mSocket, &ws);
369 
370     int res = select(mSocket + 1, NULL, &ws, NULL, &tv);
371     CHECK_GE(res, 0);
372 
373     if (res == 0) {
374         // Timed out. Not yet connected.
375 
376         msg->post();
377         return;
378     }
379 
380     int err;
381     socklen_t optionLen = sizeof(err);
382     CHECK_EQ(getsockopt(mSocket, SOL_SOCKET, SO_ERROR, &err, &optionLen), 0);
383     CHECK_EQ(optionLen, (socklen_t)sizeof(err));
384 
385     if (err != 0) {
386         ALOGE("err = %d (%s)", err, strerror(err));
387 
388         reply->setInt32("result", -err);
389 
390         mState = DISCONNECTED;
391         if (mUIDValid) {
392             HTTPBase::UnRegisterSocketUserTag(mSocket);
393             HTTPBase::UnRegisterSocketUserMark(mSocket);
394         }
395         close(mSocket);
396         mSocket = -1;
397     } else {
398         reply->setInt32("result", OK);
399         mState = CONNECTED;
400         mNextCSeq = 1;
401 
402         postReceiveReponseEvent();
403     }
404 
405     reply->post();
406 }
407 
onSendRequest(const sp<AMessage> & msg)408 void ARTSPConnection::onSendRequest(const sp<AMessage> &msg) {
409     sp<AMessage> reply;
410     CHECK(msg->findMessage("reply", &reply));
411 
412     if (mState != CONNECTED) {
413         reply->setInt32("result", -ENOTCONN);
414         reply->post();
415         return;
416     }
417 
418     AString request;
419     CHECK(msg->findString("request", &request));
420 
421     // Just in case we need to re-issue the request with proper authentication
422     // later, stash it away.
423     reply->setString("original-request", request.c_str(), request.size());
424 
425     addAuthentication(&request);
426     addUserAgent(&request);
427 
428     // Find the boundary between headers and the body.
429     ssize_t i = request.find("\r\n\r\n");
430     CHECK_GE(i, 0);
431 
432     int32_t cseq = mNextCSeq++;
433 
434     AString cseqHeader = "CSeq: ";
435     cseqHeader.append(cseq);
436     cseqHeader.append("\r\n");
437 
438     request.insert(cseqHeader, i + 2);
439 
440     ALOGV("request: '%s'", request.c_str());
441 
442     size_t numBytesSent = 0;
443     while (numBytesSent < request.size()) {
444         ssize_t n =
445             send(mSocket, request.c_str() + numBytesSent,
446                  request.size() - numBytesSent, 0);
447 
448         if (n < 0 && errno == EINTR) {
449             continue;
450         }
451 
452         if (n <= 0) {
453             performDisconnect();
454 
455             if (n == 0) {
456                 // Server closed the connection.
457                 ALOGE("Server unexpectedly closed the connection.");
458 
459                 reply->setInt32("result", ERROR_IO);
460                 reply->post();
461             } else {
462                 ALOGE("Error sending rtsp request. (%s)", strerror(errno));
463                 reply->setInt32("result", -errno);
464                 reply->post();
465             }
466 
467             return;
468         }
469 
470         numBytesSent += (size_t)n;
471     }
472 
473     mPendingRequests.add(cseq, reply);
474 }
475 
onReceiveResponse()476 void ARTSPConnection::onReceiveResponse() {
477     mReceiveResponseEventPending = false;
478 
479     if (mState != CONNECTED) {
480         return;
481     }
482 
483     struct timeval tv;
484     tv.tv_sec = 0;
485     tv.tv_usec = kSelectTimeoutUs;
486 
487     fd_set rs;
488     FD_ZERO(&rs);
489     FD_SET(mSocket, &rs);
490 
491     int res = select(mSocket + 1, &rs, NULL, NULL, &tv);
492 
493     if (res == 1) {
494         MakeSocketBlocking(mSocket, true);
495 
496         bool success = receiveRTSPReponse();
497 
498         MakeSocketBlocking(mSocket, false);
499 
500         if (!success) {
501             // Something horrible, irreparable has happened.
502             flushPendingRequests();
503             return;
504         }
505     }
506 
507     postReceiveReponseEvent();
508 }
509 
flushPendingRequests()510 void ARTSPConnection::flushPendingRequests() {
511     for (size_t i = 0; i < mPendingRequests.size(); ++i) {
512         sp<AMessage> reply = mPendingRequests.valueAt(i);
513 
514         reply->setInt32("result", -ECONNABORTED);
515         reply->post();
516     }
517 
518     mPendingRequests.clear();
519 }
520 
postReceiveReponseEvent()521 void ARTSPConnection::postReceiveReponseEvent() {
522     if (mReceiveResponseEventPending) {
523         return;
524     }
525 
526     sp<AMessage> msg = new AMessage(kWhatReceiveResponse, this);
527     msg->post();
528 
529     mReceiveResponseEventPending = true;
530 }
531 
receive(void * data,size_t size)532 status_t ARTSPConnection::receive(void *data, size_t size) {
533     size_t offset = 0;
534     while (offset < size) {
535         ssize_t n = recv(mSocket, (uint8_t *)data + offset, size - offset, 0);
536 
537         if (n < 0 && errno == EINTR) {
538             continue;
539         }
540 
541         if (n <= 0) {
542             performDisconnect();
543 
544             if (n == 0) {
545                 // Server closed the connection.
546                 ALOGE("Server unexpectedly closed the connection.");
547                 return ERROR_IO;
548             } else {
549                 ALOGE("Error reading rtsp response. (%s)", strerror(errno));
550                 return -errno;
551             }
552         }
553 
554         offset += (size_t)n;
555     }
556 
557     return OK;
558 }
559 
receiveLine(AString * line)560 bool ARTSPConnection::receiveLine(AString *line) {
561     line->clear();
562 
563     bool sawCR = false;
564     for (;;) {
565         char c;
566         if (receive(&c, 1) != OK) {
567             return false;
568         }
569 
570         if (sawCR && c == '\n') {
571             line->erase(line->size() - 1, 1);
572             return true;
573         } else if (c == '\n') {
574             // some reponse line ended with '\n', instead of '\r\n'.
575             return true;
576         }
577 
578         line->append(&c, 1);
579 
580         if (c == '$' && line->size() == 1) {
581             // Special-case for interleaved binary data.
582             return true;
583         }
584 
585         sawCR = (c == '\r');
586     }
587 }
588 
receiveBinaryData()589 sp<ABuffer> ARTSPConnection::receiveBinaryData() {
590     uint8_t x[3];
591     if (receive(x, 3) != OK) {
592         return NULL;
593     }
594 
595     sp<ABuffer> buffer = new ABuffer((x[1] << 8) | x[2]);
596     if (receive(buffer->data(), buffer->size()) != OK) {
597         return NULL;
598     }
599 
600     buffer->meta()->setInt32("index", (int32_t)x[0]);
601 
602     return buffer;
603 }
604 
IsRTSPVersion(const AString & s)605 static bool IsRTSPVersion(const AString &s) {
606     return s == "RTSP/1.0";
607 }
608 
receiveRTSPReponse()609 bool ARTSPConnection::receiveRTSPReponse() {
610     AString statusLine;
611 
612     if (!receiveLine(&statusLine)) {
613         return false;
614     }
615 
616     if (statusLine == "$") {
617         sp<ABuffer> buffer = receiveBinaryData();
618 
619         if (buffer == NULL) {
620             return false;
621         }
622 
623         if (mObserveBinaryMessage != NULL) {
624             sp<AMessage> notify = mObserveBinaryMessage->dup();
625             notify->setBuffer("buffer", buffer);
626             notify->post();
627         } else {
628             ALOGW("received binary data, but no one cares.");
629         }
630 
631         return true;
632     }
633 
634     sp<ARTSPResponse> response = new ARTSPResponse;
635     response->mStatusLine = statusLine;
636 
637     ALOGI("status: %s", response->mStatusLine.c_str());
638 
639     ssize_t space1 = response->mStatusLine.find(" ");
640     if (space1 < 0) {
641         return false;
642     }
643     ssize_t space2 = response->mStatusLine.find(" ", space1 + 1);
644     if (space2 < 0) {
645         return false;
646     }
647 
648     bool isRequest = false;
649 
650     if (!IsRTSPVersion(AString(response->mStatusLine, 0, space1))) {
651         CHECK(IsRTSPVersion(
652                     AString(
653                         response->mStatusLine,
654                         space2 + 1,
655                         response->mStatusLine.size() - space2 - 1)));
656 
657         isRequest = true;
658 
659         response->mStatusCode = 0;
660     } else {
661         AString statusCodeStr(
662                 response->mStatusLine, space1 + 1, space2 - space1 - 1);
663 
664         if (!ParseSingleUnsignedLong(
665                     statusCodeStr.c_str(), &response->mStatusCode)
666                 || response->mStatusCode < 100 || response->mStatusCode > 999) {
667             return false;
668         }
669     }
670 
671     AString line;
672     ssize_t lastDictIndex = -1;
673     for (;;) {
674         if (!receiveLine(&line)) {
675             break;
676         }
677 
678         if (line.empty()) {
679             break;
680         }
681 
682         ALOGV("line: '%s'", line.c_str());
683 
684         if (line.c_str()[0] == ' ' || line.c_str()[0] == '\t') {
685             // Support for folded header values.
686 
687             if (lastDictIndex < 0) {
688                 // First line cannot be a continuation of the previous one.
689                 return false;
690             }
691 
692             AString &value = response->mHeaders.editValueAt(lastDictIndex);
693             value.append(line);
694 
695             continue;
696         }
697 
698         ssize_t colonPos = line.find(":");
699         if (colonPos < 0) {
700             // Malformed header line.
701             return false;
702         }
703 
704         AString key(line, 0, colonPos);
705         key.trim();
706         key.tolower();
707 
708         line.erase(0, colonPos + 1);
709 
710         lastDictIndex = response->mHeaders.add(key, line);
711     }
712 
713     for (size_t i = 0; i < response->mHeaders.size(); ++i) {
714         response->mHeaders.editValueAt(i).trim();
715     }
716 
717     unsigned long contentLength = 0;
718 
719     ssize_t i = response->mHeaders.indexOfKey("content-length");
720 
721     if (i >= 0) {
722         AString value = response->mHeaders.valueAt(i);
723         if (!ParseSingleUnsignedLong(value.c_str(), &contentLength)) {
724             return false;
725         }
726     }
727 
728     if (contentLength > 0) {
729         response->mContent = new ABuffer(contentLength);
730 
731         if (receive(response->mContent->data(), contentLength) != OK) {
732             return false;
733         }
734     }
735 
736     if (response->mStatusCode == 401) {
737         if (mAuthType == NONE && mUser.size() > 0
738                 && parseAuthMethod(response)) {
739             ssize_t i;
740             CHECK_EQ((status_t)OK, findPendingRequest(response, &i));
741             CHECK_GE(i, 0);
742 
743             sp<AMessage> reply = mPendingRequests.valueAt(i);
744             mPendingRequests.removeItemsAt(i);
745 
746             AString request;
747             CHECK(reply->findString("original-request", &request));
748 
749             sp<AMessage> msg = new AMessage(kWhatSendRequest, this);
750             msg->setMessage("reply", reply);
751             msg->setString("request", request.c_str(), request.size());
752 
753             ALOGI("re-sending request with authentication headers...");
754             onSendRequest(msg);
755 
756             return true;
757         }
758     }
759 
760     return isRequest
761         ? handleServerRequest(response)
762         : notifyResponseListener(response);
763 }
764 
handleServerRequest(const sp<ARTSPResponse> & request)765 bool ARTSPConnection::handleServerRequest(const sp<ARTSPResponse> &request) {
766     // Implementation of server->client requests is optional for all methods
767     // but we do need to respond, even if it's just to say that we don't
768     // support the method.
769 
770     ssize_t space1 = request->mStatusLine.find(" ");
771     CHECK_GE(space1, 0);
772 
773     AString response;
774     response.append("RTSP/1.0 501 Not Implemented\r\n");
775 
776     ssize_t i = request->mHeaders.indexOfKey("cseq");
777 
778     if (i >= 0) {
779         AString value = request->mHeaders.valueAt(i);
780 
781         unsigned long cseq;
782         if (!ParseSingleUnsignedLong(value.c_str(), &cseq)) {
783             return false;
784         }
785 
786         response.append("CSeq: ");
787         response.append(cseq);
788         response.append("\r\n");
789     }
790 
791     response.append("\r\n");
792 
793     size_t numBytesSent = 0;
794     while (numBytesSent < response.size()) {
795         ssize_t n =
796             send(mSocket, response.c_str() + numBytesSent,
797                  response.size() - numBytesSent, 0);
798 
799         if (n < 0 && errno == EINTR) {
800             continue;
801         }
802 
803         if (n <= 0) {
804             if (n == 0) {
805                 // Server closed the connection.
806                 ALOGE("Server unexpectedly closed the connection.");
807             } else {
808                 ALOGE("Error sending rtsp response (%s).", strerror(errno));
809             }
810 
811             performDisconnect();
812 
813             return false;
814         }
815 
816         numBytesSent += (size_t)n;
817     }
818 
819     return true;
820 }
821 
822 // static
ParseSingleUnsignedLong(const char * from,unsigned long * x)823 bool ARTSPConnection::ParseSingleUnsignedLong(
824         const char *from, unsigned long *x) {
825     char *end;
826     *x = strtoul(from, &end, 10);
827 
828     if (end == from || *end != '\0') {
829         return false;
830     }
831 
832     return true;
833 }
834 
findPendingRequest(const sp<ARTSPResponse> & response,ssize_t * index) const835 status_t ARTSPConnection::findPendingRequest(
836         const sp<ARTSPResponse> &response, ssize_t *index) const {
837     *index = 0;
838 
839     ssize_t i = response->mHeaders.indexOfKey("cseq");
840 
841     if (i < 0) {
842         // This is an unsolicited server->client message.
843         *index = -1;
844         return OK;
845     }
846 
847     AString value = response->mHeaders.valueAt(i);
848 
849     unsigned long cseq;
850     if (!ParseSingleUnsignedLong(value.c_str(), &cseq)) {
851         return ERROR_MALFORMED;
852     }
853 
854     i = mPendingRequests.indexOfKey(cseq);
855 
856     if (i < 0) {
857         return -ENOENT;
858     }
859 
860     *index = i;
861 
862     return OK;
863 }
864 
notifyResponseListener(const sp<ARTSPResponse> & response)865 bool ARTSPConnection::notifyResponseListener(
866         const sp<ARTSPResponse> &response) {
867     ssize_t i;
868     status_t err = findPendingRequest(response, &i);
869 
870     if (err == OK && i < 0) {
871         // An unsolicited server response is not a problem.
872         return true;
873     }
874 
875     if (err != OK) {
876         return false;
877     }
878 
879     sp<AMessage> reply = mPendingRequests.valueAt(i);
880     mPendingRequests.removeItemsAt(i);
881 
882     reply->setInt32("result", OK);
883     reply->setObject("response", response);
884     reply->post();
885 
886     return true;
887 }
888 
parseAuthMethod(const sp<ARTSPResponse> & response)889 bool ARTSPConnection::parseAuthMethod(const sp<ARTSPResponse> &response) {
890     ssize_t i = response->mHeaders.indexOfKey("www-authenticate");
891 
892     if (i < 0) {
893         return false;
894     }
895 
896     AString value = response->mHeaders.valueAt(i);
897 
898     if (!strncmp(value.c_str(), "Basic", 5)) {
899         mAuthType = BASIC;
900     } else {
901 
902         CHECK(!strncmp(value.c_str(), "Digest", 6));
903         mAuthType = DIGEST;
904 
905         i = value.find("nonce=");
906         CHECK_GE(i, 0);
907         CHECK_EQ(value.c_str()[i + 6], '\"');
908         ssize_t j = value.find("\"", i + 7);
909         CHECK_GE(j, 0);
910 
911         mNonce.setTo(value, i + 7, j - i - 7);
912     }
913 
914     return true;
915 }
916 
H(const AString & s,AString * out)917 static void H(const AString &s, AString *out) {
918     out->clear();
919 
920     MD5_CTX m;
921     MD5_Init(&m);
922     MD5_Update(&m, s.c_str(), s.size());
923 
924     uint8_t key[16];
925     MD5_Final(key, &m);
926 
927     for (size_t i = 0; i < 16; ++i) {
928         char nibble = key[i] >> 4;
929         if (nibble <= 9) {
930             nibble += '0';
931         } else {
932             nibble += 'a' - 10;
933         }
934         out->append(&nibble, 1);
935 
936         nibble = key[i] & 0x0f;
937         if (nibble <= 9) {
938             nibble += '0';
939         } else {
940             nibble += 'a' - 10;
941         }
942         out->append(&nibble, 1);
943     }
944 }
945 
GetMethodAndURL(const AString & request,AString * method,AString * url)946 static void GetMethodAndURL(
947         const AString &request, AString *method, AString *url) {
948     ssize_t space1 = request.find(" ");
949     CHECK_GE(space1, 0);
950 
951     ssize_t space2 = request.find(" ", space1 + 1);
952     CHECK_GE(space2, 0);
953 
954     method->setTo(request, 0, space1);
955     url->setTo(request, space1 + 1, space2 - space1);
956 }
957 
addAuthentication(AString * request)958 void ARTSPConnection::addAuthentication(AString *request) {
959     if (mAuthType == NONE) {
960         return;
961     }
962 
963     // Find the boundary between headers and the body.
964     ssize_t i = request->find("\r\n\r\n");
965     CHECK_GE(i, 0);
966 
967     if (mAuthType == BASIC) {
968         AString tmp;
969         tmp.append(mUser);
970         tmp.append(":");
971         tmp.append(mPass);
972 
973         AString out;
974         encodeBase64(tmp.c_str(), tmp.size(), &out);
975 
976         AString fragment;
977         fragment.append("Authorization: Basic ");
978         fragment.append(out);
979         fragment.append("\r\n");
980 
981         request->insert(fragment, i + 2);
982 
983         return;
984     }
985 
986     CHECK_EQ((int)mAuthType, (int)DIGEST);
987 
988     AString method, url;
989     GetMethodAndURL(*request, &method, &url);
990 
991     AString A1;
992     A1.append(mUser);
993     A1.append(":");
994     A1.append("Streaming Server");
995     A1.append(":");
996     A1.append(mPass);
997 
998     AString A2;
999     A2.append(method);
1000     A2.append(":");
1001     A2.append(url);
1002 
1003     AString HA1, HA2;
1004     H(A1, &HA1);
1005     H(A2, &HA2);
1006 
1007     AString tmp;
1008     tmp.append(HA1);
1009     tmp.append(":");
1010     tmp.append(mNonce);
1011     tmp.append(":");
1012     tmp.append(HA2);
1013 
1014     AString digest;
1015     H(tmp, &digest);
1016 
1017     AString fragment;
1018     fragment.append("Authorization: Digest ");
1019     fragment.append("nonce=\"");
1020     fragment.append(mNonce);
1021     fragment.append("\", ");
1022     fragment.append("username=\"");
1023     fragment.append(mUser);
1024     fragment.append("\", ");
1025     fragment.append("uri=\"");
1026     fragment.append(url);
1027     fragment.append("\", ");
1028     fragment.append("response=\"");
1029     fragment.append(digest);
1030     fragment.append("\"");
1031     fragment.append("\r\n");
1032 
1033     request->insert(fragment, i + 2);
1034 }
1035 
addUserAgent(AString * request) const1036 void ARTSPConnection::addUserAgent(AString *request) const {
1037     // Find the boundary between headers and the body.
1038     ssize_t i = request->find("\r\n\r\n");
1039     CHECK_GE(i, 0);
1040 
1041     request->insert(sUserAgent, i + 2);
1042 }
1043 
1044 }  // namespace android
1045