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