1bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber/*
2bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * Copyright 2012, The Android Open Source Project
3bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber *
4bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * you may not use this file except in compliance with the License.
6bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * You may obtain a copy of the License at
7bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber *
8bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber *     http://www.apache.org/licenses/LICENSE-2.0
9bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber *
10bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * Unless required by applicable law or agreed to in writing, software
11bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * See the License for the specific language governing permissions and
14bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber * limitations under the License.
15bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber */
16bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
17bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber//#define LOG_NDEBUG 0
18bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber#define LOG_TAG "NetworkSession"
19bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber#include <utils/Log.h>
20bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
21bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber#include "ANetworkSession.h"
22bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber#include "ParsedMessage.h"
23bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
24bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber#include <arpa/inet.h>
25bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber#include <fcntl.h>
26bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber#include <net/if.h>
27bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber#include <netdb.h>
28bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber#include <netinet/in.h>
29bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber#include <sys/socket.h>
30bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
31bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
32bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber#include <media/stagefright/foundation/ADebug.h>
33bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber#include <media/stagefright/foundation/AMessage.h>
34bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber#include <media/stagefright/foundation/hexdump.h>
35bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber#include <media/stagefright/Utils.h>
36bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
37bb197f84c4119651e5face418285688ddaf08ea3Andreas Hubernamespace android {
38bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
39bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstatic const size_t kMaxUDPSize = 1500;
40bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
41bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstruct ANetworkSession::NetworkThread : public Thread {
42bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    NetworkThread(ANetworkSession *session);
43bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
44bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberprotected:
45bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    virtual ~NetworkThread();
46bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
47bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberprivate:
48bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    ANetworkSession *mSession;
49bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
50bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    virtual bool threadLoop();
51bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
52bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(NetworkThread);
53bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber};
54bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
55bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstruct ANetworkSession::Session : public RefBase {
56bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    enum State {
57bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        CONNECTING,
58bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        CONNECTED,
59bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        LISTENING_RTSP,
60bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        LISTENING_TCP_DGRAMS,
61bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        DATAGRAM,
62bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    };
63bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
64bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    Session(int32_t sessionID,
65bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            State state,
66bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            int s,
67bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            const sp<AMessage> &notify);
68bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
69bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    int32_t sessionID() const;
70bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    int socket() const;
71bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    sp<AMessage> getNotificationMessage() const;
72bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
73bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    bool isRTSPServer() const;
74bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    bool isTCPDatagramServer() const;
75bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
76bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    bool wantsToRead();
77bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    bool wantsToWrite();
78bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
79bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    status_t readMore();
80bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    status_t writeMore();
81bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
82bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    status_t sendRequest(const void *data, ssize_t size);
83bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
84bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    void setIsRTSPConnection(bool yesno);
85bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
86bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberprotected:
87bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    virtual ~Session();
88bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
89bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberprivate:
90bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    int32_t mSessionID;
91bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    State mState;
92bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    bool mIsRTSPConnection;
93bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    int mSocket;
94bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    sp<AMessage> mNotify;
95bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    bool mSawReceiveFailure, mSawSendFailure;
96bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
9790a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber    // for TCP / stream data
98bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    AString mOutBuffer;
9990a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber
10090a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber    // for UDP / datagrams
10190a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber    List<sp<ABuffer> > mOutDatagrams;
102bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
103bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    AString mInBuffer;
104bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
105bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    void notifyError(bool send, status_t err, const char *detail);
106bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    void notify(NotificationReason reason);
107bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
108bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(Session);
109bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber};
110bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber////////////////////////////////////////////////////////////////////////////////
111bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
112bb197f84c4119651e5face418285688ddaf08ea3Andreas HuberANetworkSession::NetworkThread::NetworkThread(ANetworkSession *session)
113bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    : mSession(session) {
114bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
115bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
116bb197f84c4119651e5face418285688ddaf08ea3Andreas HuberANetworkSession::NetworkThread::~NetworkThread() {
117bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
118bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
119bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberbool ANetworkSession::NetworkThread::threadLoop() {
120bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    mSession->threadLoop();
121bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
122bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return true;
123bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
124bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
125bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber////////////////////////////////////////////////////////////////////////////////
126bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
127bb197f84c4119651e5face418285688ddaf08ea3Andreas HuberANetworkSession::Session::Session(
128bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        int32_t sessionID,
129bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        State state,
130bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        int s,
131bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        const sp<AMessage> &notify)
132bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    : mSessionID(sessionID),
133bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber      mState(state),
134bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber      mIsRTSPConnection(false),
135bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber      mSocket(s),
136bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber      mNotify(notify),
137bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber      mSawReceiveFailure(false),
138bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber      mSawSendFailure(false) {
139bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (mState == CONNECTED) {
140bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        struct sockaddr_in localAddr;
141bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        socklen_t localAddrLen = sizeof(localAddr);
142bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
143bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        int res = getsockname(
144bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                mSocket, (struct sockaddr *)&localAddr, &localAddrLen);
145bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        CHECK_GE(res, 0);
146bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
147bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        struct sockaddr_in remoteAddr;
148bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        socklen_t remoteAddrLen = sizeof(remoteAddr);
149bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
150bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        res = getpeername(
151bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                mSocket, (struct sockaddr *)&remoteAddr, &remoteAddrLen);
152bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        CHECK_GE(res, 0);
153bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
154bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        in_addr_t addr = ntohl(localAddr.sin_addr.s_addr);
155bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        AString localAddrString = StringPrintf(
156bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                "%d.%d.%d.%d",
157bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                (addr >> 24),
158bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                (addr >> 16) & 0xff,
159bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                (addr >> 8) & 0xff,
160bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                addr & 0xff);
161bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
162bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        addr = ntohl(remoteAddr.sin_addr.s_addr);
163bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        AString remoteAddrString = StringPrintf(
164bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                "%d.%d.%d.%d",
165bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                (addr >> 24),
166bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                (addr >> 16) & 0xff,
167bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                (addr >> 8) & 0xff,
168bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                addr & 0xff);
169bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
170bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        sp<AMessage> msg = mNotify->dup();
171bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        msg->setInt32("sessionID", mSessionID);
172bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        msg->setInt32("reason", kWhatClientConnected);
173bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        msg->setString("server-ip", localAddrString.c_str());
174bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        msg->setInt32("server-port", ntohs(localAddr.sin_port));
175bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        msg->setString("client-ip", remoteAddrString.c_str());
176bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        msg->setInt32("client-port", ntohs(remoteAddr.sin_port));
177bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        msg->post();
178bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
179bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
180bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
181bb197f84c4119651e5face418285688ddaf08ea3Andreas HuberANetworkSession::Session::~Session() {
18296fc6cc65ca93009a759a3a874b82a35771b9714Andreas Huber    ALOGV("Session %d gone", mSessionID);
183bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
184bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    close(mSocket);
185bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    mSocket = -1;
186bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
187bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
188bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberint32_t ANetworkSession::Session::sessionID() const {
189bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return mSessionID;
190bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
191bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
192bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberint ANetworkSession::Session::socket() const {
193bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return mSocket;
194bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
195bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
196bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Hubervoid ANetworkSession::Session::setIsRTSPConnection(bool yesno) {
197bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    mIsRTSPConnection = yesno;
198bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber}
199bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
200bb197f84c4119651e5face418285688ddaf08ea3Andreas Hubersp<AMessage> ANetworkSession::Session::getNotificationMessage() const {
201bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return mNotify;
202bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
203bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
204bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huberbool ANetworkSession::Session::isRTSPServer() const {
205bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    return mState == LISTENING_RTSP;
206bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber}
207bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
208bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huberbool ANetworkSession::Session::isTCPDatagramServer() const {
209bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    return mState == LISTENING_TCP_DGRAMS;
210bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
211bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
212bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberbool ANetworkSession::Session::wantsToRead() {
213bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return !mSawReceiveFailure && mState != CONNECTING;
214bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
215bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
216bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberbool ANetworkSession::Session::wantsToWrite() {
217bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return !mSawSendFailure
218bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        && (mState == CONNECTING
21990a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber            || (mState == CONNECTED && !mOutBuffer.empty())
22090a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber            || (mState == DATAGRAM && !mOutDatagrams.empty()));
221bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
222bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
223bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstatus_t ANetworkSession::Session::readMore() {
224bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (mState == DATAGRAM) {
225bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        status_t err;
226bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        do {
227bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            sp<ABuffer> buf = new ABuffer(kMaxUDPSize);
228bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
229bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            struct sockaddr_in remoteAddr;
230bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            socklen_t remoteAddrLen = sizeof(remoteAddr);
231bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
232bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            ssize_t n;
233bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            do {
234bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                n = recvfrom(
235bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                        mSocket, buf->data(), buf->capacity(), 0,
236bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                        (struct sockaddr *)&remoteAddr, &remoteAddrLen);
237bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            } while (n < 0 && errno == EINTR);
238bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
239bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            err = OK;
240bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            if (n < 0) {
241bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                err = -errno;
242bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            } else if (n == 0) {
243bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                err = -ECONNRESET;
244bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            } else {
245bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                buf->setRange(0, n);
246bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
247bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                int64_t nowUs = ALooper::GetNowUs();
248bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                buf->meta()->setInt64("arrivalTimeUs", nowUs);
249bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
250bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                sp<AMessage> notify = mNotify->dup();
251bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                notify->setInt32("sessionID", mSessionID);
252bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                notify->setInt32("reason", kWhatDatagram);
253bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
254bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                uint32_t ip = ntohl(remoteAddr.sin_addr.s_addr);
255bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                notify->setString(
256bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                        "fromAddr",
257bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                        StringPrintf(
258bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                            "%u.%u.%u.%u",
259bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                            ip >> 24,
260bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                            (ip >> 16) & 0xff,
261bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                            (ip >> 8) & 0xff,
262bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                            ip & 0xff).c_str());
263bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
264bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                notify->setInt32("fromPort", ntohs(remoteAddr.sin_port));
265bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
266bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                notify->setBuffer("data", buf);
267bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                notify->post();
268bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            }
269bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        } while (err == OK);
270bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
271bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (err == -EAGAIN) {
272bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            err = OK;
273bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
274bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
275bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (err != OK) {
276bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            notifyError(false /* send */, err, "Recvfrom failed.");
277bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            mSawReceiveFailure = true;
278bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
279bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
280bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return err;
281bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
282bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
283bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    char tmp[512];
284bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    ssize_t n;
285bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    do {
286bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        n = recv(mSocket, tmp, sizeof(tmp), 0);
287bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    } while (n < 0 && errno == EINTR);
288bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
289bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    status_t err = OK;
290bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
291bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (n > 0) {
292bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        mInBuffer.append(tmp, n);
293bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
294bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber#if 0
295bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        ALOGI("in:");
296bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        hexdump(tmp, n);
297bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber#endif
298bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    } else if (n < 0) {
299bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        err = -errno;
300bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    } else {
301bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        err = -ECONNRESET;
302bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
303bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
304bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (!mIsRTSPConnection) {
305bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        // TCP stream carrying 16-bit length-prefixed datagrams.
306bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
307bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        while (mInBuffer.size() >= 2) {
308bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            size_t packetSize = U16_AT((const uint8_t *)mInBuffer.c_str());
309bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
310bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            if (mInBuffer.size() < packetSize + 2) {
311bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                break;
312bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            }
313bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
314bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            sp<ABuffer> packet = new ABuffer(packetSize);
315bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            memcpy(packet->data(), mInBuffer.c_str() + 2, packetSize);
316bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
317bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            sp<AMessage> notify = mNotify->dup();
318bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            notify->setInt32("sessionID", mSessionID);
319bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            notify->setInt32("reason", kWhatDatagram);
320bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            notify->setBuffer("data", packet);
321bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            notify->post();
322bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
323bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            mInBuffer.erase(0, packetSize + 2);
324bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        }
325bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    } else {
326bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        for (;;) {
327bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            size_t length;
328bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
329bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            if (mInBuffer.size() > 0 && mInBuffer.c_str()[0] == '$') {
330bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                if (mInBuffer.size() < 4) {
331bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    break;
332bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                }
333bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
334bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                length = U16_AT((const uint8_t *)mInBuffer.c_str() + 2);
335bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
336bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                if (mInBuffer.size() < 4 + length) {
337bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    break;
338bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                }
339bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
340bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                sp<AMessage> notify = mNotify->dup();
341bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                notify->setInt32("sessionID", mSessionID);
342bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                notify->setInt32("reason", kWhatBinaryData);
343bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                notify->setInt32("channel", mInBuffer.c_str()[1]);
344bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
345bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                sp<ABuffer> data = new ABuffer(length);
346bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                memcpy(data->data(), mInBuffer.c_str() + 4, length);
347bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
348bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                int64_t nowUs = ALooper::GetNowUs();
349bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                data->meta()->setInt64("arrivalTimeUs", nowUs);
350bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
351bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                notify->setBuffer("data", data);
352bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                notify->post();
353bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
354bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                mInBuffer.erase(0, 4 + length);
355bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                continue;
356bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            }
357bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
358bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            sp<ParsedMessage> msg =
359bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                ParsedMessage::Parse(
360bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                        mInBuffer.c_str(), mInBuffer.size(), err != OK, &length);
361bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
362bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            if (msg == NULL) {
363bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                break;
364bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            }
365bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
366bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            sp<AMessage> notify = mNotify->dup();
367bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            notify->setInt32("sessionID", mSessionID);
368bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            notify->setInt32("reason", kWhatData);
369bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            notify->setObject("data", msg);
370bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            notify->post();
371bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
372bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber#if 1
373bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            // XXX The (old) dongle sends the wrong content length header on a
374bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            // SET_PARAMETER request that signals a "wfd_idr_request".
375bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            // (17 instead of 19).
376bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            const char *content = msg->getContent();
377bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            if (content
378bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    && !memcmp(content, "wfd_idr_request\r\n", 17)
379bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    && length >= 19
380bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    && mInBuffer.c_str()[length] == '\r'
381bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    && mInBuffer.c_str()[length + 1] == '\n') {
382bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                length += 2;
383bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            }
384bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber#endif
385bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
386bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            mInBuffer.erase(0, length);
387bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
388bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            if (err != OK) {
389bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                break;
390bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            }
391bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
392bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
393bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
394bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (err != OK) {
395bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        notifyError(false /* send */, err, "Recv failed.");
396bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        mSawReceiveFailure = true;
397bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
398bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
399bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return err;
400bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
401bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
402bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstatus_t ANetworkSession::Session::writeMore() {
403bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (mState == DATAGRAM) {
40490a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber        CHECK(!mOutDatagrams.empty());
405bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
406bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        status_t err;
407bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        do {
40890a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber            const sp<ABuffer> &datagram = *mOutDatagrams.begin();
409bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
410bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            int n;
411bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            do {
41290a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber                n = send(mSocket, datagram->data(), datagram->size(), 0);
413bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            } while (n < 0 && errno == EINTR);
414bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
415bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            err = OK;
416bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
417bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            if (n > 0) {
41890a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber                mOutDatagrams.erase(mOutDatagrams.begin());
419bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            } else if (n < 0) {
420bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                err = -errno;
421bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            } else if (n == 0) {
422bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                err = -ECONNRESET;
423bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            }
42490a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber        } while (err == OK && !mOutDatagrams.empty());
425bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
426bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (err == -EAGAIN) {
427bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            err = OK;
428bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
429bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
430bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (err != OK) {
431bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            notifyError(true /* send */, err, "Send datagram failed.");
432bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            mSawSendFailure = true;
433bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
434bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
435bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return err;
436bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
437bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
438bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (mState == CONNECTING) {
439bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        int err;
440bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        socklen_t optionLen = sizeof(err);
441bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        CHECK_EQ(getsockopt(mSocket, SOL_SOCKET, SO_ERROR, &err, &optionLen), 0);
442bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        CHECK_EQ(optionLen, (socklen_t)sizeof(err));
443bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
444bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (err != 0) {
445bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            notifyError(kWhatError, -err, "Connection failed");
446bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            mSawSendFailure = true;
447bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
448bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            return -err;
449bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
450bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
451bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        mState = CONNECTED;
452bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        notify(kWhatConnected);
453bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
454bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return OK;
455bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
456bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
457bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    CHECK_EQ(mState, CONNECTED);
458bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    CHECK(!mOutBuffer.empty());
459bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
460bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    ssize_t n;
461bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    do {
462bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        n = send(mSocket, mOutBuffer.c_str(), mOutBuffer.size(), 0);
463bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    } while (n < 0 && errno == EINTR);
464bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
465bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    status_t err = OK;
466bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
467bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (n > 0) {
46872f6aea5afba3ff8ab7e8eab49552d65ee3bb97bAndreas Huber#if 0
469bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        ALOGI("out:");
470bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        hexdump(mOutBuffer.c_str(), n);
47172f6aea5afba3ff8ab7e8eab49552d65ee3bb97bAndreas Huber#endif
472bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
473bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        mOutBuffer.erase(0, n);
474bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    } else if (n < 0) {
475bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        err = -errno;
476bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    } else if (n == 0) {
477bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        err = -ECONNRESET;
478bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
479bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
480bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (err != OK) {
481bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        notifyError(true /* send */, err, "Send failed.");
482bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        mSawSendFailure = true;
483bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
484bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
485bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return err;
486bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
487bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
488bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstatus_t ANetworkSession::Session::sendRequest(const void *data, ssize_t size) {
489bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    CHECK(mState == CONNECTED || mState == DATAGRAM);
490bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
49190a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber    if (mState == DATAGRAM) {
49290a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber        CHECK_GE(size, 0);
49390a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber
49490a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber        sp<ABuffer> datagram = new ABuffer(size);
49590a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber        memcpy(datagram->data(), data, size);
49690a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber
49790a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber        mOutDatagrams.push_back(datagram);
49890a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber        return OK;
49990a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber    }
50090a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber
501bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (mState == CONNECTED && !mIsRTSPConnection) {
502bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        CHECK_LE(size, 65535);
503bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
504bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        uint8_t prefix[2];
505bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        prefix[0] = size >> 8;
506bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        prefix[1] = size & 0xff;
507bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
508bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        mOutBuffer.append((const char *)prefix, sizeof(prefix));
509bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    }
510bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
511bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    mOutBuffer.append(
512bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            (const char *)data,
513bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            (size >= 0) ? size : strlen((const char *)data));
514bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
515bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return OK;
516bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
517bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
518bb197f84c4119651e5face418285688ddaf08ea3Andreas Hubervoid ANetworkSession::Session::notifyError(
519bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        bool send, status_t err, const char *detail) {
520bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    sp<AMessage> msg = mNotify->dup();
521bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    msg->setInt32("sessionID", mSessionID);
522bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    msg->setInt32("reason", kWhatError);
523bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    msg->setInt32("send", send);
524bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    msg->setInt32("err", err);
525bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    msg->setString("detail", detail);
526bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    msg->post();
527bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
528bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
529bb197f84c4119651e5face418285688ddaf08ea3Andreas Hubervoid ANetworkSession::Session::notify(NotificationReason reason) {
530bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    sp<AMessage> msg = mNotify->dup();
531bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    msg->setInt32("sessionID", mSessionID);
532bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    msg->setInt32("reason", reason);
533bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    msg->post();
534bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
535bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
536bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber////////////////////////////////////////////////////////////////////////////////
537bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
538bb197f84c4119651e5face418285688ddaf08ea3Andreas HuberANetworkSession::ANetworkSession()
539bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    : mNextSessionID(1) {
540bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    mPipeFd[0] = mPipeFd[1] = -1;
541bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
542bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
543bb197f84c4119651e5face418285688ddaf08ea3Andreas HuberANetworkSession::~ANetworkSession() {
544bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    stop();
545bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
546bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
547bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstatus_t ANetworkSession::start() {
548bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (mThread != NULL) {
549bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return INVALID_OPERATION;
550bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
551bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
552bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    int res = pipe(mPipeFd);
553bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (res != 0) {
554bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        mPipeFd[0] = mPipeFd[1] = -1;
555bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return -errno;
556bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
557bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
558bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    mThread = new NetworkThread(this);
559bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
560bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    status_t err = mThread->run("ANetworkSession", ANDROID_PRIORITY_AUDIO);
561bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
562bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (err != OK) {
563bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        mThread.clear();
564bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
565bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        close(mPipeFd[0]);
566bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        close(mPipeFd[1]);
567bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        mPipeFd[0] = mPipeFd[1] = -1;
568bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
569bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return err;
570bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
571bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
572bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return OK;
573bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
574bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
575bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstatus_t ANetworkSession::stop() {
576bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (mThread == NULL) {
577bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return INVALID_OPERATION;
578bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
579bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
580bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    mThread->requestExit();
581bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    interrupt();
582bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    mThread->requestExitAndWait();
583bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
584bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    mThread.clear();
585bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
586bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    close(mPipeFd[0]);
587bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    close(mPipeFd[1]);
588bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    mPipeFd[0] = mPipeFd[1] = -1;
589bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
590bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return OK;
591bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
592bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
593bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstatus_t ANetworkSession::createRTSPClient(
594bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        const char *host, unsigned port, const sp<AMessage> &notify,
595bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        int32_t *sessionID) {
596bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return createClientOrServer(
597bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            kModeCreateRTSPClient,
598bcf09f8c995221e75c7cd328f25c7cc6d2b5f7c9Andreas Huber            NULL /* addr */,
599bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            0 /* port */,
600bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            host,
601bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            port,
602bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            notify,
603bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            sessionID);
604bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
605bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
606bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstatus_t ANetworkSession::createRTSPServer(
607bcf09f8c995221e75c7cd328f25c7cc6d2b5f7c9Andreas Huber        const struct in_addr &addr, unsigned port,
608bcf09f8c995221e75c7cd328f25c7cc6d2b5f7c9Andreas Huber        const sp<AMessage> &notify, int32_t *sessionID) {
609bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return createClientOrServer(
610bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            kModeCreateRTSPServer,
611bcf09f8c995221e75c7cd328f25c7cc6d2b5f7c9Andreas Huber            &addr,
612bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            port,
613bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            NULL /* remoteHost */,
614bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            0 /* remotePort */,
615bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            notify,
616bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            sessionID);
617bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
618bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
619bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstatus_t ANetworkSession::createUDPSession(
620bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        unsigned localPort, const sp<AMessage> &notify, int32_t *sessionID) {
621bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return createUDPSession(localPort, NULL, 0, notify, sessionID);
622bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
623bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
624bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstatus_t ANetworkSession::createUDPSession(
625bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        unsigned localPort,
626bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        const char *remoteHost,
627bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        unsigned remotePort,
628bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        const sp<AMessage> &notify,
629bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        int32_t *sessionID) {
630bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return createClientOrServer(
631bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            kModeCreateUDPSession,
632bcf09f8c995221e75c7cd328f25c7cc6d2b5f7c9Andreas Huber            NULL /* addr */,
633bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            localPort,
634bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            remoteHost,
635bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            remotePort,
636bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            notify,
637bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            sessionID);
638bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
639bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
640bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huberstatus_t ANetworkSession::createTCPDatagramSession(
641bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        const struct in_addr &addr, unsigned port,
642bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        const sp<AMessage> &notify, int32_t *sessionID) {
643bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    return createClientOrServer(
644bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            kModeCreateTCPDatagramSessionPassive,
645bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            &addr,
646bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            port,
647bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            NULL /* remoteHost */,
648bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            0 /* remotePort */,
649bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            notify,
650bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            sessionID);
651bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber}
652bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
653bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huberstatus_t ANetworkSession::createTCPDatagramSession(
654bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        unsigned localPort,
655bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        const char *remoteHost,
656bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        unsigned remotePort,
657bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        const sp<AMessage> &notify,
658bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        int32_t *sessionID) {
659bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    return createClientOrServer(
660bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            kModeCreateTCPDatagramSessionActive,
661bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            NULL /* addr */,
662bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            localPort,
663bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            remoteHost,
664bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            remotePort,
665bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            notify,
666bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            sessionID);
667bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber}
668bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
669bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstatus_t ANetworkSession::destroySession(int32_t sessionID) {
670bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    Mutex::Autolock autoLock(mLock);
671bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
672bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    ssize_t index = mSessions.indexOfKey(sessionID);
673bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
674bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (index < 0) {
675bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return -ENOENT;
676bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
677bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
678bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    mSessions.removeItemsAt(index);
679bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
680bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    interrupt();
681bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
682bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return OK;
683bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
684bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
685bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber// static
686bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstatus_t ANetworkSession::MakeSocketNonBlocking(int s) {
687bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    int flags = fcntl(s, F_GETFL, 0);
688bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (flags < 0) {
689bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        flags = 0;
690bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
691bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
692bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    int res = fcntl(s, F_SETFL, flags | O_NONBLOCK);
693bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (res < 0) {
694bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return -errno;
695bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
696bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
697bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return OK;
698bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
699bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
700bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstatus_t ANetworkSession::createClientOrServer(
701bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        Mode mode,
702bcf09f8c995221e75c7cd328f25c7cc6d2b5f7c9Andreas Huber        const struct in_addr *localAddr,
703bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        unsigned port,
704bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        const char *remoteHost,
705bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        unsigned remotePort,
706bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        const sp<AMessage> &notify,
707bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        int32_t *sessionID) {
708bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    Mutex::Autolock autoLock(mLock);
709bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
710bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    *sessionID = 0;
711bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    status_t err = OK;
712bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    int s, res;
713bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    sp<Session> session;
714bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
715bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    s = socket(
716bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            AF_INET,
717bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            (mode == kModeCreateUDPSession) ? SOCK_DGRAM : SOCK_STREAM,
718bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            0);
719bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
720bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (s < 0) {
721bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        err = -errno;
722bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        goto bail;
723bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
724bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
725bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (mode == kModeCreateRTSPServer
726bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            || mode == kModeCreateTCPDatagramSessionPassive) {
727bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        const int yes = 1;
728bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        res = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
729bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
730bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (res < 0) {
731bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            err = -errno;
732bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            goto bail2;
733bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
734bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
735bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
736bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (mode == kModeCreateUDPSession) {
737bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        int size = 256 * 1024;
738bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
739bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        res = setsockopt(s, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
740bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
741bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (res < 0) {
742bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            err = -errno;
743bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            goto bail2;
744bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
745bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
746bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        res = setsockopt(s, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
747bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
748bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (res < 0) {
749bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            err = -errno;
750bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            goto bail2;
751bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
752bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
753bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
754bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    err = MakeSocketNonBlocking(s);
755bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
756bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (err != OK) {
757bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        goto bail2;
758bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
759bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
760bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    struct sockaddr_in addr;
761bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
762bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    addr.sin_family = AF_INET;
763bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
764bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (mode == kModeCreateRTSPClient
765bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            || mode == kModeCreateTCPDatagramSessionActive) {
766bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        struct hostent *ent= gethostbyname(remoteHost);
767bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (ent == NULL) {
768bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            err = -h_errno;
769bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            goto bail2;
770bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
771bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
772bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        addr.sin_addr.s_addr = *(in_addr_t *)ent->h_addr;
773bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        addr.sin_port = htons(remotePort);
774bcf09f8c995221e75c7cd328f25c7cc6d2b5f7c9Andreas Huber    } else if (localAddr != NULL) {
775bcf09f8c995221e75c7cd328f25c7cc6d2b5f7c9Andreas Huber        addr.sin_addr = *localAddr;
776bcf09f8c995221e75c7cd328f25c7cc6d2b5f7c9Andreas Huber        addr.sin_port = htons(port);
777bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    } else {
778bcf09f8c995221e75c7cd328f25c7cc6d2b5f7c9Andreas Huber        addr.sin_addr.s_addr = htonl(INADDR_ANY);
779bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        addr.sin_port = htons(port);
780bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
781bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
782bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (mode == kModeCreateRTSPClient
783bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            || mode == kModeCreateTCPDatagramSessionActive) {
784bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        in_addr_t x = ntohl(addr.sin_addr.s_addr);
785bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        ALOGI("connecting socket %d to %d.%d.%d.%d:%d",
786bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber              s,
787bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber              (x >> 24),
788bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber              (x >> 16) & 0xff,
789bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber              (x >> 8) & 0xff,
790bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber              x & 0xff,
791bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber              ntohs(addr.sin_port));
792bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
793bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        res = connect(s, (const struct sockaddr *)&addr, sizeof(addr));
794bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
795bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        CHECK_LT(res, 0);
796bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (errno == EINPROGRESS) {
797bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            res = 0;
798bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
799bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    } else {
800bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        res = bind(s, (const struct sockaddr *)&addr, sizeof(addr));
801bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
802bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (res == 0) {
803bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            if (mode == kModeCreateRTSPServer
804bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    || mode == kModeCreateTCPDatagramSessionPassive) {
805bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                res = listen(s, 4);
806bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            } else {
807bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                CHECK_EQ(mode, kModeCreateUDPSession);
808bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
809bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                if (remoteHost != NULL) {
810bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    struct sockaddr_in remoteAddr;
811bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    memset(remoteAddr.sin_zero, 0, sizeof(remoteAddr.sin_zero));
812bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    remoteAddr.sin_family = AF_INET;
813bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    remoteAddr.sin_port = htons(remotePort);
814bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
815bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    struct hostent *ent= gethostbyname(remoteHost);
816bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    if (ent == NULL) {
817bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                        err = -h_errno;
818bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                        goto bail2;
819bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    }
820bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
821bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    remoteAddr.sin_addr.s_addr = *(in_addr_t *)ent->h_addr;
822bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
823bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    res = connect(
824bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                            s,
825bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                            (const struct sockaddr *)&remoteAddr,
826bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                            sizeof(remoteAddr));
827bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                }
828bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            }
829bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
830bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
831bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
832bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (res < 0) {
833bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        err = -errno;
834bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        goto bail2;
835bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
836bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
837bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    Session::State state;
838bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    switch (mode) {
839bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        case kModeCreateRTSPClient:
840bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            state = Session::CONNECTING;
841bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            break;
842bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
843bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        case kModeCreateTCPDatagramSessionActive:
844bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            state = Session::CONNECTING;
845bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            break;
846bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
847bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        case kModeCreateTCPDatagramSessionPassive:
848bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            state = Session::LISTENING_TCP_DGRAMS;
849bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            break;
850bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
851bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        case kModeCreateRTSPServer:
852bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            state = Session::LISTENING_RTSP;
853bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            break;
854bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
855bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        default:
856bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            CHECK_EQ(mode, kModeCreateUDPSession);
857bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            state = Session::DATAGRAM;
858bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            break;
859bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
860bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
861bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    session = new Session(
862bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            mNextSessionID++,
863bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            state,
864bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            s,
865bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            notify);
866bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
867bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (mode == kModeCreateTCPDatagramSessionActive) {
868bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        session->setIsRTSPConnection(false);
869bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    } else if (mode == kModeCreateRTSPClient) {
870bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        session->setIsRTSPConnection(true);
871bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    }
872bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
873bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    mSessions.add(session->sessionID(), session);
874bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
875bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    interrupt();
876bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
877bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    *sessionID = session->sessionID();
878bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
879bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    goto bail;
880bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
881bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberbail2:
882bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    close(s);
883bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    s = -1;
884bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
885bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberbail:
886bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return err;
887bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
888bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
889bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstatus_t ANetworkSession::connectUDPSession(
890bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        int32_t sessionID, const char *remoteHost, unsigned remotePort) {
891bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    Mutex::Autolock autoLock(mLock);
892bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
893bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    ssize_t index = mSessions.indexOfKey(sessionID);
894bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
895bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (index < 0) {
896bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return -ENOENT;
897bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
898bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
899bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    const sp<Session> session = mSessions.valueAt(index);
900bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    int s = session->socket();
901bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
902bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    struct sockaddr_in remoteAddr;
903bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    memset(remoteAddr.sin_zero, 0, sizeof(remoteAddr.sin_zero));
904bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    remoteAddr.sin_family = AF_INET;
905bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    remoteAddr.sin_port = htons(remotePort);
906bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
907bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    status_t err = OK;
908bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    struct hostent *ent = gethostbyname(remoteHost);
909bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (ent == NULL) {
910bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        err = -h_errno;
911bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    } else {
912bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        remoteAddr.sin_addr.s_addr = *(in_addr_t *)ent->h_addr;
913bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
914bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        int res = connect(
915bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                s,
916bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                (const struct sockaddr *)&remoteAddr,
917bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                sizeof(remoteAddr));
918bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
919bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (res < 0) {
920bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            err = -errno;
921bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
922bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
923bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
924bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return err;
925bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
926bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
927bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstatus_t ANetworkSession::sendRequest(
928bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        int32_t sessionID, const void *data, ssize_t size) {
929bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    Mutex::Autolock autoLock(mLock);
930bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
931bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    ssize_t index = mSessions.indexOfKey(sessionID);
932bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
933bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (index < 0) {
934bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return -ENOENT;
935bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
936bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
937bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    const sp<Session> session = mSessions.valueAt(index);
938bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
939bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    status_t err = session->sendRequest(data, size);
940bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
941bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    interrupt();
942bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
943bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return err;
944bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
945bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
946bb197f84c4119651e5face418285688ddaf08ea3Andreas Hubervoid ANetworkSession::interrupt() {
947bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    static const char dummy = 0;
948bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
949bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    ssize_t n;
950bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    do {
951bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        n = write(mPipeFd[1], &dummy, 1);
952bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    } while (n < 0 && errno == EINTR);
953bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
954bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (n < 0) {
955bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        ALOGW("Error writing to pipe (%s)", strerror(errno));
956bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
957bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
958bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
959bb197f84c4119651e5face418285688ddaf08ea3Andreas Hubervoid ANetworkSession::threadLoop() {
960bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    fd_set rs, ws;
961bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    FD_ZERO(&rs);
962bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    FD_ZERO(&ws);
963bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
964bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    FD_SET(mPipeFd[0], &rs);
965bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    int maxFd = mPipeFd[0];
966bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
967bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    {
968bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        Mutex::Autolock autoLock(mLock);
969bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
970bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        for (size_t i = 0; i < mSessions.size(); ++i) {
971bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            const sp<Session> &session = mSessions.valueAt(i);
972bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
973bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            int s = session->socket();
974bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
975bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            if (s < 0) {
976bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                continue;
977bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            }
978bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
979bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            if (session->wantsToRead()) {
980bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                FD_SET(s, &rs);
981bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                if (s > maxFd) {
982bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    maxFd = s;
983bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                }
984bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            }
985bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
986bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            if (session->wantsToWrite()) {
987bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                FD_SET(s, &ws);
988bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                if (s > maxFd) {
989bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    maxFd = s;
990bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                }
991bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            }
992bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
993bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
994bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
995bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    int res = select(maxFd + 1, &rs, &ws, NULL, NULL /* tv */);
996bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
997bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (res == 0) {
998bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return;
999bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
1000bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1001bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (res < 0) {
1002bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (errno == EINTR) {
1003bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            return;
1004bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
1005bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1006bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        ALOGE("select failed w/ error %d (%s)", errno, strerror(errno));
1007bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return;
1008bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
1009bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1010bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (FD_ISSET(mPipeFd[0], &rs)) {
1011bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        char c;
1012bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        ssize_t n;
1013bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        do {
1014bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            n = read(mPipeFd[0], &c, 1);
1015bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        } while (n < 0 && errno == EINTR);
1016bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1017bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (n < 0) {
1018bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            ALOGW("Error reading from pipe (%s)", strerror(errno));
1019bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
1020bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1021bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        --res;
1022bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
1023bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1024bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    {
1025bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        Mutex::Autolock autoLock(mLock);
1026bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1027bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        List<sp<Session> > sessionsToAdd;
1028bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1029bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        for (size_t i = mSessions.size(); res > 0 && i-- > 0;) {
1030bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            const sp<Session> &session = mSessions.valueAt(i);
1031bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1032bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            int s = session->socket();
1033bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1034bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            if (s < 0) {
1035bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                continue;
1036bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            }
1037bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1038bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            if (FD_ISSET(s, &rs) || FD_ISSET(s, &ws)) {
1039bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                --res;
1040bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            }
1041bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1042bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            if (FD_ISSET(s, &rs)) {
1043bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                if (session->isRTSPServer() || session->isTCPDatagramServer()) {
1044bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    struct sockaddr_in remoteAddr;
1045bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    socklen_t remoteAddrLen = sizeof(remoteAddr);
1046bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1047bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    int clientSocket = accept(
1048bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                            s, (struct sockaddr *)&remoteAddr, &remoteAddrLen);
1049bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1050bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    if (clientSocket >= 0) {
1051bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                        status_t err = MakeSocketNonBlocking(clientSocket);
1052bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1053bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                        if (err != OK) {
1054bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                            ALOGE("Unable to make client socket non blocking, "
1055bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                  "failed w/ error %d (%s)",
1056bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                  err, strerror(-err));
1057bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1058bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                            close(clientSocket);
1059bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                            clientSocket = -1;
1060bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                        } else {
1061bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                            in_addr_t addr = ntohl(remoteAddr.sin_addr.s_addr);
1062bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1063bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                            ALOGI("incoming connection from %d.%d.%d.%d:%d "
1064bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                  "(socket %d)",
1065bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                  (addr >> 24),
1066bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                  (addr >> 16) & 0xff,
1067bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                  (addr >> 8) & 0xff,
1068bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                  addr & 0xff,
1069bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                  ntohs(remoteAddr.sin_port),
1070bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                  clientSocket);
1071bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1072bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                            sp<Session> clientSession =
1073bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                // using socket sd as sessionID
1074bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                new Session(
1075bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                        mNextSessionID++,
1076bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                        Session::CONNECTED,
1077bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                        clientSocket,
1078bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                        session->getNotificationMessage());
1079bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1080bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                            clientSession->setIsRTSPConnection(
1081bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                                    session->isRTSPServer());
1082bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
1083bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                            sessionsToAdd.push_back(clientSession);
1084bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                        }
1085bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    } else {
1086bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                        ALOGE("accept returned error %d (%s)",
1087bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                              errno, strerror(errno));
1088bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    }
1089bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                } else {
1090bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    status_t err = session->readMore();
1091bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    if (err != OK) {
109296fc6cc65ca93009a759a3a874b82a35771b9714Andreas Huber                        ALOGE("readMore on socket %d failed w/ error %d (%s)",
1093bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                              s, err, strerror(-err));
1094bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    }
1095bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                }
1096bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            }
1097bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1098bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            if (FD_ISSET(s, &ws)) {
1099bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                status_t err = session->writeMore();
1100bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                if (err != OK) {
110196fc6cc65ca93009a759a3a874b82a35771b9714Andreas Huber                    ALOGE("writeMore on socket %d failed w/ error %d (%s)",
1102bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                          s, err, strerror(-err));
1103bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                }
1104bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            }
1105bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
1106bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1107bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        while (!sessionsToAdd.empty()) {
1108bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            sp<Session> session = *sessionsToAdd.begin();
1109bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            sessionsToAdd.erase(sessionsToAdd.begin());
1110bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1111bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            mSessions.add(session->sessionID(), session);
1112bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1113bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            ALOGI("added clientSession %d", session->sessionID());
1114bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
1115bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
1116bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
1117bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1118bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}  // namespace android
1119bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1120