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
4100224bf170a3904576bba81593eaab113c5d3a4e7Andreas Huber            uint8_t *data = datagram->data();
4110224bf170a3904576bba81593eaab113c5d3a4e7Andreas Huber            if (data[0] == 0x80 && (data[1] & 0x7f) == 33) {
4120224bf170a3904576bba81593eaab113c5d3a4e7Andreas Huber                int64_t nowUs = ALooper::GetNowUs();
4130224bf170a3904576bba81593eaab113c5d3a4e7Andreas Huber
4140224bf170a3904576bba81593eaab113c5d3a4e7Andreas Huber                uint32_t prevRtpTime = U32_AT(&data[4]);
4150224bf170a3904576bba81593eaab113c5d3a4e7Andreas Huber
4160224bf170a3904576bba81593eaab113c5d3a4e7Andreas Huber                // 90kHz time scale
4170224bf170a3904576bba81593eaab113c5d3a4e7Andreas Huber                uint32_t rtpTime = (nowUs * 9ll) / 100ll;
4180224bf170a3904576bba81593eaab113c5d3a4e7Andreas Huber                int32_t diffTime = (int32_t)rtpTime - (int32_t)prevRtpTime;
4190224bf170a3904576bba81593eaab113c5d3a4e7Andreas Huber
4200224bf170a3904576bba81593eaab113c5d3a4e7Andreas Huber                ALOGV("correcting rtpTime by %.0f ms", diffTime / 90.0);
4210224bf170a3904576bba81593eaab113c5d3a4e7Andreas Huber
4220224bf170a3904576bba81593eaab113c5d3a4e7Andreas Huber                data[4] = rtpTime >> 24;
4230224bf170a3904576bba81593eaab113c5d3a4e7Andreas Huber                data[5] = (rtpTime >> 16) & 0xff;
4240224bf170a3904576bba81593eaab113c5d3a4e7Andreas Huber                data[6] = (rtpTime >> 8) & 0xff;
4250224bf170a3904576bba81593eaab113c5d3a4e7Andreas Huber                data[7] = rtpTime & 0xff;
4260224bf170a3904576bba81593eaab113c5d3a4e7Andreas Huber            }
4270224bf170a3904576bba81593eaab113c5d3a4e7Andreas Huber
428bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            int n;
429bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            do {
43090a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber                n = send(mSocket, datagram->data(), datagram->size(), 0);
431bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            } while (n < 0 && errno == EINTR);
432bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
433bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            err = OK;
434bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
435bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            if (n > 0) {
43690a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber                mOutDatagrams.erase(mOutDatagrams.begin());
437bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            } else if (n < 0) {
438bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                err = -errno;
439bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            } else if (n == 0) {
440bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                err = -ECONNRESET;
441bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            }
44290a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber        } while (err == OK && !mOutDatagrams.empty());
443bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
444bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (err == -EAGAIN) {
4450224bf170a3904576bba81593eaab113c5d3a4e7Andreas Huber            if (!mOutDatagrams.empty()) {
4460224bf170a3904576bba81593eaab113c5d3a4e7Andreas Huber                ALOGI("%d datagrams remain queued.", mOutDatagrams.size());
4470224bf170a3904576bba81593eaab113c5d3a4e7Andreas Huber            }
448bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            err = OK;
449bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
450bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
451bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (err != OK) {
452bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            notifyError(true /* send */, err, "Send datagram failed.");
453bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            mSawSendFailure = true;
454bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
455bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
456bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return err;
457bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
458bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
459bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (mState == CONNECTING) {
460bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        int err;
461bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        socklen_t optionLen = sizeof(err);
462bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        CHECK_EQ(getsockopt(mSocket, SOL_SOCKET, SO_ERROR, &err, &optionLen), 0);
463bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        CHECK_EQ(optionLen, (socklen_t)sizeof(err));
464bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
465bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (err != 0) {
466bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            notifyError(kWhatError, -err, "Connection failed");
467bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            mSawSendFailure = true;
468bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
469bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            return -err;
470bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
471bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
472bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        mState = CONNECTED;
473bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        notify(kWhatConnected);
474bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
475bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return OK;
476bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
477bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
478bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    CHECK_EQ(mState, CONNECTED);
479bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    CHECK(!mOutBuffer.empty());
480bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
481bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    ssize_t n;
482bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    do {
483bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        n = send(mSocket, mOutBuffer.c_str(), mOutBuffer.size(), 0);
484bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    } while (n < 0 && errno == EINTR);
485bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
486bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    status_t err = OK;
487bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
488bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (n > 0) {
48972f6aea5afba3ff8ab7e8eab49552d65ee3bb97bAndreas Huber#if 0
490bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        ALOGI("out:");
491bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        hexdump(mOutBuffer.c_str(), n);
49272f6aea5afba3ff8ab7e8eab49552d65ee3bb97bAndreas Huber#endif
493bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
494bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        mOutBuffer.erase(0, n);
495bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    } else if (n < 0) {
496bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        err = -errno;
497bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    } else if (n == 0) {
498bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        err = -ECONNRESET;
499bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
500bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
501bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (err != OK) {
502bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        notifyError(true /* send */, err, "Send failed.");
503bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        mSawSendFailure = true;
504bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
505bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
506bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return err;
507bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
508bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
509bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstatus_t ANetworkSession::Session::sendRequest(const void *data, ssize_t size) {
510bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    CHECK(mState == CONNECTED || mState == DATAGRAM);
511bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
51290a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber    if (mState == DATAGRAM) {
51390a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber        CHECK_GE(size, 0);
51490a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber
51590a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber        sp<ABuffer> datagram = new ABuffer(size);
51690a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber        memcpy(datagram->data(), data, size);
51790a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber
51890a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber        mOutDatagrams.push_back(datagram);
51990a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber        return OK;
52090a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber    }
52190a92053219ae50ddf4bb54e3d54db2d309e2b8dAndreas Huber
522bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (mState == CONNECTED && !mIsRTSPConnection) {
523bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        CHECK_LE(size, 65535);
524bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
525bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        uint8_t prefix[2];
526bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        prefix[0] = size >> 8;
527bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        prefix[1] = size & 0xff;
528bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
529bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        mOutBuffer.append((const char *)prefix, sizeof(prefix));
530bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    }
531bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
532bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    mOutBuffer.append(
533bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            (const char *)data,
534bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            (size >= 0) ? size : strlen((const char *)data));
535bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
536bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return OK;
537bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
538bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
539bb197f84c4119651e5face418285688ddaf08ea3Andreas Hubervoid ANetworkSession::Session::notifyError(
540bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        bool send, status_t err, const char *detail) {
541bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    sp<AMessage> msg = mNotify->dup();
542bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    msg->setInt32("sessionID", mSessionID);
543bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    msg->setInt32("reason", kWhatError);
544bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    msg->setInt32("send", send);
545bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    msg->setInt32("err", err);
546bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    msg->setString("detail", detail);
547bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    msg->post();
548bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
549bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
550bb197f84c4119651e5face418285688ddaf08ea3Andreas Hubervoid ANetworkSession::Session::notify(NotificationReason reason) {
551bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    sp<AMessage> msg = mNotify->dup();
552bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    msg->setInt32("sessionID", mSessionID);
553bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    msg->setInt32("reason", reason);
554bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    msg->post();
555bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
556bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
557bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber////////////////////////////////////////////////////////////////////////////////
558bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
559bb197f84c4119651e5face418285688ddaf08ea3Andreas HuberANetworkSession::ANetworkSession()
560bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    : mNextSessionID(1) {
561bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    mPipeFd[0] = mPipeFd[1] = -1;
562bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
563bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
564bb197f84c4119651e5face418285688ddaf08ea3Andreas HuberANetworkSession::~ANetworkSession() {
565bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    stop();
566bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
567bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
568bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstatus_t ANetworkSession::start() {
569bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (mThread != NULL) {
570bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return INVALID_OPERATION;
571bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
572bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
573bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    int res = pipe(mPipeFd);
574bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (res != 0) {
575bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        mPipeFd[0] = mPipeFd[1] = -1;
576bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return -errno;
577bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
578bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
579bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    mThread = new NetworkThread(this);
580bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
581bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    status_t err = mThread->run("ANetworkSession", ANDROID_PRIORITY_AUDIO);
582bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
583bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (err != OK) {
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 err;
591bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
592bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
593bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return OK;
594bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
595bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
596bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstatus_t ANetworkSession::stop() {
597bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (mThread == NULL) {
598bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return INVALID_OPERATION;
599bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
600bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
601bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    mThread->requestExit();
602bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    interrupt();
603bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    mThread->requestExitAndWait();
604bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
605bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    mThread.clear();
606bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
607bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    close(mPipeFd[0]);
608bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    close(mPipeFd[1]);
609bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    mPipeFd[0] = mPipeFd[1] = -1;
610bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
611bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return OK;
612bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
613bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
614bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstatus_t ANetworkSession::createRTSPClient(
615bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        const char *host, unsigned port, const sp<AMessage> &notify,
616bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        int32_t *sessionID) {
617bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return createClientOrServer(
618bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            kModeCreateRTSPClient,
619bcf09f8c995221e75c7cd328f25c7cc6d2b5f7c9Andreas Huber            NULL /* addr */,
620bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            0 /* port */,
621bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            host,
622bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            port,
623bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            notify,
624bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            sessionID);
625bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
626bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
627bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstatus_t ANetworkSession::createRTSPServer(
628bcf09f8c995221e75c7cd328f25c7cc6d2b5f7c9Andreas Huber        const struct in_addr &addr, unsigned port,
629bcf09f8c995221e75c7cd328f25c7cc6d2b5f7c9Andreas Huber        const sp<AMessage> &notify, int32_t *sessionID) {
630bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return createClientOrServer(
631bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            kModeCreateRTSPServer,
632bcf09f8c995221e75c7cd328f25c7cc6d2b5f7c9Andreas Huber            &addr,
633bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            port,
634bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            NULL /* remoteHost */,
635bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            0 /* remotePort */,
636bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            notify,
637bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            sessionID);
638bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
639bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
640bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstatus_t ANetworkSession::createUDPSession(
641bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        unsigned localPort, const sp<AMessage> &notify, int32_t *sessionID) {
642bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return createUDPSession(localPort, NULL, 0, notify, sessionID);
643bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
644bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
645bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstatus_t ANetworkSession::createUDPSession(
646bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        unsigned localPort,
647bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        const char *remoteHost,
648bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        unsigned remotePort,
649bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        const sp<AMessage> &notify,
650bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        int32_t *sessionID) {
651bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return createClientOrServer(
652bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            kModeCreateUDPSession,
653bcf09f8c995221e75c7cd328f25c7cc6d2b5f7c9Andreas Huber            NULL /* addr */,
654bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            localPort,
655bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            remoteHost,
656bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            remotePort,
657bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            notify,
658bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            sessionID);
659bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
660bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
661bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huberstatus_t ANetworkSession::createTCPDatagramSession(
662bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        const struct in_addr &addr, unsigned port,
663bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        const sp<AMessage> &notify, int32_t *sessionID) {
664bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    return createClientOrServer(
665bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            kModeCreateTCPDatagramSessionPassive,
666bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            &addr,
667bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            port,
668bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            NULL /* remoteHost */,
669bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            0 /* remotePort */,
670bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            notify,
671bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            sessionID);
672bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber}
673bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
674bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huberstatus_t ANetworkSession::createTCPDatagramSession(
675bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        unsigned localPort,
676bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        const char *remoteHost,
677bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        unsigned remotePort,
678bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        const sp<AMessage> &notify,
679bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        int32_t *sessionID) {
680bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    return createClientOrServer(
681bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            kModeCreateTCPDatagramSessionActive,
682bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            NULL /* addr */,
683bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            localPort,
684bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            remoteHost,
685bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            remotePort,
686bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            notify,
687bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            sessionID);
688bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber}
689bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
690bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstatus_t ANetworkSession::destroySession(int32_t sessionID) {
691bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    Mutex::Autolock autoLock(mLock);
692bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
693bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    ssize_t index = mSessions.indexOfKey(sessionID);
694bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
695bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (index < 0) {
696bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return -ENOENT;
697bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
698bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
699bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    mSessions.removeItemsAt(index);
700bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
701bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    interrupt();
702bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
703bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return OK;
704bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
705bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
706bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber// static
707bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstatus_t ANetworkSession::MakeSocketNonBlocking(int s) {
708bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    int flags = fcntl(s, F_GETFL, 0);
709bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (flags < 0) {
710bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        flags = 0;
711bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
712bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
713bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    int res = fcntl(s, F_SETFL, flags | O_NONBLOCK);
714bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (res < 0) {
715bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return -errno;
716bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
717bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
718bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return OK;
719bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
720bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
721bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstatus_t ANetworkSession::createClientOrServer(
722bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        Mode mode,
723bcf09f8c995221e75c7cd328f25c7cc6d2b5f7c9Andreas Huber        const struct in_addr *localAddr,
724bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        unsigned port,
725bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        const char *remoteHost,
726bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        unsigned remotePort,
727bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        const sp<AMessage> &notify,
728bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        int32_t *sessionID) {
729bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    Mutex::Autolock autoLock(mLock);
730bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
731bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    *sessionID = 0;
732bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    status_t err = OK;
733bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    int s, res;
734bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    sp<Session> session;
735bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
736bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    s = socket(
737bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            AF_INET,
738bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            (mode == kModeCreateUDPSession) ? SOCK_DGRAM : SOCK_STREAM,
739bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            0);
740bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
741bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (s < 0) {
742bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        err = -errno;
743bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        goto bail;
744bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
745bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
746bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (mode == kModeCreateRTSPServer
747bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            || mode == kModeCreateTCPDatagramSessionPassive) {
748bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        const int yes = 1;
749bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        res = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
750bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
751bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (res < 0) {
752bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            err = -errno;
753bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            goto bail2;
754bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
755bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
756bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
757bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (mode == kModeCreateUDPSession) {
758bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        int size = 256 * 1024;
759bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
760bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        res = setsockopt(s, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
761bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
762bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (res < 0) {
763bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            err = -errno;
764bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            goto bail2;
765bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
766bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
767bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        res = setsockopt(s, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
768bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
769bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (res < 0) {
770bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            err = -errno;
771bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            goto bail2;
772bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
773bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
774bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
775bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    err = MakeSocketNonBlocking(s);
776bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
777bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (err != OK) {
778bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        goto bail2;
779bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
780bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
781bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    struct sockaddr_in addr;
782bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
783bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    addr.sin_family = AF_INET;
784bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
785bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (mode == kModeCreateRTSPClient
786bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            || mode == kModeCreateTCPDatagramSessionActive) {
787bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        struct hostent *ent= gethostbyname(remoteHost);
788bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (ent == NULL) {
789bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            err = -h_errno;
790bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            goto bail2;
791bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
792bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
793bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        addr.sin_addr.s_addr = *(in_addr_t *)ent->h_addr;
794bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        addr.sin_port = htons(remotePort);
795bcf09f8c995221e75c7cd328f25c7cc6d2b5f7c9Andreas Huber    } else if (localAddr != NULL) {
796bcf09f8c995221e75c7cd328f25c7cc6d2b5f7c9Andreas Huber        addr.sin_addr = *localAddr;
797bcf09f8c995221e75c7cd328f25c7cc6d2b5f7c9Andreas Huber        addr.sin_port = htons(port);
798bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    } else {
799bcf09f8c995221e75c7cd328f25c7cc6d2b5f7c9Andreas Huber        addr.sin_addr.s_addr = htonl(INADDR_ANY);
800bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        addr.sin_port = htons(port);
801bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
802bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
803bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (mode == kModeCreateRTSPClient
804bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            || mode == kModeCreateTCPDatagramSessionActive) {
805bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        in_addr_t x = ntohl(addr.sin_addr.s_addr);
806bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        ALOGI("connecting socket %d to %d.%d.%d.%d:%d",
807bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber              s,
808bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber              (x >> 24),
809bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber              (x >> 16) & 0xff,
810bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber              (x >> 8) & 0xff,
811bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber              x & 0xff,
812bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber              ntohs(addr.sin_port));
813bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
814bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        res = connect(s, (const struct sockaddr *)&addr, sizeof(addr));
815bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
816bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        CHECK_LT(res, 0);
817bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (errno == EINPROGRESS) {
818bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            res = 0;
819bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
820bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    } else {
821bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        res = bind(s, (const struct sockaddr *)&addr, sizeof(addr));
822bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
823bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (res == 0) {
824bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            if (mode == kModeCreateRTSPServer
825bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                    || mode == kModeCreateTCPDatagramSessionPassive) {
826bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                res = listen(s, 4);
827bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            } else {
828bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                CHECK_EQ(mode, kModeCreateUDPSession);
829bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
830bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                if (remoteHost != NULL) {
831bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    struct sockaddr_in remoteAddr;
832bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    memset(remoteAddr.sin_zero, 0, sizeof(remoteAddr.sin_zero));
833bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    remoteAddr.sin_family = AF_INET;
834bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    remoteAddr.sin_port = htons(remotePort);
835bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
836bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    struct hostent *ent= gethostbyname(remoteHost);
837bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    if (ent == NULL) {
838bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                        err = -h_errno;
839bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                        goto bail2;
840bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    }
841bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
842bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    remoteAddr.sin_addr.s_addr = *(in_addr_t *)ent->h_addr;
843bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
844bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    res = connect(
845bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                            s,
846bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                            (const struct sockaddr *)&remoteAddr,
847bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                            sizeof(remoteAddr));
848bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                }
849bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            }
850bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
851bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
852bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
853bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (res < 0) {
854bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        err = -errno;
855bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        goto bail2;
856bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
857bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
858bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    Session::State state;
859bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    switch (mode) {
860bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        case kModeCreateRTSPClient:
861bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            state = Session::CONNECTING;
862bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            break;
863bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
864bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        case kModeCreateTCPDatagramSessionActive:
865bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            state = Session::CONNECTING;
866bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            break;
867bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
868bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        case kModeCreateTCPDatagramSessionPassive:
869bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            state = Session::LISTENING_TCP_DGRAMS;
870bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            break;
871bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
872bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        case kModeCreateRTSPServer:
873bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber            state = Session::LISTENING_RTSP;
874bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            break;
875bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
876bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        default:
877bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            CHECK_EQ(mode, kModeCreateUDPSession);
878bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            state = Session::DATAGRAM;
879bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            break;
880bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
881bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
882bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    session = new Session(
883bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            mNextSessionID++,
884bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            state,
885bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            s,
886bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            notify);
887bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
888bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    if (mode == kModeCreateTCPDatagramSessionActive) {
889bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        session->setIsRTSPConnection(false);
890bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    } else if (mode == kModeCreateRTSPClient) {
891bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber        session->setIsRTSPConnection(true);
892bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    }
893bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
894bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    mSessions.add(session->sessionID(), session);
895bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
896bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    interrupt();
897bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
898bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    *sessionID = session->sessionID();
899bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
900bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    goto bail;
901bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
902bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberbail2:
903bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    close(s);
904bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    s = -1;
905bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
906bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberbail:
907bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return err;
908bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
909bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
910bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstatus_t ANetworkSession::connectUDPSession(
911bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        int32_t sessionID, const char *remoteHost, unsigned remotePort) {
912bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    Mutex::Autolock autoLock(mLock);
913bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
914bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    ssize_t index = mSessions.indexOfKey(sessionID);
915bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
916bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (index < 0) {
917bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return -ENOENT;
918bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
919bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
920bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    const sp<Session> session = mSessions.valueAt(index);
921bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    int s = session->socket();
922bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
923bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    struct sockaddr_in remoteAddr;
924bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    memset(remoteAddr.sin_zero, 0, sizeof(remoteAddr.sin_zero));
925bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    remoteAddr.sin_family = AF_INET;
926bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    remoteAddr.sin_port = htons(remotePort);
927bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
928bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    status_t err = OK;
929bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber    struct hostent *ent = gethostbyname(remoteHost);
930bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (ent == NULL) {
931bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        err = -h_errno;
932bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    } else {
933bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        remoteAddr.sin_addr.s_addr = *(in_addr_t *)ent->h_addr;
934bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
935bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        int res = connect(
936bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                s,
937bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                (const struct sockaddr *)&remoteAddr,
938bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                sizeof(remoteAddr));
939bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
940bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (res < 0) {
941bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            err = -errno;
942bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
943bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
944bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
945bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return err;
946bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
947bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
948bb197f84c4119651e5face418285688ddaf08ea3Andreas Huberstatus_t ANetworkSession::sendRequest(
949bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        int32_t sessionID, const void *data, ssize_t size) {
950bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    Mutex::Autolock autoLock(mLock);
951bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
952bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    ssize_t index = mSessions.indexOfKey(sessionID);
953bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
954bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (index < 0) {
955bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return -ENOENT;
956bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
957bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
958bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    const sp<Session> session = mSessions.valueAt(index);
959bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
960bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    status_t err = session->sendRequest(data, size);
961bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
962bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    interrupt();
963bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
964bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    return err;
965bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
966bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
967bb197f84c4119651e5face418285688ddaf08ea3Andreas Hubervoid ANetworkSession::interrupt() {
968bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    static const char dummy = 0;
969bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
970bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    ssize_t n;
971bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    do {
972bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        n = write(mPipeFd[1], &dummy, 1);
973bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    } while (n < 0 && errno == EINTR);
974bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
975bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (n < 0) {
976bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        ALOGW("Error writing to pipe (%s)", strerror(errno));
977bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
978bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
979bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
980bb197f84c4119651e5face418285688ddaf08ea3Andreas Hubervoid ANetworkSession::threadLoop() {
981bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    fd_set rs, ws;
982bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    FD_ZERO(&rs);
983bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    FD_ZERO(&ws);
984bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
985bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    FD_SET(mPipeFd[0], &rs);
986bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    int maxFd = mPipeFd[0];
987bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
988bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    {
989bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        Mutex::Autolock autoLock(mLock);
990bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
991bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        for (size_t i = 0; i < mSessions.size(); ++i) {
992bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            const sp<Session> &session = mSessions.valueAt(i);
993bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
994bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            int s = session->socket();
995bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
996bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            if (s < 0) {
997bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                continue;
998bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            }
999bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1000bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            if (session->wantsToRead()) {
1001bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                FD_SET(s, &rs);
1002bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                if (s > maxFd) {
1003bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    maxFd = s;
1004bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                }
1005bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            }
1006bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1007bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            if (session->wantsToWrite()) {
1008bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                FD_SET(s, &ws);
1009bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                if (s > maxFd) {
1010bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    maxFd = s;
1011bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                }
1012bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            }
1013bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
1014bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
1015bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1016bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    int res = select(maxFd + 1, &rs, &ws, NULL, NULL /* tv */);
1017bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1018bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (res == 0) {
1019bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return;
1020bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
1021bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1022bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (res < 0) {
1023bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (errno == EINTR) {
1024bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            return;
1025bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
1026bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1027bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        ALOGE("select failed w/ error %d (%s)", errno, strerror(errno));
1028bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        return;
1029bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
1030bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1031bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    if (FD_ISSET(mPipeFd[0], &rs)) {
1032bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        char c;
1033bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        ssize_t n;
1034bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        do {
1035bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            n = read(mPipeFd[0], &c, 1);
1036bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        } while (n < 0 && errno == EINTR);
1037bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1038bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        if (n < 0) {
1039bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            ALOGW("Error reading from pipe (%s)", strerror(errno));
1040bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
1041bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1042bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        --res;
1043bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
1044bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1045bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    {
1046bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        Mutex::Autolock autoLock(mLock);
1047bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1048bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        List<sp<Session> > sessionsToAdd;
1049bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1050bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        for (size_t i = mSessions.size(); res > 0 && i-- > 0;) {
1051bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            const sp<Session> &session = mSessions.valueAt(i);
1052bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1053bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            int s = session->socket();
1054bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1055bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            if (s < 0) {
1056bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                continue;
1057bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            }
1058bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1059bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            if (FD_ISSET(s, &rs) || FD_ISSET(s, &ws)) {
1060bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                --res;
1061bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            }
1062bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1063bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            if (FD_ISSET(s, &rs)) {
1064bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                if (session->isRTSPServer() || session->isTCPDatagramServer()) {
1065bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    struct sockaddr_in remoteAddr;
1066bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    socklen_t remoteAddrLen = sizeof(remoteAddr);
1067bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1068bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    int clientSocket = accept(
1069bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                            s, (struct sockaddr *)&remoteAddr, &remoteAddrLen);
1070bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1071bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    if (clientSocket >= 0) {
1072bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                        status_t err = MakeSocketNonBlocking(clientSocket);
1073bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1074bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                        if (err != OK) {
1075bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                            ALOGE("Unable to make client socket non blocking, "
1076bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                  "failed w/ error %d (%s)",
1077bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                  err, strerror(-err));
1078bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1079bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                            close(clientSocket);
1080bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                            clientSocket = -1;
1081bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                        } else {
1082bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                            in_addr_t addr = ntohl(remoteAddr.sin_addr.s_addr);
1083bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1084bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                            ALOGI("incoming connection from %d.%d.%d.%d:%d "
1085bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                  "(socket %d)",
1086bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                  (addr >> 24),
1087bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                  (addr >> 16) & 0xff,
1088bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                  (addr >> 8) & 0xff,
1089bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                  addr & 0xff,
1090bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                  ntohs(remoteAddr.sin_port),
1091bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                  clientSocket);
1092bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1093bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                            sp<Session> clientSession =
1094bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                // using socket sd as sessionID
1095bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                new Session(
1096bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                        mNextSessionID++,
1097bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                        Session::CONNECTED,
1098bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                        clientSocket,
1099bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                                        session->getNotificationMessage());
1100bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1101bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                            clientSession->setIsRTSPConnection(
1102bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber                                    session->isRTSPServer());
1103bd08e2f93bafd02abf2c25d740e9fb8bce455a99Andreas Huber
1104bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                            sessionsToAdd.push_back(clientSession);
1105bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                        }
1106bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    } else {
1107bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                        ALOGE("accept returned error %d (%s)",
1108bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                              errno, strerror(errno));
1109bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    }
1110bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                } else {
1111bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    status_t err = session->readMore();
1112bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    if (err != OK) {
111396fc6cc65ca93009a759a3a874b82a35771b9714Andreas Huber                        ALOGE("readMore on socket %d failed w/ error %d (%s)",
1114bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                              s, err, strerror(-err));
1115bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                    }
1116bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                }
1117bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            }
1118bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1119bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            if (FD_ISSET(s, &ws)) {
1120bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                status_t err = session->writeMore();
1121bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                if (err != OK) {
112296fc6cc65ca93009a759a3a874b82a35771b9714Andreas Huber                    ALOGE("writeMore on socket %d failed w/ error %d (%s)",
1123bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                          s, err, strerror(-err));
1124bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber                }
1125bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            }
1126bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
1127bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1128bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        while (!sessionsToAdd.empty()) {
1129bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            sp<Session> session = *sessionsToAdd.begin();
1130bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            sessionsToAdd.erase(sessionsToAdd.begin());
1131bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1132bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            mSessions.add(session->sessionID(), session);
1133bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1134bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber            ALOGI("added clientSession %d", session->sessionID());
1135bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber        }
1136bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber    }
1137bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}
1138bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1139bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber}  // namespace android
1140bb197f84c4119651e5face418285688ddaf08ea3Andreas Huber
1141